aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Pascoe <c.pascoe@itee.uq.edu.au>2007-12-15 01:31:09 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:04:03 -0500
commit5e3c5967da48b54e5d4ee528b51b565e2f7a3178 (patch)
tree8adc130fdbc521c9b383f63f70f78757b57e70c0
parentbc514710889ebb975be9e84ca9c04f698225b656 (diff)
V4L/DVB (6857): cx23885: correctly join I2C writes and reads from same address
When an I2C message specifies a write then a read from the same I2C address, we need to tell the chip to not release the bus between the message parts. Signed-off-by: Chris Pascoe <c.pascoe@itee.uq.edu.au> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r--drivers/media/video/cx23885/cx23885-i2c.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c
index 08e92df33168..20f3fb450f88 100644
--- a/drivers/media/video/cx23885/cx23885-i2c.c
+++ b/drivers/media/video/cx23885/cx23885-i2c.c
@@ -37,8 +37,10 @@ static unsigned int i2c_scan = 0;
37module_param(i2c_scan, int, 0444); 37module_param(i2c_scan, int, 0444);
38MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); 38MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
39 39
40#define dprintk(level,fmt, arg...) if (i2c_debug >= level) \ 40#define dprintk(level, fmt, arg...) do { \
41 printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg) 41 if (i2c_debug >= level) \
42 printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg); \
43 } while (0)
42 44
43#define I2C_WAIT_DELAY 32 45#define I2C_WAIT_DELAY 32
44#define I2C_WAIT_RETRY 64 46#define I2C_WAIT_RETRY 64
@@ -77,14 +79,18 @@ static int i2c_wait_done(struct i2c_adapter *i2c_adap)
77} 79}
78 80
79static int i2c_sendbytes(struct i2c_adapter *i2c_adap, 81static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
80 const struct i2c_msg *msg, int last) 82 const struct i2c_msg *msg, int joined_rlen)
81{ 83{
82 struct cx23885_i2c *bus = i2c_adap->algo_data; 84 struct cx23885_i2c *bus = i2c_adap->algo_data;
83 struct cx23885_dev *dev = bus->dev; 85 struct cx23885_dev *dev = bus->dev;
84 u32 wdata, addr, ctrl; 86 u32 wdata, addr, ctrl;
85 int retval, cnt; 87 int retval, cnt;
86 88
87 dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); 89 if (joined_rlen)
90 dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __FUNCTION__,
91 msg->len, joined_rlen);
92 else
93 dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
88 94
89 /* Deal with i2c probe functions with zero payload */ 95 /* Deal with i2c probe functions with zero payload */
90 if (msg->len == 0) { 96 if (msg->len == 0) {
@@ -107,6 +113,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
107 113
108 if (msg->len > 1) 114 if (msg->len > 1)
109 ctrl |= I2C_NOSTOP | I2C_EXTEND; 115 ctrl |= I2C_NOSTOP | I2C_EXTEND;
116 else if (joined_rlen)
117 ctrl |= I2C_NOSTOP;
110 118
111 cx_write(bus->reg_addr, addr); 119 cx_write(bus->reg_addr, addr);
112 cx_write(bus->reg_wdata, wdata); 120 cx_write(bus->reg_wdata, wdata);
@@ -130,6 +138,8 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
130 138
131 if (cnt < msg->len - 1) 139 if (cnt < msg->len - 1)
132 ctrl |= I2C_NOSTOP | I2C_EXTEND; 140 ctrl |= I2C_NOSTOP | I2C_EXTEND;
141 else if (joined_rlen)
142 ctrl |= I2C_NOSTOP;
133 143
134 cx_write(bus->reg_addr, addr); 144 cx_write(bus->reg_addr, addr);
135 cx_write(bus->reg_wdata, wdata); 145 cx_write(bus->reg_wdata, wdata);
@@ -151,19 +161,22 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
151 eio: 161 eio:
152 retval = -EIO; 162 retval = -EIO;
153 err: 163 err:
154 printk(" ERR: %d\n", retval); 164 if (i2c_debug)
165 printk(" ERR: %d\n", retval);
155 return retval; 166 return retval;
156} 167}
157 168
158static int i2c_readbytes(struct i2c_adapter *i2c_adap, 169static int i2c_readbytes(struct i2c_adapter *i2c_adap,
159 const struct i2c_msg *msg, int last) 170 const struct i2c_msg *msg, int joined)
160{ 171{
161 struct cx23885_i2c *bus = i2c_adap->algo_data; 172 struct cx23885_i2c *bus = i2c_adap->algo_data;
162 struct cx23885_dev *dev = bus->dev; 173 struct cx23885_dev *dev = bus->dev;
163 u32 ctrl, cnt; 174 u32 ctrl, cnt;
164 int retval; 175 int retval;
165 176
166 dprintk(1, "%s(msg->len=%d, last=%d)\n", __FUNCTION__, msg->len, last); 177
178 if (i2c_debug && !joined)
179 dprintk(1, "%s(msg->len=%d)\n", __FUNCTION__, msg->len);
167 180
168 /* Deal with i2c probe functions with zero payload */ 181 /* Deal with i2c probe functions with zero payload */
169 if (msg->len == 0) { 182 if (msg->len == 0) {
@@ -179,8 +192,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
179 return 0; 192 return 0;
180 } 193 }
181 194
182 if (i2c_debug) 195 if (i2c_debug) {
183 printk(" <R %02x", (msg->addr << 1) + 1); 196 if (joined)
197 printk(" R");
198 else
199 printk(" <R %02x", (msg->addr << 1) + 1);
200 }
184 201
185 for(cnt = 0; cnt < msg->len; cnt++) { 202 for(cnt = 0; cnt < msg->len; cnt++) {
186 203
@@ -209,7 +226,8 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap,
209 eio: 226 eio:
210 retval = -EIO; 227 retval = -EIO;
211 err: 228 err:
212 printk(" ERR: %d\n", retval); 229 if (i2c_debug)
230 printk(" ERR: %d\n", retval);
213 return retval; 231 return retval;
214} 232}
215 233
@@ -227,15 +245,22 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap,
227 __FUNCTION__, num, msgs[i].addr, msgs[i].len); 245 __FUNCTION__, num, msgs[i].addr, msgs[i].len);
228 if (msgs[i].flags & I2C_M_RD) { 246 if (msgs[i].flags & I2C_M_RD) {
229 /* read */ 247 /* read */
230 retval = i2c_readbytes(i2c_adap, &msgs[i], i+1 == num); 248 retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
249 } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
250 msgs[i].addr == msgs[i + 1].addr) {
251 /* write then read from same address */
252 retval = i2c_sendbytes(i2c_adap, &msgs[i],
253 msgs[i + 1].len);
231 if (retval < 0) 254 if (retval < 0)
232 goto err; 255 goto err;
256 i++;
257 retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
233 } else { 258 } else {
234 /* write */ 259 /* write */
235 retval = i2c_sendbytes(i2c_adap, &msgs[i], i+1 == num); 260 retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
236 if (retval < 0)
237 goto err;
238 } 261 }
262 if (retval < 0)
263 goto err;
239 } 264 }
240 return num; 265 return num;
241 266