diff options
Diffstat (limited to 'linux/drivers/media')
-rw-r--r-- | linux/drivers/media/common/saa7146_i2c.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/linux/drivers/media/common/saa7146_i2c.c b/linux/drivers/media/common/saa7146_i2c.c index 9a0092635..cade026d2 100644 --- a/linux/drivers/media/common/saa7146_i2c.c +++ b/linux/drivers/media/common/saa7146_i2c.c @@ -313,7 +313,23 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i for(i = 0; i < count; i++) { err = saa7146_i2c_writeout(dev, &buffer[i] ); if ( 0 != err) { + /* this one is unsatisfying: some i2c slaves on some + dvb cards don't acknowledge correctly, so the saa7146 + thinks that an address error occured. in that case, the + transaction should be retrying, even if an address error + occured. analog saa7146 based cards extensively rely on + i2c address probing, however, and address errors indicate that a + device is really *not* there. retrying in that case + increases the time the device needs to probe greatly, so + it should be avoided. because of the fact, that only + analog based cards use irq based i2c transactions (for dvb + cards, this screwes up other interrupt sources), we bail out + completely for analog cards after an address error and trust + the saa7146 address error detection. */ if ( -EREMOTEIO == err ) { + if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) { + goto out; + } address_err++; } DEB_I2C(("error while sending message(s). starting again.\n")); @@ -330,15 +346,6 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i } while (err != num && retries--); - /* another bug in revision 0: the i2c-registers get uploaded randomly by other - uploads, so we better clear them out before continueing */ - if( 0 == dev->revision ) { - u32 zero = 0; - if( 0 != saa7146_i2c_writeout(dev, &zero)) { - INFO(("revision 0 error. this should never happen.\n")); - } - } - /* if every retry had an address error, exit right away */ if (address_err == retries) { goto out; @@ -354,6 +361,16 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i /* return the number of delivered messages */ DEB_I2C(("transmission successful. (msg:%d).\n",err)); out: + /* another bug in revision 0: the i2c-registers get uploaded randomly by other + uploads, so we better clear them out before continueing */ + if( 0 == dev->revision ) { + u32 zero = 0; + saa7146_i2c_reset(dev); + if( 0 != saa7146_i2c_writeout(dev, &zero)) { + INFO(("revision 0 error. this should never happen.\n")); + } + } + up(&dev->i2c_lock); return err; } |