aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Boettcher <patrick.boettcher@posteo.de>2015-04-28 01:47:42 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-05-18 15:32:35 -0400
commitf7a77ebf08536da5cafd4494855001be74176efb (patch)
tree224a3cc3a1dab1f80e194f8087de1b04010f1c18
parentc5fb0f5f545cdf90c451ea7c9a6fb98ae4c64e49 (diff)
[media] cx24120: i2c-max-write-size is now configurable
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>
-rw-r--r--drivers/media/common/b2c2/flexcop-fe-tuner.c1
-rw-r--r--drivers/media/dvb-frontends/cx24120.c38
-rw-r--r--drivers/media/dvb-frontends/cx24120.h3
3 files changed, 26 insertions, 16 deletions
diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c
index 66f6910a1810..9305266d0ac0 100644
--- a/drivers/media/common/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c
@@ -630,6 +630,7 @@ static const struct cx24120_config skystar2_rev3_3_cx24120_config = {
630 .xtal_khz = 10111, 630 .xtal_khz = 10111,
631 .initial_mpeg_config = { 0xa1, 0x76, 0x07 }, 631 .initial_mpeg_config = { 0xa1, 0x76, 0x07 },
632 .request_firmware = flexcop_fe_request_firmware, 632 .request_firmware = flexcop_fe_request_firmware,
633 .i2c_wr_max = 4,
633}; 634};
634 635
635static int skystarS2_rev33_attach(struct flexcop_device *fc, 636static int skystarS2_rev33_attach(struct flexcop_device *fc,
diff --git a/drivers/media/dvb-frontends/cx24120.c b/drivers/media/dvb-frontends/cx24120.c
index ff7f21496186..2ed3fbc81e29 100644
--- a/drivers/media/dvb-frontends/cx24120.c
+++ b/drivers/media/dvb-frontends/cx24120.c
@@ -209,46 +209,53 @@ static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data)
209} 209}
210 210
211 211
212/* Write multiple registers */ 212/* Write multiple registers in chunks of i2c_wr_max-sized buffers */
213static int cx24120_writeregN(struct cx24120_state *state, 213static int cx24120_writeregN(struct cx24120_state *state,
214 u8 reg, const u8 *values, u16 len, u8 incr) 214 u8 reg, const u8 *values, u16 len, u8 incr)
215{ 215{
216 int ret; 216 int ret;
217 u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation 217 u16 max = state->config->i2c_wr_max > 0 ?
218 (very limited i2c-interface this one) */ 218 state->config->i2c_wr_max :
219 len;
219 220
220 struct i2c_msg msg = { 221 struct i2c_msg msg = {
221 .addr = state->config->i2c_addr, 222 .addr = state->config->i2c_addr,
222 .flags = 0, 223 .flags = 0,
223 .buf = buf, 224 };
224 .len = len }; 225
226 msg.buf = kmalloc(max + 1, GFP_KERNEL);
227 if (msg.buf == NULL)
228 return -ENOMEM;
225 229
226 while (len) { 230 while (len) {
227 buf[0] = reg; 231 msg.buf[0] = reg;
228 msg.len = len > 4 ? 4 : len; 232 msg.len = len > max ? max : len;
229 memcpy(&buf[1], values, msg.len); 233 memcpy(&msg.buf[1], values, msg.len);
230 234
231 len -= msg.len; /* data length revers counter */ 235 len -= msg.len; /* data length revers counter */
232 values += msg.len; /* incr data pointer */ 236 values += msg.len; /* incr data pointer */
233 237
234 if (incr) 238 if (incr)
235 reg += msg.len; 239 reg += msg.len;
236 msg.len++; /* don't forget the addr byte */ 240 msg.len++; /* don't forget the addr byte */
237 241
238 ret = i2c_transfer(state->i2c, &msg, 1); 242 ret = i2c_transfer(state->i2c, &msg, 1);
239 if (ret != 1) { 243 if (ret != 1) {
240 err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); 244 err("i2c_write error(err == %i, 0x%02x)\n", ret, reg);
241 return ret; 245 goto out;
242 } 246 }
243 247
244 dev_dbg(&state->i2c->dev, 248 dev_dbg(&state->i2c->dev,
245 "%s: reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", 249 "%s: reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n",
246 __func__, reg, 250 __func__, reg,
247 buf[1], buf[2], buf[3], buf[4]); 251 msg.buf[1], msg.buf[2], msg.buf[3], msg.buf[4]);
248
249 } 252 }
250 253
251 return 0; 254 ret = 0;
255
256out:
257 kfree(msg.buf);
258 return ret;
252} 259}
253 260
254 261
@@ -1434,7 +1441,6 @@ int cx24120_init(struct dvb_frontend *fe)
1434 } 1441 }
1435 info("FW version %i.%i.%i.%i\n", vers[0], vers[1], vers[2], vers[3]); 1442 info("FW version %i.%i.%i.%i\n", vers[0], vers[1], vers[2], vers[3]);
1436 1443
1437
1438 state->cold_init = 1; 1444 state->cold_init = 1;
1439 return 0; 1445 return 0;
1440} 1446}
diff --git a/drivers/media/dvb-frontends/cx24120.h b/drivers/media/dvb-frontends/cx24120.h
index 076d2ddb5dde..e5748aaa8418 100644
--- a/drivers/media/dvb-frontends/cx24120.h
+++ b/drivers/media/dvb-frontends/cx24120.h
@@ -37,6 +37,9 @@ struct cx24120_config {
37 37
38 int (*request_firmware)(struct dvb_frontend *fe, 38 int (*request_firmware)(struct dvb_frontend *fe,
39 const struct firmware **fw, char *name); 39 const struct firmware **fw, char *name);
40
41 /* max bytes I2C provider can write at once */
42 u16 i2c_wr_max;
40}; 43};
41 44
42#if IS_REACHABLE(CONFIG_DVB_CX24120) 45#if IS_REACHABLE(CONFIG_DVB_CX24120)