Skip to content

Commit

Permalink
[media] xc4000: handle dib0700 broken i2c stretching
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Devin Heitmueller authored and Mauro Carvalho Chehab committed Jul 27, 2011
1 parent 8583fc8 commit 799ed11
Showing 1 changed file with 29 additions and 5 deletions.
34 changes: 29 additions & 5 deletions drivers/media/common/tuners/xc4000.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct xc4000_priv {
struct firmware_properties cur_fw;
__u16 hwmodel;
__u16 hwvers;
u8 ignore_i2c_write_errors;
};

/* Misc Defines */
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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__);

Expand Down Expand Up @@ -1071,7 +1095,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type,
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;
Expand Down

0 comments on commit 799ed11

Please sign in to comment.