Commit f7a77ebf authored by Patrick Boettcher's avatar Patrick Boettcher Committed by Mauro Carvalho Chehab

[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: default avatarPatrick Boettcher <patrick.boettcher@posteo.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent c5fb0f5f
...@@ -630,6 +630,7 @@ static const struct cx24120_config skystar2_rev3_3_cx24120_config = { ...@@ -630,6 +630,7 @@ static const struct cx24120_config skystar2_rev3_3_cx24120_config = {
.xtal_khz = 10111, .xtal_khz = 10111,
.initial_mpeg_config = { 0xa1, 0x76, 0x07 }, .initial_mpeg_config = { 0xa1, 0x76, 0x07 },
.request_firmware = flexcop_fe_request_firmware, .request_firmware = flexcop_fe_request_firmware,
.i2c_wr_max = 4,
}; };
static int skystarS2_rev33_attach(struct flexcop_device *fc, static int skystarS2_rev33_attach(struct flexcop_device *fc,
......
...@@ -209,46 +209,53 @@ static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) ...@@ -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, static int cx24120_writeregN(struct cx24120_state *state,
u8 reg, const u8 *values, u16 len, u8 incr) u8 reg, const u8 *values, u16 len, u8 incr)
{ {
int ret; int ret;
u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation u16 max = state->config->i2c_wr_max > 0 ?
(very limited i2c-interface this one) */ state->config->i2c_wr_max :
len;
struct i2c_msg msg = { struct i2c_msg msg = {
.addr = state->config->i2c_addr, .addr = state->config->i2c_addr,
.flags = 0, .flags = 0,
.buf = buf, };
.len = len };
msg.buf = kmalloc(max + 1, GFP_KERNEL);
if (msg.buf == NULL)
return -ENOMEM;
while (len) { while (len) {
buf[0] = reg; msg.buf[0] = reg;
msg.len = len > 4 ? 4 : len; msg.len = len > max ? max : len;
memcpy(&buf[1], values, msg.len); memcpy(&msg.buf[1], values, msg.len);
len -= msg.len; /* data length revers counter */ len -= msg.len; /* data length revers counter */
values += msg.len; /* incr data pointer */ values += msg.len; /* incr data pointer */
if (incr) if (incr)
reg += msg.len; 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); ret = i2c_transfer(state->i2c, &msg, 1);
if (ret != 1) { if (ret != 1) {
err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); err("i2c_write error(err == %i, 0x%02x)\n", ret, reg);
return ret; goto out;
} }
dev_dbg(&state->i2c->dev, dev_dbg(&state->i2c->dev,
"%s: reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", "%s: reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n",
__func__, reg, __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) ...@@ -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]); info("FW version %i.%i.%i.%i\n", vers[0], vers[1], vers[2], vers[3]);
state->cold_init = 1; state->cold_init = 1;
return 0; return 0;
} }
......
...@@ -37,6 +37,9 @@ struct cx24120_config { ...@@ -37,6 +37,9 @@ struct cx24120_config {
int (*request_firmware)(struct dvb_frontend *fe, int (*request_firmware)(struct dvb_frontend *fe,
const struct firmware **fw, char *name); const struct firmware **fw, char *name);
/* max bytes I2C provider can write at once */
u16 i2c_wr_max;
}; };
#if IS_REACHABLE(CONFIG_DVB_CX24120) #if IS_REACHABLE(CONFIG_DVB_CX24120)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment