]>
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> | |
15c212dd | 27 | #include <linux/i2c-mux.h> |
e0d3bafd SD |
28 | #include <media/v4l2-common.h> |
29 | #include <media/tuner.h> | |
30 | ||
31 | #include "cx231xx.h" | |
32 | ||
e0d3bafd SD |
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 | ||
e0d3bafd SD |
43 | #define dprintk1(lvl, fmt, args...) \ |
44 | do { \ | |
45 | if (i2c_debug >= lvl) { \ | |
6e4f574b SD |
46 | printk(fmt, ##args); \ |
47 | } \ | |
e0d3bafd SD |
48 | } while (0) |
49 | ||
50 | #define dprintk2(lvl, fmt, args...) \ | |
51 | do { \ | |
52 | if (i2c_debug >= lvl) { \ | |
53 | printk(KERN_DEBUG "%s at %s: " fmt, \ | |
54 | dev->name, __func__ , ##args); \ | |
55 | } \ | |
56 | } while (0) | |
57 | ||
8a025348 MS |
58 | static inline int get_real_i2c_port(struct cx231xx *dev, int bus_nr) |
59 | { | |
60 | if (bus_nr == 1) | |
61 | return dev->port_3_switch_enabled ? I2C_1_MUX_3 : I2C_1_MUX_1; | |
62 | return bus_nr; | |
63 | } | |
64 | ||
3f25ffa2 MCC |
65 | static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus, |
66 | const struct i2c_msg *msg, int tuner_type) | |
67 | { | |
8a025348 MS |
68 | int i2c_port = get_real_i2c_port(dev, bus->nr); |
69 | ||
70 | if (i2c_port != dev->board.tuner_i2c_master) | |
3f25ffa2 MCC |
71 | return false; |
72 | ||
73 | if (msg->addr != dev->board.tuner_addr) | |
74 | return false; | |
75 | ||
76 | if (dev->tuner_type != tuner_type) | |
77 | return false; | |
78 | ||
79 | return true; | |
80 | } | |
81 | ||
e0d3bafd SD |
82 | /* |
83 | * cx231xx_i2c_send_bytes() | |
84 | */ | |
d4c06133 MCC |
85 | static int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap, |
86 | const struct i2c_msg *msg) | |
e0d3bafd SD |
87 | { |
88 | struct cx231xx_i2c *bus = i2c_adap->algo_data; | |
89 | struct cx231xx *dev = bus->dev; | |
84b5dbf3 MCC |
90 | struct cx231xx_i2c_xfer_data req_data; |
91 | int status = 0; | |
92 | u16 size = 0; | |
93 | u8 loop = 0; | |
94 | u8 saddr_len = 1; | |
95 | u8 *buf_ptr = NULL; | |
96 | u16 saddr = 0; | |
97 | u8 need_gpio = 0; | |
98 | ||
3f25ffa2 | 99 | if (is_tuner(dev, bus, msg, TUNER_XC5000)) { |
84b5dbf3 MCC |
100 | size = msg->len; |
101 | ||
102 | if (size == 2) { /* register write sub addr */ | |
6e4f574b SD |
103 | /* Just writing sub address will cause problem |
104 | * to XC5000. So ignore the request */ | |
84b5dbf3 | 105 | return 0; |
84b5dbf3 | 106 | } else if (size == 4) { /* register write with sub addr */ |
84b5dbf3 MCC |
107 | if (msg->len >= 2) |
108 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
109 | else if (msg->len == 1) | |
110 | saddr = msg->buf[0]; | |
111 | ||
112 | switch (saddr) { | |
113 | case 0x0000: /* start tuner calibration mode */ | |
114 | need_gpio = 1; | |
b9255176 SD |
115 | /* FW Loading is done */ |
116 | dev->xc_fw_load_done = 1; | |
84b5dbf3 MCC |
117 | break; |
118 | case 0x000D: /* Set signal source */ | |
119 | case 0x0001: /* Set TV standard - Video */ | |
120 | case 0x0002: /* Set TV standard - Audio */ | |
121 | case 0x0003: /* Set RF Frequency */ | |
122 | need_gpio = 1; | |
123 | break; | |
124 | default: | |
125 | if (dev->xc_fw_load_done) | |
126 | need_gpio = 1; | |
127 | break; | |
128 | } | |
129 | ||
130 | if (need_gpio) { | |
131 | dprintk1(1, | |
b9255176 SD |
132 | "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n", |
133 | msg->addr, msg->len, saddr); | |
84b5dbf3 MCC |
134 | |
135 | return dev->cx231xx_gpio_i2c_write(dev, | |
136 | msg->addr, | |
137 | msg->buf, | |
138 | msg->len); | |
139 | } | |
84b5dbf3 MCC |
140 | } |
141 | ||
142 | /* special case for Xc5000 tuner case */ | |
143 | saddr_len = 1; | |
144 | ||
145 | /* adjust the length to correct length */ | |
146 | size -= saddr_len; | |
147 | buf_ptr = (u8 *) (msg->buf + 1); | |
148 | ||
149 | do { | |
150 | /* prepare xfer_data struct */ | |
151 | req_data.dev_addr = msg->addr; | |
152 | req_data.direction = msg->flags; | |
153 | req_data.saddr_len = saddr_len; | |
154 | req_data.saddr_dat = msg->buf[0]; | |
155 | req_data.buf_size = size > 16 ? 16 : size; | |
156 | req_data.p_buffer = (u8 *) (buf_ptr + loop * 16); | |
157 | ||
158 | bus->i2c_nostop = (size > 16) ? 1 : 0; | |
159 | bus->i2c_reserve = (loop == 0) ? 0 : 1; | |
160 | ||
161 | /* usb send command */ | |
162 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
163 | loop++; | |
164 | ||
165 | if (size >= 16) | |
166 | size -= 16; | |
167 | else | |
168 | size = 0; | |
169 | ||
170 | } while (size > 0); | |
171 | ||
172 | bus->i2c_nostop = 0; | |
173 | bus->i2c_reserve = 0; | |
174 | ||
175 | } else { /* regular case */ | |
176 | ||
177 | /* prepare xfer_data struct */ | |
178 | req_data.dev_addr = msg->addr; | |
179 | req_data.direction = msg->flags; | |
180 | req_data.saddr_len = 0; | |
181 | req_data.saddr_dat = 0; | |
182 | req_data.buf_size = msg->len; | |
183 | req_data.p_buffer = msg->buf; | |
184 | ||
185 | /* usb send command */ | |
186 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
187 | } | |
188 | ||
189 | return status < 0 ? status : 0; | |
e0d3bafd SD |
190 | } |
191 | ||
192 | /* | |
193 | * cx231xx_i2c_recv_bytes() | |
194 | * read a byte from the i2c device | |
195 | */ | |
196 | static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 197 | const struct i2c_msg *msg) |
e0d3bafd | 198 | { |
84b5dbf3 | 199 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 200 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
201 | struct cx231xx_i2c_xfer_data req_data; |
202 | int status = 0; | |
203 | u16 saddr = 0; | |
204 | u8 need_gpio = 0; | |
205 | ||
3f25ffa2 | 206 | if (is_tuner(dev, bus, msg, TUNER_XC5000)) { |
84b5dbf3 MCC |
207 | if (msg->len == 2) |
208 | saddr = msg->buf[0] << 8 | msg->buf[1]; | |
209 | else if (msg->len == 1) | |
210 | saddr = msg->buf[0]; | |
211 | ||
212 | if (dev->xc_fw_load_done) { | |
213 | ||
214 | switch (saddr) { | |
215 | case 0x0009: /* BUSY check */ | |
216 | dprintk1(1, | |
b9255176 SD |
217 | "GPIO R E A D: Special case BUSY check \n"); |
218 | /*Try read BUSY register, just set it to zero*/ | |
84b5dbf3 MCC |
219 | msg->buf[0] = 0; |
220 | if (msg->len == 2) | |
221 | msg->buf[1] = 0; | |
222 | return 0; | |
223 | case 0x0004: /* read Lock status */ | |
224 | need_gpio = 1; | |
225 | break; | |
226 | ||
227 | } | |
228 | ||
229 | if (need_gpio) { | |
b9255176 SD |
230 | /* this is a special case to handle Xceive tuner |
231 | clock stretch issue with gpio based I2C */ | |
232 | ||
84b5dbf3 | 233 | dprintk1(1, |
b9255176 SD |
234 | "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n", |
235 | msg->addr, msg->len, | |
236 | msg->buf[0] << 8 | msg->buf[1]); | |
237 | ||
84b5dbf3 MCC |
238 | status = |
239 | dev->cx231xx_gpio_i2c_write(dev, msg->addr, | |
240 | msg->buf, | |
241 | msg->len); | |
242 | status = | |
243 | dev->cx231xx_gpio_i2c_read(dev, msg->addr, | |
244 | msg->buf, | |
245 | msg->len); | |
246 | return status; | |
247 | } | |
248 | } | |
249 | ||
250 | /* prepare xfer_data struct */ | |
251 | req_data.dev_addr = msg->addr; | |
252 | req_data.direction = msg->flags; | |
253 | req_data.saddr_len = msg->len; | |
254 | req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1]; | |
255 | req_data.buf_size = msg->len; | |
256 | req_data.p_buffer = msg->buf; | |
257 | ||
258 | /* usb send command */ | |
259 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
260 | ||
261 | } else { | |
262 | ||
263 | /* prepare xfer_data struct */ | |
264 | req_data.dev_addr = msg->addr; | |
265 | req_data.direction = msg->flags; | |
266 | req_data.saddr_len = 0; | |
267 | req_data.saddr_dat = 0; | |
268 | req_data.buf_size = msg->len; | |
269 | req_data.p_buffer = msg->buf; | |
270 | ||
271 | /* usb send command */ | |
272 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
273 | } | |
274 | ||
275 | return status < 0 ? status : 0; | |
e0d3bafd SD |
276 | } |
277 | ||
278 | /* | |
279 | * cx231xx_i2c_recv_bytes_with_saddr() | |
280 | * read a byte from the i2c device | |
281 | */ | |
282 | static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap, | |
84b5dbf3 MCC |
283 | const struct i2c_msg *msg1, |
284 | const struct i2c_msg *msg2) | |
e0d3bafd | 285 | { |
84b5dbf3 | 286 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 287 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
288 | struct cx231xx_i2c_xfer_data req_data; |
289 | int status = 0; | |
290 | u16 saddr = 0; | |
291 | u8 need_gpio = 0; | |
292 | ||
293 | if (msg1->len == 2) | |
294 | saddr = msg1->buf[0] << 8 | msg1->buf[1]; | |
295 | else if (msg1->len == 1) | |
296 | saddr = msg1->buf[0]; | |
297 | ||
3f25ffa2 | 298 | if (is_tuner(dev, bus, msg2, TUNER_XC5000)) { |
84b5dbf3 MCC |
299 | if ((msg2->len < 16)) { |
300 | ||
301 | dprintk1(1, | |
b9255176 SD |
302 | "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n", |
303 | msg2->addr, msg2->len, saddr, msg1->len); | |
84b5dbf3 MCC |
304 | |
305 | switch (saddr) { | |
306 | case 0x0008: /* read FW load status */ | |
307 | need_gpio = 1; | |
308 | break; | |
309 | case 0x0004: /* read Lock status */ | |
310 | need_gpio = 1; | |
311 | break; | |
312 | } | |
313 | ||
314 | if (need_gpio) { | |
315 | status = | |
316 | dev->cx231xx_gpio_i2c_write(dev, msg1->addr, | |
317 | msg1->buf, | |
318 | msg1->len); | |
319 | status = | |
320 | dev->cx231xx_gpio_i2c_read(dev, msg2->addr, | |
321 | msg2->buf, | |
322 | msg2->len); | |
323 | return status; | |
324 | } | |
325 | } | |
326 | } | |
327 | ||
328 | /* prepare xfer_data struct */ | |
329 | req_data.dev_addr = msg2->addr; | |
330 | req_data.direction = msg2->flags; | |
331 | req_data.saddr_len = msg1->len; | |
332 | req_data.saddr_dat = saddr; | |
333 | req_data.buf_size = msg2->len; | |
334 | req_data.p_buffer = msg2->buf; | |
335 | ||
336 | /* usb send command */ | |
337 | status = dev->cx231xx_send_usb_command(bus, &req_data); | |
338 | ||
339 | return status < 0 ? status : 0; | |
e0d3bafd SD |
340 | } |
341 | ||
342 | /* | |
343 | * cx231xx_i2c_check_for_device() | |
344 | * check if there is a i2c_device at the supplied address | |
345 | */ | |
346 | static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap, | |
84b5dbf3 | 347 | const struct i2c_msg *msg) |
e0d3bafd | 348 | { |
84b5dbf3 | 349 | struct cx231xx_i2c *bus = i2c_adap->algo_data; |
e0d3bafd | 350 | struct cx231xx *dev = bus->dev; |
84b5dbf3 MCC |
351 | struct cx231xx_i2c_xfer_data req_data; |
352 | int status = 0; | |
e0d3bafd | 353 | |
84b5dbf3 MCC |
354 | /* prepare xfer_data struct */ |
355 | req_data.dev_addr = msg->addr; | |
356 | req_data.direction = msg->flags; | |
357 | req_data.saddr_len = 0; | |
358 | req_data.saddr_dat = 0; | |
359 | req_data.buf_size = 0; | |
360 | req_data.p_buffer = NULL; | |
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 | */ | |
474 | static char *i2c_devs[128] = { | |
475 | [0x60 >> 1] = "colibri", | |
476 | [0x88 >> 1] = "hammerhead", | |
84b5dbf3 | 477 | [0x8e >> 1] = "CIR", |
e0d3bafd | 478 | [0x32 >> 1] = "GeminiIII", |
84b5dbf3 | 479 | [0x02 >> 1] = "Aquarius", |
e0d3bafd | 480 | [0xa0 >> 1] = "eeprom", |
3f25ffa2 MCC |
481 | [0xc0 >> 1] = "tuner", |
482 | [0xc2 >> 1] = "tuner", | |
e0d3bafd SD |
483 | }; |
484 | ||
485 | /* | |
486 | * cx231xx_do_i2c_scan() | |
487 | * check i2c address range for devices | |
488 | */ | |
7c894a3b | 489 | void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port) |
e0d3bafd SD |
490 | { |
491 | unsigned char buf; | |
492 | int i, rc; | |
7c894a3b | 493 | struct i2c_client client; |
e0d3bafd | 494 | |
e4de03f2 MS |
495 | if (!i2c_scan) |
496 | return; | |
497 | ||
7c894a3b | 498 | memset(&client, 0, sizeof(client)); |
c3c3f1ae | 499 | client.adapter = cx231xx_get_i2c_adap(dev, i2c_port); |
7c894a3b MS |
500 | |
501 | cx231xx_info(": Checking for I2C devices on port=%d ..\n", i2c_port); | |
e0d3bafd | 502 | for (i = 0; i < 128; i++) { |
7c894a3b MS |
503 | client.addr = i; |
504 | rc = i2c_master_recv(&client, &buf, 0); | |
e0d3bafd SD |
505 | if (rc < 0) |
506 | continue; | |
507 | cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n", | |
84b5dbf3 MCC |
508 | dev->name, i << 1, |
509 | i2c_devs[i] ? i2c_devs[i] : "???"); | |
e0d3bafd | 510 | } |
7c894a3b MS |
511 | cx231xx_info(": Completed Checking for I2C devices on port=%d.\n", |
512 | i2c_port); | |
e0d3bafd SD |
513 | } |
514 | ||
e0d3bafd SD |
515 | /* |
516 | * cx231xx_i2c_register() | |
517 | * register i2c bus | |
518 | */ | |
519 | int cx231xx_i2c_register(struct cx231xx_i2c *bus) | |
520 | { | |
84b5dbf3 | 521 | struct cx231xx *dev = bus->dev; |
e0d3bafd | 522 | |
84b5dbf3 | 523 | BUG_ON(!dev->cx231xx_send_usb_command); |
e0d3bafd | 524 | |
23ba641a | 525 | bus->i2c_adap = cx231xx_adap_template; |
e0d3bafd SD |
526 | bus->i2c_adap.dev.parent = &dev->udev->dev; |
527 | ||
8da4f2d5 | 528 | snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr); |
e0d3bafd | 529 | |
e0d3bafd | 530 | bus->i2c_adap.algo_data = bus; |
b1196126 | 531 | i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev); |
e0d3bafd SD |
532 | i2c_add_adapter(&bus->i2c_adap); |
533 | ||
e4de03f2 | 534 | if (0 != bus->i2c_rc) |
e0d3bafd | 535 | cx231xx_warn("%s: i2c bus %d register FAILED\n", |
84b5dbf3 | 536 | dev->name, bus->nr); |
e0d3bafd SD |
537 | |
538 | return bus->i2c_rc; | |
539 | } | |
540 | ||
541 | /* | |
542 | * cx231xx_i2c_unregister() | |
543 | * unregister i2c_bus | |
544 | */ | |
545 | int cx231xx_i2c_unregister(struct cx231xx_i2c *bus) | |
546 | { | |
547 | i2c_del_adapter(&bus->i2c_adap); | |
548 | return 0; | |
549 | } | |
c3c3f1ae | 550 | |
15c212dd MS |
551 | /* |
552 | * cx231xx_i2c_mux_select() | |
553 | * switch i2c master number 1 between port1 and port3 | |
554 | */ | |
555 | static int cx231xx_i2c_mux_select(struct i2c_adapter *adap, | |
556 | void *mux_priv, u32 chan_id) | |
557 | { | |
558 | struct cx231xx *dev = mux_priv; | |
559 | ||
560 | return cx231xx_enable_i2c_port_3(dev, chan_id); | |
561 | } | |
562 | ||
563 | int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no) | |
564 | { | |
565 | struct i2c_adapter *i2c_parent = &dev->i2c_bus[1].i2c_adap; | |
566 | /* what is the correct mux_dev? */ | |
567 | struct device *mux_dev = &dev->udev->dev; | |
568 | ||
569 | dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent, | |
570 | mux_dev, | |
571 | dev /* mux_priv */, | |
572 | 0, | |
573 | mux_no /* chan_id */, | |
574 | 0 /* class */, | |
575 | &cx231xx_i2c_mux_select, | |
576 | NULL); | |
577 | ||
578 | if (!dev->i2c_mux_adap[mux_no]) | |
579 | cx231xx_warn("%s: i2c mux %d register FAILED\n", | |
580 | dev->name, mux_no); | |
581 | ||
582 | return 0; | |
583 | } | |
584 | ||
585 | void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no) | |
586 | { | |
587 | i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]); | |
588 | dev->i2c_mux_adap[mux_no] = NULL; | |
589 | } | |
590 | ||
c3c3f1ae MS |
591 | struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port) |
592 | { | |
593 | switch (i2c_port) { | |
594 | case I2C_0: | |
595 | return &dev->i2c_bus[0].i2c_adap; | |
596 | case I2C_1: | |
597 | return &dev->i2c_bus[1].i2c_adap; | |
598 | case I2C_2: | |
599 | return &dev->i2c_bus[2].i2c_adap; | |
600 | case I2C_1_MUX_1: | |
15c212dd | 601 | return dev->i2c_mux_adap[0]; |
c3c3f1ae | 602 | case I2C_1_MUX_3: |
15c212dd | 603 | return dev->i2c_mux_adap[1]; |
c3c3f1ae MS |
604 | default: |
605 | return NULL; | |
606 | } | |
607 | } | |
608 | EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap); |