Skip to contentSkip to conversation

tm6000 fix i2c

PATCH In review Dmitri Belimov 4 participants 14 messages Apr 23, 2010 – Apr 28, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 tm6000 fix i2c

Hi

Rework I2C for read word from connected devices, now it works well. Add new functions for read/write blocks.

linux/drivers/staging/tm6000/tm6000-i2c.c +144 -9
diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>
 
 #include "compat.h"
 #include "tm6000.h"
@@ -45,11 +46,39 @@
 			printk(KERN_DEBUG "%s at %s: " fmt, \
 			dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+	msleep(15);
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+	msleep(15);
+}
+
 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;
+
+	if (!buf || len < 1 || len > 64)
+		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 */
@@ -59,22 +88,30 @@
 	int rc;
 	u8 b[2];
 
-	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+	if (!buf || len < 1 || len > 64)
+		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
 		 */
 		reg -= 1;
 		len += 1;
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, b, len);
 
 		*buf = b[1];
 	} else {
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
 	}
 
+	/* release mutex */
 	return rc;
 }
 
@@ -85,8 +122,106 @@
 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 */
+	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);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+				unsigned char addr, __u16 reg, char *buf,
+				int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		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+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 13800us for 64 bytes */
+	tsleep = ((len * 200) + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_30_I2C_WRITE,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 14800us for 64 bytes */
+	tsleep = ((len * 200) + 1000 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
 }
 
 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

linux/drivers/staging/tm6000/tm6000-i2c.c +144 -9

191 lines not on this page · raw message

#1 lore raw

I am still able to watch tv after applying the patch but the return code is bad and is causing unnecessary reloading of the same firmwares.

[ 2482.599040] usb 1-1: firmware: requesting tm6000-xc3028.fw
[ 2482.607229] xc2028 2-0061: Loading 77 firmware images from
tm6000-xc3028.fw, type: xc2028 firmware, ver 2.4
[ 2482.788089] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2503.620069] (0), id 00000000000000ff:
[ 2503.620078] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2504.380061] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2504.520063] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2504.536064] xc2028 2-0061: Unable to read tuner registers.
[ 2504.776079] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2525.556048] (0), id 00000000000000ff:
[ 2525.556057] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2526.312058] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2526.452061] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2526.468050] xc2028 2-0061: Unable to read tuner registers.
[ 2527.648076] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2548.460067] (0), id 00000000000000ff:
[ 2548.460076] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2549.216070] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2549.356064] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2549.372065] xc2028 2-0061: Unable to read tuner registers.
[ 2549.612052] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2570.609041] (0), id 00000000000000ff:
[ 2570.609049] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2571.397034] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2571.537025] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2571.553024] xc2028 2-0061: Unable to read tuner registers.
[ 2572.553103] Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: 0)
[ 2572.561090] tm6000: open called (dev=video0)
[ 2573.081022] Original value=96
[ 2573.093037] tm6000: VIDIOC_QUERYCAP
[ 2573.149565] tm6000: open called (dev=video0)
Quoted 208 lines · Dmitri Belimov

Hi

Rework I2C for read word from connected devices, now it works well. Add new functions for read/write blocks.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c

linux/drivers/staging/tm6000/tm6000-i2c.c Fri Apr 23 04:23:03 2010 +1000 renamed from linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +144 -9
@@ -24,6 +24,7 @@
  #include <linux/kernel.h>
  #include <linux/usb.h>
  #include <linux/i2c.h>
+#include <linux/delay.h>
 
  #include "compat.h"
  #include "tm6000.h"
@@ -45,11 +46,39 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \
                        dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);
+}
+
  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;
+
+       if (!buf || len < 1 || len > 64)
+               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 */
@@ -59,22 +88,30 @@
        int rc;
        u8 b[2];
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+       if (!buf || len < 1 || len > 64)
+               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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);
 
                *buf = b[1];
        } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
        }
 
+       /* release mutex */
        return rc;
  }
 
@@ -85,8 +122,106 @@
  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 */
+       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);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int len)
+{
+       int rc;
+
+       if (!buf || len < 1 || len > 64)
+               return -1;
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg, char *buf,
+                               int len)
+{
+       int rc;
+       unsigned int tsleep;
+
+       if (!buf || len < 1 || len > 64)
+               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+1, len-1);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int len)
+{
+       int rc;
+       unsigned int tsleep;
+
+       if (!buf || len < 1 || len > 64)
+               return -1;
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
  }
 
  static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

