diff options
Diffstat (limited to 'linux/drivers/media/common/saa7146_core.c')
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index a92511cdd..22c7f3e22 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -355,15 +355,16 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) saa7146_write(dev, ISR, isr); - if( 0 != (dev->ext->irq_mask & isr )) { - if( 0 != dev->ext->irq_func ) { - dev->ext->irq_func(dev, &isr); + if( 0 != (dev->ext)) { + if( 0 != (dev->ext->irq_mask & isr )) { + if( 0 != dev->ext->irq_func ) { + dev->ext->irq_func(dev, &isr); + } + isr &= ~dev->ext->irq_mask; } - isr &= ~dev->ext->irq_mask; } - if (0 != (isr & (MASK_27))) { - DEB_INT(("irq: RPS0.\n")); + DEB_INT(("irq: RPS0 (0x%08x).\n",isr)); saa7146_video_uops.irq_done(dev,isr); isr &= ~MASK_27; } @@ -371,14 +372,29 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) u32 mc2 = saa7146_read(dev, MC2); isr &= ~MASK_28; if( 0 != (mc2 & MASK_15)) { - DEB_INT(("irq: RPS1 vbi workaround.\n")); + DEB_INT(("irq: RPS1 vbi workaround (0x%08x).\n",isr)); wake_up(&dev->vbi_wq); saa7146_write(dev,MC2, MASK_31); return; } - DEB_INT(("irq: RPS1.\n")); + DEB_INT(("irq: RPS1 (0x%08x).\n",isr)); saa7146_vbi_uops.irq_done(dev,isr); } + if (0 != (isr & (MASK_16|MASK_17))) { + u32 status = saa7146_read(dev, I2C_STATUS); + isr &= ~(MASK_16|MASK_17); + if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { + IER_DISABLE(dev, MASK_16|MASK_17); + /* only wake up if we expect something */ + if( 0 != dev->i2c_op ) { + u32 psr = (saa7146_read(dev, PSR) >> 16) & 0x2; + u32 ssr = (saa7146_read(dev, SSR) >> 17) & 0x1f; + DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr)); + wake_up(&dev->i2c_wq); + dev->i2c_op = 0; + } + } + } if( 0 != isr ) { ERR(("warning: interrupt enabled, but not handled properly.(0x%08x)\n",isr)); ERR(("disabling interrupt source(s)!\n")); @@ -587,7 +603,7 @@ void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_ext dev->ext = NULL; return; } - INFO(("%s: registered device video%d [v4l2],%d\n", dev->name,dev->video_dev.minor & 0x1f,dev->vbi_dev.minor & 0x1f)); + INFO(("%s: registered device video%d [v4l2]\n", dev->name,dev->video_dev.minor & 0x1f)); /* initialization stuff (vbi) (only for revision > 0 and for extensions which want it)*/ if( 0 != BOARD_CAN_DO_VBI(dev)) { @@ -759,9 +775,8 @@ static int config_a_device(struct pci_dev *pci) saa7146_write(dev, MC1, MASK_31); */ - /* disable alle irqs, clear irq-mask */ + /* disable alle irqs */ saa7146_write(dev, IER, 0); - saa7146_write(dev, ISR, 0xffffffff); /* shut down all dma transfers */ saa7146_write(dev, MC1, 0x00ff0000); @@ -827,6 +842,7 @@ static int config_a_device(struct pci_dev *pci) saa7146_vbi_uops.init(dev); dev->module = THIS_MODULE; + init_waitqueue_head(&dev->i2c_wq); return try_match_device_to_extension(dev); @@ -854,7 +870,6 @@ static void unconfig_a_device(struct saa7146_dev* dev) /* disable all irqs, release irq-routine */ saa7146_write(dev, IER, 0); - saa7146_write(dev, ISR, 0xffffffff); free_irq(dev->pci->irq, (void *)dev); |