diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 72ce7935f253..26671757c70b 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -212,8 +212,9 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe, static void dvb_frontend_init(struct dvb_frontend *fe) { - dprintk ("DVB: initialising frontend %i (%s)...\n", + dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); if (fe->ops.init) @@ -686,7 +687,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe) mb(); fe_thread = kthread_run(dvb_frontend_thread, fe, - "kdvb-fe-%i", fe->dvb->num); + "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id); if (IS_ERR(fe_thread)) { ret = PTR_ERR(fe_thread); printk("dvb_frontend_start: failed to start kthread (%d)\n", ret); @@ -710,8 +711,8 @@ static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe, *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max); if (*freq_min == 0 || *freq_max == 0) - printk(KERN_WARNING "DVB: frontend %u frequency limits undefined - fix the driver\n", - fe->dvb->num); + printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", + fe->dvb->num,fe->id); } static int dvb_frontend_check_parameters(struct dvb_frontend *fe, @@ -724,8 +725,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max); if ((freq_min && parms->frequency < freq_min) || (freq_max && parms->frequency > freq_max)) { - printk(KERN_WARNING "DVB: frontend %u frequency %u out of range (%u..%u)\n", - fe->dvb->num, parms->frequency, freq_min, freq_max); + printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->frequency, freq_min, freq_max); return -EINVAL; } @@ -735,8 +736,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qpsk.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qpsk.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -746,8 +747,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, parms->u.qam.symbol_rate < fe->ops.info.symbol_rate_min) || (fe->ops.info.symbol_rate_max && parms->u.qam.symbol_rate > fe->ops.info.symbol_rate_max)) { - printk(KERN_WARNING "DVB: frontend %u symbol rate %u out of range (%u..%u)\n", - fe->dvb->num, parms->u.qam.symbol_rate, + printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n", + fe->dvb->num, fe->id, parms->u.qam.symbol_rate, fe->ops.info.symbol_rate_min, fe->ops.info.symbol_rate_max); return -EINVAL; } @@ -1807,8 +1808,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb, fe->dvb = dvb; fepriv->inversion = INVERSION_OFF; - printk ("DVB: registering frontend %i (%s)...\n", + printk ("DVB: registering adapter %i frontend %i (%s)...\n", fe->dvb->num, + fe->id, fe->ops.info.name); dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template, diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index 3055301ff3ca..db4a63b0a32e 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -222,6 +222,7 @@ struct dvb_frontend { struct dtv_frontend_properties dtv_property_cache; #define DVB_FRONTEND_COMPONENT_TUNER 0 int (*callback)(void *adapter_priv, int component, int cmd, int arg); + int id; }; extern int dvb_register_frontend(struct dvb_adapter *dvb, diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 24bd18327aa0..fe1218fd44cb 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -312,48 +312,53 @@ static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL; + struct videobuf_dvb_frontend *fe0; + + fe0 = videobuf_dvb_get_frontend(&port->frontends, 0); + if (!fe0) + return -EINVAL; /* init struct videobuf_dvb */ - port->dvb.name = dev->name; + fe0->dvb.name = dev->name; /* init frontend */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); } break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; - switch (alt_tuner) { + switch (alt_tuner) { // XXXXXX multifrontend? case 1: - port->dvb.frontend = + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(tda829x_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, 0x42, &tda829x_no_probe); - dvb_attach(tda18271_attach, port->dvb.frontend, + dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: - port->dvb.frontend = + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; @@ -361,42 +366,42 @@ static int dvb_register(struct cx23885_tsport *port) break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(mt2131_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(lgdt330x_attach, + fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF); } break; case CX23885_BOARD_HAUPPAUGE_HVR1500Q: i2c_bus = &dev->i2c_bus[1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(xc5000_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_hvr1500q_tunerconfig); break; case CX23885_BOARD_HAUPPAUGE_HVR1500: i2c_bus = &dev->i2c_bus[1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, @@ -409,7 +414,7 @@ static int dvb_register(struct cx23885_tsport *port) }; fe = dvb_attach(xc2028_attach, - port->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); } @@ -417,24 +422,24 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(tda10048_attach, + fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { - dvb_attach(tda829x_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, 0x42, &tda829x_no_probe); - dvb_attach(tda18271_attach, port->dvb.frontend, + dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(dib7000p_attach, + fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, @@ -449,7 +454,7 @@ static int dvb_register(struct cx23885_tsport *port) }; fe = dvb_attach(xc2028_attach, - port->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); } @@ -457,25 +462,25 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; - port->dvb.frontend = dvb_attach(s5h1409_attach, + fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend == NULL) - port->dvb.frontend = dvb_attach(s5h1411_attach, + if (fe0->dvb.frontend == NULL) + fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) - dvb_attach(xc5000_attach, port->dvb.frontend, + if (fe0->dvb.frontend != NULL) + dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &dvico_xc5000_tunerconfig); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: { i2c_bus = &dev->i2c_bus[port->nr - 1]; - port->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, @@ -487,7 +492,7 @@ static int dvb_register(struct cx23885_tsport *port) .demod = XC3028_FE_ZARLINK456, }; - fe = dvb_attach(xc2028_attach, port->dvb.frontend, + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); @@ -497,10 +502,10 @@ static int dvb_register(struct cx23885_tsport *port) case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: i2c_bus = &dev->i2c_bus[0]; - port->dvb.frontend = dvb_attach(zl10353_attach, + fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); - if (port->dvb.frontend != NULL) { + if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, @@ -512,7 +517,7 @@ static int dvb_register(struct cx23885_tsport *port) .demod = XC3028_FE_ZARLINK456, }; - fe = dvb_attach(xc2028_attach, port->dvb.frontend, + fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg); if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) fe->ops.tuner_ops.set_config(fe, &ctl); @@ -523,29 +528,36 @@ static int dvb_register(struct cx23885_tsport *port) dev->name); break; } - if (NULL == port->dvb.frontend) { + if (NULL == fe0->dvb.frontend) { printk("%s: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ - port->dvb.frontend->callback = cx23885_tuner_callback; + fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ cx23885_call_i2c_clients(i2c_bus, TUNER_SET_STANDBY, NULL); - if (port->dvb.frontend->ops.analog_ops.standby) - port->dvb.frontend->ops.analog_ops.standby(port->dvb.frontend); + if (fe0->dvb.frontend->ops.analog_ops.standby) + fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ - return videobuf_dvb_register(&port->dvb, THIS_MODULE, port, + return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr); + } int cx23885_dvb_register(struct cx23885_tsport *port) { + + struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err; + fe0 = videobuf_dvb_get_frontend(&port->frontends, 0); + if (!fe0) + err = -EINVAL; + dprintk(1, "%s\n", __func__); dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, @@ -557,7 +569,7 @@ int cx23885_dvb_register(struct cx23885_tsport *port) /* dvb stuff */ printk("%s: cx23885 based dvb card\n", dev->name); - videobuf_queue_sg_init(&port->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, + videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops, &dev->pci->dev, &port->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, sizeof(struct cx23885_buffer), port); err = dvb_register(port); @@ -569,9 +581,12 @@ int cx23885_dvb_register(struct cx23885_tsport *port) int cx23885_dvb_unregister(struct cx23885_tsport *port) { + struct videobuf_dvb_frontend *fe0; + + fe0 = videobuf_dvb_get_frontend(&port->frontends, 0); /* dvb */ - if(port->dvb.frontend) - videobuf_dvb_unregister(&port->dvb); + if(fe0->dvb.frontend) + videobuf_dvb_unregister_bus(&port->frontends); return 0; } diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index ba4e0aaed463..aa34bf9ea4d9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -225,7 +225,7 @@ struct cx23885_tsport { int nr; int sram_chno; - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; /* dma queues */ struct cx23885_dmaqueue mpegq; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 5da04e811ca2..638d9ec38d7f 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1291,6 +1291,7 @@ static const struct cx88_board cx88_boards[] = { .gpio0 = 0x84bf, }}, .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_NORWOOD_MICRO] = { .name = "Norwood Micro TV Tuner", @@ -1761,6 +1762,7 @@ static const struct cx88_board cx88_boards[] = { } }, /* fixme: Add radio support */ .mpeg = CX88_MPEG_DVB, + .num_frontends = 2, }, [CX88_BOARD_HAUPPAUGE_HVR4000LITE] = { .name = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2", @@ -3002,12 +3004,17 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) cx88_card_list(core, pci); } + memset(&core->board, 0, sizeof(core->board)); 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-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 344ed2626e59..099de66c72c4 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -116,13 +116,24 @@ 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", __FUNCTION__); + 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 +407,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 +494,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 +502,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 +521,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 +552,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); @@ -573,20 +595,28 @@ static struct stv0288_config tevii_tuner_earda_config = { static int dvb_register(struct cx8802_dev *dev) { - struct cx88_core *core = dev->core; + //struct cx88_core *core = dev->core; - /* init struct videobuf_dvb */ - dev->dvb.name = core->name; - dev->ts_gen_cntrl = 0x0c; + ///* init struct videobuf_dvb */ + //fe->dvb.name = core->name; + //dev->ts_gen_cntrl = 0x0c; + + struct cx88_core *core = dev->core; + struct videobuf_dvb_frontend *fe0, *fe1 = NULL; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; /* init frontend */ 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 +626,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 +640,65 @@ 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", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-S Init: failed\n", __FUNCTION__); + } + /* DVB-T init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + 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", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR3000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__); + } + 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 +706,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 +738,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 +750,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 +764,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 +787,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 +813,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 +831,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 +849,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 +870,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 +896,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 +951,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 +969,116 @@ 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: - case CX88_BOARD_HAUPPAUGE_HVR4000LITE: - /* Support for DVB-S only, not DVB-T support */ - dev->dvb.frontend = dvb_attach(cx24116_attach, + /* DVB-S/S2 Init */ + 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) { + 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", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-S Init: failed\n", __FUNCTION__); + } + /* DVB-T Init */ + fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); + if (fe1) { + 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", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: failed\n", __FUNCTION__); + } + } else { + dprintk( 1, "%s(): HVR4000 - DVB-T Init: can't find frontend 2.\n", __FUNCTION__); + } + break; + case CX88_BOARD_HAUPPAUGE_HVR4000LITE: + fe0->dvb.frontend = dvb_attach(cx24116_attach, + &hauppauge_hvr4000_config, + &dev->core->i2c_adap); + 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 +1086,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); 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 +1135,66 @@ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; + + case CX88_BOARD_HAUPPAUGE_HVR3000: /* ? */ + 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); + 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; + 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 +1212,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 +1225,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,12 +1246,23 @@ 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", __FUNCTION__, 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", @@ -1105,9 +1276,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 8e74d64fdcd2..582769de26b5 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -116,18 +116,23 @@ 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_frontend *fe0 = 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) { + /* Get the first frontend and assume that all I2C is routed through it */ + /* TODO: Get _THIS_FE_ then find the right i2c_gate_ctrl for it */ + fe0 = videobuf_dvb_get_frontend(&core->dvbdev->frontends, 1); + + if (fe0 && fe0->dvb.frontend && fe0->dvb.frontend->ops.i2c_gate_ctrl) + fe0->dvb.frontend->ops.i2c_gate_ctrl(fe0->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 (fe0 && fe0->dvb.frontend && fe0->dvb.frontend->ops.i2c_gate_ctrl) + fe0->dvb.frontend->ops.i2c_gate_ctrl(fe0->dvb.frontend, 0); } else #endif i2c_clients_command(&core->i2c_adap, cmd, arg); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index 8683d104de72..17150cb88c80 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -495,6 +495,7 @@ void cx88_ir_irq(struct cx88_core *core) case CX88_BOARD_PINNACLE_PCTV_HD_800i: ircode = ir_decode_biphase(ir->samples, ir->scount, 5, 7); ir_dprintk("biphase decoded: %x\n", ircode); +//TODO Darron has other code here if ((ircode & 0xfffff000) != 0x3000) break; ir_input_keydown(ir->input, &ir->ir, ircode & 0x3f, ircode); diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a6b061c2644a..22c2a88fbf1c 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", __FUNCTION__, 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.frontend.felist); + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __FUNCTION__, core->board.num_frontends); + + for (i = 1; i <= core->board.num_frontends; i++) { + demod = videobuf_dvb_alloc_frontend(dev, &dev->frontends, i); + if(demod == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", __FUNCTION__); + 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.h b/drivers/media/video/cx88/cx88.h index dbf01b8b57a5..063f7b57e42a 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -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) || \ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 87c10983266f..8ada0497fa03 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -535,11 +535,15 @@ static int configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf, struct tda827x_config *tuner_conf) { - dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); - if (dev->dvb.frontend) { + struct videobuf_dvb_frontend *fe0; + + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 0); + + fe0->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); + if (fe0->dvb.frontend) { if (cdec_conf->i2c_gate) - dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - if (dvb_attach(tda827x_attach, dev->dvb.frontend, + fe0->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; + if (dvb_attach(tda827x_attach, fe0->dvb.frontend, cdec_conf->tuner_address, &dev->i2c_adap, tuner_conf)) return 0; @@ -944,12 +948,18 @@ static int dvb_init(struct saa7134_dev *dev) { int ret; int attach_xc3028 = 0; + struct videobuf_dvb_frontend *fe0; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 0); + if (!fe0) + return -EINVAL; /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; - dev->dvb.name = dev->name; - videobuf_queue_sg_init(&dev->dvb.dvbq, &saa7134_ts_qops, + fe0->dvb.name = dev->name; + videobuf_queue_sg_init(&fe0->dvb.dvbq, &saa7134_ts_qops, &dev->pci->dev, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_ALTERNATE, @@ -959,47 +969,47 @@ static int dvb_init(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: dprintk("pinnacle 300i dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i, + fe0->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params; } break; case SAA7134_BOARD_AVERMEDIA_777: case SAA7134_BOARD_AVERMEDIA_A16AR: dprintk("avertv 777 dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777, &dev->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_TD1316); } break; case SAA7134_BOARD_AVERMEDIA_A16D: dprintk("AverMedia A16D dvb setup\n"); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; break; case SAA7134_BOARD_MD7134: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus, &dev->i2c_adap); - if (dev->dvb.frontend) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) { + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, medion_cardbus.tuner_address, TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_PHILIPS_TOUGH: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_60_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; case SAA7134_BOARD_FLYDVBTDUO: @@ -1010,24 +1020,24 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; - dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; - dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + if (fe0->dvb.frontend) { + dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep; + fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep; + fe0->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; + fe0->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_61_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_tu1216_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_tda6651_pll_set; } break; case SAA7134_BOARD_KWORLD_DVBT_210: @@ -1060,20 +1070,20 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_0) < 0) goto dettach_frontend; break; - case SAA7134_BOARD_FLYDVB_TRIO: + case SAA7134_BOARD_FLYDVB_TRIO: // XXXXXX multifrontend if (!use_frontend) { /* terrestrial */ if (configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x63, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, + if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); goto dettach_frontend; @@ -1083,11 +1093,11 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331: case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &ads_tech_duo_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda827x_attach,dev->dvb.frontend, + if (fe0->dvb.frontend) { + if (dvb_attach(tda827x_attach,fe0->dvb.frontend, ads_tech_duo_config.tuner_address, &dev->i2c_adap, &ads_duo_cfg) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", @@ -1108,15 +1118,15 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_0) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - struct dvb_frontend *fe = dev->dvb.frontend; + if (fe0->dvb.frontend) { + struct dvb_frontend *fe = fe0->dvb.frontend; u8 dev_id = dev->eedata[2]; u8 data = 0xc4; struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; - if (dvb_attach(tda826x_attach, dev->dvb.frontend, + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Medion Quadro, no tda826x " "found !\n", __func__); @@ -1150,31 +1160,31 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: - dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, &dev->i2c_adap); - if (dev->dvb.frontend) - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, + if (fe0->dvb.frontend) + dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_TDHU2); break; case SAA7134_BOARD_ADS_INSTANT_HDTV_PCI: case SAA7134_BOARD_KWORLD_ATSC110: - dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, + fe0->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); - if (dev->dvb.frontend) - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + if (fe0->dvb.frontend) + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D); break; case SAA7134_BOARD_FLYDVBS_LR300: - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(isl6421_attach, dev->dvb.frontend, + if (dvb_attach(isl6421_attach, fe0->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: No ISL6421 found!\n", __func__); goto dettach_frontend; @@ -1182,25 +1192,25 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; - dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; + if (fe0->dvb.frontend) { + dev->original_demod_sleep = fe0->dvb.frontend->ops.sleep; + fe0->dvb.frontend->ops.sleep = philips_europa_demod_sleep; - dvb_attach(simple_tuner_attach, dev->dvb.frontend, + dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &dev->i2c_adap, medion_cardbus.tuner_address, TUNER_PHILIPS_FMD1216ME_MK3); } break; case SAA7134_BOARD_VIDEOMATE_DVBT_200A: - dev->dvb.frontend = dvb_attach(tda10046_attach, + fe0->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config, &dev->i2c_adap); - if (dev->dvb.frontend) { - dev->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; - dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; + if (fe0->dvb.frontend) { + fe0->dvb.frontend->ops.tuner_ops.init = philips_td1316_tuner_init; + fe0->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; } break; case SAA7134_BOARD_CINERGY_HT_PCMCIA: @@ -1239,15 +1249,15 @@ static int dvb_init(struct saa7134_dev *dev) goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_SNAKE: - dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { - if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + if (fe0->dvb.frontend) { + if (dvb_attach(tda826x_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: No lnbp21 found!\n", __func__); goto dettach_frontend; @@ -1269,24 +1279,24 @@ static int dvb_init(struct saa7134_dev *dev) saa7134_set_gpio(dev, 25, 0); msleep(10); saa7134_set_gpio(dev, 25, 1); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; break; case SAA7134_BOARD_MD7134_BRIDGE_2: - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &sd1878_4m, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (fe0->dvb.frontend) { struct dvb_frontend *fe; - if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, + if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) { wprintk("%s: MD7134 DVB-S, no SD1878 " "found !\n", __func__); goto dettach_frontend; } /* we need to open the i2c gate (we know it exists) */ - fe = dev->dvb.frontend; + fe = fe0->dvb.frontend; fe->ops.i2c_gate_ctrl(fe, 1); if (dvb_attach(isl6405_attach, fe, &dev->i2c_adap, 0x08, 0, 0) == NULL) { @@ -1305,7 +1315,7 @@ static int dvb_init(struct saa7134_dev *dev) saa7134_set_gpio(dev, 25, 0); msleep(10); saa7134_set_gpio(dev, 25, 1); - dev->dvb.frontend = dvb_attach(mt352_attach, + fe0->dvb.frontend = dvb_attach(mt352_attach, &avermedia_xc3028_mt352_dev, &dev->i2c_adap); attach_xc3028 = 1; @@ -1316,17 +1326,17 @@ static int dvb_init(struct saa7134_dev *dev) &tda827x_cfg_2) < 0) goto dettach_frontend; } else { /* satellite */ - dev->dvb.frontend = dvb_attach(tda10086_attach, + fe0->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (fe0->dvb.frontend) { if (dvb_attach(tda826x_attach, - dev->dvb.frontend, 0x60, + fe0->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no " "tda826x found!\n", __func__); goto dettach_frontend; } - if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + if (dvb_attach(lnbp21_attach, fe0->dvb.frontend, &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: Asus Tiger 3in1, no lnbp21" " found!\n", __func__); @@ -1352,10 +1362,10 @@ static int dvb_init(struct saa7134_dev *dev) .i2c_addr = 0x61, }; - if (!dev->dvb.frontend) + if (!fe0->dvb.frontend) return -1; - 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->name); @@ -1363,40 +1373,47 @@ static int dvb_init(struct saa7134_dev *dev) } } - if (NULL == dev->dvb.frontend) { + if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ - dev->dvb.frontend->callback = saa7134_tuner_callback; + fe0->dvb.frontend->callback = saa7134_tuner_callback; /* register everything else */ - ret = videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, - adapter_nr); + ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, + &dev->pci->dev, adapter_nr); /* this sequence is necessary to make the tda1004x load its firmware * and to enter analog mode of hybrid boards */ if (!ret) { - if (dev->dvb.frontend->ops.init) - dev->dvb.frontend->ops.init(dev->dvb.frontend); - if (dev->dvb.frontend->ops.sleep) - dev->dvb.frontend->ops.sleep(dev->dvb.frontend); - if (dev->dvb.frontend->ops.tuner_ops.sleep) - dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); + if (fe0->dvb.frontend->ops.init) + fe0->dvb.frontend->ops.init(fe0->dvb.frontend); + if (fe0->dvb.frontend->ops.sleep) + fe0->dvb.frontend->ops.sleep(fe0->dvb.frontend); + if (fe0->dvb.frontend->ops.tuner_ops.sleep) + fe0->dvb.frontend->ops.tuner_ops.sleep(fe0->dvb.frontend); } return ret; dettach_frontend: - 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 -1; } static int dvb_fini(struct saa7134_dev *dev) { + struct videobuf_dvb_frontend *fe0; + + /* Get the first frontend */ + fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); + if (!fe0) + return -EINVAL; + /* FIXME: I suspect that this code is bogus, since the entry for Pinnacle 300I DVB-T PAL already defines the proper init to allow the detection of mt2032 (TDA9887_PORT2_INACTIVE) @@ -1416,7 +1433,7 @@ static int dvb_fini(struct saa7134_dev *dev) u8 data = 0x80; struct i2c_msg msg = {.addr = 0x08, .buf = &data, .flags = 0, .len = 1}; struct dvb_frontend *fe; - fe = dev->dvb.frontend; + fe = fe0->dvb.frontend; if (fe->ops.i2c_gate_ctrl) { fe->ops.i2c_gate_ctrl(fe, 1); i2c_transfer(&dev->i2c_adap, &msg, 1); @@ -1424,8 +1441,8 @@ static int dvb_fini(struct saa7134_dev *dev) } } } - if (dev->dvb.frontend) - videobuf_dvb_unregister(&dev->dvb); + if (fe0->dvb.frontend) + videobuf_dvb_unregister_bus(&dev->frontends); return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 491ab1f8fdd3..24096d6e1ef8 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -581,7 +581,7 @@ struct saa7134_dev { #if defined(CONFIG_VIDEO_SAA7134_DVB) || defined(CONFIG_VIDEO_SAA7134_DVB_MODULE) /* SAA7134_MPEG_DVB only */ - struct videobuf_dvb dvb; + struct videobuf_dvb_frontends frontends; int (*original_demod_sleep)(struct dvb_frontend *fe); int (*original_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); int (*original_set_high_voltage)(struct dvb_frontend *fe, long arg); diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index b56cffcbfd45..194fb765e58b 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c @@ -135,29 +135,75 @@ static int videobuf_dvb_stop_feed(struct dvb_demux_feed *feed) } /* ------------------------------------------------------------------ */ - -int videobuf_dvb_register(struct videobuf_dvb *dvb, +/* Register a single adapter and one or more frontends */ +int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, - short *adapter_nr) + short *adapter_nr) //NEW +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe; + int res = -EINVAL; + + fe = videobuf_dvb_get_frontend(f, 1); + if (!fe) { + printk(KERN_WARNING "Unable to register the adapter which has no frontends\n"); + goto err; + } + + /* Bring up the adapter */ + res = videobuf_dvb_register_adapter(f, module, adapter_priv, device, fe->dvb.name, adapter_nr); //NEW + if (res < 0) { + printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res); + goto err; + } + + /* Attach all of the frontends to the adapter */ + mutex_lock(&f->lock); + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + + res = videobuf_dvb_register_frontend(&f->adapter, &fe->dvb); + if (res < 0) { + printk(KERN_WARNING "%s: videobuf_dvb_register_frontend failed (errno = %d)\n", + fe->dvb.name, res); + } + } + mutex_unlock(&f->lock); + +err: + return res; +} + +int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe, + struct module *module, + void *adapter_priv, + struct device *device, + char *adapter_name, + short *adapter_nr) //NEW { int result; - mutex_init(&dvb->lock); + mutex_init(&fe->lock); /* register adapter */ - result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device, - adapter_nr); + result = dvb_register_adapter(&fe->adapter, adapter_name, module, device, adapter_nr); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n", - dvb->name, result); - goto fail_adapter; + adapter_name, result); } - dvb->adapter.priv = adapter_priv; + fe->adapter.priv = adapter_priv; + + return result; +} + +int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb) +{ + int result; /* register frontend */ - result = dvb_register_frontend(&dvb->adapter, dvb->frontend); + result = dvb_register_frontend(adapter, dvb->frontend); if (result < 0) { printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n", dvb->name, result); @@ -183,7 +229,9 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, dvb->dmxdev.filternum = 256; dvb->dmxdev.demux = &dvb->demux.dmx; dvb->dmxdev.capabilities = 0; - result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + //result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter); + result = dvb_dmxdev_init(&dvb->dmxdev, adapter); + if (result < 0) { printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n", dvb->name, result); @@ -214,7 +262,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb, } /* register network adapter */ - dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx); return 0; fail_fe_conn: @@ -230,24 +278,101 @@ fail_dmx: fail_frontend: dvb_frontend_detach(dvb->frontend); dvb_unregister_adapter(&dvb->adapter); -fail_adapter: + return result; } -void videobuf_dvb_unregister(struct videobuf_dvb *dvb) +void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f) { - dvb_net_release(&dvb->net); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); - dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw); - dvb_dmxdev_release(&dvb->dmxdev); - dvb_dmx_release(&dvb->demux); - dvb_unregister_frontend(dvb->frontend); - dvb_frontend_detach(dvb->frontend); - dvb_unregister_adapter(&dvb->adapter); + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe; + + mutex_lock(&f->lock); + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + + dvb_net_release(&fe->dvb.net); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_mem); + fe->dvb.demux.dmx.remove_frontend(&fe->dvb.demux.dmx, &fe->dvb.fe_hw); + dvb_dmxdev_release(&fe->dvb.dmxdev); + dvb_dmx_release(&fe->dvb.demux); + dvb_unregister_frontend(fe->dvb.frontend); + dvb_frontend_detach(fe->dvb.frontend); + + list_del(list); + kfree(fe); + } + mutex_unlock(&f->lock); + + dvb_unregister_adapter(&f->adapter); } -EXPORT_SYMBOL(videobuf_dvb_register); -EXPORT_SYMBOL(videobuf_dvb_unregister); +struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe, *ret = NULL; + + mutex_lock(&f->lock); + + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + if (fe->id == id) { + ret = fe; + break; + } + } + + mutex_unlock(&f->lock); + + return ret; +} + +int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p) +{ + struct list_head *list, *q; + struct videobuf_dvb_frontend *fe = NULL; + int ret = 0; + + mutex_lock(&f->lock); + + list_for_each_safe(list, q, &f->frontend.felist) { + fe = list_entry(list, struct videobuf_dvb_frontend, felist); + if (fe->dvb.frontend == p) { + ret = fe->id; + break; + } + } + + mutex_unlock(&f->lock); + + return ret; +} + +struct videobuf_dvb_frontend * videobuf_dvb_alloc_frontend(void *private, struct videobuf_dvb_frontends *f, int id) +{ + struct videobuf_dvb_frontend *fe; + + fe = kzalloc(sizeof(struct videobuf_dvb_frontend),GFP_KERNEL); + if (fe == NULL) + goto fail_alloc; + + fe->dev = private; + fe->id = id; + mutex_init(&fe->dvb.lock); + + mutex_lock(&f->lock); + list_add_tail(&fe->felist,&f->frontend.felist); + mutex_unlock(&f->lock); + +fail_alloc: + return fe; +} + +EXPORT_SYMBOL(videobuf_dvb_register_bus); +EXPORT_SYMBOL(videobuf_dvb_unregister_bus); +EXPORT_SYMBOL(videobuf_dvb_alloc_frontend); +EXPORT_SYMBOL(videobuf_dvb_get_frontend); +EXPORT_SYMBOL(videobuf_dvb_find_frontend); /* ------------------------------------------------------------------ */ /* diff --git a/include/media/videobuf-dvb.h b/include/media/videobuf-dvb.h index b77748696329..09547ec3f3c3 100644 --- a/include/media/videobuf-dvb.h +++ b/include/media/videobuf-dvb.h @@ -24,12 +24,42 @@ struct videobuf_dvb { struct dvb_net net; }; -int videobuf_dvb_register(struct videobuf_dvb *dvb, +struct videobuf_dvb_frontend { + void *dev; + struct list_head felist; + int id; + struct videobuf_dvb dvb; +}; + +struct videobuf_dvb_frontends { + struct mutex lock; + struct dvb_adapter adapter; + int active_fe_id; /* Indicates which frontend in the felist is in use */ + struct videobuf_dvb_frontend frontend; +}; + +int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f, struct module *module, void *adapter_priv, struct device *device, - short *adapter_nr); -void videobuf_dvb_unregister(struct videobuf_dvb *dvb); + short *adapter_nr); //NEW + +void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f); + +int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *f, + struct module *module, + void *adapter_priv, + struct device *device, + char *adapter_name, + short *adapter_nr); //NEW + +int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, struct videobuf_dvb *dvb); + +struct videobuf_dvb_frontend * videobuf_dvb_alloc_frontend(void *private, struct videobuf_dvb_frontends *f, int id); + +struct videobuf_dvb_frontend * videobuf_dvb_get_frontend(struct videobuf_dvb_frontends *f, int id); +int videobuf_dvb_find_frontend(struct videobuf_dvb_frontends *f, struct dvb_frontend *p); + /* * Local variables: