diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-03-27 22:18:30 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:07:55 -0400 |
commit | 99e09eac25f752b25f65392da7bd747b77040fea (patch) | |
tree | 0d60bc8f498aa0d43b92f334e30771131b04dd63 | |
parent | a2401d9eed955d90e682b911c343d7fb4ad22436 (diff) |
V4L/DVB (7448): Add support for Kworld ATSC 120
This board has a s5h1409 demod, plus a xc30x8 tuner (probably, xc3018).
This patch adds proper support for radio, video, s-video, composite and ATSC.
However, support for radio and video depends on having s5h1409 i2c gate open,
otherwise, xc30x8 chip won't be visible.
For a better support, some rework is needed on cx88 driver, to allow adding
xc30x8 to i2c bus without sending i2c 0 byte reading to 0xc2 address.
Thanks to Vanessa Ezekowitz <vanessaezekowitz@gmail.com> for helping to figure
out the proper parameters for s5h1409 and the GPIO pins used by each
configuration.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
-rw-r--r-- | Documentation/video4linux/CARDLIST.cx88 | 1 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 110 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 30 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 3 |
4 files changed, 114 insertions, 30 deletions
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index a01991dcb317..543957346469 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 | |||
@@ -65,3 +65,4 @@ | |||
65 | 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] | 65 | 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] |
66 | 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] | 66 | 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] |
67 | 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] | 67 | 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] |
68 | 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] | ||
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6b83e3457b70..70505b4e5b46 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include "cx88.h" | 28 | #include "cx88.h" |
29 | #include "tea5767.h" | 29 | #include "tea5767.h" |
30 | #include "tuner-xc2028.h" | ||
31 | 30 | ||
32 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | 31 | static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; |
33 | static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; | 32 | static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; |
@@ -1614,6 +1613,45 @@ static const struct cx88_board cx88_boards[] = { | |||
1614 | .gpio2 = 0x0cfb, | 1613 | .gpio2 = 0x0cfb, |
1615 | }, | 1614 | }, |
1616 | }, | 1615 | }, |
1616 | /* Both radio, analog and ATSC work with this board. | ||
1617 | However, for analog to work, s5h1409 gate should be open, | ||
1618 | otherwise, tuner-xc3028 won't be detected. | ||
1619 | A proper fix require using the newer i2c methods to add | ||
1620 | tuner-xc3028 without doing an i2c probe. | ||
1621 | */ | ||
1622 | [CX88_BOARD_KWORLD_ATSC_120] = { | ||
1623 | .name = "Kworld PlusTV HD PCI 120 (ATSC 120)", | ||
1624 | .tuner_type = TUNER_XC2028, | ||
1625 | .radio_type = UNSET, | ||
1626 | .tuner_addr = ADDR_UNSET, | ||
1627 | .radio_addr = ADDR_UNSET, | ||
1628 | .input = { { | ||
1629 | .type = CX88_VMUX_TELEVISION, | ||
1630 | .vmux = 0, | ||
1631 | .gpio0 = 0x000000ff, | ||
1632 | .gpio1 = 0x0000f35d, | ||
1633 | .gpio2 = 0x00000000, | ||
1634 | }, { | ||
1635 | .type = CX88_VMUX_COMPOSITE1, | ||
1636 | .vmux = 1, | ||
1637 | .gpio0 = 0x000000ff, | ||
1638 | .gpio1 = 0x0000f37e, | ||
1639 | .gpio2 = 0x00000000, | ||
1640 | }, { | ||
1641 | .type = CX88_VMUX_SVIDEO, | ||
1642 | .vmux = 2, | ||
1643 | .gpio0 = 0x000000ff, | ||
1644 | .gpio1 = 0x0000f37e, | ||
1645 | .gpio2 = 0x00000000, | ||
1646 | } }, | ||
1647 | .radio = { | ||
1648 | .type = CX88_RADIO, | ||
1649 | .gpio0 = 0x000000ff, | ||
1650 | .gpio1 = 0x0000f35d, | ||
1651 | .gpio2 = 0x00000000, | ||
1652 | }, | ||
1653 | .mpeg = CX88_MPEG_DVB, | ||
1654 | }, | ||
1617 | }; | 1655 | }; |
1618 | 1656 | ||
1619 | /* ------------------------------------------------------------------ */ | 1657 | /* ------------------------------------------------------------------ */ |
@@ -1959,6 +1997,10 @@ static const struct cx88_subid cx88_subids[] = { | |||
1959 | .subvendor = 0x1554, | 1997 | .subvendor = 0x1554, |
1960 | .subdevice = 0x4935, | 1998 | .subdevice = 0x4935, |
1961 | .card = CX88_BOARD_PROLINK_PV_8000GT, | 1999 | .card = CX88_BOARD_PROLINK_PV_8000GT, |
2000 | }, { | ||
2001 | .subvendor = 0x17de, | ||
2002 | .subdevice = 0x08c1, | ||
2003 | .card = CX88_BOARD_KWORLD_ATSC_120, | ||
1962 | }, | 2004 | }, |
1963 | }; | 2005 | }; |
1964 | 2006 | ||
@@ -2200,6 +2242,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, | |||
2200 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | 2242 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: |
2201 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | 2243 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: |
2202 | case CX88_BOARD_GENIATECH_X8000_MT: | 2244 | case CX88_BOARD_GENIATECH_X8000_MT: |
2245 | case CX88_BOARD_KWORLD_ATSC_120: | ||
2203 | return cx88_xc3028_geniatech_tuner_callback(core, | 2246 | return cx88_xc3028_geniatech_tuner_callback(core, |
2204 | command, arg); | 2247 | command, arg); |
2205 | case CX88_BOARD_PROLINK_PV_8000GT: | 2248 | case CX88_BOARD_PROLINK_PV_8000GT: |
@@ -2363,6 +2406,40 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
2363 | } | 2406 | } |
2364 | } | 2407 | } |
2365 | 2408 | ||
2409 | /* | ||
2410 | * Sets board-dependent xc3028 configuration | ||
2411 | */ | ||
2412 | void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) | ||
2413 | { | ||
2414 | memset(ctl, 0, sizeof(*ctl)); | ||
2415 | |||
2416 | ctl->fname = XC2028_DEFAULT_FIRMWARE; | ||
2417 | ctl->max_len = 64; | ||
2418 | |||
2419 | switch (core->boardnr) { | ||
2420 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | ||
2421 | /* Doesn't work with firmware version 2.7 */ | ||
2422 | ctl->fname = "xc3028-v25.fw"; | ||
2423 | break; | ||
2424 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | ||
2425 | ctl->scode_table = XC3028_FE_ZARLINK456; | ||
2426 | break; | ||
2427 | case CX88_BOARD_KWORLD_ATSC_120: | ||
2428 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
2429 | ctl->demod = XC3028_FE_OREN538; | ||
2430 | break; | ||
2431 | case CX88_BOARD_PROLINK_PV_8000GT: | ||
2432 | /* | ||
2433 | * This board uses non-MTS firmware | ||
2434 | */ | ||
2435 | break; | ||
2436 | default: | ||
2437 | ctl->demod = XC3028_FE_OREN538; | ||
2438 | ctl->mts = 1; | ||
2439 | } | ||
2440 | } | ||
2441 | EXPORT_SYMBOL_GPL(cx88_setup_xc3028); | ||
2442 | |||
2366 | static void cx88_card_setup(struct cx88_core *core) | 2443 | static void cx88_card_setup(struct cx88_core *core) |
2367 | { | 2444 | { |
2368 | static u8 eeprom[256]; | 2445 | static u8 eeprom[256]; |
@@ -2481,36 +2558,13 @@ static void cx88_card_setup(struct cx88_core *core) | |||
2481 | struct v4l2_priv_tun_config xc2028_cfg; | 2558 | struct v4l2_priv_tun_config xc2028_cfg; |
2482 | struct xc2028_ctrl ctl; | 2559 | struct xc2028_ctrl ctl; |
2483 | 2560 | ||
2484 | memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); | 2561 | /* Fills device-dependent initialization parameters */ |
2485 | memset(&ctl, 0, sizeof(ctl)); | 2562 | cx88_setup_xc3028(core, &ctl); |
2486 | |||
2487 | ctl.fname = XC2028_DEFAULT_FIRMWARE; | ||
2488 | ctl.max_len = 64; | ||
2489 | |||
2490 | switch (core->boardnr) { | ||
2491 | case CX88_BOARD_POWERCOLOR_REAL_ANGEL: | ||
2492 | /* Doesn't work with firmware version 2.7 */ | ||
2493 | ctl.fname = "xc3028-v25.fw"; | ||
2494 | break; | ||
2495 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: | ||
2496 | ctl.scode_table = XC3028_FE_ZARLINK456; | ||
2497 | break; | ||
2498 | case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: | ||
2499 | ctl.demod = XC3028_FE_OREN538; | ||
2500 | break; | ||
2501 | case CX88_BOARD_PROLINK_PV_8000GT: | ||
2502 | /* | ||
2503 | * This board uses non-MTS firmware | ||
2504 | */ | ||
2505 | break; | ||
2506 | default: | ||
2507 | ctl.demod = XC3028_FE_OREN538; | ||
2508 | ctl.mts = 1; | ||
2509 | } | ||
2510 | 2563 | ||
2564 | /* Sends parameters to xc2028/3028 tuner */ | ||
2565 | memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); | ||
2511 | xc2028_cfg.tuner = TUNER_XC2028; | 2566 | xc2028_cfg.tuner = TUNER_XC2028; |
2512 | xc2028_cfg.priv = &ctl; | 2567 | xc2028_cfg.priv = &ctl; |
2513 | |||
2514 | info_printk(core, "Asking xc2028/3028 to load firmware %s\n", | 2568 | info_printk(core, "Asking xc2028/3028 to load firmware %s\n", |
2515 | ctl.fname); | 2569 | ctl.fname); |
2516 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); | 2570 | cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8dca20b944dd..13cc395ca656 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include "nxt200x.h" | 45 | #include "nxt200x.h" |
46 | #include "cx24123.h" | 46 | #include "cx24123.h" |
47 | #include "isl6421.h" | 47 | #include "isl6421.h" |
48 | #include "tuner-xc2028.h" | ||
49 | #include "tuner-xc2028-types.h" | 48 | #include "tuner-xc2028-types.h" |
50 | #include "tuner-simple.h" | 49 | #include "tuner-simple.h" |
51 | #include "tda9887.h" | 50 | #include "tda9887.h" |
@@ -443,6 +442,16 @@ static struct s5h1409_config dvico_hdtv5_pci_nano_config = { | |||
443 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | 442 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, |
444 | }; | 443 | }; |
445 | 444 | ||
445 | static struct s5h1409_config kworld_atsc_120_config = { | ||
446 | .demod_address = 0x32 >> 1, | ||
447 | .qam_if = 44000, | ||
448 | .output_mode = S5H1409_SERIAL_OUTPUT, | ||
449 | .gpio = S5H1409_GPIO_OFF, | ||
450 | .inversion = S5H1409_INVERSION_OFF, | ||
451 | .status_mode = S5H1409_DEMODLOCKING, | ||
452 | .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, | ||
453 | }; | ||
454 | |||
446 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { | 455 | static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { |
447 | .i2c_address = 0x64, | 456 | .i2c_address = 0x64, |
448 | .if_khz = 5380, | 457 | .if_khz = 5380, |
@@ -457,9 +466,12 @@ static struct zl10353_config cx88_geniatech_x8000_mt = { | |||
457 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | 466 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) |
458 | { | 467 | { |
459 | struct dvb_frontend *fe; | 468 | struct dvb_frontend *fe; |
469 | struct xc2028_ctrl ctl; | ||
460 | struct xc2028_config cfg = { | 470 | struct xc2028_config cfg = { |
461 | .i2c_adap = &dev->core->i2c_adap, | 471 | .i2c_adap = &dev->core->i2c_adap, |
462 | .i2c_addr = addr, | 472 | .i2c_addr = addr, |
473 | .ctrl = &ctl, | ||
474 | .callback = cx88_tuner_callback, | ||
463 | }; | 475 | }; |
464 | 476 | ||
465 | if (!dev->dvb.frontend) { | 477 | if (!dev->dvb.frontend) { |
@@ -469,6 +481,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
469 | return -EINVAL; | 481 | return -EINVAL; |
470 | } | 482 | } |
471 | 483 | ||
484 | /* | ||
485 | * Some xc3028 devices may be hidden by an I2C gate. This is known | ||
486 | * to happen with some s5h1409-based devices. | ||
487 | * Now that I2C gate is open, sets up xc3028 configuration | ||
488 | */ | ||
489 | cx88_setup_xc3028(dev->core, &ctl); | ||
490 | |||
472 | fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); | 491 | fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); |
473 | if (!fe) { | 492 | if (!fe) { |
474 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", | 493 | printk(KERN_ERR "%s/2: xc3028 attach failed\n", |
@@ -810,7 +829,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
810 | return -EINVAL; | 829 | return -EINVAL; |
811 | break; | 830 | break; |
812 | case CX88_BOARD_GENIATECH_X8000_MT: | 831 | case CX88_BOARD_GENIATECH_X8000_MT: |
813 | dev->ts_gen_cntrl = 0x00; | 832 | dev->ts_gen_cntrl = 0x00; |
814 | 833 | ||
815 | dev->dvb.frontend = dvb_attach(zl10353_attach, | 834 | dev->dvb.frontend = dvb_attach(zl10353_attach, |
816 | &cx88_geniatech_x8000_mt, | 835 | &cx88_geniatech_x8000_mt, |
@@ -818,6 +837,13 @@ static int dvb_register(struct cx8802_dev *dev) | |||
818 | if (attach_xc3028(0x61, dev) < 0) | 837 | if (attach_xc3028(0x61, dev) < 0) |
819 | return -EINVAL; | 838 | return -EINVAL; |
820 | break; | 839 | break; |
840 | case CX88_BOARD_KWORLD_ATSC_120: | ||
841 | dev->dvb.frontend = dvb_attach(s5h1409_attach, | ||
842 | &kworld_atsc_120_config, | ||
843 | &dev->core->i2c_adap); | ||
844 | if (attach_xc3028(0x61, dev) < 0) | ||
845 | return -EINVAL; | ||
846 | break; | ||
821 | default: | 847 | default: |
822 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", | 848 | printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", |
823 | dev->core->name); | 849 | dev->core->name); |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index c0f4912793e9..d17ca71c5d95 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include "btcx-risc.h" | 38 | #include "btcx-risc.h" |
39 | #include "cx88-reg.h" | 39 | #include "cx88-reg.h" |
40 | #include "tuner-xc2028.h" | ||
40 | 41 | ||
41 | #include <linux/version.h> | 42 | #include <linux/version.h> |
42 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
@@ -219,6 +220,7 @@ extern struct sram_channel cx88_sram_channels[]; | |||
219 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 | 220 | #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 |
220 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 | 221 | #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 |
221 | #define CX88_BOARD_PROLINK_PV_8000GT 66 | 222 | #define CX88_BOARD_PROLINK_PV_8000GT 66 |
223 | #define CX88_BOARD_KWORLD_ATSC_120 67 | ||
222 | 224 | ||
223 | enum cx88_itype { | 225 | enum cx88_itype { |
224 | CX88_VMUX_COMPOSITE1 = 1, | 226 | CX88_VMUX_COMPOSITE1 = 1, |
@@ -603,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg); | |||
603 | extern int cx88_get_resources(const struct cx88_core *core, | 605 | extern int cx88_get_resources(const struct cx88_core *core, |
604 | struct pci_dev *pci); | 606 | struct pci_dev *pci); |
605 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); | 607 | extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); |
608 | extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); | ||
606 | 609 | ||
607 | /* ----------------------------------------------------------- */ | 610 | /* ----------------------------------------------------------- */ |
608 | /* cx88-tvaudio.c */ | 611 | /* cx88-tvaudio.c */ |