diff options
Diffstat (limited to 'drivers/media/pci/cx23885')
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-alsa.c | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-core.c | 132 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-dvb.c | 6 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-input.c | 2 | ||||
-rw-r--r-- | drivers/media/pci/cx23885/cx23885-reg.h | 14 |
5 files changed, 133 insertions, 23 deletions
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index 20b3cb17f97f..db1e8ff35474 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -95,7 +95,7 @@ static int cx23885_alsa_dma_init(struct cx23885_audio_dev *chip, int nr_pages) memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); buf->nr_pages = nr_pages; - buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); + buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages)); if (NULL == buf->sglist) goto vzalloc_err; diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index 019fac49db5b..94b996ff12a9 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -422,19 +422,30 @@ static void cx23885_wakeup(struct cx23885_tsport *port, struct cx23885_dmaqueue *q, u32 count) { struct cx23885_buffer *buf; - - if (list_empty(&q->active)) - return; - buf = list_entry(q->active.next, - struct cx23885_buffer, queue); - - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - buf->vb.sequence = q->count++; - dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, - buf->vb.vb2_buf.index, - count, q->count); - list_del(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + int count_delta; + int max_buf_done = 5; /* service maximum five buffers */ + + do { + if (list_empty(&q->active)) + return; + buf = list_entry(q->active.next, + struct cx23885_buffer, queue); + + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + buf->vb.sequence = q->count++; + if (count != (q->count % 65536)) { + dprintk(1, "[%p/%d] wakeup reg=%d buf=%d\n", buf, + buf->vb.vb2_buf.index, count, q->count); + } else { + dprintk(7, "[%p/%d] wakeup reg=%d buf=%d\n", buf, + buf->vb.vb2_buf.index, count, q->count); + } + list_del(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); + max_buf_done--; + /* count register is 16 bits so apply modulo appropriately */ + count_delta = ((int)count - (int)(q->count % 65536)); + } while ((count_delta > 0) && (max_buf_done > 0)); } int cx23885_sram_channel_setup(struct cx23885_dev *dev, @@ -590,6 +601,25 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port, } } +static void cx23885_clear_bridge_error(struct cx23885_dev *dev) +{ + uint32_t reg1_val = cx_read(TC_REQ); /* read-only */ + uint32_t reg2_val = cx_read(TC_REQ_SET); + + if (reg1_val && reg2_val) { + cx_write(TC_REQ, reg1_val); + cx_write(TC_REQ_SET, reg2_val); + cx_read(VID_B_DMA); + cx_read(VBI_B_DMA); + cx_read(VID_C_DMA); + cx_read(VBI_C_DMA); + + dev_info(&dev->pci->dev, + "dma in progress detected 0x%08x 0x%08x, clearing\n", + reg1_val, reg2_val); + } +} + static void cx23885_shutdown(struct cx23885_dev *dev) { /* disable RISC controller */ @@ -635,6 +665,8 @@ static void cx23885_reset(struct cx23885_dev *dev) cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000); cx_write(PAD_CTRL, 0x00500300); + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); mdelay(100); cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], @@ -651,6 +683,11 @@ static void cx23885_reset(struct cx23885_dev *dev) cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0); cx23885_gpio_setup(dev); + + cx23885_irq_get_mask(dev); + + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); } @@ -665,6 +702,8 @@ static int cx23885_pci_quirks(struct cx23885_dev *dev) if (dev->bridge == CX23885_BRIDGE_885) cx_clear(RDR_TLCTL0, 1 << 4); + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); return 0; } @@ -1329,6 +1368,18 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en)); dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __func__, port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk)); + dprintk(1, "%s() ts_int_status(0x%08X) 0x%08x\n", __func__, + port->reg_ts_int_stat, cx_read(port->reg_ts_int_stat)); + dprintk(1, "%s() PCI_INT_STAT 0x%08X\n", __func__, + cx_read(PCI_INT_STAT)); + dprintk(1, "%s() VID_B_INT_MSTAT 0x%08X\n", __func__, + cx_read(VID_B_INT_MSTAT)); + dprintk(1, "%s() VID_B_INT_SSTAT 0x%08X\n", __func__, + cx_read(VID_B_INT_SSTAT)); + dprintk(1, "%s() VID_C_INT_MSTAT 0x%08X\n", __func__, + cx_read(VID_C_INT_MSTAT)); + dprintk(1, "%s() VID_C_INT_SSTAT 0x%08X\n", __func__, + cx_read(VID_C_INT_SSTAT)); } int cx23885_start_dma(struct cx23885_tsport *port, @@ -1341,6 +1392,9 @@ int cx23885_start_dma(struct cx23885_tsport *port, dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__, dev->width, dev->height, dev->field); + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); + /* Stop the fifo and risc engine for this port */ cx_clear(port->reg_dma_ctl, port->dma_ctl_val); @@ -1410,8 +1464,15 @@ int cx23885_start_dma(struct cx23885_tsport *port, reg = reg | 0xa; cx_write(PAD_CTRL, reg); - /* FIXME and these two registers should be documented. */ + /* Sets MOE_CLK_DIS to disable MoE clock */ + /* sets MCLK_DLY_SEL/BCLK_DLY_SEL to 1 buffer delay each */ cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011); + + /* ALT_GPIO_ALT_SET: GPIO[0] + * IR_ALT_TX_SEL: GPIO[1] + * GPIO1_ALT_SEL: VIP_656_DATA[0] + * GPIO0_ALT_SEL: VIP_656_CLK + */ cx_write(ALT_PIN_OUT_SEL, 0x10100045); } @@ -1421,16 +1482,26 @@ int cx23885_start_dma(struct cx23885_tsport *port, case CX23885_BRIDGE_888: /* enable irqs */ dprintk(1, "%s() enabling TS int's and DMA\n", __func__); + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); cx_set(port->reg_dma_ctl, port->dma_ctl_val); + + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); cx23885_irq_add(dev, port->pci_irqmask); cx23885_irq_enable_all(dev); + + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); break; default: BUG(); } cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) cx23885_av_clk(dev, 1); @@ -1438,6 +1509,11 @@ int cx23885_start_dma(struct cx23885_tsport *port, if (debug > 4) cx23885_tsport_reg_dump(port); + cx23885_irq_get_mask(dev); + + /* clear dma in progress */ + cx23885_clear_bridge_error(dev); + return 0; } @@ -1445,15 +1521,28 @@ static int cx23885_stop_dma(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; u32 reg; + int delay = 0; + uint32_t reg1_val; + uint32_t reg2_val; dprintk(1, "%s()\n", __func__); /* Stop interrupts and DMA */ cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val); cx_clear(port->reg_dma_ctl, port->dma_ctl_val); + /* just in case wait for any dma to complete before allowing dealloc */ + mdelay(20); + for (delay = 0; delay < 100; delay++) { + reg1_val = cx_read(TC_REQ); + reg2_val = cx_read(TC_REQ_SET); + if (reg1_val == 0 || reg2_val == 0) + break; + mdelay(1); + } + dev_dbg(&dev->pci->dev, "delay=%d reg1=0x%08x reg2=0x%08x\n", + delay, reg1_val, reg2_val); if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) { - reg = cx_read(PAD_CTRL); /* Set TS1_OE */ @@ -1464,7 +1553,6 @@ static int cx23885_stop_dma(struct cx23885_tsport *port) cx_write(PAD_CTRL, reg); cx_write(port->reg_src_sel, 0); cx_write(port->reg_gen_ctrl, 8); - } if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) @@ -1693,6 +1781,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) pci_status = cx_read(PCI_INT_STAT); pci_mask = cx23885_irq_get_mask(dev); + if ((pci_status & pci_mask) == 0) { + dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", + pci_status, pci_mask); + goto out; + } + vida_status = cx_read(VID_A_INT_STAT); vida_mask = cx_read(VID_A_INT_MSK); audint_status = cx_read(AUDIO_INT_INT_STAT); @@ -1702,7 +1796,9 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) ts2_status = cx_read(VID_C_INT_STAT); ts2_mask = cx_read(VID_C_INT_MSK); - if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0)) + if (((pci_status & pci_mask) == 0) && + ((ts2_status & ts2_mask) == 0) && + ((ts1_status & ts1_mask) == 0)) goto out; vida_count = cx_read(VID_A_GPCNT); @@ -1829,7 +1925,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) } if (handled) - cx_write(PCI_INT_STAT, pci_status); + cx_write(PCI_INT_STAT, pci_status & pci_mask); out: return IRQ_RETVAL(handled); } diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c index 114d9bcbe4f4..7d52173073d6 100644 --- a/drivers/media/pci/cx23885/cx23885-dvb.c +++ b/drivers/media/pci/cx23885/cx23885-dvb.c @@ -252,7 +252,6 @@ static struct mt2131_config hauppauge_generic_tunerconfig = { }; static struct lgdt330x_config fusionhdtv_5_express = { - .demod_address = 0x0e, .demod_chip = LGDT3303, .serial_mpeg = 0x40, }; @@ -1321,8 +1320,9 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, - &fusionhdtv_5_express, - &i2c_bus->i2c_adap); + &fusionhdtv_5_express, + 0x0e, + &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) break; dvb_attach(simple_tuner_attach, fe0->dvb.frontend, diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c index be49589a61d2..395ff9bba759 100644 --- a/drivers/media/pci/cx23885/cx23885-input.c +++ b/drivers/media/pci/cx23885/cx23885-input.c @@ -13,7 +13,7 @@ * Copyright (C) 2008 <srinivasa.deevi at conexant dot com> * Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> * Markus Rechberger <mrechberger@gmail.com> - * Mauro Carvalho Chehab <mchehab@infradead.org> + * Mauro Carvalho Chehab <mchehab@kernel.org> * Sascha Sommer <saschasommer@freenet.de> * Copyright (C) 2004, 2005 Chris Pascoe * Copyright (C) 2003, 2004 Gerd Knorr diff --git a/drivers/media/pci/cx23885/cx23885-reg.h b/drivers/media/pci/cx23885/cx23885-reg.h index 2d3cbafe2402..08cec8d91742 100644 --- a/drivers/media/pci/cx23885/cx23885-reg.h +++ b/drivers/media/pci/cx23885/cx23885-reg.h @@ -288,6 +288,18 @@ Channel manager Data Structure entry = 20 DWORD #define AUDIO_EXT_INT_MSTAT 0x00040068 #define AUDIO_EXT_INT_SSTAT 0x0004006C +/* Bits [7:0] set in both TC_REQ and TC_REQ_SET + * indicate a stall in the RISC engine for a + * particular rider traffic class. This causes + * the 885 and 888 bridges (unknown about 887) + * to become inoperable. Setting bits in + * TC_REQ_SET resets the corresponding bits + * in TC_REQ (and TC_REQ_SET) allowing + * operation to continue. + */ +#define TC_REQ 0x00040090 +#define TC_REQ_SET 0x00040094 + #define RDR_CFG0 0x00050000 #define RDR_CFG1 0x00050004 #define RDR_CFG2 0x00050008 @@ -386,6 +398,8 @@ Channel manager Data Structure entry = 20 DWORD #define VID_B_PIXEL_FRMT 0x00130184 /* Video C Interface */ +#define VID_C_DMA 0x00130200 +#define VBI_C_DMA 0x00130208 #define VID_C_GPCNT 0x00130220 #define VID_C_GPCNT_CTL 0x00130230 #define VBI_C_GPCNT_CTL 0x00130234 |