]>
Commit | Line | Data |
---|---|---|
e0d3bafd SD |
1 | /* |
2 | cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices | |
3 | ||
4 | Copyright (C) 2008 <srinivasa.deevi at conexant dot com> | |
b9255176 SD |
5 | Based on em28xx driver |
6 | Based on Cx23885 driver | |
e0d3bafd SD |
7 | |
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | */ | |
22 | ||
589dadf2 | 23 | #include "cx231xx.h" |
e0d3bafd SD |
24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | |
e0d3bafd | 26 | #include <linux/i2c.h> |
15c212dd | 27 | #include <linux/i2c-mux.h> |
e0d3bafd SD |
28 | #include <media/v4l2-common.h> |
29 | #include <media/tuner.h> | |
30 | ||
e0d3bafd | 31 | |
e0d3bafd SD |
32 | /* ----------------------------------------------------------- */ |
33 | ||
34 | static unsigned int i2c_scan; | |
35 | module_param(i2c_scan, int, 0444); | |
36 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | |
37 | ||
38 | static unsigned int i2c_debug; | |
39 | module_param(i2c_debug, int, 0644); | |
40 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |
41 | ||
e0d3bafd SD |
42 | #define dprintk1(lvl, fmt, args...) \ |
43 | do { \ | |
44 | if (i2c_debug >= lvl) { \ | |
6e4f574b SD |
45 | printk(fmt, ##args); \ |
46 | } \ | |
e0d3bafd SD |
47 | } while (0) |
48 | ||
49 | #define dprintk2(lvl, fmt, args...) \ | |
50 | do { \ | |
51 | if (i2c_debug >= lvl) { \ | |
52 | printk(KERN_DEBUG "%s at %s: " fmt, \ | |
53 | dev->name, __func__ , ##args); \ | |
54 | } \ | |
55 | } while (0) | |
56 | ||
8a025348 MS |
57 | static inline int get_real_i2c_port(struct cx231xx *dev, int bus_nr) |
58 | { | |
59 | if (bus_nr == 1) | |
60 | return dev->port_3_switch_enabled ? I2C_1_MUX_3 : I2C_1_MUX_1; | |
61 | return bus_nr; | |
62 | } | |
63 | ||
3f25ffa2 MCC |
64 | static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus, |
65 | const struct i2c_msg *msg, int tuner_type) | |
66 | { | |
8a025348 MS |
67 | int i2c_port = get_real_i2c_port(dev, bus->nr); |
68 | ||
69 | if (i2c_port != dev->board.tuner_i2c_master) | |
3f25ffa2 MCC |
70 | return false; |
71 | ||
72 | if (msg->addr != dev->board.tuner_addr) | |
73 | return false; | |
74 | ||
75 | if (dev->tuner_type != tuner_type) | |
76 | return false; | |
77 | ||
78 | return true; | |
79 | } | |
80 | ||
e0d3bafd SD |
81 | /* |
82 | * cx231xx_i2c_send_bytes() | |
83 | */ | |
d4c06133 MCC |
84 | static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, |
85 | const struct i2c_msg *msg) | |
e0d3bafd SD |
86 | { |
87 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
88 | struct cx231xx *dev = bus->dev; | |
84b5dbf3 MCC |
89 | struct cx231xx_i2c_xfer_data req_data; |
90 | int status = 0; | |
91 | u16 size = 0; | |
92 | u8 loop = 0; | |
93 | u8 saddr_len = 1; | |
94 | u8 *buf_ptr = NULL; | |
95 | u16 saddr = 0; | |
96 | u8 need_gpio = 0; | |
97 | ||
3f25ffa2 | 98 | if (is_tuner(dev, bus, msg, TUNER_XC5000)) { |
84b5dbf3 MCC |
99 | size = msg->len; |
100 | ||
101 | if (size == 2) { /* register write sub addr */ | |
6e4f574b SD |
102 | /* Just writing sub address will cause problem |
103 | * to XC5000. So ignore the request */ | |
84b5dbf3 | 104 | return 0; |
84b5dbf3 | 105 | } else if (size == 4) { /* register write with sub addr */ |
84b5dbf3 MCC |
106 | if (msg->len >= 2) |
107 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
108 | else if (msg->len == 1) | |
109 | saddr = msg->buf[0]; | |
110 | ||
111 | switch (saddr) { | |
112 | case 0x0000: /* start tuner calibration mode */ | |
113 | need_gpio = 1; | |
b9255176 SD |
114 | /* FW Loading is done */ |
115 | dev->xc_fw_load_done = 1; | |
84b5dbf3 MCC |
116 | break; |
117 | case 0x000D: /* Set signal source */ | |
118 | case 0x0001: /* Set TV standard - Video */ | |
119 | case 0x0002: /* Set TV standard - Audio */ | |
120 | case 0x0003: /* Set RF Frequency */ | |
121 | need_gpio = 1; | |
122 | break; | |
123 | default: | |
124 | if (dev->xc_fw_load_done) | |
125 | need_gpio = 1; | |
126 | break; | |
127 | } | |
128 | ||
129 | if (need_gpio) { | |
130 | dprintk1(1, | |
b9255176 SD |
131 | "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n", |
132 | msg->addr, msg->len, saddr); | |
84b5dbf3 MCC |
133 | |
134 | return dev->cx231xx_gpio_i2c_write(dev, | |
135 | msg->addr, | |
136 | msg->buf, | |
137 | msg->len); | |
138 | } | |
84b5dbf3 MCC |
139 | } |
140 | ||
141 | /* special case for Xc5000 tuner case */ | |
142 | saddr_len = 1; | |
143 | ||
144 | /* adjust the length to correct length */ | |
145 | size -= saddr_len; | |
146 | buf_ptr = (u8 *) (msg->buf + 1); | |
147 | ||
148 | do { | |
149 | /* prepare xfer_data struct */ | |
150 | req_data.dev_addr = msg->addr; | |
151 | req_data.direction = msg->flags; | |
152 | req_data.saddr_len = saddr_len; | |
153 | req_data.saddr_dat = msg->buf[0]; | |
154 | req_data.buf_size = size > 16 ? 16 : size; | |
155 | req_data.p_buffer = (u8 *) (buf_ptr + loop * 16); | |
156 | ||
157 | bus->i2c_nostop = (size > 16) ? 1 : 0; | |
158 | bus->i2c_reserve = (loop == 0) ? 0 : 1; | |
159 | ||
160 | /* usb send command */ | |
161 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
162 | loop++; | |
163 | ||
164 | if (size >= 16) | |
165 | size -= 16; | |
166 | else | |
167 | size = 0; | |
168 | ||
169 | } while (size > 0); | |
170 | ||
171 | bus->i2c_nostop = 0; | |
172 | bus->i2c_reserve = 0; | |
173 | ||
174 | } else { /* regular case */ | |
175 | ||
176 | /* prepare xfer_data struct */ | |
177 | req_data.dev_addr = msg->addr; | |
178 | req_data.direction = msg->flags; | |
179 | req_data.saddr_len = 0; | |
180 | req_data.saddr_dat = 0; | |
181 | req_data.buf_size = msg->len; | |
182 | req_data.p_buffer = msg->buf; | |
183 | ||
184 | /* usb send command */ | |
185 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
186 | } | |
187 | ||
188 | return status < 0 ? status : 0; | |
e0d3bafd SD |
189 | } |
190 | ||
191 | /* | |
192 | * cx231xx_i2c_recv_bytes() | |
193 | * read a byte from the i2c device | |
194 | */ | |
195 | static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 196 | const struct i2c_msg *msg) |
e0d3bafd | 197 | { |
84b5dbf3 | 198 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 199 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
200 | struct cx231xx_i2c_xfer_data req_data; |
201 | int status = 0; | |
202 | u16 saddr = 0; | |
203 | u8 need_gpio = 0; | |
204 | ||
3f25ffa2 | 205 | if (is_tuner(dev, bus, msg, TUNER_XC5000)) { |
84b5dbf3 MCC |
206 | if (msg->len == 2) |
207 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
208 | else if (msg->len == 1) | |
209 | saddr = msg->buf[0]; | |
210 | ||
211 | if (dev->xc_fw_load_done) { | |
212 | ||
213 | switch (saddr) { | |
214 | case 0x0009: /* BUSY check */ | |
215 | dprintk1(1, | |
b9255176 SD |
216 | "GPIO R E A D: Special case BUSY check \n"); |
217 | /*Try read BUSY register, just set it to zero*/ | |
84b5dbf3 MCC |
218 | msg->buf[0] = 0; |
219 | if (msg->len == 2) | |
220 | msg->buf[1] = 0; | |
221 | return 0; | |
222 | case 0x0004: /* read Lock status */ | |
223 | need_gpio = 1; | |
224 | break; | |
225 | ||
226 | } | |
227 | ||
228 | if (need_gpio) { | |
b9255176 SD |
229 | /* this is a special case to handle Xceive tuner |
230 | clock stretch issue with gpio based I2C */ | |
231 | ||
84b5dbf3 | 232 | dprintk1(1, |
b9255176 SD |
233 | "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n", |
234 | msg->addr, msg->len, | |
235 | msg->buf[0] << 8 | msg->buf[1]); | |
236 | ||
84b5dbf3 MCC |
237 | status = |
238 | dev->cx231xx_gpio_i2c_write(dev, msg->addr, | |
239 | msg->buf, | |
240 | msg->len); | |
241 | status = | |
242 | dev->cx231xx_gpio_i2c_read(dev, msg->addr, | |
243 | msg->buf, | |
244 | msg->len); | |
245 | return status; | |
246 | } | |
247 | } | |
248 | ||
249 | /* prepare xfer_data struct */ | |
250 | req_data.dev_addr = msg->addr; | |
251 | req_data.direction = msg->flags; | |
252 | req_data.saddr_len = msg->len; | |
253 | req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; | |
254 | req_data.buf_size = msg->len; | |
255 | req_data.p_buffer = msg->buf; | |
256 | ||
257 | /* usb send command */ | |
258 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
259 | ||
260 | } else { | |
261 | ||
262 | /* prepare xfer_data struct */ | |
263 | req_data.dev_addr = msg->addr; | |
264 | req_data.direction = msg->flags; | |
265 | req_data.saddr_len = 0; | |
266 | req_data.saddr_dat = 0; | |
267 | req_data.buf_size = msg->len; | |
268 | req_data.p_buffer = msg->buf; | |
269 | ||
270 | /* usb send command */ | |
271 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
272 | } | |
273 | ||
274 | return status < 0 ? status : 0; | |
e0d3bafd SD |
275 | } |
276 | ||
277 | /* | |
278 | * cx231xx_i2c_recv_bytes_with_saddr() | |
279 | * read a byte from the i2c device | |
280 | */ | |
281 | static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, | |
84b5dbf3 MCC |
282 | const struct i2c_msg *msg1, |
283 | const struct i2c_msg *msg2) | |
e0d3bafd | 284 | { |
84b5dbf3 | 285 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 286 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
287 | struct cx231xx_i2c_xfer_data req_data; |
288 | int status = 0; | |
289 | u16 saddr = 0; | |
290 | u8 need_gpio = 0; | |
291 | ||
292 | if (msg1->len == 2) | |
293 | saddr = msg1->buf[0] << 8 | msg1->buf[1]; | |
294 | else if (msg1->len == 1) | |
295 | saddr = msg1->buf[0]; | |
296 | ||
3f25ffa2 | 297 | if (is_tuner(dev, bus, msg2, TUNER_XC5000)) { |
84b5dbf3 MCC |
298 | if ((msg2->len < 16)) { |
299 | ||
300 | dprintk1(1, | |
b9255176 SD |
301 | "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n", |
302 | msg2->addr, msg2->len, saddr, msg1->len); | |
84b5dbf3 MCC |
303 | |
304 | switch (saddr) { | |
305 | case 0x0008: /* read FW load status */ | |
306 | need_gpio = 1; | |
307 | break; | |
308 | case 0x0004: /* read Lock status */ | |
309 | need_gpio = 1; | |
310 | break; | |
311 | } | |
312 | ||
313 | if (need_gpio) { | |
314 | status = | |
315 | dev->cx231xx_gpio_i2c_write(dev, msg1->addr, | |
316 | msg1->buf, | |
317 | msg1->len); | |
318 | status = | |
319 | dev->cx231xx_gpio_i2c_read(dev, msg2->addr, | |
320 | msg2->buf, | |
321 | msg2->len); | |
322 | return status; | |
323 | } | |
324 | } | |
325 | } | |
326 | ||
327 | /* prepare xfer_data struct */ | |
328 | req_data.dev_addr = msg2->addr; | |
329 | req_data.direction = msg2->flags; | |
330 | req_data.saddr_len = msg1->len; | |
331 | req_data.saddr_dat = saddr; | |
332 | req_data.buf_size = msg2->len; | |
333 | req_data.p_buffer = msg2->buf; | |
334 | ||
335 | /* usb send command */ | |
336 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
337 | ||
338 | return status < 0 ? status : 0; | |
e0d3bafd SD |
339 | } |
340 | ||
341 | /* | |
342 | * cx231xx_i2c_check_for_device() | |
343 | * check if there is a i2c_device at the supplied address | |
344 | */ | |
345 | static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 346 | const struct i2c_msg *msg) |
e0d3bafd | 347 | { |
84b5dbf3 | 348 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 349 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
350 | struct cx231xx_i2c_xfer_data req_data; |
351 | int status = 0; | |
0d88d091 | 352 | u8 buf[1]; |
e0d3bafd | 353 | |
84b5dbf3 MCC |
354 | /* prepare xfer_data struct */ |
355 | req_data.dev_addr = msg->addr; | |
0d88d091 | 356 | req_data.direction = I2C_M_RD; |
84b5dbf3 MCC |
357 | req_data.saddr_len = 0; |
358 | req_data.saddr_dat = 0; | |
0d88d091 MS |
359 | req_data.buf_size = 1; |
360 | req_data.p_buffer = buf; | |
e0d3bafd | 361 | |
84b5dbf3 MCC |
362 | /* usb send command */ |
363 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
e0d3bafd | 364 | |
84b5dbf3 | 365 | return status < 0 ? status : 0; |
e0d3bafd SD |
366 | } |
367 | ||
368 | /* | |
369 | * cx231xx_i2c_xfer() | |
370 | * the main i2c transfer function | |
371 | */ | |
372 | static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 373 | struct i2c_msg msgs[], int num) |
e0d3bafd SD |
374 | { |
375 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
376 | struct cx231xx *dev = bus->dev; | |
377 | int addr, rc, i, byte; | |
378 | ||
379 | if (num <= 0) | |
380 | return 0; | |
64fbf444 | 381 | mutex_lock(&dev->i2c_lock); |
e0d3bafd SD |
382 | for (i = 0; i < num; i++) { |
383 | ||
1134e9d1 | 384 | addr = msgs[i].addr; |
e0d3bafd | 385 | |
1134e9d1 | 386 | dprintk2(2, "%s %s addr=0x%x len=%d:", |
e0d3bafd SD |
387 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", |
388 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | |
b9255176 SD |
389 | if (!msgs[i].len) { |
390 | /* no len: check only for device presence */ | |
e0d3bafd SD |
391 | rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); |
392 | if (rc < 0) { | |
393 | dprintk2(2, " no device\n"); | |
b8383962 | 394 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd SD |
395 | return rc; |
396 | } | |
397 | ||
398 | } else if (msgs[i].flags & I2C_M_RD) { | |
399 | /* read bytes */ | |
400 | rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); | |
401 | if (i2c_debug >= 2) { | |
402 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e | 403 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
e0d3bafd SD |
404 | } |
405 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | |
84b5dbf3 | 406 | msgs[i].addr == msgs[i + 1].addr |
64fbf444 | 407 | && (msgs[i].len <= 2) && (bus->nr < 3)) { |
1134e9d1 MS |
408 | /* write bytes */ |
409 | if (i2c_debug >= 2) { | |
410 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e MS |
411 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
412 | printk(KERN_CONT "\n"); | |
1134e9d1 | 413 | } |
e0d3bafd | 414 | /* read bytes */ |
1134e9d1 MS |
415 | dprintk2(2, "plus %s %s addr=0x%x len=%d:", |
416 | (msgs[i+1].flags & I2C_M_RD) ? "read" : "write", | |
417 | i+1 == num - 1 ? "stop" : "nonstop", addr, msgs[i+1].len); | |
84b5dbf3 MCC |
418 | rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, |
419 | &msgs[i], | |
420 | &msgs[i + 1]); | |
e0d3bafd | 421 | if (i2c_debug >= 2) { |
1134e9d1 | 422 | for (byte = 0; byte < msgs[i+1].len; byte++) |
6f64eb0e | 423 | printk(KERN_CONT " %02x", msgs[i+1].buf[byte]); |
e0d3bafd | 424 | } |
84b5dbf3 | 425 | i++; |
e0d3bafd SD |
426 | } else { |
427 | /* write bytes */ | |
428 | if (i2c_debug >= 2) { | |
429 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e | 430 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
e0d3bafd | 431 | } |
84b5dbf3 | 432 | rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]); |
e0d3bafd SD |
433 | } |
434 | if (rc < 0) | |
435 | goto err; | |
436 | if (i2c_debug >= 2) | |
6f64eb0e | 437 | printk(KERN_CONT "\n"); |
e0d3bafd | 438 | } |
64fbf444 | 439 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd | 440 | return num; |
b9255176 | 441 | err: |
e0d3bafd | 442 | dprintk2(2, " ERROR: %i\n", rc); |
64fbf444 | 443 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd SD |
444 | return rc; |
445 | } | |
446 | ||
447 | /* ----------------------------------------------------------- */ | |
448 | ||
449 | /* | |
450 | * functionality() | |
451 | */ | |
452 | static u32 functionality(struct i2c_adapter *adap) | |
453 | { | |
454 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | |
455 | } | |
456 | ||
e0d3bafd | 457 | static struct i2c_algorithm cx231xx_algo = { |
84b5dbf3 | 458 | .master_xfer = cx231xx_i2c_xfer, |
e0d3bafd SD |
459 | .functionality = functionality, |
460 | }; | |
461 | ||
462 | static struct i2c_adapter cx231xx_adap_template = { | |
463 | .owner = THIS_MODULE, | |
e0d3bafd | 464 | .name = "cx231xx", |
e0d3bafd | 465 | .algo = &cx231xx_algo, |
e0d3bafd SD |
466 | }; |
467 | ||
e0d3bafd SD |
468 | /* ----------------------------------------------------------- */ |
469 | ||
470 | /* | |
471 | * i2c_devs | |
472 | * incomplete list of known devices | |
473 | */ | |
ec2a387e MCC |
474 | static const char *i2c_devs[128] = { |
475 | [0x20 >> 1] = "demod", | |
e0d3bafd SD |
476 | [0x60 >> 1] = "colibri", |
477 | [0x88 >> 1] = "hammerhead", | |
84b5dbf3 | 478 | [0x8e >> 1] = "CIR", |
e0d3bafd | 479 | [0x32 >> 1] = "GeminiIII", |
84b5dbf3 | 480 | [0x02 >> 1] = "Aquarius", |
e0d3bafd | 481 | [0xa0 >> 1] = "eeprom", |
3f25ffa2 MCC |
482 | [0xc0 >> 1] = "tuner", |
483 | [0xc2 >> 1] = "tuner", | |
e0d3bafd SD |
484 | }; |
485 | ||
486 | /* | |
487 | * cx231xx_do_i2c_scan() | |
488 | * check i2c address range for devices | |
489 | */ | |
7c894a3b | 490 | void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port) |
e0d3bafd SD |
491 | { |
492 | unsigned char buf; | |
493 | int i, rc; | |
7c894a3b | 494 | struct i2c_client client; |
e0d3bafd | 495 | |
e4de03f2 MS |
496 | if (!i2c_scan) |
497 | return; | |
498 | ||
77e97ba2 MCC |
499 | /* Don't generate I2C errors during scan */ |
500 | dev->i2c_scan_running = true; | |
501 | ||
7c894a3b | 502 | memset(&client, 0, sizeof(client)); |
c3c3f1ae | 503 | client.adapter = cx231xx_get_i2c_adap(dev, i2c_port); |
7c894a3b | 504 | |
e0d3bafd | 505 | for (i = 0; i < 128; i++) { |
7c894a3b MS |
506 | client.addr = i; |
507 | rc = i2c_master_recv(&client, &buf, 0); | |
e0d3bafd SD |
508 | if (rc < 0) |
509 | continue; | |
336fea92 | 510 | dev_info(dev->dev, |
ac550faa MCC |
511 | "i2c scan: found device @ port %d addr 0x%x [%s]\n", |
512 | i2c_port, | |
b7085c08 MCC |
513 | i << 1, |
514 | i2c_devs[i] ? i2c_devs[i] : "???"); | |
e0d3bafd | 515 | } |
77e97ba2 MCC |
516 | |
517 | dev->i2c_scan_running = false; | |
e0d3bafd SD |
518 | } |
519 | ||
e0d3bafd SD |
520 | /* |
521 | * cx231xx_i2c_register() | |
522 | * register i2c bus | |
523 | */ | |
524 | int cx231xx_i2c_register(struct cx231xx_i2c *bus) | |
525 | { | |
84b5dbf3 | 526 | struct cx231xx *dev = bus->dev; |
e0d3bafd | 527 | |
84b5dbf3 | 528 | BUG_ON(!dev->cx231xx_send_usb_command); |
e0d3bafd | 529 | |
23ba641a | 530 | bus->i2c_adap = cx231xx_adap_template; |
336fea92 | 531 | bus->i2c_adap.dev.parent = dev->dev; |
e0d3bafd | 532 | |
8da4f2d5 | 533 | snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr); |
e0d3bafd | 534 | |
e0d3bafd | 535 | bus->i2c_adap.algo_data = bus; |
b1196126 | 536 | i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); |
e0d3bafd SD |
537 | i2c_add_adapter(&bus->i2c_adap); |
538 | ||
e4de03f2 | 539 | if (0 != bus->i2c_rc) |
336fea92 | 540 | dev_warn(dev->dev, |
b7085c08 | 541 | "i2c bus %d register FAILED\n", bus->nr); |
e0d3bafd SD |
542 | |
543 | return bus->i2c_rc; | |
544 | } | |
545 | ||
546 | /* | |
547 | * cx231xx_i2c_unregister() | |
548 | * unregister i2c_bus | |
549 | */ | |
550 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) | |
551 | { | |
552 | i2c_del_adapter(&bus->i2c_adap); | |
553 | return 0; | |
554 | } | |
c3c3f1ae | 555 | |
15c212dd MS |
556 | /* |
557 | * cx231xx_i2c_mux_select() | |
558 | * switch i2c master number 1 between port1 and port3 | |
559 | */ | |
560 | static int cx231xx_i2c_mux_select(struct i2c_adapter *adap, | |
561 | void *mux_priv, u32 chan_id) | |
562 | { | |
563 | struct cx231xx *dev = mux_priv; | |
564 | ||
565 | return cx231xx_enable_i2c_port_3(dev, chan_id); | |
566 | } | |
567 | ||
568 | int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no) | |
569 | { | |
570 | struct i2c_adapter *i2c_parent = &dev->i2c_bus[1].i2c_adap; | |
571 | /* what is the correct mux_dev? */ | |
336fea92 | 572 | struct device *mux_dev = dev->dev; |
15c212dd MS |
573 | |
574 | dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent, | |
575 | mux_dev, | |
576 | dev /* mux_priv */, | |
577 | 0, | |
578 | mux_no /* chan_id */, | |
579 | 0 /* class */, | |
580 | &cx231xx_i2c_mux_select, | |
581 | NULL); | |
582 | ||
583 | if (!dev->i2c_mux_adap[mux_no]) | |
336fea92 | 584 | dev_warn(dev->dev, |
b7085c08 | 585 | "i2c mux %d register FAILED\n", mux_no); |
15c212dd MS |
586 | |
587 | return 0; | |
588 | } | |
589 | ||
590 | void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no) | |
591 | { | |
592 | i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]); | |
593 | dev->i2c_mux_adap[mux_no] = NULL; | |
594 | } | |
595 | ||
c3c3f1ae MS |
596 | struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) |
597 | { | |
598 | switch (i2c_port) { | |
599 | case I2C_0: | |
600 | return &dev->i2c_bus[0].i2c_adap; | |
601 | case I2C_1: | |
602 | return &dev->i2c_bus[1].i2c_adap; | |
603 | case I2C_2: | |
604 | return &dev->i2c_bus[2].i2c_adap; | |
605 | case I2C_1_MUX_1: | |
15c212dd | 606 | return dev->i2c_mux_adap[0]; |
c3c3f1ae | 607 | case I2C_1_MUX_3: |
15c212dd | 608 | return dev->i2c_mux_adap[1]; |
c3c3f1ae MS |
609 | default: |
610 | return NULL; | |
611 | } | |
612 | } | |
613 | EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap); |