Commit 1882f59f authored by Alessandro Radicati's avatar Alessandro Radicati Committed by Mauro Carvalho Chehab

[media] af9035: fix for MXL5007T devices with I2C read issues

The MXL5007T tuner will lock-up on some devices after an I2C read
transaction.  This patch works around this issue by inhibiting such
operations and emulating a 0x00 response. The workaround is only
applied to USB devices known to exhibit this flaw.
Signed-off-by: default avatarAlessandro Radicati <alessandro@radicati.net>
Signed-off-by: default avatarAntti Palosaari <crope@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 57f1c053
...@@ -348,6 +348,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -348,6 +348,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
ret = af9035_rd_regs(d, reg, &msg[1].buf[0], ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
msg[1].len); msg[1].len);
} else if (state->no_read) {
memset(msg[1].buf, 0, msg[1].len);
ret = 0;
} else { } else {
/* I2C write + read */ /* I2C write + read */
u8 buf[MAX_XFER_SIZE]; u8 buf[MAX_XFER_SIZE];
...@@ -436,6 +439,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, ...@@ -436,6 +439,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
if (msg[0].len > 40) { if (msg[0].len > 40) {
/* TODO: correct limits > 40 */ /* TODO: correct limits > 40 */
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
} else if (state->no_read) {
memset(msg[0].buf, 0, msg[0].len);
ret = 0;
} else { } else {
/* I2C read */ /* I2C read */
u8 buf[5]; u8 buf[5];
...@@ -977,6 +983,21 @@ static int af9035_read_config(struct dvb_usb_device *d) ...@@ -977,6 +983,21 @@ static int af9035_read_config(struct dvb_usb_device *d)
state->af9033_config[i].clock = clock_lut_af9035[tmp]; state->af9033_config[i].clock = clock_lut_af9035[tmp];
} }
state->no_read = false;
/* Some MXL5007T devices cannot properly handle tuner I2C read ops. */
if (state->af9033_config[0].tuner == AF9033_TUNER_MXL5007T &&
le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA)
switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
case USB_PID_AVERMEDIA_A867:
case USB_PID_AVERMEDIA_TWINSTAR:
dev_info(&d->udev->dev,
"%s: Device may have issues with I2C read operations. Enabling fix.\n",
KBUILD_MODNAME);
state->no_read = true;
break;
}
return 0; return 0;
err: err:
......
...@@ -62,6 +62,7 @@ struct state { ...@@ -62,6 +62,7 @@ struct state {
u8 chip_version; u8 chip_version;
u16 chip_type; u16 chip_type;
u8 dual_mode:1; u8 dual_mode:1;
u8 no_read:1;
u16 eeprom_addr; u16 eeprom_addr;
u8 af9033_i2c_addr[2]; u8 af9033_i2c_addr[2];
struct af9033_config af9033_config[2]; struct af9033_config af9033_config[2];
......
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