]>
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 | ||
23 | #include <linux/module.h> | |
24 | #include <linux/kernel.h> | |
25 | #include <linux/usb.h> | |
26 | #include <linux/i2c.h> | |
27 | #include <media/v4l2-common.h> | |
28 | #include <media/tuner.h> | |
29 | ||
30 | #include "cx231xx.h" | |
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; | |
e0d3bafd | 352 | |
84b5dbf3 MCC |
353 | /* prepare xfer_data struct */ |
354 | req_data.dev_addr = msg->addr; | |
355 | req_data.direction = msg->flags; | |
356 | req_data.saddr_len = 0; | |
357 | req_data.saddr_dat = 0; | |
358 | req_data.buf_size = 0; | |
359 | req_data.p_buffer = NULL; | |
e0d3bafd | 360 | |
84b5dbf3 MCC |
361 | /* usb send command */ |
362 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
e0d3bafd | 363 | |
84b5dbf3 | 364 | return status < 0 ? status : 0; |
e0d3bafd SD |
365 | } |
366 | ||
367 | /* | |
368 | * cx231xx_i2c_xfer() | |
369 | * the main i2c transfer function | |
370 | */ | |
371 | static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 372 | struct i2c_msg msgs[], int num) |
e0d3bafd SD |
373 | { |
374 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
375 | struct cx231xx *dev = bus->dev; | |
376 | int addr, rc, i, byte; | |
377 | ||
378 | if (num <= 0) | |
379 | return 0; | |
64fbf444 | 380 | mutex_lock(&dev->i2c_lock); |
e0d3bafd SD |
381 | for (i = 0; i < num; i++) { |
382 | ||
1134e9d1 | 383 | addr = msgs[i].addr; |
e0d3bafd | 384 | |
1134e9d1 | 385 | dprintk2(2, "%s %s addr=0x%x len=%d:", |
e0d3bafd SD |
386 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", |
387 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | |
b9255176 SD |
388 | if (!msgs[i].len) { |
389 | /* no len: check only for device presence */ | |
e0d3bafd SD |
390 | rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); |
391 | if (rc < 0) { | |
392 | dprintk2(2, " no device\n"); | |
b8383962 | 393 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd SD |
394 | return rc; |
395 | } | |
396 | ||
397 | } else if (msgs[i].flags & I2C_M_RD) { | |
398 | /* read bytes */ | |
399 | rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); | |
400 | if (i2c_debug >= 2) { | |
401 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e | 402 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
e0d3bafd SD |
403 | } |
404 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | |
84b5dbf3 | 405 | msgs[i].addr == msgs[i + 1].addr |
64fbf444 | 406 | && (msgs[i].len <= 2) && (bus->nr < 3)) { |
1134e9d1 MS |
407 | /* write bytes */ |
408 | if (i2c_debug >= 2) { | |
409 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e MS |
410 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
411 | printk(KERN_CONT "\n"); | |
1134e9d1 | 412 | } |
e0d3bafd | 413 | /* read bytes */ |
1134e9d1 MS |
414 | dprintk2(2, "plus %s %s addr=0x%x len=%d:", |
415 | (msgs[i+1].flags & I2C_M_RD) ? "read" : "write", | |
416 | i+1 == num - 1 ? "stop" : "nonstop", addr, msgs[i+1].len); | |
84b5dbf3 MCC |
417 | rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, |
418 | &msgs[i], | |
419 | &msgs[i + 1]); | |
e0d3bafd | 420 | if (i2c_debug >= 2) { |
1134e9d1 | 421 | for (byte = 0; byte < msgs[i+1].len; byte++) |
6f64eb0e | 422 | printk(KERN_CONT " %02x", msgs[i+1].buf[byte]); |
e0d3bafd | 423 | } |
84b5dbf3 | 424 | i++; |
e0d3bafd SD |
425 | } else { |
426 | /* write bytes */ | |
427 | if (i2c_debug >= 2) { | |
428 | for (byte = 0; byte < msgs[i].len; byte++) | |
6f64eb0e | 429 | printk(KERN_CONT " %02x", msgs[i].buf[byte]); |
e0d3bafd | 430 | } |
84b5dbf3 | 431 | rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]); |
e0d3bafd SD |
432 | } |
433 | if (rc < 0) | |
434 | goto err; | |
435 | if (i2c_debug >= 2) | |
6f64eb0e | 436 | printk(KERN_CONT "\n"); |
e0d3bafd | 437 | } |
64fbf444 | 438 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd | 439 | return num; |
b9255176 | 440 | err: |
e0d3bafd | 441 | dprintk2(2, " ERROR: %i\n", rc); |
64fbf444 | 442 | mutex_unlock(&dev->i2c_lock); |
e0d3bafd SD |
443 | return rc; |
444 | } | |
445 | ||
446 | /* ----------------------------------------------------------- */ | |
447 | ||
448 | /* | |
449 | * functionality() | |
450 | */ | |
451 | static u32 functionality(struct i2c_adapter *adap) | |
452 | { | |
453 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | |
454 | } | |
455 | ||
e0d3bafd | 456 | static struct i2c_algorithm cx231xx_algo = { |
84b5dbf3 | 457 | .master_xfer = cx231xx_i2c_xfer, |
e0d3bafd SD |
458 | .functionality = functionality, |
459 | }; | |
460 | ||
461 | static struct i2c_adapter cx231xx_adap_template = { | |
462 | .owner = THIS_MODULE, | |
e0d3bafd | 463 | .name = "cx231xx", |
e0d3bafd | 464 | .algo = &cx231xx_algo, |
e0d3bafd SD |
465 | }; |
466 | ||
e0d3bafd SD |
467 | /* ----------------------------------------------------------- */ |
468 | ||
469 | /* | |
470 | * i2c_devs | |
471 | * incomplete list of known devices | |
472 | */ | |
473 | static char *i2c_devs[128] = { | |
474 | [0x60 >> 1] = "colibri", | |
475 | [0x88 >> 1] = "hammerhead", | |
84b5dbf3 | 476 | [0x8e >> 1] = "CIR", |
e0d3bafd | 477 | [0x32 >> 1] = "GeminiIII", |
84b5dbf3 | 478 | [0x02 >> 1] = "Aquarius", |
e0d3bafd | 479 | [0xa0 >> 1] = "eeprom", |
3f25ffa2 MCC |
480 | [0xc0 >> 1] = "tuner", |
481 | [0xc2 >> 1] = "tuner", | |
e0d3bafd SD |
482 | }; |
483 | ||
484 | /* | |
485 | * cx231xx_do_i2c_scan() | |
486 | * check i2c address range for devices | |
487 | */ | |
7c894a3b | 488 | void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port) |
e0d3bafd SD |
489 | { |
490 | unsigned char buf; | |
491 | int i, rc; | |
7c894a3b | 492 | struct i2c_client client; |
e0d3bafd | 493 | |
7c894a3b | 494 | memset(&client, 0, sizeof(client)); |
c3c3f1ae | 495 | client.adapter = cx231xx_get_i2c_adap(dev, i2c_port); |
7c894a3b MS |
496 | |
497 | cx231xx_info(": Checking for I2C devices on port=%d ..\n", i2c_port); | |
e0d3bafd | 498 | for (i = 0; i < 128; i++) { |
7c894a3b MS |
499 | client.addr = i; |
500 | rc = i2c_master_recv(&client, &buf, 0); | |
e0d3bafd SD |
501 | if (rc < 0) |
502 | continue; | |
503 | cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", | |
84b5dbf3 MCC |
504 | dev->name, i << 1, |
505 | i2c_devs[i] ? i2c_devs[i] : "???"); | |
e0d3bafd | 506 | } |
7c894a3b MS |
507 | cx231xx_info(": Completed Checking for I2C devices on port=%d.\n", |
508 | i2c_port); | |
e0d3bafd SD |
509 | } |
510 | ||
e0d3bafd SD |
511 | /* |
512 | * cx231xx_i2c_register() | |
513 | * register i2c bus | |
514 | */ | |
515 | int cx231xx_i2c_register(struct cx231xx_i2c *bus) | |
516 | { | |
84b5dbf3 | 517 | struct cx231xx *dev = bus->dev; |
e0d3bafd | 518 | |
84b5dbf3 | 519 | BUG_ON(!dev->cx231xx_send_usb_command); |
e0d3bafd | 520 | |
23ba641a | 521 | bus->i2c_adap = cx231xx_adap_template; |
e0d3bafd SD |
522 | bus->i2c_adap.dev.parent = &dev->udev->dev; |
523 | ||
8da4f2d5 | 524 | snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr); |
e0d3bafd | 525 | |
e0d3bafd | 526 | bus->i2c_adap.algo_data = bus; |
b1196126 | 527 | i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); |
e0d3bafd SD |
528 | i2c_add_adapter(&bus->i2c_adap); |
529 | ||
e0d3bafd | 530 | if (0 == bus->i2c_rc) { |
e0d3bafd | 531 | if (i2c_scan) |
7c894a3b | 532 | cx231xx_do_i2c_scan(dev, bus->nr); |
e0d3bafd SD |
533 | } else |
534 | cx231xx_warn("%s: i2c bus %d register FAILED\n", | |
84b5dbf3 | 535 | dev->name, bus->nr); |
e0d3bafd SD |
536 | |
537 | return bus->i2c_rc; | |
538 | } | |
539 | ||
540 | /* | |
541 | * cx231xx_i2c_unregister() | |
542 | * unregister i2c_bus | |
543 | */ | |
544 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) | |
545 | { | |
546 | i2c_del_adapter(&bus->i2c_adap); | |
547 | return 0; | |
548 | } | |
c3c3f1ae MS |
549 | |
550 | struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) | |
551 | { | |
552 | switch (i2c_port) { | |
553 | case I2C_0: | |
554 | return &dev->i2c_bus[0].i2c_adap; | |
555 | case I2C_1: | |
556 | return &dev->i2c_bus[1].i2c_adap; | |
557 | case I2C_2: | |
558 | return &dev->i2c_bus[2].i2c_adap; | |
559 | case I2C_1_MUX_1: | |
560 | case I2C_1_MUX_3: | |
561 | return &dev->i2c_bus[1].i2c_adap; | |
562 | default: | |
563 | return NULL; | |
564 | } | |
565 | } | |
566 | EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap); |