summaryrefslogtreecommitdiff
path: root/linux/drivers/media/common/saa7146_i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/drivers/media/common/saa7146_i2c.c')
-rw-r--r--linux/drivers/media/common/saa7146_i2c.c89
1 files changed, 33 insertions, 56 deletions
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)) {