summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorMichael Hunold <devnull@localhost>2002-12-22 19:34:54 +0000
committerMichael Hunold <devnull@localhost>2002-12-22 19:34:54 +0000
commit8b66183832300c20e17957fdfabc112b2d0ed8d1 (patch)
treec002284e1874e0350c7d0a2825e51159d7d64fea /linux
parent12c89ec2f0b891897eeb8a0ff6c38a6067553a7d (diff)
downloadmediapointer-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.h4
-rw-r--r--linux/drivers/media/common/saa7146_core.c39
-rw-r--r--linux/drivers/media/common/saa7146_i2c.c23
-rw-r--r--linux/drivers/media/dvb/av7110/av7110.c5
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);