[media] af9015: fix and refactor i2c adapter algo logic
* fix write+read when write has more than one byte * remove lock, not needed on that case * remove useless i2c msg send loop, as we support only write, read and write+read as one go and nothing more Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
d029799b2f
commit
d83886ff11
@ -206,9 +206,9 @@ static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
|||||||
{
|
{
|
||||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||||
struct af9015_state *state = d_to_priv(d);
|
struct af9015_state *state = d_to_priv(d);
|
||||||
int ret = 0, i = 0;
|
int ret;
|
||||||
u16 addr;
|
u16 addr;
|
||||||
u8 uninitialized_var(mbox), addr_len;
|
u8 mbox, addr_len;
|
||||||
struct req_t req;
|
struct req_t req;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -233,84 +233,89 @@ Due to that the only way to select correct tuner is use demodulator I2C-gate.
|
|||||||
| addr 0x3a | | addr 0xc6 |
|
| addr 0x3a | | addr 0xc6 |
|
||||||
|____________| |____________|
|
|____________| |____________|
|
||||||
*/
|
*/
|
||||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
while (i < num) {
|
|
||||||
if (msg[i].addr == state->af9013_config[0].i2c_addr ||
|
|
||||||
msg[i].addr == state->af9013_config[1].i2c_addr) {
|
|
||||||
addr = msg[i].buf[0] << 8;
|
|
||||||
addr += msg[i].buf[1];
|
|
||||||
mbox = msg[i].buf[2];
|
|
||||||
addr_len = 3;
|
|
||||||
} else {
|
|
||||||
addr = msg[i].buf[0];
|
|
||||||
addr_len = 1;
|
|
||||||
/* mbox is don't care in that case */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
|
|
||||||
if (msg[i].len > 3 || msg[i+1].len > 61) {
|
|
||||||
ret = -EOPNOTSUPP;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (msg[i].addr == state->af9013_config[0].i2c_addr)
|
|
||||||
req.cmd = READ_MEMORY;
|
|
||||||
else
|
|
||||||
req.cmd = READ_I2C;
|
|
||||||
req.i2c_addr = msg[i].addr;
|
|
||||||
req.addr = addr;
|
|
||||||
req.mbox = mbox;
|
|
||||||
req.addr_len = addr_len;
|
|
||||||
req.data_len = msg[i+1].len;
|
|
||||||
req.data = &msg[i+1].buf[0];
|
|
||||||
ret = af9015_ctrl_msg(d, &req);
|
|
||||||
i += 2;
|
|
||||||
} else if (msg[i].flags & I2C_M_RD) {
|
|
||||||
if (msg[i].len > 61) {
|
|
||||||
ret = -EOPNOTSUPP;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (msg[i].addr == state->af9013_config[0].i2c_addr) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
req.cmd = READ_I2C;
|
|
||||||
req.i2c_addr = msg[i].addr;
|
|
||||||
req.addr = addr;
|
|
||||||
req.mbox = mbox;
|
|
||||||
req.addr_len = addr_len;
|
|
||||||
req.data_len = msg[i].len;
|
|
||||||
req.data = &msg[i].buf[0];
|
|
||||||
ret = af9015_ctrl_msg(d, &req);
|
|
||||||
i += 1;
|
|
||||||
} else {
|
|
||||||
if (msg[i].len > 21) {
|
|
||||||
ret = -EOPNOTSUPP;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (msg[i].addr == state->af9013_config[0].i2c_addr)
|
|
||||||
req.cmd = WRITE_MEMORY;
|
|
||||||
else
|
|
||||||
req.cmd = WRITE_I2C;
|
|
||||||
req.i2c_addr = msg[i].addr;
|
|
||||||
req.addr = addr;
|
|
||||||
req.mbox = mbox;
|
|
||||||
req.addr_len = addr_len;
|
|
||||||
req.data_len = msg[i].len-addr_len;
|
|
||||||
req.data = &msg[i].buf[addr_len];
|
|
||||||
ret = af9015_ctrl_msg(d, &req);
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
if (ret)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
|
if (msg[0].len == 0 || msg[0].flags & I2C_M_RD) {
|
||||||
|
addr = 0x0000;
|
||||||
|
mbox = 0;
|
||||||
|
addr_len = 0;
|
||||||
|
} else if (msg[0].len == 1) {
|
||||||
|
addr = msg[0].buf[0];
|
||||||
|
mbox = 0;
|
||||||
|
addr_len = 1;
|
||||||
|
} else if (msg[0].len == 2) {
|
||||||
|
addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0;
|
||||||
|
mbox = 0;
|
||||||
|
addr_len = 2;
|
||||||
|
} else {
|
||||||
|
addr = msg[0].buf[0] << 8|msg[0].buf[1] << 0;
|
||||||
|
mbox = msg[0].buf[2];
|
||||||
|
addr_len = 3;
|
||||||
}
|
}
|
||||||
ret = i;
|
|
||||||
|
|
||||||
error:
|
if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
|
||||||
mutex_unlock(&d->i2c_mutex);
|
/* i2c write */
|
||||||
|
if (msg[0].len > 21) {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (msg[0].addr == state->af9013_config[0].i2c_addr)
|
||||||
|
req.cmd = WRITE_MEMORY;
|
||||||
|
else
|
||||||
|
req.cmd = WRITE_I2C;
|
||||||
|
req.i2c_addr = msg[0].addr;
|
||||||
|
req.addr = addr;
|
||||||
|
req.mbox = mbox;
|
||||||
|
req.addr_len = addr_len;
|
||||||
|
req.data_len = msg[0].len-addr_len;
|
||||||
|
req.data = &msg[0].buf[addr_len];
|
||||||
|
ret = af9015_ctrl_msg(d, &req);
|
||||||
|
} else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
|
||||||
|
(msg[1].flags & I2C_M_RD)) {
|
||||||
|
/* i2c write + read */
|
||||||
|
if (msg[0].len > 3 || msg[1].len > 61) {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (msg[0].addr == state->af9013_config[0].i2c_addr)
|
||||||
|
req.cmd = READ_MEMORY;
|
||||||
|
else
|
||||||
|
req.cmd = READ_I2C;
|
||||||
|
req.i2c_addr = msg[0].addr;
|
||||||
|
req.addr = addr;
|
||||||
|
req.mbox = mbox;
|
||||||
|
req.addr_len = addr_len;
|
||||||
|
req.data_len = msg[1].len;
|
||||||
|
req.data = &msg[1].buf[0];
|
||||||
|
ret = af9015_ctrl_msg(d, &req);
|
||||||
|
} else if (num == 1 && (msg[0].flags & I2C_M_RD)) {
|
||||||
|
/* i2c read */
|
||||||
|
if (msg[0].len > 61) {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (msg[0].addr == state->af9013_config[0].i2c_addr) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
req.cmd = READ_I2C;
|
||||||
|
req.i2c_addr = msg[0].addr;
|
||||||
|
req.addr = addr;
|
||||||
|
req.mbox = mbox;
|
||||||
|
req.addr_len = addr_len;
|
||||||
|
req.data_len = msg[0].len;
|
||||||
|
req.data = &msg[0].buf[0];
|
||||||
|
ret = af9015_ctrl_msg(d, &req);
|
||||||
|
} else {
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
dev_dbg(&d->udev->dev, "%s: unknown msg, num %u\n",
|
||||||
|
__func__, num);
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
err:
|
||||||
|
dev_dbg(&d->udev->dev, "%s: failed %d\n", __func__, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user