#2 lore raw

Hi

It's my error. This code good only for tm6010. Now I rework my patch.

With my best regards, Dmitry.

Quoted 285 lines

I am still able to watch tv after applying the patch but the return code is bad and is causing unnecessary reloading of the same firmwares.

[ 2482.599040] usb 1-1: firmware: requesting tm6000-xc3028.fw
[ 2482.607229] xc2028 2-0061: Loading 77 firmware images from
tm6000-xc3028.fw, type: xc2028 firmware, ver 2.4
[ 2482.788089] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2503.620069] (0), id 00000000000000ff:
[ 2503.620078] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2504.380061] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2504.520063] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2504.536064] xc2028 2-0061: Unable to read tuner registers.
[ 2504.776079] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2525.556048] (0), id 00000000000000ff:
[ 2525.556057] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2526.312058] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2526.452061] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2526.468050] xc2028 2-0061: Unable to read tuner registers.
[ 2527.648076] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2548.460067] (0), id 00000000000000ff:
[ 2548.460076] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2549.216070] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2549.356064] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2549.372065] xc2028 2-0061: Unable to read tuner registers.
[ 2549.612052] xc2028 2-0061: Loading firmware for type=BASE F8MHZ
(3), id 0000000000000000.
[ 2570.609041] (0), id 00000000000000ff:
[ 2570.609049] xc2028 2-0061: Loading firmware for type=(0), id
0000000100000007.
[ 2571.397034] xc2028 2-0061: Loading SCODE for type=MONO SCODE
HAS_IF_5320 (60008000), id 0000000f00000007.
[ 2571.537025] xc2028 2-0061: i2c input error: rc = -32 (should be 2)
[ 2571.553024] xc2028 2-0061: Unable to read tuner registers.
[ 2572.553103] Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load
status: 0) [ 2572.561090] tm6000: open called (dev=video0)
[ 2573.081022] Original value=96
[ 2573.093037] tm6000: VIDIOC_QUERYCAP
[ 2573.149565] tm6000: open called (dev=video0)
Quoted 232 lines · Dmitri Belimov

Hi

Rework I2C for read word from connected devices, now it works well. Add new functions for read/write blocks.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c --- a/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +++ b/linux/drivers/staging/tm6000/tm6000-i2c.c Fri Apr 23 04:23:03 2010 +1000 @@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>

 #include "compat.h"
 #include "tm6000.h"

(quoted diff) +0 -0
@@ -45,11 +46,39 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \

                       dev->name, __FUNCTION__ , ##args); } while
(0)

linux/drivers/staging/tm6000/tm6000-i2c.c +3 -0
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,

TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);

(quoted diff) +2 -0
+}
+

 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;

linux/drivers/staging/tm6000/tm6000-i2c.c +6 -0
+
+       if (!buf || len < 1 || len > 64)
+               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);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       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 */

linux/drivers/staging/tm6000/tm6000-i2c.c +7 -3
@@ -59,22 +88,30 @@
        int rc;
        u8 b[2];
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 ==
 addr) && (reg % 2 == 0)) {
+       if (!buf || len < 1 || len > 64)
+               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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<
 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);

               *buf = b[1];
       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
       }

+       /* release mutex */
       return rc;
 }

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -2
@@ -85,8 +122,106 @@
  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 */
+       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);

linux/drivers/staging/tm6000/tm6000-i2c.c +8 -0
+
+       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);

linux/drivers/staging/tm6000/tm6000-i2c.c +11 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev,

