diff options
Diffstat (limited to 'linux/drivers/media/common/saa7146_i2c.c')
-rw-r--r-- | linux/drivers/media/common/saa7146_i2c.c | 89 |
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)) { |