summaryrefslogtreecommitdiff
path: root/drivers/media/pci/cx23885/cx23885-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/pci/cx23885/cx23885-core.c')
-rw-r--r--drivers/media/pci/cx23885/cx23885-core.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 3f553199eb4d..cd0e1b806930 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -601,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 */
@@ -646,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],
@@ -662,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);
}
@@ -676,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;
}
@@ -1352,6 +1380,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);
@@ -1432,16 +1463,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);
@@ -1449,6 +1490,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;
}
@@ -1456,15 +1502,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 */
@@ -1475,7 +1534,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)