unsigned char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +8 -0
+{
+       int rc;
+
+       if (!buf || len < 1 || len > 64)
+               return -1;
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;

linux/drivers/staging/tm6000/tm6000-i2c.c +4 -0
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg, char

*buf,
+                               int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+{
+       int rc;
+       unsigned int tsleep;
+
+       if (!buf || len < 1 || len > 64)
+               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+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +15 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned

char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+{
+       int rc;
+       unsigned int tsleep;
+
+       if (!buf || len < 1 || len > 64)
+               return -1;
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_OUT |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;

 }

 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov
<[email protected]>

With my best regards, Dmitry.

#3 lore raw
In reply to Dmitri Belimov

Am 23.04.2010 02:48, schrieb Dmitri Belimov:

Quoted 113 lines

Hi

Rework I2C for read word from connected devices, now it works well. Add new functions for read/write blocks.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c

linux/drivers/staging/tm6000/tm6000-i2c.c +57 -9
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>
 
 #include "compat.h"
 #include "tm6000.h"
@@ -45,11 +46,39 @@
 			printk(KERN_DEBUG "%s at %s: " fmt, \
 			dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+	msleep(15);
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+	msleep(15);
+}
+
 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;
+
+	if (!buf || len < 1 || len > 64)
+		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 */
@@ -59,22 +88,30 @@
 	int rc;
 	u8 b[2];
 
-	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+	if (!buf || len < 1 || len > 64)
+		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
 		 */
 		reg -= 1;
 		len += 1;
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, b, len);
 
 		*buf = b[1];
 	} else {
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
 	}
 
+	/* release mutex */
 	return rc;
 }
 
@@ -85,8 +122,106 @@
 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 */
+	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) {

linux/drivers/staging/tm6000/tm6000-i2c.c line 147

Quoted 10 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +9 -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);
+
 

not all can this request (chip revision 0xf3 and 0xf4 can it)

Quoted 12 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{

linux/drivers/staging/tm6000/tm6000-i2c.c line 226

Quoted 10 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+	int rc;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);
 

ditto

Quoted 65 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +57 -0
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+				unsigned char addr, __u16 reg, char *buf,
+				int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		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+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 13800us for 64 bytes */
+	tsleep = ((len * 200) + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_30_I2C_WRITE,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 14800us for 64 bytes */
+	tsleep = ((len * 200) + 1000 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
 }

static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

Signature · 1 line
Stefan Ringel <[email protected]>
#4 lore raw

Hi

It's my error. This code good only for tm6010. Now I rework my patch.

With my best regards, Dmitry.

Quoted 241 lines

Am 23.04.2010 02:48, schrieb Dmitri Belimov:

Quoted 136 lines

Hi

Rework I2C for read word from connected devices, now it works well. Add new functions for read/write blocks.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c
--- a/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05
22:56:43 2010 -0400 +++
b/linux/drivers/staging/tm6000/tm6000-i2c.c Fri Apr 23
04:23:03 2010 +1000 @@ -24,6 +24,7 @@ #include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/i2c.h>

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -2
+#include <linux/delay.h>
 
 #include "compat.h"
 #include "tm6000.h"
@@ -45,11 +46,39 @@
 			printk(KERN_DEBUG "%s at %s: " fmt, \
 			dev->name, __FUNCTION__ , ##args); } while
 (0) 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
 TM6000_GPIO_CLK, 0);
+	msleep(15);
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
 TM6000_GPIO_CLK, 1);
+	msleep(15);
+}
+
 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);

linux/drivers/staging/tm6000/tm6000-i2c.c +8 -0
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +21 -3
+		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 */
@@ -59,22 +88,30 @@
 	int rc;
 	u8 b[2];
 
-	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 ==
 addr) && (reg % 2 == 0)) {
+	if (!buf || len < 1 || len > 64)
+		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
 		 */
 		reg -= 1;
 		len += 1;
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<
 8, 0, b, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +2 -1
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, b, len);
 
 		*buf = b[1];
 	} else {
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR | USB_RECIP_DEVICE,

(quoted diff) +0 -1
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<

8, 0, buf, len);

(quoted diff) +1 -0
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -2
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
 	}
 
+	/* release mutex */
 	return rc;
 }
@@ -85,8 +122,106 @@
 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 */
+	ureg = reg & 0xFF;
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +10 -0
+		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 |

linux/drivers/staging/tm6000/tm6000-i2c.c line 146

Quoted 3 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +3 -0
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);
+

not all can this request (chip revision 0xf3 and 0xf4 can it)

Quoted 22 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +10 -0
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev,

unsigned char addr,

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |

Review

Quoted 2 lines
(quoted diff) +2 -0
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);

ditto

Quoted 70 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +6 -0
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+				unsigned char addr, __u16 reg,

char *buf,

