summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Radicati <alessandro@radicati.net>2016-05-12 07:47:12 -0300
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2016-06-09 08:46:00 -0300
commit1882f59f93066cb4ae922d68526bd0f33d2277cb (patch)
treeacfa3e3d2286e6cce9c312d73d7960f14d589709
parent57f1c0533850c0d68d114353b3b3a61148498698 (diff)
[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: Alessandro Radicati <alessandro@radicati.net> Signed-off-by: Antti Palosaari <crope@iki.fi> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c21
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.h1
2 files changed, 22 insertions, 0 deletions
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 09a549b49400..a8ab592bf761 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -348,6 +348,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
msg[1].len);
+ } else if (state->no_read) {
+ memset(msg[1].buf, 0, msg[1].len);
+ ret = 0;
} else {
/* I2C write + read */
u8 buf[MAX_XFER_SIZE];
@@ -436,6 +439,9 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
if (msg[0].len > 40) {
/* TODO: correct limits > 40 */
ret = -EOPNOTSUPP;
+ } else if (state->no_read) {
+ memset(msg[0].buf, 0, msg[0].len);
+ ret = 0;
} else {
/* I2C read */
u8 buf[5];
@@ -977,6 +983,21 @@ skip_eeprom:
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;
err:
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h
index 89e629a24aec..c91d1a3789e6 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.h
+++ b/drivers/media/usb/dvb-usb-v2/af9035.h
@@ -62,6 +62,7 @@ struct state {
u8 chip_version;
u16 chip_type;
u8 dual_mode:1;
+ u8 no_read:1;
u16 eeprom_addr;
u8 af9033_i2c_addr[2];
struct af9033_config af9033_config[2];