diff options
author | Antti Palosaari <crope@iki.fi> | 2012-04-02 19:18:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-04-09 13:53:30 -0400 |
commit | ad30e91befd7153827a97faa8281dcd48aa6702d (patch) | |
tree | a2074436e1b52588761ebd357b2e8942288a8d72 /drivers | |
parent | 48bf7e1a9dce24adf79ea118ef001e781fb0e2e4 (diff) |
[media] af9035: fix and enhance I2C adapter
There was a bug I2C adapter writes and reads one byte too much.
As the most I2C clients has auto-increment register addressing
this leads next register from the target register overwritten by
garbage data.
As a change remove whole register address byte usage and write
data directly to the I2C bus without saying what are register
address bytes to firmware.
Signed-off-by: Antti Palosaari <crope@iki.fi>
Cc: Michael Buesch <m@bues.ch>
Cc: Hans-Frieder Vogt <hfvogt@gmx.net>
Cc: Gianluca Gennari <gennarone@gmail.com>
Tested-by: Michael Buesch <m@bues.ch>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9035.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c index 73044632d943..58fe69deda1f 100644 --- a/drivers/media/dvb/dvb-usb/af9035.c +++ b/drivers/media/dvb/dvb-usb/af9035.c | |||
@@ -224,6 +224,22 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, | |||
224 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 224 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
225 | return -EAGAIN; | 225 | return -EAGAIN; |
226 | 226 | ||
227 | /* | ||
228 | * I2C sub header is 5 bytes long. Meaning of those bytes are: | ||
229 | * 0: data len | ||
230 | * 1: I2C addr << 1 | ||
231 | * 2: reg addr len | ||
232 | * byte 3 and 4 can be used as reg addr | ||
233 | * 3: reg addr MSB | ||
234 | * used when reg addr len is set to 2 | ||
235 | * 4: reg addr LSB | ||
236 | * used when reg addr len is set to 1 or 2 | ||
237 | * | ||
238 | * For the simplify we do not use register addr at all. | ||
239 | * NOTE: As a firmware knows tuner type there is very small possibility | ||
240 | * there could be some tuner I2C hacks done by firmware and this may | ||
241 | * lead problems if firmware expects those bytes are used. | ||
242 | */ | ||
227 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && | 243 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && |
228 | (msg[1].flags & I2C_M_RD)) { | 244 | (msg[1].flags & I2C_M_RD)) { |
229 | if (msg[0].len > 40 || msg[1].len > 40) { | 245 | if (msg[0].len > 40 || msg[1].len > 40) { |
@@ -237,14 +253,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, | |||
237 | msg[1].len); | 253 | msg[1].len); |
238 | } else { | 254 | } else { |
239 | /* I2C */ | 255 | /* I2C */ |
240 | u8 buf[4 + msg[0].len]; | 256 | u8 buf[5 + msg[0].len]; |
241 | struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), | 257 | struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf), |
242 | buf, msg[1].len, msg[1].buf }; | 258 | buf, msg[1].len, msg[1].buf }; |
243 | buf[0] = msg[1].len; | 259 | buf[0] = msg[1].len; |
244 | buf[1] = msg[0].addr << 1; | 260 | buf[1] = msg[0].addr << 1; |
245 | buf[2] = 0x01; | 261 | buf[2] = 0x00; /* reg addr len */ |
246 | buf[3] = 0x00; | 262 | buf[3] = 0x00; /* reg addr MSB */ |
247 | memcpy(&buf[4], msg[0].buf, msg[0].len); | 263 | buf[4] = 0x00; /* reg addr LSB */ |
264 | memcpy(&buf[5], msg[0].buf, msg[0].len); | ||
248 | ret = af9035_ctrl_msg(d->udev, &req); | 265 | ret = af9035_ctrl_msg(d->udev, &req); |
249 | } | 266 | } |
250 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | 267 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { |
@@ -259,14 +276,15 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap, | |||
259 | msg[0].len - 3); | 276 | msg[0].len - 3); |
260 | } else { | 277 | } else { |
261 | /* I2C */ | 278 | /* I2C */ |
262 | u8 buf[4 + msg[0].len]; | 279 | u8 buf[5 + msg[0].len]; |
263 | struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, | 280 | struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf, |
264 | 0, NULL }; | 281 | 0, NULL }; |
265 | buf[0] = msg[0].len; | 282 | buf[0] = msg[0].len; |
266 | buf[1] = msg[0].addr << 1; | 283 | buf[1] = msg[0].addr << 1; |
267 | buf[2] = 0x01; | 284 | buf[2] = 0x00; /* reg addr len */ |
268 | buf[3] = 0x00; | 285 | buf[3] = 0x00; /* reg addr MSB */ |
269 | memcpy(&buf[4], msg[0].buf, msg[0].len); | 286 | buf[4] = 0x00; /* reg addr LSB */ |
287 | memcpy(&buf[5], msg[0].buf, msg[0].len); | ||
270 | ret = af9035_ctrl_msg(d->udev, &req); | 288 | ret = af9035_ctrl_msg(d->udev, &req); |
271 | } | 289 | } |
272 | } else { | 290 | } else { |