diff options
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r-- | drivers/media/video/cx88/cx88-cards.c | 58 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-core.c | 3 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 405 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-i2c.c | 17 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-mpeg.c | 22 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-tvaudio.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88-video.c | 52 | ||||
-rw-r--r-- | drivers/media/video/cx88/cx88.h | 7 |
8 files changed, 405 insertions, 170 deletions
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 5da04e811ca..fbc224f46e0 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1270,27 +1270,40 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_HAUPPAUGE_HVR3000] = { - /* FIXME: Add dvb & radio support */ .name = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T", .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .audio_chip = V4L2_IDENT_WM8775, .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x84bf, + /* 1: TV Audio / FM Mono */ + .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x84bf, + /* 2: Line-In */ + .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x84bf, + /* 2: Line-In */ + .audioroute = 2, }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x84bf, + /* 4: FM Stereo (untested) */ + .audioroute = 8, + }, .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_NORWOOD_MICRO] = { .name = "Norwood Micro TV Tuner", @@ -1356,23 +1369,27 @@ static const struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xef88, + /* 1: TV Audio / FM Mono */ .audioroute = 1, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xef88, + /* 2: Line-In */ .audioroute = 2, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xef88, + /* 2: Line-In */ .audioroute = 2, }}, - /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD, .radio = { .type = CX88_RADIO, .gpio0 = 0xef88, + /* 4: FM Stereo (untested) */ + .audioroute = 8, }, }, [CX88_BOARD_ADSTECH_PTV_390] = { @@ -1716,6 +1733,7 @@ static const struct cx88_board cx88_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .audio_chip = V4L2_IDENT_WM8775, /* * GPIO0 (WINTV2000) * @@ -1729,7 +1747,7 @@ static const struct cx88_board cx88_boards[] = { * BIT VALUE FUNCTION GP{x}_IO * 0 1 I:? * 1 1 I:? - * 2 1 O:DVB-T DEMOD ENABLE LOW/ANALOG DEMOD ENABLE HIGH + * 2 1 O:MPEG PORT 0=DVB-T 1=DVB-S * 3 1 I:? * 4 1 I:? * 5 1 I:? @@ -1745,22 +1763,41 @@ static const struct cx88_board cx88_boards[] = { * d 0 I * e 1 O * f 1 O + * + * WM8775 ADC + * + * 1: TV Audio / FM Mono + * 2: Line-In + * 3: Line-In Expansion + * 4: FM Stereo */ .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0xc4bf, + /* 1: TV Audio / FM Mono */ + .audioroute = 1, }, { .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0xc4bf, + /* 2: Line-In */ + .audioroute = 2, }, { .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0xc4bf, + /* 2: Line-In */ + .audioroute = 2, } }, - /* fixme: Add radio support */ + .radio = { + .type = CX88_RADIO, + .gpio0 = 0xc4bf, + /* 4: FM Stereo */ + .audioroute = 8, + }, .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", @@ -2662,10 +2699,13 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: /* Init GPIO */ cx_write(MO_GP0_IO, core->board.input[0].gpio0); udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ + udelay(1000); break; } } @@ -3004,10 +3044,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board)); - info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + if (!core->board.num_frontends) + core->board.num_frontends=1; + + info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n", pci->subsystem_vendor, pci->subsystem_device, core->board.name, core->boardnr, card[core->nr] == core->boardnr ? - "insmod option" : "autodetected"); + "insmod option" : "autodetected", + core->board.num_frontends); if (tuner[core->nr] != UNSET) core->board.tuner_type = tuner[core->nr]; diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index d656fec5901..60705b08bfe 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -549,7 +549,8 @@ void cx88_wakeup(struct cx88_core *core, mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); } if (bc != 1) - printk("%s: %d buffers handled (should be 1)\n",__func__,bc); + dprintk(2, "%s: %d buffers handled (should be 1)\n", + __func__, bc); } void cx88_shutdown(struct cx88_core *core) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 344ed2626e5..6968ab0181a 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -116,13 +116,23 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) struct cx8802_dev *dev= fe->dvb->priv; struct cx8802_driver *drv = NULL; int ret = 0; + int fe_id; + + fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe); + if (!fe_id) { + printk(KERN_ERR "%s() No frontend found\n", __func__); + return -EINVAL; + } drv = cx8802_get_driver(dev, CX88_MPEG_DVB); if (drv) { - if (acquire) + if (acquire){ + dev->frontends.active_fe_id = fe_id; ret = drv->request_acquire(drv); - else + } else { ret = drv->request_release(drv); + dev->frontends.active_fe_id = 0; + } } return ret; @@ -396,7 +406,7 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe, cx_write(MO_GP0_IO, 0x00006060); break; case SEC_VOLTAGE_OFF: - printk("LNB Voltage SEC_VOLTAGE_off\n"); + printk("LNB Voltage SEC_VOLTAGE_off\n"); break; } @@ -483,6 +493,7 @@ static struct xc5000_config dvico_fusionhdtv7_tuner_config = { static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; + struct videobuf_dvb_frontend *fe0 = NULL; struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, @@ -490,7 +501,12 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) .ctrl = &ctl, }; - if (!dev->dvb.frontend) { + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + + if (!fe0->dvb.frontend) { printk(KERN_ERR "%s/2: dvb frontend not attached. " "Can't attach xc3028\n", dev->core->name); @@ -504,10 +520,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) */ cx88_setup_xc3028(dev->core, &ctl); - fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->core->name); + dvb_frontend_detach(fe0->dvb.frontend); + dvb_unregister_frontend(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; return -EINVAL; } @@ -532,8 +551,10 @@ static int cx24116_reset_device(struct dvb_frontend *fe) struct cx88_core *core = dev->core; /* Reset the part */ + /* Put the cx24116 into reset */ cx_write(MO_SRST_IO, 0); msleep(10); + /* Take the cx24116 out of reset */ cx_write(MO_SRST_IO, 1); msleep(10); @@ -554,14 +575,14 @@ static struct cx24116_config tevii_s460_config = { static struct stv0299_config tevii_tuner_sharp_config = { .demod_address = 0x68, - .inittab = sharp_z0194a__inittab, + .inittab = sharp_z0194a_inittab, .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, .lock_output = 1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, - .set_symbol_rate = sharp_z0194a__set_symbol_rate, + .set_symbol_rate = sharp_z0194a_set_symbol_rate, .set_ts_params = cx24116_set_ts_param, }; @@ -574,19 +595,25 @@ static struct stv0288_config tevii_tuner_earda_config = { static int dvb_register(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; + struct videobuf_dvb_frontend *fe0, *fe1 = NULL; + int mfe_shared = 0; /* bus not shared by default */ - /* init struct videobuf_dvb */ - dev->dvb.name = core->name; - dev->ts_gen_cntrl = 0x0c; + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; - /* init frontend */ + /* multi-frontend gate control is undefined or defaults to fe0 */ + dev->frontends.gate = 0; + + /* init frontend(s) */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap, DVB_PLL_THOMSON_DTT759X)) goto frontend_detach; @@ -596,11 +623,11 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; @@ -610,33 +637,67 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: - case CX88_BOARD_HAUPPAUGE_HVR3000: - dev->dvb.frontend = dvb_attach(cx22702_attach, + fe0->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; } break; + case CX88_BOARD_HAUPPAUGE_HVR3000: + /* DVB-S init */ + fe0->dvb.frontend = dvb_attach(cx24123_attach, + &hauppauge_novas_config, + &dev->core->i2c_adap); + if (fe0->dvb.frontend) { + if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, + &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) { + dprintk( 1, "%s(): HVR3000 - DVB-S LNB Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __func__); + } + /* DVB-T init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + dev->frontends.gate = 2; + mfe_shared = 1; + fe1->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr_config, + &dev->core->i2c_adap); + if (fe1->dvb.frontend) { + fe1->dvb.frontend->id = 1; + if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) { + dprintk( 1, "%s(): HVR3000 - DVB-T misc Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __func__); + } + break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } @@ -644,31 +705,31 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: /* The tin box says DEE1601, but it seems to be DTT7579 * compatible, with a slightly different MT352 AGC gain. */ - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_LG_Z201)) goto frontend_detach; } @@ -676,11 +737,11 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_UNKNOWN_1)) goto frontend_detach; } @@ -688,10 +749,10 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: #if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE)) /* MT352 is on a secondary I2C bus made from some GPIO lines */ - dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, + fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_FMD1216ME_MK3)) goto frontend_detach; @@ -702,22 +763,22 @@ static int dvb_register(struct cx8802_dev *dev) #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_FE6600)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &core->i2c_adap); - if (dev->dvb.frontend == NULL) - dev->dvb.frontend = dvb_attach(mt352_attach, + if (fe0->dvb.frontend == NULL) + fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &core->i2c_adap); /* @@ -725,16 +786,16 @@ static int dvb_register(struct cx8802_dev *dev) * We must not permit gate_ctrl to be performed, or * the xc3028 cannot communicate on the bus. */ - if (dev->dvb.frontend) - dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (fe0->dvb.frontend) + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; case CX88_BOARD_PCHDTV_HD3000: - dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, + fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; @@ -751,11 +812,11 @@ static int dvb_register(struct cx8802_dev *dev) /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_MICROTUNE_4042FI5)) goto frontend_detach; @@ -769,11 +830,11 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; @@ -787,15 +848,15 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; - if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } @@ -808,25 +869,25 @@ static int dvb_register(struct cx8802_dev *dev) mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); - dev->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF)) goto frontend_detach; - if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + if (!dvb_attach(tda9887_attach, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: - dev->dvb.frontend = dvb_attach(nxt200x_attach, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D)) goto frontend_detach; @@ -834,49 +895,49 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &core->i2c_adap); - if (dev->dvb.frontend) { - if (!dvb_attach(isl6421_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + if (!dvb_attach(isl6421_attach, fe0->dvb.frontend, &core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVBS_100: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &core->i2c_adap); - if (dev->dvb.frontend) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; + if (fe0->dvb.frontend) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: - dev->dvb.frontend = dvb_attach(cx24123_attach, + fe0->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &core->i2c_adap); - if (dev->dvb.frontend) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; + if (fe0->dvb.frontend) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &pinnacle_pctv_hd_800i_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, @@ -889,17 +950,17 @@ static int dvb_register(struct cx8802_dev *dev) }; fe = dvb_attach(xc2028_attach, - dev->dvb.frontend, &cfg); + fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.i2c_gate_ctrl = NULL; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } @@ -907,85 +968,118 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; - dev->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_KWORLD_ATSC_120: - dev->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: - dev->dvb.frontend = dvb_attach(s5h1411_attach, + fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(xc5000_attach, fe0->dvb.frontend, &core->i2c_adap, &dvico_fusionhdtv7_tuner_config)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR4000: + /* DVB-S/S2 Init */ + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &dev->core->i2c_adap); + if (fe0->dvb.frontend) { + if(!dvb_attach(isl6421_attach, fe0->dvb.frontend, + &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00)) { + dprintk( 1, "%s(): HVR4000 - DVB-S LNB Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __func__); + } + /* DVB-T Init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + dev->frontends.gate = 2; + mfe_shared = 1; + fe1->dvb.frontend = dvb_attach(cx22702_attach, + &hauppauge_hvr_config, + &dev->core->i2c_adap); + if (fe1->dvb.frontend) { + fe1->dvb.frontend->id = 1; + if(!dvb_attach(simple_tuner_attach, fe1->dvb.frontend, + &dev->core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) { + dprintk( 1, "%s(): HVR4000 - DVB-T misc Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __func__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __func__); + } + break; case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - /* Support for DVB-S only, not DVB-T support */ - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &dev->core->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(isl6421_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->core->i2c_adap, 0x08, ISL6421_DCL, 0x00); } break; case CX88_BOARD_TEVII_S420: - dev->dvb.frontend = dvb_attach(stv0299_attach, + fe0->dvb.frontend = dvb_attach(stv0299_attach, &tevii_tuner_sharp_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &core->i2c_adap, DVB_PLL_OPERA1)) goto frontend_detach; - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } else { - dev->dvb.frontend = dvb_attach(stv0288_attach, + fe0->dvb.frontend = dvb_attach(stv0288_attach, &tevii_tuner_earda_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - if (!dvb_attach(stb6000_attach, dev->dvb.frontend, 0x61, + if (fe0->dvb.frontend != NULL) { + if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap)) goto frontend_detach; - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } } break; case CX88_BOARD_TEVII_S460: - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + if (fe0->dvb.frontend != NULL) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; case CX88_BOARD_OMICOM_SS4_PCI: case CX88_BOARD_TBS_8920: case CX88_BOARD_PROF_7300: - dev->dvb.frontend = dvb_attach(cx24116_attach, + fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &core->i2c_adap); - if (dev->dvb.frontend != NULL) { - core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; - dev->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; + if (fe0->dvb.frontend != NULL) { + core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage; + fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } break; default: @@ -993,29 +1087,32 @@ static int dvb_register(struct cx8802_dev *dev) core->name); break; } - if (NULL == dev->dvb.frontend) { + + if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { printk(KERN_ERR "%s/2: frontend initialization failed\n", core->name); return -EINVAL; } /* define general-purpose callback pointer */ - dev->dvb.frontend->callback = cx88_tuner_callback; + fe0->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ - dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; + fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; + if (fe1) + fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); /* register everything */ - return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, - &dev->pci->dev, adapter_nr); + return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: - if (dev->dvb.frontend) { - dvb_frontend_detach(dev->dvb.frontend); - dev->dvb.frontend = NULL; + if (fe0->dvb.frontend) { + dvb_frontend_detach(fe0->dvb.frontend); + fe0->dvb.frontend = NULL; } return -EINVAL; } @@ -1039,6 +1136,38 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; + + case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + if(core->dvbdev->frontends.active_fe_id == 1) { + /* DVB-S/S2 Enabled */ + + /* Toggle reset on cx22702 leaving i2c active */ + cx_write(MO_GP0_IO, (core->board.input[0].gpio0 & 0x0000ff00) | 0x00000080); + udelay(1000); + cx_clear(MO_GP0_IO, 0x00000080); + udelay(50); + cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset */ + cx_set(MO_GP0_IO, 0x00000004); /* tri-state the cx22702 pins */ + udelay(1000); + + cx_write(MO_SRST_IO, 1); /* Take the cx24116/cx24123 out of reset */ + core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ + } else + if (core->dvbdev->frontends.active_fe_id == 2) { + /* DVB-T Enabled */ + + /* Put the cx24116/cx24123 into reset */ + cx_write(MO_SRST_IO, 0); + + /* cx22702 out of reset and enable it */ + cx_set(MO_GP0_IO, 0x00000080); + cx_clear(MO_GP0_IO, 0x00000004); + core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ + udelay(1000); + } + break; + default: err = -ENODEV; } @@ -1056,6 +1185,9 @@ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) case CX88_BOARD_HAUPPAUGE_HVR1300: /* Do Nothing, leave the cx22702 on the bus. */ break; + case CX88_BOARD_HAUPPAUGE_HVR3000: + case CX88_BOARD_HAUPPAUGE_HVR4000: + break; default: err = -ENODEV; } @@ -1066,7 +1198,8 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; - int err; + int err, i; + struct videobuf_dvb_frontend *fe; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", @@ -1086,18 +1219,28 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); - videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops, + dev->ts_gen_cntrl = 0x0c; + + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); + if (!fe) { + printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i); + continue; + } + videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx88_buffer), dev); + /* init struct videobuf_dvb */ + fe->dvb.name = dev->core->name; + } err = dvb_register(dev); if (err != 0) printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", core->name, err); - - fail_core: +fail_core: return err; } @@ -1105,9 +1248,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx8802_dev *dev = drv->core->dvbdev; - /* dvb */ - if (dev->dvb.frontend) - videobuf_dvb_unregister(&dev->dvb); + videobuf_dvb_unregister_bus(&dev->frontends); vp3054_i2c_remove(dev); diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 8e74d64fdcd..01de2300709 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -116,18 +116,25 @@ static int detach_inform(struct i2c_client *client) void cx88_call_i2c_clients(struct cx88_core *core, unsigned int cmd, void *arg) { + struct videobuf_dvb_frontends *f = &core->dvbdev->frontends; + struct videobuf_dvb_frontend *fe = NULL; if (0 != core->i2c_rc) return; #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) - if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) { - if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1); + if (core->dvbdev && f) { + if(f->gate <= 1) /* undefined or fe0 */ + fe = videobuf_dvb_get_frontend(f, 1); + else + fe = videobuf_dvb_get_frontend(f, f->gate); + + if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) + fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 1); i2c_clients_command(&core->i2c_adap, cmd, arg); - if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl) - core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0); + if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) + fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, 0); } else #endif i2c_clients_command(&core->i2c_adap, cmd, arg); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a6b061c2644..6df5cf31418 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -768,7 +768,8 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, { struct cx8802_dev *dev; struct cx88_core *core; - int err; + struct videobuf_dvb_frontend *demod; + int err,i; /* general setup */ core = cx88_core_get(pci_dev); @@ -781,6 +782,11 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, if (!core->board.mpeg) goto fail_core; + if (!core->board.num_frontends) { + printk(KERN_ERR "%s() .num_frontends should be non-zero, err = %d\n", __func__, err); + goto fail_core; + } + err = -ENOMEM; dev = kzalloc(sizeof(*dev),GFP_KERNEL); if (NULL == dev) @@ -795,6 +801,20 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, INIT_LIST_HEAD(&dev->drvlist); list_add_tail(&dev->devlist,&cx8802_devlist); + mutex_init(&dev->frontends.lock); + INIT_LIST_HEAD(&dev->frontends.felist); + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); + + for (i = 1; i <= core->board.num_frontends; i++) { + demod = videobuf_dvb_alloc_frontend(&dev->frontends, i); + if(demod == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", __func__); + err = -ENOMEM; + goto fail_free; + } + } + /* Maintain a reference so cx88-video can query the 8802 device. */ core->dvbdev = dev; diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c index 3a1977f41e2..7dd506b987f 100644 --- a/drivers/media/video/cx88/cx88-tvaudio.c +++ b/drivers/media/video/cx88/cx88-tvaudio.c @@ -767,6 +767,14 @@ void cx88_set_tvaudio(struct cx88_core *core) case WW_FM: set_audio_standard_FM(core, radio_deemphasis); break; + case WW_I2SADC: + set_audio_start(core, 0x01); + /* Slave/Philips/Autobaud */ + cx_write(AUD_I2SINPUTCNTL, 0); + /* Switch to "I2S ADC mode" */ + cx_write(AUD_I2SCNTL, 0x1); + set_audio_finish(core, EN_I2SIN_ENABLE); + break; case WW_NONE: default: printk("%s/0: unknown tv audio mode [%d]\n", @@ -895,6 +903,9 @@ void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) break; } break; + case WW_I2SADC: + /* DO NOTHING */ + break; } if (UNSET != ctl) { diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index be45955dff6..3904b73f52e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -426,24 +426,7 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) /* if there are audioroutes defined, we have an external ADC to deal with audio */ - if (INPUT(input).audioroute) { - - /* cx2388's C-ADC is connected to the tuner only. - When used with S-Video, that ADC is busy dealing with - chroma, so an external must be used for baseband audio */ - - if (INPUT(input).type != CX88_VMUX_TELEVISION && - INPUT(input).type != CX88_RADIO) { - /* "ADC mode" */ - cx_write(AUD_I2SCNTL, 0x1); - cx_set(AUD_CTL, EN_I2SIN_ENABLE); - } else { - /* Normal mode */ - cx_write(AUD_I2SCNTL, 0x0); - cx_clear(AUD_CTL, EN_I2SIN_ENABLE); - } - /* The wm8775 module has the "2" route hardwired into the initialization. Some boards may use different routes for different inputs. HVR-1300 surely does */ @@ -454,9 +437,19 @@ int cx88_video_mux(struct cx88_core *core, unsigned int input) route.input = INPUT(input).audioroute; cx88_call_i2c_clients(core, VIDIOC_INT_S_AUDIO_ROUTING, &route); - } - + /* cx2388's C-ADC is connected to the tuner only. + When used with S-Video, that ADC is busy dealing with + chroma, so an external must be used for baseband audio */ + if (INPUT(input).type != CX88_VMUX_TELEVISION ) { + /* "I2S ADC mode" */ + core->tvaudio = WW_I2SADC; + cx88_set_tvaudio(core); + } else { + /* Normal mode */ + cx_write(AUD_I2SCNTL, 0x0); + cx_clear(AUD_CTL, EN_I2SIN_ENABLE); + } } return 0; @@ -832,9 +825,24 @@ static int video_open(struct inode *inode, struct file *file) cx_write(MO_GP0_IO, core->board.radio.gpio0); cx_write(MO_GP1_IO, core->board.radio.gpio1); cx_write(MO_GP2_IO, core->board.radio.gpio2); - core->tvaudio = WW_FM; - cx88_set_tvaudio(core); - cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); + if (core->board.radio.audioroute) { + if(core->board.audio_chip && + core->board.audio_chip == V4L2_IDENT_WM8775) { + struct v4l2_routing route; + + route.input = core->board.radio.audioroute; + cx88_call_i2c_clients(core, + VIDIOC_INT_S_AUDIO_ROUTING, &route); + } + /* "I2S ADC mode" */ + core->tvaudio = WW_I2SADC; + cx88_set_tvaudio(core); + } else { + /* FM Mode */ + core->tvaudio = WW_FM; + cx88_set_tvaudio(core); + cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); + } cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); } unlock_kernel(); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index dbf01b8b57a..76207c2856b 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -247,7 +247,7 @@ struct cx88_input { enum cx88_itype type; u32 gpio0, gpio1, gpio2, gpio3; unsigned int vmux:2; - unsigned int audioroute:2; + unsigned int audioroute:4; }; struct cx88_board { @@ -261,6 +261,7 @@ struct cx88_board { struct cx88_input radio; enum cx88_board_type mpeg; unsigned int audio_chip; + int num_frontends; }; struct cx88_subid { @@ -356,6 +357,7 @@ struct cx88_core { struct cx8802_dev *dvbdev; enum cx88_board_type active_type_id; int active_ref; + int active_fe_id; }; struct cx8800_dev; @@ -490,7 +492,7 @@ struct cx8802_dev { #if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) /* for dvb only */ - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; #endif #if defined(CONFIG_VIDEO_CX88_VP3054) || \ @@ -628,6 +630,7 @@ extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); #define WW_EIAJ 7 #define WW_I2SPT 8 #define WW_FM 9 +#define WW_I2SADC 10 void cx88_set_tvaudio(struct cx88_core *core); void cx88_newstation(struct cx88_core *core); |