summaryrefslogtreecommitdiff
path: root/linux/drivers/media/common/saa7146_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/common/saa7146_core.c')
-rw-r--r--linux/drivers/media/common/saa7146_core.c39
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);