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