V4L/DVB (11074): au0828: fix i2c enumeration bug
authorDevin Heitmueller <dheitmueller@linuxtv.org>
Wed, 11 Mar 2009 06:00:56 +0000 (03:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 30 Mar 2009 15:43:26 +0000 (12:43 -0300)
There was a bug where enumerating the i2c for devices would result in false
positives.  The root of the issue was the scanning was using SMBUS_QUICK
messages, which are zero length write requests (which our i2c adapter
implementation didn't handle).  Because we never strobed any bytes onto the
bus, the status register would still contain the value from the previous
request.

Thanks to Michael Krufky <mkrufky@linuxtv.org> and Steven Toth
<stoth@linuxtv.org> for providing sample hardware, engineering level support,
and testing.

Signed-off-by: Devin Heitmueller <dheitmueller@linuxtv.org>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/au0828/au0828-i2c.c

index ee3e3040d54cddd3223a8945543c2d19be4f1571..d57a38f5c738a57679d8ff2411475159cb2774ce 100644 (file)
@@ -156,6 +156,24 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
 
        dprintk(4, "SEND: %02x\n", msg->addr);
 
+       /* Deal with i2c_scan */
+       if (msg->len == 0) {
+               /* The analog tuner detection code makes use of the SMBUS_QUICK
+                  message (which involves a zero length i2c write).  To avoid
+                  checking the status register when we didn't strobe out any
+                  actual bytes to the bus, just do a read check.  This is
+                  consistent with how I saw i2c device checking done in the
+                  USB trace of the Windows driver */
+               au0828_write(dev, REG_200, 0x20);
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+
+               if (i2c_wait_read_ack(i2c_adap))
+                       return -EIO;
+
+               return 0;
+       }
+
        for (i = 0; i < msg->len;) {
 
                dprintk(4, " %02x\n", msg->buf[i]);