linux/drivers/staging/tm6000/tm6000-i2c.c +10 -0
+				int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +17 -0
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 13800us for 64 bytes */
+	tsleep = ((len * 200) + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned

char addr,

linux/drivers/staging/tm6000/tm6000-i2c.c +10 -0
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+	unsigned int tsleep;
+
+	if (!buf || len < 1 || len > 64)
+		return -1;
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_OUT |

USB_TYPE_VENDOR |

linux/drivers/staging/tm6000/tm6000-i2c.c +14 -0
+		USB_RECIP_DEVICE, REQ_30_I2C_WRITE,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 14800us for 64 bytes */
+	tsleep = ((len * 200) + 1000 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
 }
 
 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov
<[email protected]>

With my best regards, Dmitry.

Signature · 1 line
Stefan Ringel <[email protected]>
#5 lore raw
In reply to Stefan Ringel

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

linux/drivers/staging/tm6000/tm6000-i2c.c +195 -9
diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>
 
 #include "compat.h"
 #include "tm6000.h"
@@ -45,11 +46,49 @@
 			printk(KERN_DEBUG "%s at %s: " fmt, \
 			dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+	msleep(15);
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+	msleep(15);
+}
+
 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("Incorrect lenght 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 */
@@ -58,23 +97,41 @@
 {
 	int rc;
 	u8 b[2];
+	unsigned int i2c_packet_limit = 16;
 
-	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+	if (dev->dev_type == TM6010)
+		i2c_packet_limit = 64;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > i2c_packet_limit){
+		printk("Incorrect lenght 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
 		 */
 		reg -= 1;
 		len += 1;
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, b, len);
 
 		*buf = b[1];
 	} else {
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
 	}
 
+	/* release mutex */
 	return rc;
 }
 
@@ -85,8 +142,137 @@
 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_read_sequence(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+
+	if (dev->dev_type != TM6010)
+		return -1;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > 64){
+		printk("Incorrect lenght of i2c packet = %d, limit set to 64\n",
+			len);
+		return -1;
+	}
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+				unsigned char addr, __u16 reg, char *buf,
+				int 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("Incorrect lenght 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+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 13800us for 64 bytes */
+	tsleep = ((len * 200) + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int 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("Incorrect lenght 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_30_I2C_WRITE,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 14800us for 64 bytes */
+	tsleep = ((len * 200) + 1000 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
 }
 
 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

linux/drivers/staging/tm6000/tm6000-i2c.c +195 -9

243 lines not on this page · raw message

#6 lore raw

thanks. This is work fine on my tm5600.

btw, can you use the git tree? There is some codes update from Stefan there for the tm6000-i2c that is still not sync with hg.

Quoted 261 lines · Dmitri Belimov

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c

linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 26 04:15:56 2010 +1000 renamed from linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +195 -9
@@ -24,6 +24,7 @@
  #include <linux/kernel.h>
  #include <linux/usb.h>
  #include <linux/i2c.h>
+#include <linux/delay.h>
 
  #include "compat.h"
  #include "tm6000.h"
@@ -45,11 +46,49 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \
                        dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);
+}
+
  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("Incorrect lenght 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 */
@@ -58,23 +97,41 @@
  {
        int rc;
        u8 b[2];
+       unsigned int i2c_packet_limit = 16;
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);
 
                *buf = b[1];
        } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
        }
 
+       /* release mutex */
        return rc;
  }
 
@@ -85,8 +142,137 @@
  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_read_sequence(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int len)
+{
+       int rc;
+
+       if (dev->dev_type != TM6010)
+               return -1;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > 64){
+               printk("Incorrect lenght of i2c packet = %d, limit set to 64\n",
+                       len);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg, char *buf,
+                               int 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("Incorrect lenght 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+1, len-1);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int 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("Incorrect lenght 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_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
  }
 
  static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

#7 lore raw
Quoted 1 line · On Mon, 26 Apr 2010 20:58:24 +0800 Bee Hock Goh <[email protected]> wrote:

thanks. This is work fine on my tm5600.

Good news.

Quoted 2 lines

btw, can you use the git tree? There is some codes update from Stefan there for the tm6000-i2c that is still not sync with hg.

no problemm. Give me access and URL.

With my best regards, Dmitry.

Quoted 294 lines
Quoted 292 lines · Dmitri Belimov

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c --- a/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +++ b/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 26 04:15:56 2010 +1000 @@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>

 #include "compat.h"
 #include "tm6000.h"

(quoted diff) +0 -0
@@ -45,11 +46,49 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \

                       dev->name, __FUNCTION__ , ##args); } while
(0)

linux/drivers/staging/tm6000/tm6000-i2c.c +3 -0
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,

TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);

(quoted diff) +2 -0
+}
+

 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;

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       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 */

linux/drivers/staging/tm6000/tm6000-i2c.c +17 -3
@@ -58,23 +97,41 @@
  {
        int rc;
        u8 b[2];
+       unsigned int i2c_packet_limit = 16;
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 ==
 addr) && (reg % 2 == 0)) {
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<
 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);

               *buf = b[1];
       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
       }

+       /* release mutex */
       return rc;
 }

linux/drivers/staging/tm6000/tm6000-i2c.c +10 -2
@@ -85,8 +142,137 @@
  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);

linux/drivers/staging/tm6000/tm6000-i2c.c +8 -0
+
+               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);
+       }

linux/drivers/staging/tm6000/tm6000-i2c.c +6 -0
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev,

unsigned char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +11 -0
+{
+       int rc;
+
+       if (dev->dev_type != TM6010)
+               return -1;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > 64){
+               printk("Incorrect lenght of i2c packet = %d, limit

set to 64\n",
+                       len);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;

linux/drivers/staging/tm6000/tm6000-i2c.c +4 -0
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg, char

*buf,
+                               int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +13 -0
+{
+       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("Incorrect lenght 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+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +15 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned

char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +13 -0
+{
+       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("Incorrect lenght 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_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;

 }

 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

#8 lore raw

wiki is your best friend. :)

http://www.linuxtv.org/wiki/index.php/Maintaining_Git_trees
http://www.linuxtv.org/wiki/index.php/Using_a_git_driver_development_tree

Quoted 309 lines · Dmitri Belimov
Quoted 1 line · On Mon, 26 Apr 2010 20:58:24 +0800 Bee Hock Goh <[email protected]> wrote:

thanks. This is work fine on my tm5600.

Good news.

Quoted 2 lines

btw, can you use the git tree? There is some codes update from Stefan there for the tm6000-i2c that is still not sync with hg.

no problemm. Give me access and URL.

With my best regards, Dmitry.

Quoted 294 lines
Quoted 292 lines · Dmitri Belimov

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c --- a/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +++ b/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 26 04:15:56 2010 +1000 @@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>

 #include "compat.h"
 #include "tm6000.h"

(quoted diff) +0 -0
@@ -45,11 +46,49 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \

                       dev->name, __FUNCTION__ , ##args); } while
(0)

linux/drivers/staging/tm6000/tm6000-i2c.c +3 -0
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,

TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);

(quoted diff) +2 -0
+}
+

 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;

linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       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 */

linux/drivers/staging/tm6000/tm6000-i2c.c +17 -3
@@ -58,23 +97,41 @@
  {
        int rc;
        u8 b[2];
+       unsigned int i2c_packet_limit = 16;
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 ==
 addr) && (reg % 2 == 0)) {
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<
 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);

               *buf = b[1];
       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
       }

+       /* release mutex */
       return rc;
 }

linux/drivers/staging/tm6000/tm6000-i2c.c +10 -2
@@ -85,8 +142,137 @@
  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);

linux/drivers/staging/tm6000/tm6000-i2c.c +8 -0
+
+               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);
+       }

linux/drivers/staging/tm6000/tm6000-i2c.c +6 -0
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev,

