diff options
author | Michael Hunold <devnull@localhost> | 2002-12-22 19:34:54 +0000 |
---|---|---|
committer | Michael Hunold <devnull@localhost> | 2002-12-22 19:34:54 +0000 |
commit | 8b66183832300c20e17957fdfabc112b2d0ed8d1 (patch) | |
tree | c002284e1874e0350c7d0a2825e51159d7d64fea /linux | |
parent | 12c89ec2f0b891897eeb8a0ff6c38a6067553a7d (diff) | |
download | mediapointer-dvb-s2-8b66183832300c20e17957fdfabc112b2d0ed8d1.tar.gz mediapointer-dvb-s2-8b66183832300c20e17957fdfabc112b2d0ed8d1.tar.bz2 |
Changed i2c_writeout() and the irq handler to use a waitqueue
instead of busy waiting for an i2c transaction to finish. Left the
old method in there. if you need it (or if i screwed up),
set "use_i2c_irq" to zero in saa7146_i2c.c to get the old behaviour.
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drivers/media/common/saa7146.h | 4 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 39 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_i2c.c | 23 | ||||
-rw-r--r-- | linux/drivers/media/dvb/av7110/av7110.c | 5 |
4 files changed, 54 insertions, 17 deletions
diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index 282be0531..c650cf70d 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -237,6 +237,8 @@ struct saa7146_dev /* i2c-stuff */ u32 i2c_bitrate; u32* i2c_mem; /* pointer to i2c memory */ + wait_queue_head_t i2c_wq; + int i2c_op; /* memories */ u32* clipping; /* pointer to clipping memory */ @@ -257,7 +259,7 @@ struct saa7146_dev /* video capture */ struct saa7146_dmaqueue video_q; - struct saa7146_fh *streaming; + struct saa7146_fh *streaming; /* common: fixme? shouldn't this be in saa7146_fh? (this leads to a more complicated question: shall the driver 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); diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index ed5f23930..1a2781da6 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -188,6 +188,8 @@ int saa7146_i2c_reset(struct saa7146_dev *dev) return 0; } +static int use_i2c_irq = 1; + /* this functions writes out the data-byte 'dword' to the i2c-device. it returns 0 if ok, -1 if the transfer failed, -2 if the transfer failed badly (e.g. address error) */ @@ -197,9 +199,23 @@ int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) int i = 0; u32 status = 0, mc2 = 0; - DEB_I2C(("before: 0x%08x\n",*dword)); - /* write out i2c-command */ +if( 0 != use_i2c_irq ) { + dev->i2c_op = 1; + DEB_I2C(("before: 0x%08x (status: 0x%08x), %d\n",*dword,saa7146_read(dev, I2C_STATUS), dev->i2c_op)); + + saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); + saa7146_write(dev, I2C_TRANSFER, *dword); + IER_ENABLE(dev, MASK_16|MASK_17); + saa7146_write(dev, MC2, (MASK_00 | MASK_16)); + + wait_event_interruptible(dev->i2c_wq, (0 == dev->i2c_op) ); + if( 0 != dev->i2c_op ) { + printk("saa7146: bogus i2c stuff happened.\n"); + dev->i2c_op = 0; + } + status = saa7146_read(dev, I2C_STATUS); +} else { saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); saa7146_write(dev, I2C_TRANSFER, *dword); saa7146_write(dev, MC2, (MASK_00 | MASK_16)); @@ -232,6 +248,7 @@ int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) DEB_I2C(("timeout error. #2\n")); return -1; } +} /* give a detailed status report */ if ( 0 != (status & SAA7146_I2C_ERR)) { @@ -378,6 +395,8 @@ struct i2c_algorithm saa7146_algo = { int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate) { + DEB_EE(("bitrate: 0x%08x\n",bitrate)); + dev->i2c_bitrate = bitrate; saa7146_i2c_reset(dev); diff --git a/linux/drivers/media/dvb/av7110/av7110.c b/linux/drivers/media/dvb/av7110/av7110.c index 7662a8b78..de9d40b31 100644 --- a/linux/drivers/media/dvb/av7110/av7110.c +++ b/linux/drivers/media/dvb/av7110/av7110.c @@ -4360,11 +4360,12 @@ int av7110_attach (struct saa7146_dev* dev) dvb_register_adapter(&av7110->dvb_adapter, av7110->card_type->name); + /* FIXME: speed ok? */ + saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_480); + av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, av7110->dvb_adapter, 0); - /* FIXME: speed ok? */ - saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_480); av7110->i2c_bus = dvb_register_i2c_bus (master_xfer, dev, av7110->dvb_adapter, 0); |