diff options
author | Thierry MERLE <thierry.merle@free.fr> | 2006-12-04 06:31:45 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:22:49 -0500 |
commit | 483dfdb64fd4a9f240c84e0e225a90c044d65402 (patch) | |
tree | 385380b96155dea3a281cd88617f65ae8e610f66 /drivers/media/video/usbvision/usbvision-i2c.c | |
parent | d8159a3684007e0ded915cb7465c9534a2650c53 (diff) |
V4L/DVB (4937): Usbvision cleanup and code reorganization
- removal of overlay stuff
- reorganization of functions in 3 files:
* usbvision-i2c for I2C-related stuff
* usbvision-video for v4l2 entry points
* usbvision-core for all peripheral controls and utilities
Signed-off-by: Thierry MERLE <thierry.merle@free.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/usbvision/usbvision-i2c.c')
-rw-r--r-- | drivers/media/video/usbvision/usbvision-i2c.c | 382 |
1 files changed, 347 insertions, 35 deletions
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index 48afcd2aca3f..2de74e48cbe5 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -37,16 +37,18 @@ | |||
37 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
38 | #include <linux/usb.h> | 38 | #include <linux/usb.h> |
39 | #include <linux/i2c.h> | 39 | #include <linux/i2c.h> |
40 | #include "usbvision-i2c.h" | 40 | #include "usbvision.h" |
41 | 41 | ||
42 | static int debug_i2c_usb = 0; | 42 | #define DBG_I2C 1<<0 |
43 | #define DBG_ALGO 1<<1 | ||
43 | 44 | ||
44 | #if defined(module_param) // Showing parameters under SYSFS | 45 | static int i2c_debug = 0; |
45 | module_param (debug_i2c_usb, int, 0444); // debug_i2c_usb mode of the device driver | 46 | |
46 | #else | 47 | module_param (i2c_debug, int, 0644); // debug_i2c_usb mode of the device driver |
47 | MODULE_PARM(debug_i2c_usb, "i"); // debug_i2c_usb mode of the device driver | 48 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); |
48 | #endif | ||
49 | 49 | ||
50 | #define PDEBUG(level, fmt, args...) \ | ||
51 | if (i2c_debug & (level)) info("[%s:%d] " fmt, __PRETTY_FUNCTION__, __LINE__ , ## args) | ||
50 | 52 | ||
51 | static inline int try_write_address(struct i2c_adapter *i2c_adap, | 53 | static inline int try_write_address(struct i2c_adapter *i2c_adap, |
52 | unsigned char addr, int retries) | 54 | unsigned char addr, int retries) |
@@ -67,11 +69,9 @@ static inline int try_write_address(struct i2c_adapter *i2c_adap, | |||
67 | break; | 69 | break; |
68 | udelay(adap->udelay); | 70 | udelay(adap->udelay); |
69 | } | 71 | } |
70 | if (debug_i2c_usb) { | 72 | if (i) { |
71 | if (i) { | 73 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); |
72 | info("%s: Needed %d retries for address %#2x", __FUNCTION__, i, addr); | 74 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); |
73 | info("%s: Maybe there's no device at this address", __FUNCTION__); | ||
74 | } | ||
75 | } | 75 | } |
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
@@ -94,11 +94,9 @@ static inline int try_read_address(struct i2c_adapter *i2c_adap, | |||
94 | break; | 94 | break; |
95 | udelay(adap->udelay); | 95 | udelay(adap->udelay); |
96 | } | 96 | } |
97 | if (debug_i2c_usb) { | 97 | if (i) { |
98 | if (i) { | 98 | PDEBUG(DBG_ALGO,"Needed %d retries for address %#2x", i, addr); |
99 | info("%s: Needed %d retries for address %#2x", __FUNCTION__, i, addr); | 99 | PDEBUG(DBG_ALGO,"Maybe there's no device at this address"); |
100 | info("%s: Maybe there's no device at this address", __FUNCTION__); | ||
101 | } | ||
102 | } | 100 | } |
103 | return ret; | 101 | return ret; |
104 | } | 102 | } |
@@ -166,9 +164,7 @@ usb_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | |||
166 | pmsg = &msgs[i]; | 164 | pmsg = &msgs[i]; |
167 | ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); | 165 | ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr); |
168 | if (ret != 0) { | 166 | if (ret != 0) { |
169 | if (debug_i2c_usb) { | 167 | PDEBUG(DBG_ALGO,"got NAK from device, message #%d", i); |
170 | info("%s: got NAK from device, message #%d\n", __FUNCTION__, i); | ||
171 | } | ||
172 | return (ret < 0) ? ret : -EREMOTEIO; | 168 | return (ret < 0) ? ret : -EREMOTEIO; |
173 | } | 169 | } |
174 | 170 | ||
@@ -215,6 +211,9 @@ static struct i2c_algorithm i2c_usb_algo = { | |||
215 | */ | 211 | */ |
216 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) | 212 | int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) |
217 | { | 213 | { |
214 | PDEBUG(DBG_I2C, "I2C debugging is enabled [i2c]"); | ||
215 | PDEBUG(DBG_ALGO, "ALGO debugging is enabled [i2c]"); | ||
216 | |||
218 | /* register new adapter to i2c module... */ | 217 | /* register new adapter to i2c module... */ |
219 | 218 | ||
220 | adap->algo = &i2c_usb_algo; | 219 | adap->algo = &i2c_usb_algo; |
@@ -222,17 +221,9 @@ int usbvision_i2c_usb_add_bus(struct i2c_adapter *adap) | |||
222 | adap->timeout = 100; /* default values, should */ | 221 | adap->timeout = 100; /* default values, should */ |
223 | adap->retries = 3; /* be replaced by defines */ | 222 | adap->retries = 3; /* be replaced by defines */ |
224 | 223 | ||
225 | #ifdef MODULE | ||
226 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 21) | ||
227 | MOD_INC_USE_COUNT; | ||
228 | #endif | ||
229 | #endif | ||
230 | |||
231 | i2c_add_adapter(adap); | 224 | i2c_add_adapter(adap); |
232 | 225 | ||
233 | if (debug_i2c_usb) { | 226 | PDEBUG(DBG_ALGO,"i2c bus for %s registered", adap->name); |
234 | info("i2c bus for %s registered", adap->name); | ||
235 | } | ||
236 | 227 | ||
237 | return 0; | 228 | return 0; |
238 | } | 229 | } |
@@ -243,17 +234,338 @@ int usbvision_i2c_usb_del_bus(struct i2c_adapter *adap) | |||
243 | 234 | ||
244 | i2c_del_adapter(adap); | 235 | i2c_del_adapter(adap); |
245 | 236 | ||
246 | if (debug_i2c_usb) { | 237 | PDEBUG(DBG_ALGO,"i2c bus for %s unregistered", adap->name); |
247 | info("i2c bus for %s unregistered", adap->name); | 238 | |
239 | return 0; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* ----------------------------------------------------------------------- */ | ||
244 | /* usbvision specific I2C functions */ | ||
245 | /* ----------------------------------------------------------------------- */ | ||
246 | static struct i2c_adapter i2c_adap_template; | ||
247 | static struct i2c_algo_usb_data i2c_algo_template; | ||
248 | static struct i2c_client i2c_client_template; | ||
249 | |||
250 | int usbvision_init_i2c(struct usb_usbvision *usbvision) | ||
251 | { | ||
252 | memcpy(&usbvision->i2c_adap, &i2c_adap_template, | ||
253 | sizeof(struct i2c_adapter)); | ||
254 | memcpy(&usbvision->i2c_algo, &i2c_algo_template, | ||
255 | sizeof(struct i2c_algo_usb_data)); | ||
256 | memcpy(&usbvision->i2c_client, &i2c_client_template, | ||
257 | sizeof(struct i2c_client)); | ||
258 | |||
259 | sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name), | ||
260 | " #%d", usbvision->vdev->minor & 0x1f); | ||
261 | PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name); | ||
262 | |||
263 | i2c_set_adapdata(&usbvision->i2c_adap, usbvision); | ||
264 | i2c_set_clientdata(&usbvision->i2c_client, usbvision); | ||
265 | i2c_set_algo_usb_data(&usbvision->i2c_algo, usbvision); | ||
266 | |||
267 | usbvision->i2c_adap.algo_data = &usbvision->i2c_algo; | ||
268 | usbvision->i2c_client.adapter = &usbvision->i2c_adap; | ||
269 | |||
270 | if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) { | ||
271 | printk(KERN_ERR "usbvision_init_i2c: can't write reg\n"); | ||
272 | return -EBUSY; | ||
273 | } | ||
274 | |||
275 | #ifdef CONFIG_MODULES | ||
276 | /* Request the load of the i2c modules we need */ | ||
277 | switch (usbvision_device_data[usbvision->DevModel].Codec) { | ||
278 | case CODEC_SAA7113: | ||
279 | request_module("saa7115"); | ||
280 | break; | ||
281 | case CODEC_SAA7111: | ||
282 | request_module("saa7115"); | ||
283 | break; | ||
284 | } | ||
285 | if (usbvision_device_data[usbvision->DevModel].Tuner == 1) { | ||
286 | request_module("tuner"); | ||
248 | } | 287 | } |
249 | #ifdef MODULE | ||
250 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 21) | ||
251 | MOD_DEC_USE_COUNT; | ||
252 | #endif | ||
253 | #endif | 288 | #endif |
254 | 289 | ||
290 | return usbvision_i2c_usb_add_bus(&usbvision->i2c_adap); | ||
291 | } | ||
292 | |||
293 | void call_i2c_clients(struct usb_usbvision *usbvision, unsigned int cmd, | ||
294 | void *arg) | ||
295 | { | ||
296 | BUG_ON(NULL == usbvision->i2c_adap.algo_data); | ||
297 | i2c_clients_command(&usbvision->i2c_adap, cmd, arg); | ||
298 | } | ||
299 | |||
300 | static int attach_inform(struct i2c_client *client) | ||
301 | { | ||
302 | struct usb_usbvision *usbvision; | ||
303 | |||
304 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
305 | |||
306 | switch (client->addr << 1) { | ||
307 | case 0x43: | ||
308 | case 0x4b: | ||
309 | { | ||
310 | struct tuner_setup tun_setup; | ||
311 | |||
312 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
313 | tun_setup.type = TUNER_TDA9887; | ||
314 | tun_setup.addr = client->addr; | ||
315 | |||
316 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
317 | |||
318 | break; | ||
319 | } | ||
320 | case 0x42: | ||
321 | PDEBUG(DBG_I2C,"attach_inform: saa7114 detected."); | ||
322 | break; | ||
323 | case 0x4a: | ||
324 | PDEBUG(DBG_I2C,"attach_inform: saa7113 detected."); | ||
325 | break; | ||
326 | case 0xa0: | ||
327 | PDEBUG(DBG_I2C,"attach_inform: eeprom detected."); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | { | ||
332 | struct tuner_setup tun_setup; | ||
333 | |||
334 | PDEBUG(DBG_I2C,"attach inform: detected I2C address %x", client->addr << 1); | ||
335 | usbvision->tuner_addr = client->addr; | ||
336 | |||
337 | if ((usbvision->have_tuner) && (usbvision->tuner_type != -1)) { | ||
338 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | ||
339 | tun_setup.type = usbvision->tuner_type; | ||
340 | tun_setup.addr = usbvision->tuner_addr; | ||
341 | call_i2c_clients(usbvision, TUNER_SET_TYPE_ADDR, &tun_setup); | ||
342 | } | ||
343 | } | ||
344 | break; | ||
345 | } | ||
255 | return 0; | 346 | return 0; |
256 | } | 347 | } |
257 | 348 | ||
349 | static int detach_inform(struct i2c_client *client) | ||
350 | { | ||
351 | struct usb_usbvision *usbvision; | ||
352 | |||
353 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) | ||
354 | usbvision = (struct usb_usbvision *)client->adapter->data; | ||
355 | #else | ||
356 | usbvision = (struct usb_usbvision *)i2c_get_adapdata(client->adapter); | ||
357 | #endif | ||
358 | |||
359 | PDEBUG(DBG_I2C,"usbvision[%d] detaches %s", usbvision->nr, client->name); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static int | ||
364 | usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, | ||
365 | char *buf, short len) | ||
366 | { | ||
367 | int rc, retries; | ||
368 | |||
369 | for (retries = 5;;) { | ||
370 | rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr); | ||
371 | if (rc < 0) | ||
372 | return rc; | ||
373 | |||
374 | /* Initiate byte read cycle */ | ||
375 | /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */ | ||
376 | /* d3 0=Wr 1=Rd */ | ||
377 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
378 | (len & 0x07) | 0x18); | ||
379 | if (rc < 0) | ||
380 | return rc; | ||
381 | |||
382 | /* Test for Busy and ACK */ | ||
383 | do { | ||
384 | /* USBVISION_SER_CONT -> d4 == 0 busy */ | ||
385 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
386 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
387 | if (rc < 0) | ||
388 | return rc; | ||
389 | |||
390 | /* USBVISION_SER_CONT -> d5 == 1 Not ack */ | ||
391 | if ((rc & 0x20) == 0) /* Ack? */ | ||
392 | break; | ||
393 | |||
394 | /* I2C abort */ | ||
395 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
396 | if (rc < 0) | ||
397 | return rc; | ||
398 | |||
399 | if (--retries < 0) | ||
400 | return -1; | ||
401 | } | ||
402 | |||
403 | switch (len) { | ||
404 | case 4: | ||
405 | buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); | ||
406 | case 3: | ||
407 | buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); | ||
408 | case 2: | ||
409 | buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); | ||
410 | case 1: | ||
411 | buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); | ||
412 | break; | ||
413 | default: | ||
414 | printk(KERN_ERR | ||
415 | "usbvision_i2c_read_max4: buffer length > 4\n"); | ||
416 | } | ||
417 | |||
418 | if (i2c_debug & DBG_I2C) { | ||
419 | int idx; | ||
420 | for (idx = 0; idx < len; idx++) { | ||
421 | PDEBUG(DBG_I2C,"read %x from address %x", (unsigned char)buf[idx], addr); | ||
422 | } | ||
423 | } | ||
424 | return len; | ||
425 | } | ||
426 | |||
427 | |||
428 | static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision, | ||
429 | unsigned char addr, const char *buf, | ||
430 | short len) | ||
431 | { | ||
432 | int rc, retries; | ||
433 | int i; | ||
434 | unsigned char value[6]; | ||
435 | unsigned char ser_cont; | ||
436 | |||
437 | ser_cont = (len & 0x07) | 0x10; | ||
438 | |||
439 | value[0] = addr; | ||
440 | value[1] = ser_cont; | ||
441 | for (i = 0; i < len; i++) | ||
442 | value[i + 2] = buf[i]; | ||
443 | |||
444 | for (retries = 5;;) { | ||
445 | rc = usb_control_msg(usbvision->dev, | ||
446 | usb_sndctrlpipe(usbvision->dev, 1), | ||
447 | USBVISION_OP_CODE, | ||
448 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
449 | USB_RECIP_ENDPOINT, 0, | ||
450 | (__u16) USBVISION_SER_ADRS, value, | ||
451 | len + 2, HZ); | ||
452 | |||
453 | if (rc < 0) | ||
454 | return rc; | ||
455 | |||
456 | rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, | ||
457 | (len & 0x07) | 0x10); | ||
458 | if (rc < 0) | ||
459 | return rc; | ||
460 | |||
461 | /* Test for Busy and ACK */ | ||
462 | do { | ||
463 | rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT); | ||
464 | } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */ | ||
465 | if (rc < 0) | ||
466 | return rc; | ||
467 | |||
468 | if ((rc & 0x20) == 0) /* Ack? */ | ||
469 | break; | ||
470 | |||
471 | /* I2C abort */ | ||
472 | usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00); | ||
473 | |||
474 | if (--retries < 0) | ||
475 | return -1; | ||
476 | |||
477 | } | ||
478 | |||
479 | if (i2c_debug & DBG_I2C) { | ||
480 | int idx; | ||
481 | for (idx = 0; idx < len; idx++) { | ||
482 | PDEBUG(DBG_I2C,"wrote %x at address %x", (unsigned char)buf[idx], addr); | ||
483 | } | ||
484 | } | ||
485 | return len; | ||
486 | } | ||
487 | |||
488 | static int usbvision_i2c_write(void *data, unsigned char addr, char *buf, | ||
489 | short len) | ||
490 | { | ||
491 | char *bufPtr = buf; | ||
492 | int retval; | ||
493 | int wrcount = 0; | ||
494 | int count; | ||
495 | int maxLen = 4; | ||
496 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
497 | |||
498 | while (len > 0) { | ||
499 | count = (len > maxLen) ? maxLen : len; | ||
500 | retval = usbvision_i2c_write_max4(usbvision, addr, bufPtr, count); | ||
501 | if (retval > 0) { | ||
502 | len -= count; | ||
503 | bufPtr += count; | ||
504 | wrcount += count; | ||
505 | } else | ||
506 | return (retval < 0) ? retval : -EFAULT; | ||
507 | } | ||
508 | return wrcount; | ||
509 | } | ||
510 | |||
511 | static int usbvision_i2c_read(void *data, unsigned char addr, char *buf, | ||
512 | short len) | ||
513 | { | ||
514 | char temp[4]; | ||
515 | int retval, i; | ||
516 | int rdcount = 0; | ||
517 | int count; | ||
518 | struct usb_usbvision *usbvision = (struct usb_usbvision *) data; | ||
519 | |||
520 | while (len > 0) { | ||
521 | count = (len > 3) ? 4 : len; | ||
522 | retval = usbvision_i2c_read_max4(usbvision, addr, temp, count); | ||
523 | if (retval > 0) { | ||
524 | for (i = 0; i < len; i++) | ||
525 | buf[rdcount + i] = temp[i]; | ||
526 | len -= count; | ||
527 | rdcount += count; | ||
528 | } else | ||
529 | return (retval < 0) ? retval : -EFAULT; | ||
530 | } | ||
531 | return rdcount; | ||
532 | } | ||
533 | |||
534 | static struct i2c_algo_usb_data i2c_algo_template = { | ||
535 | .data = NULL, | ||
536 | .inb = usbvision_i2c_read, | ||
537 | .outb = usbvision_i2c_write, | ||
538 | .udelay = 10, | ||
539 | .mdelay = 10, | ||
540 | .timeout = 100, | ||
541 | }; | ||
542 | |||
543 | static struct i2c_adapter i2c_adap_template = { | ||
544 | .owner = THIS_MODULE, | ||
545 | .name = "usbvision", | ||
546 | .id = I2C_HW_B_BT848, /* FIXME */ | ||
547 | .algo = NULL, | ||
548 | .algo_data = NULL, | ||
549 | .client_register = attach_inform, | ||
550 | .client_unregister = detach_inform, | ||
551 | #if defined (I2C_ADAP_CLASS_TV_ANALOG) | ||
552 | .class = I2C_ADAP_CLASS_TV_ANALOG, | ||
553 | #elif defined (I2C_CLASS_TV_ANALOG) | ||
554 | .class = I2C_CLASS_TV_ANALOG, | ||
555 | #endif | ||
556 | }; | ||
557 | |||
558 | static struct i2c_client i2c_client_template = { | ||
559 | .name = "usbvision internal", | ||
560 | }; | ||
561 | |||
258 | EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); | 562 | EXPORT_SYMBOL(usbvision_i2c_usb_add_bus); |
259 | EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); | 563 | EXPORT_SYMBOL(usbvision_i2c_usb_del_bus); |
564 | |||
565 | /* | ||
566 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
567 | * --------------------------------------------------------------------------- | ||
568 | * Local variables: | ||
569 | * c-basic-offset: 8 | ||
570 | * End: | ||
571 | */ | ||