unsigned char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +11 -0
+{
+       int rc;
+
+       if (dev->dev_type != TM6010)
+               return -1;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > 64){
+               printk("Incorrect lenght of i2c packet = %d, limit

set to 64\n",
+                       len);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;

linux/drivers/staging/tm6000/tm6000-i2c.c +4 -0
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg, char

*buf,
+                               int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +13 -0
+{
+       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("Incorrect lenght 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+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +15 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned

char addr,
+                                 __u16 reg, char *buf, int len)

linux/drivers/staging/tm6000/tm6000-i2c.c +13 -0
+{
+       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("Incorrect lenght 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_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);

linux/drivers/staging/tm6000/tm6000-i2c.c +12 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;

 }

 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

#9 lore raw
Quoted 4 lines · On Tue, 27 Apr 2010 14:07:00 +0800 Bee Hock Goh <[email protected]> wrote:

wiki is your best friend. :)

http://www.linuxtv.org/wiki/index.php/Maintaining_Git_trees
http://www.linuxtv.org/wiki/index.php/Using_a_git_driver_development_tree

Ok.

This is new version. Made by git.

drivers/staging/tm6000/tm6000-i2c.c +78 -4
index 2ab632b..e9b568d 100644
@@ -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("Incorrect lenght 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("Incorrect lenght 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,37 @@ 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,
Quoted 309 lines
Quoted 306 lines · Dmitri Belimov
Quoted 1 line · On Mon, 26 Apr 2010 20:58:24 +0800 Bee Hock Goh <[email protected]> wrote:

thanks. This is work fine on my tm5600.

Good news.

Quoted 2 lines

btw, can you use the git tree? There is some codes update from Stefan there for the tm6000-i2c that is still not sync with hg.

no problemm. Give me access and URL.

With my best regards, Dmitry.

Quoted 292 lines
Quoted 290 lines · Dmitri Belimov

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c --- a/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 05 22:56:43 2010 -0400 +++ b/linux/drivers/staging/tm6000/tm6000-i2c.c Mon Apr 26 04:15:56 2010 +1000 @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>

 #include "compat.h"
 #include "tm6000.h"

(quoted diff) +0 -0
@@ -45,11 +46,49 @@
                        printk(KERN_DEBUG "%s at %s: " fmt, \

                       dev->name, __FUNCTION__ , ##args); } while
(0)

(quoted diff) +3 -0
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,

TM6000_GPIO_CLK, 0);
+       msleep(15);
+       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(15);

(quoted diff) +2 -0
+}
+

 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;

(quoted diff) +9 -0
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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);

(quoted diff) +12 -0
+
+       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 */

(quoted diff) +17 -3
@@ -58,23 +97,41 @@
  {
        int rc;
        u8 b[2];
+       unsigned int i2c_packet_limit = 16;
 
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 ==
 addr) && (reg % 2 == 0)) {
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit){
+               printk("Incorrect lenght 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
                 */
                reg -= 1;
                len += 1;
 
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN |
 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg <<
 8, 0, b, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN |

USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, b, len);

               *buf = b[1];
       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
       }

+       /* release mutex */
       return rc;
 }

(quoted diff) +10 -2
@@ -85,8 +142,137 @@
  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);

(quoted diff) +8 -0
+
+               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);
+       }

(quoted diff) +6 -0
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_read_sequence(struct tm6000_core *dev,

unsigned char addr,
+                                 __u16 reg, char *buf, int len)

(quoted diff) +11 -0
+{
+       int rc;
+
+       if (dev->dev_type != TM6010)
+               return -1;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > 64){
+               printk("Incorrect lenght of i2c packet = %d,

limit set to 64\n",
+                       len);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+               reg, 0, buf, len);
+       /* release mutex */
+       return rc;

(quoted diff) +4 -0
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+                               unsigned char addr, __u16 reg,

char *buf,
+                               int len)

