V4L/DVB: tm6000: fix i2c read
authorDmitri Belimov <d.belimov@gmail.com>
Wed, 28 Apr 2010 01:32:43 +0000 (22:32 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 19 May 2010 15:58:17 +0000 (12:58 -0300)
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

[mchehab@redhat.com: Fix CodingStyle]
Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/staging/tm6000/tm6000-i2c.c

index 2ab632b6fd1d50143c450f9c2924d852309dd98f..94ff489a1bbb3396fad0d26edabd5d5525a1b45e 100644 (file)
@@ -47,8 +47,38 @@ MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
 static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
                                __u8 reg, char *buf, int len)
 {
-       return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+       int rc;
+       unsigned int tsleep;
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14000us for 64 bytes */
+       tsleep = ((len * 200) + 200 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
 }
 
 /* Generic read - doesn't work fine with 16bit registers */
@@ -57,7 +87,21 @@ static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
 {
        int rc;
        u8 b[2];
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
 
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
        if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
                /*
                 * Workaround an I2C bug when reading from zl10353
@@ -74,6 +118,7 @@ static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
                        REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
        }
 
+       /* release mutex */
        return rc;
 }
 
@@ -84,8 +129,36 @@ static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
 static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
                                  __u16 reg, char *buf, int len)
 {
-       return tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               REQ_14_SET_GET_I2C_WR2_RDN, addr, reg, buf, len);
+       int rc;
+       unsigned char ureg;
+
+       if (!buf || len != 2)
+               return -1;
+
+       /* capture mutex */
+       if (dev->dev_type == TM6010) {
+               ureg = reg & 0xFF;
+               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+                       addr | (reg & 0xFF00), 0, &ureg, 1);
+
+               if (rc < 0) {
+                       /* release mutex */
+                       return rc;
+               }
+
+               msleep(1400 / 1000);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+                       reg, 0, buf, len);
+       } else {
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
+                       addr, reg, buf, len);
+       }
+
+       /* release mutex */
+       return rc;
 }
 
 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,