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> | |
84b5dbf3 MCC |
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) { \ | |
45 | printk(fmt, ##args); \ | |
46 | } \ | |
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 | ||
e0d3bafd SD |
57 | /* |
58 | * cx231xx_i2c_send_bytes() | |
59 | */ | |
60 | int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 61 | const struct i2c_msg *msg) |
e0d3bafd SD |
62 | { |
63 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
64 | struct cx231xx *dev = bus->dev; | |
84b5dbf3 MCC |
65 | struct cx231xx_i2c_xfer_data req_data; |
66 | int status = 0; | |
67 | u16 size = 0; | |
68 | u8 loop = 0; | |
69 | u8 saddr_len = 1; | |
70 | u8 *buf_ptr = NULL; | |
71 | u16 saddr = 0; | |
72 | u8 need_gpio = 0; | |
73 | ||
74 | if ((bus->nr == 1) && (msg->addr == 0x61) | |
75 | && (dev->tuner_type == TUNER_XC5000)) { | |
76 | ||
77 | size = msg->len; | |
78 | ||
79 | if (size == 2) { /* register write sub addr */ | |
80 | ||
81 | /* Just writing sub address will cause problem to XC5000 | |
82 | So ignore the request */ | |
83 | return 0; | |
84 | ||
85 | } else if (size == 4) { /* register write with sub addr */ | |
86 | ||
87 | if (msg->len >= 2) | |
88 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
89 | else if (msg->len == 1) | |
90 | saddr = msg->buf[0]; | |
91 | ||
92 | switch (saddr) { | |
93 | case 0x0000: /* start tuner calibration mode */ | |
94 | need_gpio = 1; | |
95 | dev->xc_fw_load_done = 1; /* FW Loading is done */ | |
96 | break; | |
97 | case 0x000D: /* Set signal source */ | |
98 | case 0x0001: /* Set TV standard - Video */ | |
99 | case 0x0002: /* Set TV standard - Audio */ | |
100 | case 0x0003: /* Set RF Frequency */ | |
101 | need_gpio = 1; | |
102 | break; | |
103 | default: | |
104 | if (dev->xc_fw_load_done) | |
105 | need_gpio = 1; | |
106 | break; | |
107 | } | |
108 | ||
109 | if (need_gpio) { | |
110 | dprintk1(1, | |
111 | " GPIO W R I T E : addr 0x%x, len %d, saddr 0x%x\n", | |
112 | msg->addr, msg->len, saddr); | |
113 | ||
114 | return dev->cx231xx_gpio_i2c_write(dev, | |
115 | msg->addr, | |
116 | msg->buf, | |
117 | msg->len); | |
118 | } | |
119 | ||
120 | } | |
121 | ||
122 | /* special case for Xc5000 tuner case */ | |
123 | saddr_len = 1; | |
124 | ||
125 | /* adjust the length to correct length */ | |
126 | size -= saddr_len; | |
127 | buf_ptr = (u8 *) (msg->buf + 1); | |
128 | ||
129 | do { | |
130 | /* prepare xfer_data struct */ | |
131 | req_data.dev_addr = msg->addr; | |
132 | req_data.direction = msg->flags; | |
133 | req_data.saddr_len = saddr_len; | |
134 | req_data.saddr_dat = msg->buf[0]; | |
135 | req_data.buf_size = size > 16 ? 16 : size; | |
136 | req_data.p_buffer = (u8 *) (buf_ptr + loop * 16); | |
137 | ||
138 | bus->i2c_nostop = (size > 16) ? 1 : 0; | |
139 | bus->i2c_reserve = (loop == 0) ? 0 : 1; | |
140 | ||
141 | /* usb send command */ | |
142 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
143 | loop++; | |
144 | ||
145 | if (size >= 16) | |
146 | size -= 16; | |
147 | else | |
148 | size = 0; | |
149 | ||
150 | } while (size > 0); | |
151 | ||
152 | bus->i2c_nostop = 0; | |
153 | bus->i2c_reserve = 0; | |
154 | ||
155 | } else { /* regular case */ | |
156 | ||
157 | /* prepare xfer_data struct */ | |
158 | req_data.dev_addr = msg->addr; | |
159 | req_data.direction = msg->flags; | |
160 | req_data.saddr_len = 0; | |
161 | req_data.saddr_dat = 0; | |
162 | req_data.buf_size = msg->len; | |
163 | req_data.p_buffer = msg->buf; | |
164 | ||
165 | /* usb send command */ | |
166 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
167 | } | |
168 | ||
169 | return status < 0 ? status : 0; | |
e0d3bafd SD |
170 | } |
171 | ||
172 | /* | |
173 | * cx231xx_i2c_recv_bytes() | |
174 | * read a byte from the i2c device | |
175 | */ | |
176 | static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 177 | const struct i2c_msg *msg) |
e0d3bafd | 178 | { |
84b5dbf3 | 179 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 180 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
181 | struct cx231xx_i2c_xfer_data req_data; |
182 | int status = 0; | |
183 | u16 saddr = 0; | |
184 | u8 need_gpio = 0; | |
185 | ||
186 | if ((bus->nr == 1) && (msg->addr == 0x61) | |
187 | && dev->tuner_type == TUNER_XC5000) { | |
188 | ||
189 | if (msg->len == 2) | |
190 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
191 | else if (msg->len == 1) | |
192 | saddr = msg->buf[0]; | |
193 | ||
194 | if (dev->xc_fw_load_done) { | |
195 | ||
196 | switch (saddr) { | |
197 | case 0x0009: /* BUSY check */ | |
198 | dprintk1(1, | |
199 | " GPIO R E A D : Special case BUSY check \n"); | |
200 | /* Try to read BUSY register, just set it to zero */ | |
201 | msg->buf[0] = 0; | |
202 | if (msg->len == 2) | |
203 | msg->buf[1] = 0; | |
204 | return 0; | |
205 | case 0x0004: /* read Lock status */ | |
206 | need_gpio = 1; | |
207 | break; | |
208 | ||
209 | } | |
210 | ||
211 | if (need_gpio) { | |
212 | /* this is a special case to handle Xceive tuner clock stretch issue | |
213 | with gpio based I2C interface */ | |
214 | dprintk1(1, | |
215 | " GPIO R E A D : addr 0x%x, len %d, saddr 0x%x\n", | |
216 | msg->addr, msg->len, | |
217 | msg->buf[0] << 8 | msg->buf[1]); | |
218 | status = | |
219 | dev->cx231xx_gpio_i2c_write(dev, msg->addr, | |
220 | msg->buf, | |
221 | msg->len); | |
222 | status = | |
223 | dev->cx231xx_gpio_i2c_read(dev, msg->addr, | |
224 | msg->buf, | |
225 | msg->len); | |
226 | return status; | |
227 | } | |
228 | } | |
229 | ||
230 | /* prepare xfer_data struct */ | |
231 | req_data.dev_addr = msg->addr; | |
232 | req_data.direction = msg->flags; | |
233 | req_data.saddr_len = msg->len; | |
234 | req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; | |
235 | req_data.buf_size = msg->len; | |
236 | req_data.p_buffer = msg->buf; | |
237 | ||
238 | /* usb send command */ | |
239 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
240 | ||
241 | } else { | |
242 | ||
243 | /* prepare xfer_data struct */ | |
244 | req_data.dev_addr = msg->addr; | |
245 | req_data.direction = msg->flags; | |
246 | req_data.saddr_len = 0; | |
247 | req_data.saddr_dat = 0; | |
248 | req_data.buf_size = msg->len; | |
249 | req_data.p_buffer = msg->buf; | |
250 | ||
251 | /* usb send command */ | |
252 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
253 | } | |
254 | ||
255 | return status < 0 ? status : 0; | |
e0d3bafd SD |
256 | } |
257 | ||
258 | /* | |
259 | * cx231xx_i2c_recv_bytes_with_saddr() | |
260 | * read a byte from the i2c device | |
261 | */ | |
262 | static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, | |
84b5dbf3 MCC |
263 | const struct i2c_msg *msg1, |
264 | const struct i2c_msg *msg2) | |
e0d3bafd | 265 | { |
84b5dbf3 | 266 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 267 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
268 | struct cx231xx_i2c_xfer_data req_data; |
269 | int status = 0; | |
270 | u16 saddr = 0; | |
271 | u8 need_gpio = 0; | |
272 | ||
273 | if (msg1->len == 2) | |
274 | saddr = msg1->buf[0] << 8 | msg1->buf[1]; | |
275 | else if (msg1->len == 1) | |
276 | saddr = msg1->buf[0]; | |
277 | ||
278 | if ((bus->nr == 1) && (msg2->addr == 0x61) | |
279 | && dev->tuner_type == TUNER_XC5000) { | |
280 | ||
281 | if ((msg2->len < 16)) { | |
282 | ||
283 | dprintk1(1, | |
284 | " i2c_read : addr 0x%x, len %d, subaddr 0x%x, leng %d\n", | |
285 | msg2->addr, msg2->len, saddr, msg1->len); | |
286 | ||
287 | switch (saddr) { | |
288 | case 0x0008: /* read FW load status */ | |
289 | need_gpio = 1; | |
290 | break; | |
291 | case 0x0004: /* read Lock status */ | |
292 | need_gpio = 1; | |
293 | break; | |
294 | } | |
295 | ||
296 | if (need_gpio) { | |
297 | status = | |
298 | dev->cx231xx_gpio_i2c_write(dev, msg1->addr, | |
299 | msg1->buf, | |
300 | msg1->len); | |
301 | status = | |
302 | dev->cx231xx_gpio_i2c_read(dev, msg2->addr, | |
303 | msg2->buf, | |
304 | msg2->len); | |
305 | return status; | |
306 | } | |
307 | } | |
308 | } | |
309 | ||
310 | /* prepare xfer_data struct */ | |
311 | req_data.dev_addr = msg2->addr; | |
312 | req_data.direction = msg2->flags; | |
313 | req_data.saddr_len = msg1->len; | |
314 | req_data.saddr_dat = saddr; | |
315 | req_data.buf_size = msg2->len; | |
316 | req_data.p_buffer = msg2->buf; | |
317 | ||
318 | /* usb send command */ | |
319 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
320 | ||
321 | return status < 0 ? status : 0; | |
e0d3bafd SD |
322 | } |
323 | ||
324 | /* | |
325 | * cx231xx_i2c_check_for_device() | |
326 | * check if there is a i2c_device at the supplied address | |
327 | */ | |
328 | static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 329 | const struct i2c_msg *msg) |
e0d3bafd | 330 | { |
84b5dbf3 | 331 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 332 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
333 | struct cx231xx_i2c_xfer_data req_data; |
334 | int status = 0; | |
e0d3bafd | 335 | |
84b5dbf3 MCC |
336 | /* prepare xfer_data struct */ |
337 | req_data.dev_addr = msg->addr; | |
338 | req_data.direction = msg->flags; | |
339 | req_data.saddr_len = 0; | |
340 | req_data.saddr_dat = 0; | |
341 | req_data.buf_size = 0; | |
342 | req_data.p_buffer = NULL; | |
e0d3bafd | 343 | |
84b5dbf3 MCC |
344 | /* usb send command */ |
345 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
e0d3bafd | 346 | |
84b5dbf3 | 347 | return status < 0 ? status : 0; |
e0d3bafd SD |
348 | } |
349 | ||
350 | /* | |
351 | * cx231xx_i2c_xfer() | |
352 | * the main i2c transfer function | |
353 | */ | |
354 | static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 355 | struct i2c_msg msgs[], int num) |
e0d3bafd SD |
356 | { |
357 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
358 | struct cx231xx *dev = bus->dev; | |
359 | int addr, rc, i, byte; | |
360 | ||
361 | if (num <= 0) | |
362 | return 0; | |
363 | ||
364 | for (i = 0; i < num; i++) { | |
365 | ||
366 | addr = msgs[i].addr >> 1; | |
367 | ||
368 | dprintk2(2, "%s %s addr=%x len=%d:", | |
369 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", | |
370 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | |
84b5dbf3 | 371 | if (!msgs[i].len) { /* no len: check only for device presence */ |
e0d3bafd SD |
372 | rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); |
373 | if (rc < 0) { | |
374 | dprintk2(2, " no device\n"); | |
375 | return rc; | |
376 | } | |
377 | ||
378 | } else if (msgs[i].flags & I2C_M_RD) { | |
379 | /* read bytes */ | |
380 | rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]); | |
381 | if (i2c_debug >= 2) { | |
382 | for (byte = 0; byte < msgs[i].len; byte++) | |
383 | printk(" %02x", msgs[i].buf[byte]); | |
384 | } | |
385 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | |
84b5dbf3 MCC |
386 | msgs[i].addr == msgs[i + 1].addr |
387 | && (msgs[i].len <= 2) && (bus->nr < 2)) { | |
e0d3bafd | 388 | /* read bytes */ |
84b5dbf3 MCC |
389 | rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, |
390 | &msgs[i], | |
391 | &msgs[i + 1]); | |
e0d3bafd SD |
392 | if (i2c_debug >= 2) { |
393 | for (byte = 0; byte < msgs[i].len; byte++) | |
394 | printk(" %02x", msgs[i].buf[byte]); | |
395 | } | |
84b5dbf3 | 396 | i++; |
e0d3bafd SD |
397 | } else { |
398 | /* write bytes */ | |
399 | if (i2c_debug >= 2) { | |
400 | for (byte = 0; byte < msgs[i].len; byte++) | |
401 | printk(" %02x", msgs[i].buf[byte]); | |
402 | } | |
84b5dbf3 | 403 | rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]); |
e0d3bafd SD |
404 | } |
405 | if (rc < 0) | |
406 | goto err; | |
407 | if (i2c_debug >= 2) | |
408 | printk("\n"); | |
409 | } | |
410 | ||
411 | return num; | |
84b5dbf3 | 412 | err: |
e0d3bafd SD |
413 | dprintk2(2, " ERROR: %i\n", rc); |
414 | return rc; | |
415 | } | |
416 | ||
417 | /* ----------------------------------------------------------- */ | |
418 | ||
419 | /* | |
420 | * functionality() | |
421 | */ | |
422 | static u32 functionality(struct i2c_adapter *adap) | |
423 | { | |
424 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; | |
425 | } | |
426 | ||
427 | /* | |
428 | * attach_inform() | |
429 | * gets called when a device attaches to the i2c bus | |
430 | * does some basic configuration | |
431 | */ | |
432 | static int attach_inform(struct i2c_client *client) | |
433 | { | |
84b5dbf3 | 434 | struct cx231xx_i2c *bus = i2c_get_adapdata(client->adapter); |
e0d3bafd SD |
435 | struct cx231xx *dev = bus->dev; |
436 | ||
437 | switch (client->addr << 1) { | |
438 | case 0x32: | |
439 | dprintk1(1, "attach_inform: Geminit III detected.\n"); | |
440 | break; | |
441 | case 0x02: | |
442 | dprintk1(1, "attach_inform: Acquarius detected.\n"); | |
443 | break; | |
444 | case 0xa0: | |
445 | dprintk1(1, "attach_inform: eeprom detected.\n"); | |
446 | break; | |
447 | case 0x60: | |
84b5dbf3 | 448 | dprintk1(1, "attach_inform: Colibri detected.\n"); |
e0d3bafd | 449 | break; |
84b5dbf3 MCC |
450 | case 0x8e: |
451 | { | |
452 | struct IR_i2c *ir = i2c_get_clientdata(client); | |
453 | dprintk1(1, "attach_inform: IR detected (%s).\n", | |
454 | ir->phys); | |
455 | cx231xx_set_ir(dev, ir); | |
456 | break; | |
457 | } | |
e0d3bafd SD |
458 | case 0x80: |
459 | case 0x88: | |
460 | dprintk1(1, "attach_inform: Hammerhead detected.\n"); | |
461 | break; | |
462 | ||
463 | default: | |
464 | if (!dev->tuner_addr) | |
465 | dev->tuner_addr = client->addr; | |
466 | ||
467 | dprintk1(1, "attach inform: detected I2C address %x\n", | |
84b5dbf3 | 468 | client->addr << 1); |
e0d3bafd SD |
469 | } |
470 | ||
471 | return 0; | |
472 | } | |
473 | ||
474 | static int detach_inform(struct i2c_client *client) | |
475 | { | |
476 | dprintk1(1, "i2c detach [client=%s]\n", client->name); | |
477 | return 0; | |
478 | } | |
479 | ||
e0d3bafd | 480 | static struct i2c_algorithm cx231xx_algo = { |
84b5dbf3 | 481 | .master_xfer = cx231xx_i2c_xfer, |
e0d3bafd SD |
482 | .functionality = functionality, |
483 | }; | |
484 | ||
485 | static struct i2c_adapter cx231xx_adap_template = { | |
486 | .owner = THIS_MODULE, | |
487 | .class = I2C_CLASS_TV_ANALOG, | |
488 | .name = "cx231xx", | |
489 | .id = I2C_HW_B_CX231XX, | |
490 | .algo = &cx231xx_algo, | |
84b5dbf3 | 491 | .client_register = attach_inform, |
e0d3bafd SD |
492 | .client_unregister = detach_inform, |
493 | }; | |
494 | ||
495 | static struct i2c_client cx231xx_client_template = { | |
496 | .name = "cx231xx internal", | |
497 | }; | |
498 | ||
499 | /* ----------------------------------------------------------- */ | |
500 | ||
501 | /* | |
502 | * i2c_devs | |
503 | * incomplete list of known devices | |
504 | */ | |
505 | static char *i2c_devs[128] = { | |
506 | [0x60 >> 1] = "colibri", | |
507 | [0x88 >> 1] = "hammerhead", | |
84b5dbf3 | 508 | [0x8e >> 1] = "CIR", |
e0d3bafd | 509 | [0x32 >> 1] = "GeminiIII", |
84b5dbf3 | 510 | [0x02 >> 1] = "Aquarius", |
e0d3bafd SD |
511 | [0xa0 >> 1] = "eeprom", |
512 | [0xc0 >> 1] = "tuner/XC3028", | |
513 | [0xc2 >> 1] = "tuner/XC5000", | |
514 | }; | |
515 | ||
516 | /* | |
517 | * cx231xx_do_i2c_scan() | |
518 | * check i2c address range for devices | |
519 | */ | |
520 | void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c) | |
521 | { | |
522 | unsigned char buf; | |
523 | int i, rc; | |
524 | ||
84b5dbf3 | 525 | cx231xx_info(": Checking for I2C devices ..\n"); |
e0d3bafd SD |
526 | for (i = 0; i < 128; i++) { |
527 | c->addr = i; | |
528 | rc = i2c_master_recv(c, &buf, 0); | |
529 | if (rc < 0) | |
530 | continue; | |
531 | cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", | |
84b5dbf3 MCC |
532 | dev->name, i << 1, |
533 | i2c_devs[i] ? i2c_devs[i] : "???"); | |
e0d3bafd | 534 | } |
84b5dbf3 | 535 | cx231xx_info(": Completed Checking for I2C devices.\n"); |
e0d3bafd SD |
536 | } |
537 | ||
538 | /* | |
539 | * cx231xx_i2c_call_clients() | |
540 | * send commands to all attached i2c devices | |
541 | */ | |
84b5dbf3 MCC |
542 | void cx231xx_i2c_call_clients(struct cx231xx_i2c *bus, unsigned int cmd, |
543 | void *arg) | |
e0d3bafd SD |
544 | { |
545 | /* struct cx231xx *dev = bus->dev; */ | |
546 | ||
547 | BUG_ON(NULL == bus->i2c_adap.algo_data); | |
548 | i2c_clients_command(&bus->i2c_adap, cmd, arg); | |
549 | } | |
550 | ||
551 | /* | |
552 | * cx231xx_i2c_register() | |
553 | * register i2c bus | |
554 | */ | |
555 | int cx231xx_i2c_register(struct cx231xx_i2c *bus) | |
556 | { | |
84b5dbf3 | 557 | struct cx231xx *dev = bus->dev; |
e0d3bafd | 558 | |
84b5dbf3 | 559 | BUG_ON(!dev->cx231xx_send_usb_command); |
e0d3bafd | 560 | |
84b5dbf3 | 561 | cx231xx_info("%s(bus = %d)\n", __func__, bus->nr); |
e0d3bafd | 562 | |
84b5dbf3 MCC |
563 | memcpy(&bus->i2c_adap, &cx231xx_adap_template, sizeof(bus->i2c_adap)); |
564 | memcpy(&bus->i2c_algo, &cx231xx_algo, sizeof(bus->i2c_algo)); | |
e0d3bafd SD |
565 | memcpy(&bus->i2c_client, &cx231xx_client_template, |
566 | sizeof(bus->i2c_client)); | |
567 | ||
568 | bus->i2c_adap.dev.parent = &dev->udev->dev; | |
569 | ||
84b5dbf3 | 570 | strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name)); |
e0d3bafd SD |
571 | |
572 | bus->i2c_algo.data = bus; | |
573 | bus->i2c_adap.algo_data = bus; | |
574 | i2c_set_adapdata(&bus->i2c_adap, bus); | |
575 | i2c_add_adapter(&bus->i2c_adap); | |
576 | ||
577 | bus->i2c_client.adapter = &bus->i2c_adap; | |
578 | ||
579 | if (0 == bus->i2c_rc) { | |
580 | cx231xx_info("%s: i2c bus %d registered\n", dev->name, bus->nr); | |
581 | if (i2c_scan) | |
582 | cx231xx_do_i2c_scan(dev, &bus->i2c_client); | |
583 | } else | |
584 | cx231xx_warn("%s: i2c bus %d register FAILED\n", | |
84b5dbf3 | 585 | dev->name, bus->nr); |
e0d3bafd SD |
586 | |
587 | return bus->i2c_rc; | |
588 | } | |
589 | ||
590 | /* | |
591 | * cx231xx_i2c_unregister() | |
592 | * unregister i2c_bus | |
593 | */ | |
594 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) | |
595 | { | |
596 | i2c_del_adapter(&bus->i2c_adap); | |
597 | return 0; | |
598 | } |