diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/dvb-usb/m920x.c | 52 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/m920x.h | 28 |
2 files changed, 47 insertions, 33 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[], | |||
141 | int i, j; | 141 | int i, j; |
142 | int ret = 0; | 142 | int ret = 0; |
143 | 143 | ||
144 | if (!num) | ||
145 | return -EINVAL; | ||
146 | |||
144 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | 147 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) |
145 | return -EAGAIN; | 148 | return -EAGAIN; |
146 | 149 | ||
147 | for (i = 0; i < num; i++) { | 150 | for (i = 0; i < num; i++) { |
148 | if (msg[i].flags & I2C_M_RD) { | 151 | if (msg[i].flags & (I2C_M_NO_RD_ACK|I2C_M_IGNORE_NAK|I2C_M_TEN)) { |
149 | 152 | ret = -ENOTSUPP; | |
150 | if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr << 1) | 0x01, 0x80)) != 0) | 153 | goto unlock; |
154 | } | ||
155 | /* Send START & address/RW bit */ | ||
156 | if (!(msg[i].flags & I2C_M_NOSTART)) { | ||
157 | if ((ret = m9206_write(d->udev, M9206_I2C, (msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:00), 0x80)) != 0) | ||
151 | goto unlock; | 158 | goto unlock; |
152 | 159 | /* Should check for ack here, if we knew how. */ | |
153 | for(j = 0; j < msg[i].len; j++) { | 160 | } |
154 | if (j + 1 == msg[i].len && i + 1== num) { | 161 | if (msg[i].flags & I2C_M_RD) { |
155 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x60, &msg[i].buf[j], msg[i].len)) != 0) | 162 | for (j = 0; j < msg[i].len; j++) { |
156 | goto unlock; | 163 | /* Last byte of transaction? Send STOP, otherwise send ACK. */ |
157 | } else { | 164 | int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x01; |
158 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x21, &msg[i].buf[j], msg[i].len)) != 0) | 165 | if ((ret = m9206_read(d->udev, M9206_I2C, 0x0, 0x20|stop, &msg[i].buf[j], 1)) != 0) |
159 | goto unlock; | 166 | goto unlock; |
160 | } | ||
161 | } | 167 | } |
162 | |||
163 | } else { | 168 | } else { |
164 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].addr << 1, 0x80)) != 0) | 169 | for (j = 0; j < msg[i].len; j++) { |
165 | goto unlock; | 170 | /* Last byte of transaction? Then send STOP. */ |
166 | 171 | int stop = (i+1 == num && j+1 == msg[i].len)?0x40:0x00; | |
167 | for(j = 0; j < msg[i].len; j++) { | 172 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0) |
168 | if (j + 1 == msg[i].len && i + 1== num) { | 173 | goto unlock; |
169 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], 0x40)) != 0) | 174 | /* Should check for ack here too. */ |
170 | goto unlock; | ||
171 | |||
172 | } else { | ||
173 | if ((ret = m9206_write(d->udev, M9206_I2C, msg[i].buf[j], 0x0)) != 0) | ||
174 | goto unlock; | ||
175 | } | ||
176 | } | 175 | } |
177 | } | 176 | } |
178 | } | 177 | } |
179 | ret = num; | 178 | ret = num; |
180 | unlock: | 179 | |
180 | unlock: | ||
181 | mutex_unlock(&d->i2c_mutex); | 181 | mutex_unlock(&d->i2c_mutex); |
182 | 182 | ||
183 | return ret; | 183 | return ret; |
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h index c5ef592cbfee..7dd3db65c80e 100644 --- a/drivers/media/dvb/dvb-usb/m920x.h +++ b/drivers/media/dvb/dvb-usb/m920x.h | |||
@@ -37,13 +37,27 @@ this sequence works: | |||
37 | (0x21 in byte)* | 37 | (0x21 in byte)* |
38 | 0x60 in byte | 38 | 0x60 in byte |
39 | 39 | ||
40 | _my guess_: | 40 | Guess at API of the I2C function: |
41 | 0x80: begin i2c transfer using address. value=address<<1|(reading?1:0) | 41 | I2C operation is done one byte at a time with USB control messages. The |
42 | 0x00: write byte | 42 | index the messages is sent to is made up of a set of flags that control |
43 | 0x21: read byte, more to follow | 43 | the I2C bus state: |
44 | 0x40: write last byte of message sequence | 44 | 0x80: Send START condition. After a START condition, one would normally |
45 | 0x60: read last byte of message sequence | 45 | always send the 7-bit slave I2C address as the 7 MSB, followed by |
46 | */ | 46 | the read/write bit as the LSB. |
47 | 0x40: Send STOP condition. This should be set on the last byte of an | ||
48 | I2C transaction. | ||
49 | 0x20: Read a byte from the slave. As opposed to writing a byte to the | ||
50 | slave. The slave will normally not produce any data unless you | ||
51 | set the R/W bit to 1 when sending the slave's address after the | ||
52 | START condition. | ||
53 | 0x01: Respond with ACK, as opposed to a NACK. For a multi-byte read, | ||
54 | the master should send an ACK, that is pull SDA low during the 9th | ||
55 | clock cycle, after every byte but the last. This flags only makes | ||
56 | sense when bit 0x20 is set, indicating a read. | ||
57 | |||
58 | What any other bits might mean, or how to get the slave's ACK/NACK | ||
59 | response to a write, is unknown. | ||
60 | */ | ||
47 | 61 | ||
48 | struct m9206_state { | 62 | struct m9206_state { |
49 | u16 filters[M9206_MAX_FILTERS]; | 63 | u16 filters[M9206_MAX_FILTERS]; |