[media] cx24120: i2c-max-write-size is now configurable
authorPatrick Boettcher <patrick.boettcher@posteo.de>
Tue, 28 Apr 2015 05:47:42 +0000 (02:47 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 18 May 2015 19:32:35 +0000 (16:32 -0300)
Some i2c-hosts are quite limited regarding maximum
i2c-burst-write-sizes. This patch makes the previously
hardcoded field configurable by users of the driver.

Signed-off-by: Patrick Boettcher <patrick.boettcher@posteo.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/common/b2c2/flexcop-fe-tuner.c
drivers/media/dvb-frontends/cx24120.c
drivers/media/dvb-frontends/cx24120.h

index 66f6910a18108bb85d4669d2c3e7135a1c2567eb..9305266d0ac073495edfa585660b274de25bad9d 100644 (file)
@@ -630,6 +630,7 @@ static const struct cx24120_config skystar2_rev3_3_cx24120_config = {
        .xtal_khz = 10111,
        .initial_mpeg_config = { 0xa1, 0x76, 0x07 },
        .request_firmware = flexcop_fe_request_firmware,
+       .i2c_wr_max = 4,
 };
 
 static int skystarS2_rev33_attach(struct flexcop_device *fc,
index ff7f214961862f22970f1a6fee39521e07c0e690..2ed3fbc81e290891e50250a34a635461ddd20079 100644 (file)
@@ -209,46 +209,53 @@ static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data)
 }
 
 
-/* Write multiple registers */
+/* Write multiple registers in chunks of i2c_wr_max-sized buffers */
 static int cx24120_writeregN(struct cx24120_state *state,
                        u8 reg, const u8 *values, u16 len, u8 incr)
 {
        int ret;
-       u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation
-                       (very limited i2c-interface this one) */
+       u16 max = state->config->i2c_wr_max > 0 ?
+                               state->config->i2c_wr_max :
+                               len;
 
        struct i2c_msg msg = {
                .addr = state->config->i2c_addr,
                .flags = 0,
-               .buf = buf,
-               .len = len };
+       };
+
+       msg.buf = kmalloc(max + 1, GFP_KERNEL);
+       if (msg.buf == NULL)
+               return -ENOMEM;
 
        while (len) {
-               buf[0] = reg;
-               msg.len = len > 4 ? 4 : len;
-               memcpy(&buf[1], values, msg.len);
+               msg.buf[0] = reg;
+               msg.len = len > max ? max : len;
+               memcpy(&msg.buf[1], values, msg.len);
 
-               len  -= msg.len;                /* data length revers counter */
-               values += msg.len;              /* incr data pointer */
+               len    -= msg.len;      /* data length revers counter */
+               values += msg.len;      /* incr data pointer */
 
                if (incr)
                        reg += msg.len;
-               msg.len++;                      /* don't forget the addr byte */
+               msg.len++;              /* don't forget the addr byte */
 
                ret = i2c_transfer(state->i2c, &msg, 1);
                if (ret != 1) {
                        err("i2c_write error(err == %i, 0x%02x)\n", ret, reg);
-                       return ret;
+                       goto out;
                }
 
                dev_dbg(&state->i2c->dev,
                        "%s: reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n",
                        __func__, reg,
-                       buf[1], buf[2], buf[3], buf[4]);
-
+                       msg.buf[1], msg.buf[2], msg.buf[3], msg.buf[4]);
        }
 
-       return 0;
+       ret = 0;
+
+out:
+       kfree(msg.buf);
+       return ret;
 }
 
 
@@ -1434,7 +1441,6 @@ int cx24120_init(struct dvb_frontend *fe)
        }
        info("FW version %i.%i.%i.%i\n", vers[0], vers[1], vers[2], vers[3]);
 
-
        state->cold_init = 1;
        return 0;
 }
index 076d2ddb5dde8f4ecf58ad35e1ba7f0bff73db8b..e5748aaa8418ecc2a34f0a347cd9fe7eb20d8fd9 100644 (file)
@@ -37,6 +37,9 @@ struct cx24120_config {
 
        int (*request_firmware)(struct dvb_frontend *fe,
                                const struct firmware **fw, char *name);
+
+       /* max bytes I2C provider can write at once */
+       u16 i2c_wr_max;
 };
 
 #if IS_REACHABLE(CONFIG_DVB_CX24120)