diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-17 20:48:00 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:42 -0400 |
commit | c67ec53f8f4e90ebd482789e2f6d121f41a0bd90 (patch) | |
tree | 7c5c242cb50e8b1bfdeab4157370c7dbfda34bf9 /drivers/media/video/em28xx/em28xx-cards.c | |
parent | 82ac4f876505615ba9dc6a73cd9a584bad8fe23f (diff) |
V4L/DVB (7615): em28xx: Provide the proper support for switching between analog/digital
Before this patch, HVR900/HVR950 were incorreclty going back to analog. The
result is that only digital were working.
This patch provides the proper setup for analog/digital and tuner callback.
It also properly resets analog into a sane state at open().
Thanks to Steven Toth <stoth@linuxtv.org> and Michael Krufky <mkrufky@linuxtv.org>
for helping to set the proper parameters to GPO/GPIO em2883 ports.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 81 |
1 files changed, 34 insertions, 47 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index ed50b4e55264..13ffde281067 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -436,19 +436,25 @@ MODULE_DEVICE_TABLE(usb, em28xx_id_table); | |||
436 | 436 | ||
437 | /* Board Hauppauge WinTV HVR 900 analog */ | 437 | /* Board Hauppauge WinTV HVR 900 analog */ |
438 | struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { | 438 | struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { |
439 | { -1, -1, 6}, | 439 | {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, |
440 | {EM28XX_R08_GPIO, 0x2d, 10}, | 440 | {0x05, 0xff, 0x10, 10}, |
441 | {EM28XX_R08_GPIO, 0x3d, 5}, | 441 | { -1, -1, -1, -1}, |
442 | { -1, -1, -1}, | ||
443 | }; | 442 | }; |
443 | |||
444 | /* Board Hauppauge WinTV HVR 900 digital */ | 444 | /* Board Hauppauge WinTV HVR 900 digital */ |
445 | struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { | 445 | struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { |
446 | { -1, -1, 6}, | 446 | {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, |
447 | {EM28XX_R08_GPIO, 0x2e, 6}, | 447 | {EM2880_R04_GPO, 0x04, 0x0f, 10}, |
448 | {EM28XX_R08_GPIO, 0x3e, 6}, | 448 | {EM2880_R04_GPO, 0x0c, 0x0f, 10}, |
449 | {EM2880_R04_GPO, 0x04, 10}, | 449 | { -1, -1, -1, -1}, |
450 | {EM2880_R04_GPO, 0x0c, 10}, | 450 | }; |
451 | { -1, -1, -1}, | 451 | |
452 | /* Board Hauppauge WinTV HVR 900 tuner_callback */ | ||
453 | struct em28xx_reg_seq hauppauge_wintv_hvr_900_tuner_callback[] = { | ||
454 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, | ||
455 | {EM28XX_R08_GPIO, 0, EM_GPIO_4, 10}, | ||
456 | {EM28XX_R08_GPIO, EM_GPIO_4, EM_GPIO_4, 10}, | ||
457 | { -1, -1, -1, -1}, | ||
452 | }; | 458 | }; |
453 | 459 | ||
454 | /* | 460 | /* |
@@ -469,7 +475,6 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) | |||
469 | { | 475 | { |
470 | int rc = 0; | 476 | int rc = 0; |
471 | struct em28xx *dev = ptr; | 477 | struct em28xx *dev = ptr; |
472 | struct em28xx_reg_seq *gpio; | ||
473 | 478 | ||
474 | if (dev->tuner_type != TUNER_XC2028) | 479 | if (dev->tuner_type != TUNER_XC2028) |
475 | return 0; | 480 | return 0; |
@@ -478,32 +483,10 @@ int em28xx_tuner_callback(void *ptr, int command, int arg) | |||
478 | return 0; | 483 | return 0; |
479 | 484 | ||
480 | if (dev->mode == EM28XX_ANALOG_MODE) | 485 | if (dev->mode == EM28XX_ANALOG_MODE) |
481 | gpio = dev->analog_gpio; | 486 | rc = em28xx_gpio_set(dev, dev->tun_analog_gpio); |
482 | else | 487 | else |
483 | gpio = dev->digital_gpio; | 488 | rc = em28xx_gpio_set(dev, dev->tun_digital_gpio); |
484 | 489 | ||
485 | /* djh - Not sure if these are still required */ | ||
486 | dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); | ||
487 | if (dev->mode == EM28XX_ANALOG_MODE) | ||
488 | dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); | ||
489 | else | ||
490 | dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x37", 1); | ||
491 | msleep(6); | ||
492 | |||
493 | if (!gpio) | ||
494 | return rc; | ||
495 | |||
496 | /* Send GPIO reset sequences specified at board entry */ | ||
497 | while (gpio->sleep >= 0) { | ||
498 | if (gpio->reg >= 0) | ||
499 | rc = dev->em28xx_write_regs(dev, | ||
500 | gpio->reg, | ||
501 | &gpio->val, 1); | ||
502 | if (gpio->sleep > 0) | ||
503 | msleep(gpio->sleep); | ||
504 | |||
505 | gpio++; | ||
506 | } | ||
507 | return rc; | 490 | return rc; |
508 | } | 491 | } |
509 | EXPORT_SYMBOL_GPL(em28xx_tuner_callback); | 492 | EXPORT_SYMBOL_GPL(em28xx_tuner_callback); |
@@ -527,6 +510,10 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
527 | { | 510 | { |
528 | int rc; | 511 | int rc; |
529 | 512 | ||
513 | rc = em28xx_read_reg(dev, EM2880_R04_GPO); | ||
514 | if (rc >= 0) | ||
515 | dev->reg_gpo = rc; | ||
516 | |||
530 | dev->wait_after_write = 5; | 517 | dev->wait_after_write = 5; |
531 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); | 518 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); |
532 | if (rc > 0) { | 519 | if (rc > 0) { |
@@ -547,24 +534,24 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
547 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 534 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
548 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | 535 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
549 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: | 536 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: |
550 | em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); | 537 | em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); |
551 | em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); | 538 | em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); |
552 | em28xx_write_regs(dev, 0x08, "\xff", 1); | ||
553 | em28xx_write_regs(dev, 0x04, "\x00", 1); | ||
554 | msleep(100); | ||
555 | em28xx_write_regs(dev, 0x04, "\x08", 1); | ||
556 | msleep(100); | ||
557 | em28xx_write_regs(dev, 0x08, "\xff", 1); | ||
558 | msleep(50); | ||
559 | em28xx_write_regs(dev, 0x08, "\x2d", 1); | ||
560 | msleep(50); | 539 | msleep(50); |
561 | em28xx_write_regs(dev, 0x08, "\x3d", 1); | ||
562 | 540 | ||
563 | dev->analog_gpio = hauppauge_wintv_hvr_900_analog; | 541 | /* Sets GPO/GPIO sequences for this device */ |
564 | dev->digital_gpio = hauppauge_wintv_hvr_900_digital; | 542 | dev->analog_gpio = hauppauge_wintv_hvr_900_analog; |
543 | dev->digital_gpio = hauppauge_wintv_hvr_900_digital; | ||
544 | dev->tun_analog_gpio = hauppauge_wintv_hvr_900_tuner_callback; | ||
545 | dev->tun_digital_gpio = hauppauge_wintv_hvr_900_tuner_callback; | ||
565 | 546 | ||
566 | break; | 547 | break; |
567 | } | 548 | } |
549 | |||
550 | em28xx_gpio_set(dev, dev->tun_analog_gpio); | ||
551 | em28xx_set_mode(dev, EM28XX_ANALOG_MODE); | ||
552 | |||
553 | /* Unlock device */ | ||
554 | em28xx_set_mode(dev, EM28XX_MODE_UNDEFINED); | ||
568 | } | 555 | } |
569 | 556 | ||
570 | void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) | 557 | void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) |