diff options
author | Devin Heitmueller <dheitmueller@kernellabs.com> | 2009-10-05 06:09:18 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-28 00:52:30 +0400 |
commit | 799ed11afe7694858584d1ed4e9ae2f9e48142ec (patch) | |
tree | ef723e6d86876d60ecbf8a95623939a147b13576 /drivers/media/common | |
parent | 8583fc834e704312fa9e7c756244895de55d800a (diff) | |
download | linux-799ed11afe7694858584d1ed4e9ae2f9e48142ec.tar.xz |
[media] xc4000: handle dib0700 broken i2c stretching
It was confirmed by DibCom that i2c stretching is broken in the i2c master
on the dib7700. So we need to put a hack into the xc4000 driver to not
complain in certain very specific cases where we know i2c stretching occurs.
Signed-off-by: Devin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r-- | drivers/media/common/tuners/xc4000.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c index 2dacf209d427..b3b33d266b7c 100644 --- a/drivers/media/common/tuners/xc4000.c +++ b/drivers/media/common/tuners/xc4000.c @@ -89,6 +89,7 @@ struct xc4000_priv { struct firmware_properties cur_fw; __u16 hwmodel; __u16 hwvers; + u8 ignore_i2c_write_errors; }; /* Misc Defines */ @@ -255,8 +256,15 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0, .buf = buf, .len = len }; if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { - printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", len); - return XC_RESULT_I2C_WRITE_FAILURE; + if (priv->ignore_i2c_write_errors == 0) { + printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", + len); + if (len == 4) { + printk("bytes %02x %02x %02x %02x\n", buf[0], + buf[1], buf[2], buf[3]); + } + return XC_RESULT_I2C_WRITE_FAILURE; + } } return XC_RESULT_SUCCESS; } @@ -371,10 +379,15 @@ static int xc_SetTVStandard(struct xc4000_priv *priv, __func__, XC4000_Standard[priv->video_standard].Name); + /* Don't complain when the request fails because of i2c stretching */ + priv->ignore_i2c_write_errors = 1; + ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); if (ret == XC_RESULT_SUCCESS) ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); + priv->ignore_i2c_write_errors = 0; + return ret; } @@ -506,10 +519,16 @@ static u16 WaitForLock(struct xc4000_priv *priv) static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode) { int found = 0; + int result = 0; dprintk(1, "%s(%u)\n", __func__, freq_hz); - if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) + /* Don't complain when the request fails because of i2c stretching */ + priv->ignore_i2c_write_errors = 1; + result = xc_set_RF_frequency(priv, freq_hz); + priv->ignore_i2c_write_errors = 0; + + if (result != XC_RESULT_SUCCESS) return 0; if (mode == XC_TUNE_ANALOG) { @@ -721,8 +740,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, p = priv->firm[pos].ptr; printk("firmware length = %d\n", priv->firm[pos].size); + /* Don't complain when the request fails because of i2c stretching */ + priv->ignore_i2c_write_errors = 1; + rc = xc_load_i2c_sequence(fe, p); + priv->ignore_i2c_write_errors = 0; + return rc; } @@ -954,7 +978,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, int rc = 0, is_retry = 0; u16 version, hwmodel; v4l2_std_id std0; - u8 hw_major, hw_minor, fw_major, fw_minor; + u8 hw_major, hw_minor, fw_major, fw_minor; dprintk(1, "%s called\n", __func__); @@ -1071,7 +1095,7 @@ skip_std_specific: check_device: rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel); - if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major, + if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major, &fw_minor) != XC_RESULT_SUCCESS) { printk("Unable to read tuner registers.\n"); goto fail; |