(quoted diff) +13 -0
+{
+       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("Incorrect lenght 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+1, len-1);

(quoted diff) +15 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 13800us for 64 bytes */
+       tsleep = ((len * 200) + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev,

unsigned char addr,
+                                 __u16 reg, char *buf, int len)

(quoted diff) +13 -0
+{
+       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("Incorrect lenght 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_30_I2C_WRITE,
+               addr | reg << 8, 0, buf+1, len-1);

(quoted diff) +12 -0
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* Calculate delay time, 14800us for 64 bytes */
+       tsleep = ((len * 200) + 1000 + 1000) / 1000;
+       msleep(tsleep);
+
+       /* release mutex */
+       return rc;

 }

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
Quoted 4 lines

 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,

With my best regards, Dmitry.

With my best regards, Dmitry.

drivers/staging/tm6000/tm6000-i2c.c +78 -4

107 lines not on this page · raw message

#11 lore raw

Re: tm6000

its working fine on my tm5600. Run fine for more than 5mins without crashing.

But it does crashed everytime when its playing on the first channel and I switch channel in mythtv. I am waiting for usb/serial cable to arrive from ebay to find out why.

I hope to work on the audio part though.

Quoted 8 lines · Dmitri Belimov

Hi

Anyone can watch TV with tm6000 module??

I try mplayer. My PC crashed inside copy_streams function after some time.

With my best regards, Dmitry.

#12 lore raw

Re: tm6000

In reply to Dmitri Belimov
Quoted 7 lines · Dmitri Belimov

Hi

Anyone can watch TV with tm6000 module??

I try mplayer. My PC crashed inside copy_streams function after some time.

With my best regards, Dmitry.

It is still causing panic on my tests. Probably, the routine is still writing something out of the buffer area.

Signature · 2 lines
Cheers,
Mauro
#13 lore raw
In reply to Dmitri Belimov

Hi Dmitri,

Quoted 12 lines · Dmitri Belimov

Hi

Rework last I2C patch.
Set correct limit for I2C packet.
Use different method for the tm5600/tm6000 and tm6010 to read word.

Try this patch.

diff -r 7c0b887911cf linux/drivers/staging/tm6000/tm6000-i2c.c

linux/drivers/staging/tm6000/tm6000-i2c.c line 27

Quoted 4 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +1 -0
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
+#include <linux/delay.h>

You probably don't need this.

Quoted 230 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +185 -9
 #include "compat.h"
 #include "tm6000.h"
@@ -45,11 +46,49 @@
 			printk(KERN_DEBUG "%s at %s: " fmt, \
 			dev->name, __FUNCTION__ , ##args); } while (0)
 
+static void tm6000_i2c_reset(struct tm6000_core *dev)
+{
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+	msleep(15);
+	tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+	msleep(15);
+}
+
 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("Incorrect lenght 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 */
@@ -58,23 +97,41 @@
 {
 	int rc;
 	u8 b[2];
+	unsigned int i2c_packet_limit = 16;
 
-	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+	if (dev->dev_type == TM6010)
+		i2c_packet_limit = 64;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > i2c_packet_limit){
+		printk("Incorrect lenght 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
 		 */
 		reg -= 1;
 		len += 1;
 
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, b, len);
 
 		*buf = b[1];
 	} else {
-		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+		addr | reg << 8, 0, buf, len);
 	}
 
+	/* release mutex */
 	return rc;
 }
 
@@ -85,8 +142,137 @@
 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_read_sequence(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int len)
+{
+	int rc;
+
+	if (dev->dev_type != TM6010)
+		return -1;
+
+	if (!buf)
+		return -1;
+
+	if (len < 1 || len > 64){
+		printk("Incorrect lenght of i2c packet = %d, limit set to 64\n",
+			len);
+		return -1;
+	}
+
+	/* capture mutex */
+	rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+		reg, 0, buf, len);
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_sequence(struct tm6000_core *dev,
+				unsigned char addr, __u16 reg, char *buf,
+				int 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("Incorrect lenght 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+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */
+		return rc;
+	}
+
+	/* Calculate delay time, 13800us for 64 bytes */
+	tsleep = ((len * 200) + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
+}
+
+static int tm6000_i2c_write_uni(struct tm6000_core *dev, unsigned char addr,
+				  __u16 reg, char *buf, int 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("Incorrect lenght 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_30_I2C_WRITE,
+		addr | reg << 8, 0, buf+1, len-1);
+
+	if (rc < 0) {
+		/* release mutex */

linux/drivers/staging/tm6000/tm6000-i2c.c line 276

Quoted 10 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +9 -0
+		return rc;
+	}
+
+	/* Calculate delay time, 14800us for 64 bytes */
+	tsleep = ((len * 200) + 1000 + 1000) / 1000;
+	msleep(tsleep);
+
+	/* release mutex */
+	return rc;
 }

There are some troubles here that I noticed on your first patch: you're adding some new functions that aren't used on the code, generating some warnings. Please remove them or use.

Quoted 6 lines
linux/drivers/staging/tm6000/tm6000-i2c.c +0 -0
 static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
 

With my best regards, Dmitry.

Signature · 2 lines
Cheers,
Mauro