diff options
Diffstat (limited to 'linux/drivers/media/common')
-rw-r--r-- | linux/drivers/media/common/saa7146.h | 6 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_core.c | 11 | ||||
-rw-r--r-- | linux/drivers/media/common/saa7146_i2c.c | 89 |
3 files changed, 43 insertions, 63 deletions
diff --git a/linux/drivers/media/common/saa7146.h b/linux/drivers/media/common/saa7146.h index b5ee99d64..39ecdda33 100644 --- a/linux/drivers/media/common/saa7146.h +++ b/linux/drivers/media/common/saa7146.h @@ -73,6 +73,9 @@ struct saa7146_pgtable { struct saa7146_extension { char name[32]; /* name of the device */ +#define SAA7146_USE_I2C_IRQ 0x1 + int flags; + struct saa7146_ext_vv *ext_vv_data; struct list_head item; @@ -80,8 +83,7 @@ struct saa7146_extension /* pairs of subvendor and subdevice ids for supported devices, last entry 0xffff, 0xfff */ struct saa7146_sub_info *devices; - - struct module* module; + struct module *module; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) void (*inc_use)(struct saa7146_dev*); diff --git a/linux/drivers/media/common/saa7146_core.c b/linux/drivers/media/common/saa7146_core.c index bd079b0e5..f064b49d0 100644 --- a/linux/drivers/media/common/saa7146_core.c +++ b/linux/drivers/media/common/saa7146_core.c @@ -180,12 +180,12 @@ static void interrupt_hw(int irq, void *dev_id, struct pt_regs *regs) DEB_I2C(("irq: i2c, status: 0x%08x, psr:0x%02x, ssr:0x%02x).\n",status,psr,ssr)); dev->i2c_op = 0; wake_up(&dev->i2c_wq); - } - else + } else { DEB_I2C(("unexpected irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); - } - else + } + } else { DEB_I2C(("unhandled irq: i2c, status: 0x%08x, isr %#x\n",status, isr)); + } isr &= ~(MASK_16|MASK_17); } if( 0 != isr ) { @@ -229,14 +229,15 @@ void try_attach_extension_and_device(struct saa7146_dev *dev, struct saa7146_ext return; } + dev->ext = ext; if( 0 != ext->probe) { if( 0 != ext->probe(dev, dev->pci->subsystem_vendor, dev->pci->subsystem_device) ) { DEB_D(("ext->probe() failed for %p. skipping device.\n",dev)); + dev->ext = NULL; return; } } - dev->ext = ext; if( 0 != ext->attach(dev, &ext->devices[i]) ) { DEB_D(("ext->attach() failed for %p. skipping device.\n",dev)); dev->ext = NULL; diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index 8a8c86265..9a62cb176 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -7,10 +7,8 @@ static void my_wait(struct saa7146_dev *dev, long ms) { - unsigned long timeout = jiffies + ((ms+9)/10); - while(time_before(jiffies, timeout)) { - schedule(); - } + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((((ms+10)/10)*HZ)/1000); } u32 saa7146_i2c_func(struct i2c_adapter *adapter) @@ -188,74 +186,53 @@ 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) */ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) { - int i = 0; u32 status = 0, mc2 = 0; - const int timeout = SAA7146_I2C_TIMEOUT * HZ / 1000; /* 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_17); - saa7146_write(dev, MC2, (MASK_00 | MASK_16)); + if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { - interruptible_sleep_on_timeout(&dev->i2c_wq, timeout); - if( 0 != dev->i2c_op ) { - DEB_I2C(("error: i2c timeout\n")); - dev->i2c_op = 0; - status = saa7146_read(dev, I2C_STATUS); - if( 0 != (status & SAA7146_I2C_APERR) ) { - DEB_I2C(("timeout in address phase.\n")); - return -2; + saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate); + saa7146_write(dev, I2C_TRANSFER, *dword); + + dev->i2c_op = 1; + IER_ENABLE(dev, MASK_16|MASK_17); + saa7146_write(dev, MC2, (MASK_00 | MASK_16)); + + wait_event_interruptible(dev->i2c_wq, dev->i2c_op == 0); + if (signal_pending (current)) { + /* a signal arrived */ + return -ERESTARTSYS; } - return -1; - } - 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)); - - /* do not poll for i2c-status before upload is complete */ - for (i = 5; i > 0; i--) { - mc2 = (saa7146_read(dev, MC2) & 0x1); - if( 0 != mc2 ) - break; - my_wait(dev,SAA7146_I2C_DELAY); - } - if (0 == i) { - DEB_I2C(("timeout error. #1\n")); - return -1; - } + 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)); - /* wait until busy flag becomes inactive or we time out */ - for (i = 5; i > 0; i--) { - status = saa7146_i2c_status(dev); - /* check busy flag */ - if ( 0 == (status & SAA7146_I2C_BUSY)) - break; - /* check error flag */ - if ( 0 != (status & SAA7146_I2C_ERR)) { - break; + /* do not poll for i2c-status before upload is complete */ + while(1) { + mc2 = (saa7146_read(dev, MC2) & 0x1); + if( 0 != mc2 ) { + break; + } + } + /* wait until we get a transfer done or error */ + while(1) { + status = saa7146_i2c_status(dev); + if( (0x3 == (status & 0x3)) || (0 == (status & 0x1)) ) { + break; + } + my_wait(dev,1); } - my_wait(dev,SAA7146_I2C_DELAY); - } - if (0 == i) { - DEB_I2C(("timeout error. #2\n")); - return -1; } -} /* give a detailed status report */ if ( 0 != (status & SAA7146_I2C_ERR)) { |