diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
index 621819f6597aec5fa45f3003f16dcab5b15fe368..08469ccabb72a85d8fb2e373c06c54033ffbf215 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;
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
index c5ef592cbfee41606e0380dc9bde3a0a6e73e908..7dd3db65c80eeba1a573be349bd9b6675fa4c968 100644
--- a/drivers/media/dvb/dvb-usb/m920x.h
+++ b/drivers/media/dvb/dvb-usb/m920x.h
@@ -37,13 +37,27 @@ this sequence works:
 (0x21 in byte)*
 0x60 in byte
 
-_my guess_:
-0x80: begin i2c transfer using address. value=address<<1|(reading?1:0)
-0x00: write byte
-0x21: read byte, more to follow
-0x40: write last byte of message sequence
-0x60: read last byte of message sequence
- */
+Guess at API of the I2C function:
+I2C operation is done one byte at a time with USB control messages.  The
+index the messages is sent to is made up of a set of flags that control
+the I2C bus state:
+0x80:  Send START condition.  After a START condition, one would normally
+       always send the 7-bit slave I2C address as the 7 MSB, followed by
+       the read/write bit as the LSB.
+0x40:  Send STOP condition.  This should be set on the last byte of an
+       I2C transaction.
+0x20:  Read a byte from the slave.  As opposed to writing a byte to the
+       slave.  The slave will normally not produce any data unless you
+       set the R/W bit to 1 when sending the slave's address after the
+       START condition.
+0x01:  Respond with ACK, as opposed to a NACK.  For a multi-byte read,
+       the master should send an ACK, that is pull SDA low during the 9th
+       clock cycle, after every byte but the last.  This flags only makes
+       sense when bit 0x20 is set, indicating a read.
+
+What any other bits might mean, or how to get the slave's ACK/NACK
+response to a write, is unknown.
+*/
 
 struct m9206_state {
 	u16 filters[M9206_MAX_FILTERS];