summaryrefslogtreecommitdiff
path: root/drivers/media/dvb/dvb-usb/m920x.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2007-03-05 23:55:00 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-04-27 15:44:42 -0300
commitd40860f8e2edb31196f4233d3691704d313dbdd6 (patch)
tree033a5354d255a7090aadbf1c134a392aaf6409bc /drivers/media/dvb/dvb-usb/m920x.c
parent634bc48da766a9817e55e7dbd9909a6b26567e92 (diff)
V4L/DVB (5427): M920x: Improve I2C operations
Write some better documentation about what might be known about how the m920x I2C works, since a datasheet is lacking. The I2C xfer function should now handle more types of I2C transactions than it could before. Those it can't, will return error codes instead of being executed incorrectly. Multi-byte reads were not being done correctly, which should be fixed. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/dvb-usb/m920x.c')
-rw-r--r--drivers/media/dvb/dvb-usb/m920x.c52
1 files changed, 26 insertions, 26 deletions
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index 621819f6597a..08469ccabb72 100644
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ b/drivers/media/dvb/dvb-usb/m920x.c
@@ -141,43 +141,43 @@ static int m9206_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int i, j;
int ret = 0;
+ if (!num)
+ return -EINVAL;
+
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
for (i = 0; i < num; i++) {
- if (msg[i].flags & I2C_M_RD) {
-
- if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr << 1) | 0x01, 0x80)) != 0)
+ if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN)) {
+ ret = -ENOTSUPP;
+ goto unlock;
+ }
+ /* Send START & address/RW bit */
+ if (!(msg[i].flags & I2C_M_NOSTART)) {
+ if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:00), 0x80)) != 0)
goto unlock;
-
- for(j = 0; j < msg[i].len; j++) {
- if (j + 1 == msg[i].len && i + 1== num) {
- if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, &msg[i].buf[j], msg[i].len)) != 0)
- goto unlock;
- } else {
- if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x21, &msg[i].buf[j], msg[i].len)) != 0)
- goto unlock;
- }
+ /* Should check for ack here, if we knew how. */
+ }
+ if (msg[i].flags & I2C_M_RD) {
+ for (j = 0; j < msg[i].len; j++) {
+ /* Last byte of transaction? Send STOP, otherwise send ACK. */
+ int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01;
+ if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0)
+ goto unlock;
}
-
} else {
- if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr << 1, 0x80)) != 0)
- goto unlock;
-
- for(j = 0; j < msg[i].len; j++) {
- if (j + 1 == msg[i].len && i + 1== num) {
- if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], 0x40)) != 0)
- goto unlock;
-
- } else {
- if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], 0x0)) != 0)
- goto unlock;
- }
+ for (j = 0; j < msg[i].len; j++) {
+ /* Last byte of transaction? Then send STOP. */
+ int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00;
+ if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
+ goto unlock;
+ /* Should check for ack here too. */
}
}
}
ret = num;
- unlock:
+
+unlock:
mutex_unlock(&d->i2c_mutex);
return ret;