diff options
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 207 |
1 files changed, 116 insertions, 91 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index aae7753fef11..50ccf3771204 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <media/v4l2-common.h> | 36 | #include <media/v4l2-common.h> |
37 | 37 | ||
38 | #include "em28xx.h" | 38 | #include "em28xx.h" |
39 | #include "tuner-xc2028.h" | ||
40 | 39 | ||
41 | static int tuner = -1; | 40 | static int tuner = -1; |
42 | module_param(tuner, int, 0444); | 41 | module_param(tuner, int, 0444); |
@@ -52,26 +51,6 @@ struct em28xx_hash_table { | |||
52 | unsigned int tuner; | 51 | unsigned int tuner; |
53 | }; | 52 | }; |
54 | 53 | ||
55 | /* Boards supported by driver */ | ||
56 | |||
57 | #define EM2800_BOARD_UNKNOWN 0 | ||
58 | #define EM2820_BOARD_UNKNOWN 1 | ||
59 | #define EM2820_BOARD_TERRATEC_CINERGY_250 2 | ||
60 | #define EM2820_BOARD_PINNACLE_USB_2 3 | ||
61 | #define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 4 | ||
62 | #define EM2820_BOARD_MSI_VOX_USB_2 5 | ||
63 | #define EM2800_BOARD_TERRATEC_CINERGY_200 6 | ||
64 | #define EM2800_BOARD_LEADTEK_WINFAST_USBII 7 | ||
65 | #define EM2800_BOARD_KWORLD_USB2800 8 | ||
66 | #define EM2820_BOARD_PINNACLE_DVC_90 9 | ||
67 | #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 10 | ||
68 | #define EM2880_BOARD_TERRATEC_HYBRID_XS 11 | ||
69 | #define EM2820_BOARD_KWORLD_PVRTV2800RF 12 | ||
70 | #define EM2880_BOARD_TERRATEC_PRODIGY_XS 13 | ||
71 | #define EM2820_BOARD_PROLINK_PLAYTV_USB2 14 | ||
72 | #define EM2800_BOARD_VGEAR_POCKETTV 15 | ||
73 | #define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 | ||
74 | |||
75 | struct em28xx_board em28xx_boards[] = { | 54 | struct em28xx_board em28xx_boards[] = { |
76 | [EM2800_BOARD_UNKNOWN] = { | 55 | [EM2800_BOARD_UNKNOWN] = { |
77 | .name = "Unknown EM2800 video grabber", | 56 | .name = "Unknown EM2800 video grabber", |
@@ -200,6 +179,7 @@ struct em28xx_board em28xx_boards[] = { | |||
200 | .tuner_type = TUNER_XC2028, | 179 | .tuner_type = TUNER_XC2028, |
201 | .mts_firmware = 1, | 180 | .mts_firmware = 1, |
202 | .has_12mhz_i2s = 1, | 181 | .has_12mhz_i2s = 1, |
182 | .has_dvb = 1, | ||
203 | .decoder = EM28XX_TVP5150, | 183 | .decoder = EM28XX_TVP5150, |
204 | .input = { { | 184 | .input = { { |
205 | .type = EM28XX_VMUX_TELEVISION, | 185 | .type = EM28XX_VMUX_TELEVISION, |
@@ -214,9 +194,6 @@ struct em28xx_board em28xx_boards[] = { | |||
214 | .vmux = TVP5150_SVIDEO, | 194 | .vmux = TVP5150_SVIDEO, |
215 | .amux = 1, | 195 | .amux = 1, |
216 | } }, | 196 | } }, |
217 | |||
218 | /* gpio's 4, 1, 0 */ | ||
219 | .analog_gpio = 0x003d2d, | ||
220 | }, | 197 | }, |
221 | [EM2880_BOARD_TERRATEC_HYBRID_XS] = { | 198 | [EM2880_BOARD_TERRATEC_HYBRID_XS] = { |
222 | .name = "Terratec Hybrid XS", | 199 | .name = "Terratec Hybrid XS", |
@@ -331,7 +308,7 @@ struct em28xx_board em28xx_boards[] = { | |||
331 | .name = "Kworld USB2800", | 308 | .name = "Kworld USB2800", |
332 | .is_em2800 = 1, | 309 | .is_em2800 = 1, |
333 | .vchannels = 3, | 310 | .vchannels = 3, |
334 | .tuner_type = TUNER_PHILIPS_ATSC, | 311 | .tuner_type = TUNER_PHILIPS_FCV1236D, |
335 | .tda9887_conf = TDA9887_PRESENT, | 312 | .tda9887_conf = TDA9887_PRESENT, |
336 | .decoder = EM28XX_SAA7113, | 313 | .decoder = EM28XX_SAA7113, |
337 | .input = { { | 314 | .input = { { |
@@ -453,7 +430,36 @@ struct usb_device_id em28xx_id_table [] = { | |||
453 | }; | 430 | }; |
454 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); | 431 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
455 | 432 | ||
456 | /* EEPROM hash table for devices with generic USB IDs */ | 433 | /* |
434 | * Reset sequences for analog/digital modes | ||
435 | */ | ||
436 | |||
437 | /* Board Hauppauge WinTV HVR 900 analog */ | ||
438 | static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = { | ||
439 | {EM28XX_R08_GPIO, 0x2d, ~EM_GPIO_4, 10}, | ||
440 | {0x05, 0xff, 0x10, 10}, | ||
441 | { -1, -1, -1, -1}, | ||
442 | }; | ||
443 | |||
444 | /* Board Hauppauge WinTV HVR 900 digital */ | ||
445 | static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = { | ||
446 | {EM28XX_R08_GPIO, 0x2e, ~EM_GPIO_4, 10}, | ||
447 | {EM2880_R04_GPO, 0x04, 0x0f, 10}, | ||
448 | {EM2880_R04_GPO, 0x0c, 0x0f, 10}, | ||
449 | { -1, -1, -1, -1}, | ||
450 | }; | ||
451 | |||
452 | /* Board Hauppauge WinTV HVR 900 tuner_callback */ | ||
453 | static 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}, | ||
458 | }; | ||
459 | |||
460 | /* | ||
461 | * EEPROM hash table for devices with generic USB IDs | ||
462 | */ | ||
457 | static struct em28xx_hash_table em28xx_eeprom_hash [] = { | 463 | static struct em28xx_hash_table em28xx_eeprom_hash [] = { |
458 | /* P/N: SA 60002070465 Tuner: TVF7533-MF */ | 464 | /* P/N: SA 60002070465 Tuner: TVF7533-MF */ |
459 | {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, | 465 | {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF}, |
@@ -465,79 +471,113 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { | |||
465 | {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, | 471 | {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, |
466 | }; | 472 | }; |
467 | 473 | ||
474 | int em28xx_tuner_callback(void *ptr, int command, int arg) | ||
475 | { | ||
476 | int rc = 0; | ||
477 | struct em28xx *dev = ptr; | ||
478 | |||
479 | if (dev->tuner_type != TUNER_XC2028) | ||
480 | return 0; | ||
481 | |||
482 | if (command != XC2028_TUNER_RESET) | ||
483 | return 0; | ||
484 | |||
485 | if (dev->mode == EM28XX_ANALOG_MODE) | ||
486 | rc = em28xx_gpio_set(dev, dev->tun_analog_gpio); | ||
487 | else | ||
488 | rc = em28xx_gpio_set(dev, dev->tun_digital_gpio); | ||
489 | |||
490 | return rc; | ||
491 | } | ||
492 | EXPORT_SYMBOL_GPL(em28xx_tuner_callback); | ||
493 | |||
494 | static void em28xx_set_model(struct em28xx *dev) | ||
495 | { | ||
496 | dev->is_em2800 = em28xx_boards[dev->model].is_em2800; | ||
497 | dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; | ||
498 | dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; | ||
499 | dev->decoder = em28xx_boards[dev->model].decoder; | ||
500 | dev->video_inputs = em28xx_boards[dev->model].vchannels; | ||
501 | dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; | ||
502 | dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; | ||
503 | dev->has_dvb = em28xx_boards[dev->model].has_dvb; | ||
504 | } | ||
505 | |||
468 | /* Since em28xx_pre_card_setup() requires a proper dev->model, | 506 | /* Since em28xx_pre_card_setup() requires a proper dev->model, |
469 | * this won't work for boards with generic PCI IDs | 507 | * this won't work for boards with generic PCI IDs |
470 | */ | 508 | */ |
471 | void em28xx_pre_card_setup(struct em28xx *dev) | 509 | void em28xx_pre_card_setup(struct em28xx *dev) |
472 | { | 510 | { |
511 | int rc; | ||
512 | |||
513 | rc = em28xx_read_reg(dev, EM2880_R04_GPO); | ||
514 | if (rc >= 0) | ||
515 | dev->reg_gpo = rc; | ||
516 | |||
517 | dev->wait_after_write = 5; | ||
518 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); | ||
519 | if (rc > 0) { | ||
520 | switch (rc) { | ||
521 | case CHIP_ID_EM2883: | ||
522 | em28xx_info("chip ID is em2882/em2883\n"); | ||
523 | dev->wait_after_write = 0; | ||
524 | break; | ||
525 | default: | ||
526 | em28xx_info("em28xx chip ID = %d\n", rc); | ||
527 | } | ||
528 | } | ||
529 | em28xx_set_model(dev); | ||
530 | |||
473 | /* request some modules */ | 531 | /* request some modules */ |
474 | switch (dev->model) { | 532 | switch (dev->model) { |
475 | case EM2880_BOARD_TERRATEC_PRODIGY_XS: | 533 | case EM2880_BOARD_TERRATEC_PRODIGY_XS: |
476 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | 534 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: |
477 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: | ||
478 | case EM2880_BOARD_TERRATEC_HYBRID_XS: | 535 | case EM2880_BOARD_TERRATEC_HYBRID_XS: |
479 | em28xx_write_regs(dev, XCLK_REG, "\x27", 1); | 536 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: |
480 | em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1); | 537 | em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x27", 1); |
481 | em28xx_write_regs(dev, 0x08, "\xff", 1); | 538 | em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1); |
482 | em28xx_write_regs(dev, 0x04, "\x00", 1); | ||
483 | msleep(100); | ||
484 | em28xx_write_regs(dev, 0x04, "\x08", 1); | ||
485 | msleep(100); | ||
486 | em28xx_write_regs(dev, 0x08, "\xff", 1); | ||
487 | msleep(50); | ||
488 | em28xx_write_regs(dev, 0x08, "\x2d", 1); | ||
489 | msleep(50); | 539 | msleep(50); |
490 | em28xx_write_regs(dev, 0x08, "\x3d", 1); | 540 | |
541 | /* Sets GPO/GPIO sequences for this device */ | ||
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; | ||
546 | |||
491 | break; | 547 | break; |
492 | } | 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); | ||
493 | } | 555 | } |
494 | 556 | ||
495 | static int em28xx_tuner_callback(void *ptr, int command, int arg) | 557 | static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl) |
496 | { | 558 | { |
497 | int rc = 0; | 559 | memset(ctl, 0, sizeof(*ctl)); |
498 | struct em28xx *dev = ptr; | ||
499 | 560 | ||
500 | if (dev->tuner_type != TUNER_XC2028) | 561 | ctl->fname = XC2028_DEFAULT_FIRMWARE; |
501 | return 0; | 562 | ctl->max_len = 64; |
502 | 563 | ctl->mts = em28xx_boards[dev->model].mts_firmware; | |
503 | switch (command) { | ||
504 | case XC2028_TUNER_RESET: | ||
505 | { | ||
506 | /* GPIO and initialization codes for analog TV and radio | ||
507 | This code should be complemented for DTV, since reset | ||
508 | codes are different. | ||
509 | */ | ||
510 | |||
511 | dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1); | ||
512 | dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1); | ||
513 | |||
514 | if (dev->analog_gpio) { | ||
515 | char gpio0 = dev->analog_gpio & 0xff; | ||
516 | char gpio1 = (dev->analog_gpio >> 8) & 0xff; | ||
517 | char gpio4 = dev->analog_gpio >> 24; | ||
518 | |||
519 | if (gpio4) { | ||
520 | dev->em28xx_write_regs(dev, 0x04, &gpio4, 1); | ||
521 | msleep(140); | ||
522 | } | ||
523 | |||
524 | msleep(6); | ||
525 | dev->em28xx_write_regs(dev, 0x08, &gpio0, 1); | ||
526 | msleep(10); | ||
527 | dev->em28xx_write_regs(dev, 0x08, &gpio1, 1); | ||
528 | msleep(5); | ||
529 | } | ||
530 | 564 | ||
565 | switch (dev->model) { | ||
566 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900: | ||
567 | ctl->demod = XC3028_FE_ZARLINK456; | ||
531 | break; | 568 | break; |
569 | case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950: | ||
570 | /* FIXME: Better to specify the needed IF */ | ||
571 | ctl->demod = XC3028_FE_DEFAULT; | ||
572 | break; | ||
573 | default: | ||
574 | ctl->demod = XC3028_FE_OREN538; | ||
532 | } | 575 | } |
533 | } | ||
534 | return rc; | ||
535 | } | 576 | } |
536 | 577 | ||
537 | static void em28xx_config_tuner(struct em28xx *dev) | 578 | static void em28xx_config_tuner(struct em28xx *dev) |
538 | { | 579 | { |
539 | struct v4l2_priv_tun_config xc2028_cfg; | 580 | struct v4l2_priv_tun_config xc2028_cfg; |
540 | struct xc2028_ctrl ctl; | ||
541 | struct tuner_setup tun_setup; | 581 | struct tuner_setup tun_setup; |
542 | struct v4l2_frequency f; | 582 | struct v4l2_frequency f; |
543 | 583 | ||
@@ -552,11 +592,9 @@ static void em28xx_config_tuner(struct em28xx *dev) | |||
552 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); | 592 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); |
553 | 593 | ||
554 | if (dev->tuner_type == TUNER_XC2028) { | 594 | if (dev->tuner_type == TUNER_XC2028) { |
555 | memset(&ctl, 0, sizeof(ctl)); | 595 | struct xc2028_ctrl ctl; |
556 | 596 | ||
557 | ctl.fname = XC2028_DEFAULT_FIRMWARE; | 597 | em28xx_setup_xc3028(dev, &ctl); |
558 | ctl.max_len = 64; | ||
559 | ctl.mts = em28xx_boards[dev->model].mts_firmware; | ||
560 | 598 | ||
561 | xc2028_cfg.tuner = TUNER_XC2028; | 599 | xc2028_cfg.tuner = TUNER_XC2028; |
562 | xc2028_cfg.priv = &ctl; | 600 | xc2028_cfg.priv = &ctl; |
@@ -654,19 +692,6 @@ static int em28xx_hint_board(struct em28xx *dev) | |||
654 | return -1; | 692 | return -1; |
655 | } | 693 | } |
656 | 694 | ||
657 | |||
658 | static void em28xx_set_model(struct em28xx *dev) | ||
659 | { | ||
660 | dev->is_em2800 = em28xx_boards[dev->model].is_em2800; | ||
661 | dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx; | ||
662 | dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf; | ||
663 | dev->decoder = em28xx_boards[dev->model].decoder; | ||
664 | dev->video_inputs = em28xx_boards[dev->model].vchannels; | ||
665 | dev->analog_gpio = em28xx_boards[dev->model].analog_gpio; | ||
666 | dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; | ||
667 | dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; | ||
668 | } | ||
669 | |||
670 | /* ----------------------------------------------------------------------- */ | 695 | /* ----------------------------------------------------------------------- */ |
671 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) | 696 | void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir) |
672 | { | 697 | { |