Commit 799ed11a authored by Devin Heitmueller's avatar Devin Heitmueller Committed by Mauro Carvalho Chehab

[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: default avatarDevin Heitmueller <dheitmueller@kernellabs.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 8583fc83
...@@ -89,6 +89,7 @@ struct xc4000_priv { ...@@ -89,6 +89,7 @@ struct xc4000_priv {
struct firmware_properties cur_fw; struct firmware_properties cur_fw;
__u16 hwmodel; __u16 hwmodel;
__u16 hwvers; __u16 hwvers;
u8 ignore_i2c_write_errors;
}; };
/* Misc Defines */ /* Misc Defines */
...@@ -255,9 +256,16 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) ...@@ -255,9 +256,16 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
struct i2c_msg msg = { .addr = priv->i2c_props.addr, struct i2c_msg msg = { .addr = priv->i2c_props.addr,
.flags = 0, .buf = buf, .len = len }; .flags = 0, .buf = buf, .len = len };
if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", len); 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_I2C_WRITE_FAILURE;
} }
}
return XC_RESULT_SUCCESS; return XC_RESULT_SUCCESS;
} }
...@@ -371,10 +379,15 @@ static int xc_SetTVStandard(struct xc4000_priv *priv, ...@@ -371,10 +379,15 @@ static int xc_SetTVStandard(struct xc4000_priv *priv,
__func__, __func__,
XC4000_Standard[priv->video_standard].Name); 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); ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
if (ret == XC_RESULT_SUCCESS) if (ret == XC_RESULT_SUCCESS)
ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode); ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
priv->ignore_i2c_write_errors = 0;
return ret; return ret;
} }
...@@ -506,10 +519,16 @@ static u16 WaitForLock(struct xc4000_priv *priv) ...@@ -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) static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz, int mode)
{ {
int found = 0; int found = 0;
int result = 0;
dprintk(1, "%s(%u)\n", __func__, freq_hz); 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; return 0;
if (mode == XC_TUNE_ANALOG) { if (mode == XC_TUNE_ANALOG) {
...@@ -721,8 +740,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type, ...@@ -721,8 +740,13 @@ static int load_firmware(struct dvb_frontend *fe, unsigned int type,
p = priv->firm[pos].ptr; p = priv->firm[pos].ptr;
printk("firmware length = %d\n", priv->firm[pos].size); 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); rc = xc_load_i2c_sequence(fe, p);
priv->ignore_i2c_write_errors = 0;
return rc; return rc;
} }
......
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