* [PATCH] tm6000 fix i2c
@ 2010-04-23 0:48 Dmitri Belimov
2010-04-23 12:57 ` Bee Hock Goh
2010-04-23 15:15 ` Stefan Ringel
0 siblings, 2 replies; 14+ messages in thread
From: Dmitri Belimov @ 2010-04-23 0:48 UTC (permalink / raw)
To: linux-media, Mauro Carvalho Chehab
[-- Attachment #1: Type: text/plain, Size: 5286 bytes --]
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"
@@ -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,
Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
With my best regards, Dmitry.
[-- Attachment #2: tm6000_i2c.patch --]
[-- Type: text/x-patch, Size: 5141 bytes --]
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"
@@ -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,
Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com>
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH] tm6000 fix i2c 2010-04-23 0:48 [PATCH] tm6000 fix i2c Dmitri Belimov @ 2010-04-23 12:57 ` Bee Hock Goh 2010-04-25 23:46 ` Dmitri Belimov 2010-04-23 15:15 ` Stefan Ringel 1 sibling, 1 reply; 14+ messages in thread From: Bee Hock Goh @ 2010-04-23 12:57 UTC (permalink / raw) To: Dmitri Belimov; +Cc: linux-media, Mauro Carvalho Chehab 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) On Fri, Apr 23, 2010 at 8:48 AM, Dmitri Belimov <d.belimov@gmail.com> wrote: > 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" > @@ -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, > > Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> > > > With my best regards, Dmitry. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-23 12:57 ` Bee Hock Goh @ 2010-04-25 23:46 ` Dmitri Belimov 0 siblings, 0 replies; 14+ messages in thread From: Dmitri Belimov @ 2010-04-25 23:46 UTC (permalink / raw) To: Bee Hock Goh; +Cc: linux-media, Mauro Carvalho Chehab Hi It's my error. This code good only for tm6010. Now I rework my patch. With my best regards, Dmitry. > 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) > > > > On Fri, Apr 23, 2010 at 8:48 AM, Dmitri Belimov <d.belimov@gmail.com> > wrote: > > 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" > > @@ -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, > > > > Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov > > <d.belimov@gmail.com> > > > > > > With my best regards, Dmitry. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-23 0:48 [PATCH] tm6000 fix i2c Dmitri Belimov 2010-04-23 12:57 ` Bee Hock Goh @ 2010-04-23 15:15 ` Stefan Ringel 2010-04-25 23:47 ` Dmitri Belimov 2010-04-26 0:25 ` Dmitri Belimov 1 sibling, 2 replies; 14+ messages in thread From: Stefan Ringel @ 2010-04-23 15:15 UTC (permalink / raw) To: Dmitri Belimov; +Cc: linux-media, Mauro Carvalho Chehab Am 23.04.2010 02:48, schrieb 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" > @@ -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); > + > not all can this request (chip revision 0xf3 and 0xf4 can it) > + 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); > ditto > + /* 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, > > Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> > > > With my best regards, Dmitry. -- Stefan Ringel <stefan.ringel@arcor.de> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-23 15:15 ` Stefan Ringel @ 2010-04-25 23:47 ` Dmitri Belimov 2010-04-26 0:25 ` Dmitri Belimov 1 sibling, 0 replies; 14+ messages in thread From: Dmitri Belimov @ 2010-04-25 23:47 UTC (permalink / raw) To: Stefan Ringel; +Cc: linux-media, Mauro Carvalho Chehab Hi It's my error. This code good only for tm6010. Now I rework my patch. With my best regards, Dmitry. > Am 23.04.2010 02:48, schrieb 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" > > @@ -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); > > + > > > not all can this request (chip revision 0xf3 and 0xf4 can it) > > + 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); > > > ditto > > + /* 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, > > > > Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov > > <d.belimov@gmail.com> > > > > > > With my best regards, Dmitry. > > > -- > Stefan Ringel <stefan.ringel@arcor.de> > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-23 15:15 ` Stefan Ringel 2010-04-25 23:47 ` Dmitri Belimov @ 2010-04-26 0:25 ` Dmitri Belimov 2010-04-26 12:58 ` Bee Hock Goh 2010-04-26 13:29 ` [PATCH] tm6000 fix i2c Mauro Carvalho Chehab 1 sibling, 2 replies; 14+ messages in thread From: Dmitri Belimov @ 2010-04-26 0:25 UTC (permalink / raw) To: Stefan Ringel; +Cc: linux-media, Mauro Carvalho Chehab, Bee Hock Goh [-- Attachment #1: Type: text/plain, Size: 6472 bytes --] 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" @@ -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. [-- Attachment #2: tm6000_i2c.patch --] [-- Type: text/x-patch, Size: 6293 bytes --] 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" @@ -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, ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-26 0:25 ` Dmitri Belimov @ 2010-04-26 12:58 ` Bee Hock Goh 2010-04-27 5:15 ` Dmitri Belimov 2010-04-26 13:29 ` [PATCH] tm6000 fix i2c Mauro Carvalho Chehab 1 sibling, 1 reply; 14+ messages in thread From: Bee Hock Goh @ 2010-04-26 12:58 UTC (permalink / raw) To: Dmitri Belimov; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab 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. On Mon, Apr 26, 2010 at 8:25 AM, Dmitri Belimov <d.belimov@gmail.com> wrote: > 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" > @@ -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. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-26 12:58 ` Bee Hock Goh @ 2010-04-27 5:15 ` Dmitri Belimov 2010-04-27 6:07 ` Bee Hock Goh 0 siblings, 1 reply; 14+ messages in thread From: Dmitri Belimov @ 2010-04-27 5:15 UTC (permalink / raw) To: Bee Hock Goh; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab On Mon, 26 Apr 2010 20:58:24 +0800 Bee Hock Goh <beehock@gmail.com> wrote: > thanks. This is work fine on my tm5600. Good news. > 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. > On Mon, Apr 26, 2010 at 8:25 AM, Dmitri Belimov <d.belimov@gmail.com> > wrote: > > 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" > > @@ -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. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-27 5:15 ` Dmitri Belimov @ 2010-04-27 6:07 ` Bee Hock Goh 2010-04-28 1:32 ` Dmitri Belimov 2010-04-28 5:49 ` tm6000 Dmitri Belimov 0 siblings, 2 replies; 14+ messages in thread From: Bee Hock Goh @ 2010-04-27 6:07 UTC (permalink / raw) To: Dmitri Belimov; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab 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 On Tue, Apr 27, 2010 at 1:15 PM, Dmitri Belimov <d.belimov@gmail.com> wrote: > On Mon, 26 Apr 2010 20:58:24 +0800 > Bee Hock Goh <beehock@gmail.com> wrote: > >> thanks. This is work fine on my tm5600. > > Good news. > >> 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. > >> On Mon, Apr 26, 2010 at 8:25 AM, Dmitri Belimov <d.belimov@gmail.com> >> wrote: >> > 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" >> > @@ -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. > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-27 6:07 ` Bee Hock Goh @ 2010-04-28 1:32 ` Dmitri Belimov 2010-04-28 5:49 ` tm6000 Dmitri Belimov 1 sibling, 0 replies; 14+ messages in thread From: Dmitri Belimov @ 2010-04-28 1:32 UTC (permalink / raw) To: Bee Hock Goh; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab [-- Attachment #1: Type: text/plain, Size: 15790 bytes --] On Tue, 27 Apr 2010 14:07:00 +0800 Bee Hock Goh <beehock@gmail.com> 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. diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 2ab632b..e9b568d 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -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, Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> > > On Tue, Apr 27, 2010 at 1:15 PM, Dmitri Belimov <d.belimov@gmail.com> > wrote: > > On Mon, 26 Apr 2010 20:58:24 +0800 > > Bee Hock Goh <beehock@gmail.com> wrote: > > > >> thanks. This is work fine on my tm5600. > > > > Good news. > > > >> 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. > > > >> On Mon, Apr 26, 2010 at 8:25 AM, Dmitri Belimov > >> <d.belimov@gmail.com> wrote: > >> > 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" > >> > @@ -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. > > With my best regards, Dmitry. [-- Attachment #2: tm6000_i2c.patch --] [-- Type: text/x-patch, Size: 3310 bytes --] diff --git a/drivers/staging/tm6000/tm6000-i2c.c b/drivers/staging/tm6000/tm6000-i2c.c index 2ab632b..e9b568d 100644 --- a/drivers/staging/tm6000/tm6000-i2c.c +++ b/drivers/staging/tm6000/tm6000-i2c.c @@ -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, Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> ^ permalink raw reply related [flat|nested] 14+ messages in thread
* tm6000 2010-04-27 6:07 ` Bee Hock Goh 2010-04-28 1:32 ` Dmitri Belimov @ 2010-04-28 5:49 ` Dmitri Belimov 2010-04-28 7:32 ` tm6000 Bee Hock Goh 2010-04-28 12:14 ` tm6000 Mauro Carvalho Chehab 1 sibling, 2 replies; 14+ messages in thread From: Dmitri Belimov @ 2010-04-28 5:49 UTC (permalink / raw) To: Bee Hock Goh; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab 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. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: tm6000 2010-04-28 5:49 ` tm6000 Dmitri Belimov @ 2010-04-28 7:32 ` Bee Hock Goh 2010-04-28 12:14 ` tm6000 Mauro Carvalho Chehab 1 sibling, 0 replies; 14+ messages in thread From: Bee Hock Goh @ 2010-04-28 7:32 UTC (permalink / raw) To: Dmitri Belimov; +Cc: Stefan Ringel, linux-media, Mauro Carvalho Chehab 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. On Wed, Apr 28, 2010 at 1:49 PM, Dmitri Belimov <d.belimov@gmail.com> wrote: > 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. > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: tm6000 2010-04-28 5:49 ` tm6000 Dmitri Belimov 2010-04-28 7:32 ` tm6000 Bee Hock Goh @ 2010-04-28 12:14 ` Mauro Carvalho Chehab 1 sibling, 0 replies; 14+ messages in thread From: Mauro Carvalho Chehab @ 2010-04-28 12:14 UTC (permalink / raw) To: Dmitri Belimov; +Cc: Bee Hock Goh, Stefan Ringel, linux-media Dmitri Belimov wrote: > 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. -- Cheers, Mauro ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] tm6000 fix i2c 2010-04-26 0:25 ` Dmitri Belimov 2010-04-26 12:58 ` Bee Hock Goh @ 2010-04-26 13:29 ` Mauro Carvalho Chehab 1 sibling, 0 replies; 14+ messages in thread From: Mauro Carvalho Chehab @ 2010-04-26 13:29 UTC (permalink / raw) To: Dmitri Belimov; +Cc: Stefan Ringel, linux-media, Bee Hock Goh Hi Dmitri, Dmitri Belimov wrote: > 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> You probably don't need this. > > #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; > } 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. > > static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap, > > > With my best regards, Dmitry. > -- Cheers, Mauro ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2010-04-28 12:14 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-04-23 0:48 [PATCH] tm6000 fix i2c Dmitri Belimov 2010-04-23 12:57 ` Bee Hock Goh 2010-04-25 23:46 ` Dmitri Belimov 2010-04-23 15:15 ` Stefan Ringel 2010-04-25 23:47 ` Dmitri Belimov 2010-04-26 0:25 ` Dmitri Belimov 2010-04-26 12:58 ` Bee Hock Goh 2010-04-27 5:15 ` Dmitri Belimov 2010-04-27 6:07 ` Bee Hock Goh 2010-04-28 1:32 ` Dmitri Belimov 2010-04-28 5:49 ` tm6000 Dmitri Belimov 2010-04-28 7:32 ` tm6000 Bee Hock Goh 2010-04-28 12:14 ` tm6000 Mauro Carvalho Chehab 2010-04-26 13:29 ` [PATCH] tm6000 fix i2c Mauro Carvalho Chehab
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.