diff options
author | Devin Heitmueller <dheitmueller@kernellabs.com> | 2009-10-04 22:09:18 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:52:30 -0400 |
commit | 799ed11afe7694858584d1ed4e9ae2f9e48142ec (patch) | |
tree | ef723e6d86876d60ecbf8a95623939a147b13576 /drivers/media/common | |
parent | 8583fc834e704312fa9e7c756244895de55d800a (diff) |
[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 { | |||
89 | struct firmware_properties cur_fw; | 89 | struct firmware_properties cur_fw; |
90 | __u16 hwmodel; | 90 | __u16 hwmodel; |
91 | __u16 hwvers; | 91 | __u16 hwvers; |
92 | u8 ignore_i2c_write_errors; | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | /* Misc Defines */ | 95 | /* Misc Defines */ |
@@ -255,8 +256,15 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) | |||
255 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, | 256 | struct i2c_msg msg = { .addr = priv->i2c_props.addr, |
256 | .flags = 0, .buf = buf, .len = len }; | 257 | .flags = 0, .buf = buf, .len = len }; |
257 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { | 258 | if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { |
258 | printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", len); | 259 | if (priv->ignore_i2c_write_errors == 0) { |
259 | return XC_RESULT_I2C_WRITE_FAILURE; | 260 | printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", |
261 | len); | ||
262 | if (len == 4) { | ||
263 | printk("bytes %02x %02x %02x %02x\n", buf[0], | ||
264 | buf[1], buf[2], buf[3]); | ||
265 | } | ||
266 | return XC_RESULT_I2C_WRITE_FAILURE; | ||
267 | } | ||
260 | } | 268 | } |
261 | return XC_RESULT_SUCCESS; | 269 | return XC_RESULT_SUCCESS; |
262 | } | 270 | } |
@@ -371,10 +379,15 @@ static int xc_SetTVStandard(struct xc4000_priv *priv, | |||
371 | __func__, | 379 | __func__, |
372 | XC4000_Standard[priv->video_standard].Name); | 380 | XC4000_Standard[priv->video_standard].Name); |
373 | 381 | ||
382 | /* Don't complain when the request fails because of i2c stretching */ | ||
383 | priv->ignore_i2c_write_errors = 1; | ||
384 | |||
374 | ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); | 385 | ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode); |
375 | if (ret == XC_RESULT_SUCCESS) | 386 | if (ret == XC_RESULT_SUCCESS) |
376 | ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); | 387 | ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); |
377 | 388 | ||
389 | priv->ignore_i2c_write_errors = 0; | ||
390 | |||
378 | return ret; | 391 | return ret; |
379 | } | 392 | } |
380 | 393 | ||
@@ -506,10 +519,16 @@ static u16 WaitForLock(struct xc4000_priv *priv) | |||
506 | static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode) | 519 | static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode) |
507 | { | 520 | { |
508 | int found = 0; | 521 | int found = 0; |
522 | int result = 0; | ||
509 | 523 | ||
510 | dprintk(1, "%s(%u)\n", __func__, freq_hz); | 524 | dprintk(1, "%s(%u)\n", __func__, freq_hz); |
511 | 525 | ||
512 | if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS) | 526 | /* Don't complain when the request fails because of i2c stretching */ |
527 | priv->ignore_i2c_write_errors = 1; | ||
528 | result = xc_set_RF_frequency(priv, freq_hz); | ||
529 | priv->ignore_i2c_write_errors = 0; | ||
530 | |||
531 | if (result != XC_RESULT_SUCCESS) | ||
513 | return 0; | 532 | return 0; |
514 | 533 | ||
515 | if (mode == XC_TUNE_ANALOG) { | 534 | if (mode == XC_TUNE_ANALOG) { |
@@ -721,8 +740,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, | |||
721 | p = priv->firm[pos].ptr; | 740 | p = priv->firm[pos].ptr; |
722 | printk("firmware length = %d\n", priv->firm[pos].size); | 741 | printk("firmware length = %d\n", priv->firm[pos].size); |
723 | 742 | ||
743 | /* Don't complain when the request fails because of i2c stretching */ | ||
744 | priv->ignore_i2c_write_errors = 1; | ||
745 | |||
724 | rc = xc_load_i2c_sequence(fe, p); | 746 | rc = xc_load_i2c_sequence(fe, p); |
725 | 747 | ||
748 | priv->ignore_i2c_write_errors = 0; | ||
749 | |||
726 | return rc; | 750 | return rc; |
727 | } | 751 | } |
728 | 752 | ||
@@ -954,7 +978,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, | |||
954 | int rc = 0, is_retry = 0; | 978 | int rc = 0, is_retry = 0; |
955 | u16 version, hwmodel; | 979 | u16 version, hwmodel; |
956 | v4l2_std_id std0; | 980 | v4l2_std_id std0; |
957 | u8 hw_major, hw_minor, fw_major, fw_minor; | 981 | u8 hw_major, hw_minor, fw_major, fw_minor; |
958 | 982 | ||
959 | dprintk(1, "%s called\n", __func__); | 983 | dprintk(1, "%s called\n", __func__); |
960 | 984 | ||
@@ -1071,7 +1095,7 @@ skip_std_specific: | |||
1071 | check_device: | 1095 | check_device: |
1072 | rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel); | 1096 | rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel); |
1073 | 1097 | ||
1074 | if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major, | 1098 | if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major, |
1075 | &fw_minor) != XC_RESULT_SUCCESS) { | 1099 | &fw_minor) != XC_RESULT_SUCCESS) { |
1076 | printk("Unable to read tuner registers.\n"); | 1100 | printk("Unable to read tuner registers.\n"); |
1077 | goto fail; | 1101 | goto fail; |