Skip to content

Commit

Permalink
[media] tda18271: allow restricting max out to 4 bytes
Browse files Browse the repository at this point in the history
By default, tda18271 tries to optimize I2C bus by updating all registers
at the same time. Unfortunately, some devices doesn't support it.

The current logic has a problem when small_i2c is equal to 8, since there
are some transfers using 11 + 1 bytes.

Fix the problem by enforcing the max size at the right place, and allows
reducing it to max = 3 + 1.

Acked-by: Michael Krufky <mkrufky@kernellabs.com>
Acked-by: Sri Deevi <Srinivasa.Deevi@conexant.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Mauro Carvalho Chehab committed Oct 21, 2010
1 parent 78bb6df commit e350d44
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 28 deletions.
59 changes: 34 additions & 25 deletions drivers/media/common/tuners/tda18271-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,46 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
unsigned char *regs = priv->tda18271_regs;
unsigned char buf[TDA18271_NUM_REGS + 1];
struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
.buf = buf, .len = len + 1 };
int i, ret;
.buf = buf };
int i, ret = 1, max;

BUG_ON((len == 0) || (idx + len > sizeof(buf)));

buf[0] = idx;
for (i = 1; i <= len; i++)
buf[i] = regs[idx - 1 + i];

switch (priv->small_i2c) {
case TDA18271_03_BYTE_CHUNK_INIT:
max = 3;
break;
case TDA18271_08_BYTE_CHUNK_INIT:
max = 8;
break;
case TDA18271_16_BYTE_CHUNK_INIT:
max = 16;
break;
case TDA18271_39_BYTE_CHUNK_INIT:
default:
max = 39;
}

tda18271_i2c_gate_ctrl(fe, 1);
while (len) {
if (max > len)
max = len;

buf[0] = idx;
for (i = 1; i <= max; i++)
buf[i] = regs[idx - 1 + i];

/* write registers */
ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
msg.len = max + 1;

/* write registers */
ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
if (ret != 1)
break;

idx += max;
len -= max;
}
tda18271_i2c_gate_ctrl(fe, 0);

if (ret != 1)
Expand Down Expand Up @@ -326,24 +352,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
regs[R_EB22] = 0x48;
regs[R_EB23] = 0xb0;

switch (priv->small_i2c) {
case TDA18271_08_BYTE_CHUNK_INIT:
tda18271_write_regs(fe, 0x00, 0x08);
tda18271_write_regs(fe, 0x08, 0x08);
tda18271_write_regs(fe, 0x10, 0x08);
tda18271_write_regs(fe, 0x18, 0x08);
tda18271_write_regs(fe, 0x20, 0x07);
break;
case TDA18271_16_BYTE_CHUNK_INIT:
tda18271_write_regs(fe, 0x00, 0x10);
tda18271_write_regs(fe, 0x10, 0x10);
tda18271_write_regs(fe, 0x20, 0x07);
break;
case TDA18271_39_BYTE_CHUNK_INIT:
default:
tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
break;
}
tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);

/* setup agc1 gain */
regs[R_EB17] = 0x00;
Expand Down
5 changes: 3 additions & 2 deletions drivers/media/common/tuners/tda18271.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ enum tda18271_output_options {

enum tda18271_small_i2c {
TDA18271_39_BYTE_CHUNK_INIT = 0,
TDA18271_16_BYTE_CHUNK_INIT = 1,
TDA18271_08_BYTE_CHUNK_INIT = 2,
TDA18271_16_BYTE_CHUNK_INIT = 16,
TDA18271_08_BYTE_CHUNK_INIT = 8,
TDA18271_03_BYTE_CHUNK_INIT = 3,
};

struct tda18271_config {
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/tuner-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
{
struct tda18271_config cfg = {
.config = t->config,
.small_i2c = TDA18271_08_BYTE_CHUNK_INIT,
.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
};

if (!dvb_attach(tda18271_attach, &t->fe, t->i2c->addr,
Expand Down

0 comments on commit e350d44

Please sign in to comment.