static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL; struct videobuf_dvb_frontend *fe0, *fe1 = NULL; int mfe_shared = 0; /* bus not shared by default */ int ret; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (!fe0) return -EINVAL; /* init struct videobuf_dvb */ fe0->dvb.name = dev->name; /* multi-frontend gate control is undefined or defaults to fe0 */ port->frontends.gate = 0; /* Sets the gate control callback to be used by i2c command calls */ port->gate_ctrl = cx23885_dvb_gate_ctrl; /* init frontend */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); 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_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hauppauge_lgdt3305_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1255: case CX23885_BOARD_HAUPPAUGE_HVR1255_22111: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } tda18271_attach(&dev->ts1.analog_fe, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { case 1: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; } break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_OREN538, }; 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); } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1210: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1210_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1210_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_DIBCOM52, /* This is true for all demods with v36 firmware? */ .type = XC2028_D2633, }; 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); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc4000_config cfg = { .i2c_address = 0x61, .default_pm = 0, .dvb_amplitude = 134, .set_smoothedcvbs = 1, .if_khz = 4560 }; fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc4000 attach failed\n", dev->name); goto frontend_detach; } } break; case CX23885_BOARD_TBS_6920: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tbs_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; break; case CX23885_BOARD_TEVII_S470: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(ts2020_attach, fe0->dvb.frontend, &tevii_ts2020_config, &i2c_bus->i2c_adap); fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; } break; case CX23885_BOARD_DVBWORLD_2005: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: i2c_bus = &dev->i2c_bus[0]; switch (port->nr) { /* port B */ case 1: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 0); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_a, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL | LNBH24_TTX, LNBH24_TEN, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; /* port C */ case 2: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 1); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_b, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL | LNBH24_TTX, LNBH24_TEN, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; } break; case CX23885_BOARD_MYGICA_X8506: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &mygica_x8506_lgs8gl5_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config); } break; case CX23885_BOARD_MAGICPRO_PROHDTVE2: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &magicpro_prohdtve2_lgs8g75_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &magicpro_prohdtve2_xc5000_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1850: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); tda18271_attach(&dev->ts1.analog_fe, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); break; case CX23885_BOARD_HAUPPAUGE_HVR1290: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); break; case CX23885_BOARD_MYGICA_X8558PRO: switch (port->nr) { /* port B */ case 1: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(atbm8830_attach, &mygica_x8558pro_atbm8830_cfg1, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(max2165_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &mygic_x8558pro_max2165_cfg1); } break; /* port C */ case 2: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(atbm8830_attach, &mygica_x8558pro_atbm8830_cfg2, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(max2165_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &mygic_x8558pro_max2165_cfg2); } break; } break; case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: i2c_bus = &dev->i2c_bus[0]; mfe_shared = 1;/* MFE */ port->frontends.gate = 0;/* not clear for me yet */ /* ports B, C */ /* MFE frontend 1 DVB-T */ fe0->dvb.frontend = dvb_attach(stv0367ter_attach, &netup_stv0367_config[port->nr - 1], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (NULL == dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &netup_xc5000_config[port->nr - 1])) goto frontend_detach; /* load xc5000 firmware */ fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend); } /* MFE frontend 2 */ fe1 = videobuf_dvb_get_frontend(&port->frontends, 2); if (fe1 == NULL) goto frontend_detach; /* DVB-C init */ fe1->dvb.frontend = dvb_attach(stv0367cab_attach, &netup_stv0367_config[port->nr - 1], &i2c_bus->i2c_adap); if (fe1->dvb.frontend != NULL) { fe1->dvb.frontend->id = 1; if (NULL == dvb_attach(xc5000_attach, fe1->dvb.frontend, &i2c_bus->i2c_adap, &netup_xc5000_config[port->nr - 1])) goto frontend_detach; } break; case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; switch (port->nr) { /* port b */ case 1: fe0->dvb.frontend = dvb_attach(drxk_attach, &terratec_drxk_config[0], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(mt2063_attach, fe0->dvb.frontend, &terratec_mt2063_config[0], &i2c_bus2->i2c_adap)) goto frontend_detach; } break; /* port c */ case 2: fe0->dvb.frontend = dvb_attach(drxk_attach, &terratec_drxk_config[1], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(mt2063_attach, fe0->dvb.frontend, &terratec_mt2063_config[1], &i2c_bus2->i2c_adap)) goto frontend_detach; } break; } break; case CX23885_BOARD_TEVII_S471: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(ts2020_attach, fe0->dvb.frontend, &tevii_ts2020_config, &i2c_bus->i2c_adap); } break; case CX23885_BOARD_PROF_8000: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(stv090x_attach, &prof_8000_stv090x_config, &i2c_bus->i2c_adap, STV090x_DEMODULATOR_0); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(stb6100_attach, fe0->dvb.frontend, &prof_8000_stb6100_config, &i2c_bus->i2c_adap)) goto frontend_detach; fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; } break; case CX23885_BOARD_HAUPPAUGE_HVR4400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10071_attach, &hauppauge_tda10071_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(a8293_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_a8293_config); } break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", dev->name); break; } if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) { printk(KERN_ERR "%s: frontend initialization failed\n", dev->name); goto frontend_detach; } /* define general-purpose callback pointer */ fe0->dvb.frontend->callback = cx23885_tuner_callback; if (fe1) fe1->dvb.frontend->callback = cx23885_tuner_callback; #if 0 /* Ensure all frontends negotiate bus access */ fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl; if (fe1) fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl; #endif /* Put the analog decoder in standby to keep it quiet */ call_all(dev, core, s_power, 0); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, mfe_shared); if (ret) goto frontend_detach; /* init CI & MAC */ switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { static struct netup_card_info cinfo; netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); memcpy(port->frontends.adapter.proposed_mac, cinfo.port[port->nr - 1].mac, 6); printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", port->nr, port->frontends.adapter.proposed_mac); netup_ci_init(port); break; } case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { struct altera_ci_config netup_ci_cfg = { .dev = dev,/* magic number to identify*/ .adapter = &port->frontends.adapter,/* for CI */ .demux = &fe0->dvb.demux,/* for hw pid filter */ .fpga_rw = netup_altera_fpga_rw, }; altera_ci_init(&netup_ci_cfg, port->nr); break; } case CX23885_BOARD_TEVII_S470: { u8 eeprom[256]; /* 24C02 i2c eeprom */ if (port->nr != 1) break; /* Read entire EEPROM */ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0); memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); break; } } return ret; frontend_detach: port->gate_ctrl = NULL; videobuf_dvb_dealloc_frontends(&port->frontends); return -EINVAL; } int cx23885_dvb_register(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err, i; /* Here we need to allocate the correct number of frontends, * as reflected in the cards struct. The reality is that currently * no cx23885 boards support this - yet. But, if we don't modify this * code then the second frontend would never be allocated (later) * and fail with error before the attach in dvb_register(). * Without these changes we risk an OOPS later. The changes here * are for safety, and should provide a good foundation for the * future addition of any multi-frontend cx23885 based boards. */ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, port->num_frontends); for (i = 1; i <= port->num_frontends; i++) { if (videobuf_dvb_alloc_frontend( &port->frontends, i) == NULL) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } fe0 = videobuf_dvb_get_frontend(&port->frontends, i); if (!fe0) err = -EINVAL; dprintk(1, "%s\n", __func__); dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, dev->pci_bus, dev->pci_slot); err = -ENODEV; /* dvb stuff */ /* We have to init the queue for each frontend on a port. */ printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name); 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, NULL); } err = dvb_register(port); if (err != 0) printk(KERN_ERR "%s() dvb_register failed err = %d\n", __func__, err); return err; } int cx23885_dvb_unregister(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; /* FIXME: in an error condition where the we have * an expected number of frontends (attach problem) * then this might not clean up correctly, if 1 * is invalid. * This comment only applies to future boards IF they * implement MFE support. */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (fe0 && fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); switch (port->dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: netup_ci_exit(port); break; case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: altera_ci_release(port->dev, port->nr); break; } port->gate_ctrl = NULL; return 0; }
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, .i2c_addr = addr, .ctrl = &ctl, }; /* 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); return -EINVAL; } /* * Some xc3028 devices may be hidden by an I2C gate. This is known * to happen with some s5h1409-based devices. * Now that I2C gate is open, sets up xc3028 configuration */ cx88_setup_xc3028(dev->core, &ctl); 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; } printk(KERN_INFO "%s/2: xc3028 attached\n", dev->core->name); return 0; } static int cx24116_set_ts_param(struct dvb_frontend *fe, int is_punctured) { struct cx8802_dev *dev = fe->dvb->priv; dev->ts_gen_cntrl = 0x2; return 0; } static int cx24116_reset_device(struct dvb_frontend *fe) { struct cx8802_dev *dev = fe->dvb->priv; 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); return 0; } static struct cx24116_config hauppauge_hvr4000_config = { .demod_address = 0x05, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; static struct cx24116_config tevii_s460_config = { .demod_address = 0x55, .set_ts_params = cx24116_set_ts_param, .reset_device = cx24116_reset_device, }; static struct stv0299_config tevii_tuner_sharp_config = { .demod_address = 0x68, .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_ts_params = cx24116_set_ts_param, }; static struct stv0288_config tevii_tuner_earda_config = { .demod_address = 0x68, .min_delay_ms = 100, .set_ts_params = cx24116_set_ts_param, }; static int cx8802_alloc_frontends(struct cx8802_dev *dev) { struct cx88_core *core = dev->core; struct videobuf_dvb_frontend *fe = NULL; int i; mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); if (!core->board.num_frontends) return -ENODEV; printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); for (i = 1; i <= core->board.num_frontends; i++) { fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); if (!fe) { printk(KERN_ERR "%s() failed to alloc\n", __func__); videobuf_dvb_dealloc_frontends(&dev->frontends); return -ENOMEM; } } return 0; } 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 */ if (0 != core->i2c_rc) { printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); goto frontend_detach; } /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); if (!fe0) goto frontend_detach; /* multi-frontend gate control is undefined or defaults to fe0 */ dev->frontends.gate = 0; /* Sets the gate control callback to be used by i2c command calls */ core->gate_ctrl = cx88_dvb_gate_ctrl; /* init frontend(s) */ switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); 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; } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: case CX88_BOARD_CONEXANT_DVB_T1: case CX88_BOARD_KWORLD_DVB_T_CX22702: case CX88_BOARD_WINFAST_DTV1000: fe0->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, &core->i2c_adap); 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; } break; case CX88_BOARD_WINFAST_DTV2000H: case CX88_BOARD_HAUPPAUGE_HVR1100: case CX88_BOARD_HAUPPAUGE_HVR1100LP: case CX88_BOARD_HAUPPAUGE_HVR1300: fe0->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, &core->i2c_adap); 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: /* MFE frontend 1 */ mfe_shared = 1; dev->frontends.gate = 2; /* 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)) goto frontend_detach; } /* MFE frontend 2 */ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); if (!fe1) goto frontend_detach; /* DVB-T init */ 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)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); 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 */ fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) goto frontend_detach; } break; 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. */ fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, &core->i2c_adap); 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 */ fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_LG_Z201)) goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVB_T: case CX88_BOARD_DNTV_LIVE_DVB_T: case CX88_BOARD_ADSTECH_DVB_T_PCI: fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x61, NULL, DVB_PLL_UNKNOWN_1)) goto frontend_detach; } break; 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 */ fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); 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; } #else printk(KERN_ERR "%s/2: built without vp3054 support\n", core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &core->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, &core->i2c_adap); /* * On this board, the demod provides the I2C bus pullup. * We must not permit gate_ctrl to be performed, or * the xc3028 cannot communicate on the bus. */ if (fe0->dvb.frontend) fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; break; case CX88_BOARD_PCHDTV_HD3000: fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); /* Select RF connector callback */ fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_MICROTUNE_4042FI5)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, &core->i2c_adap); 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, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_PCHDTV_HD5500: dev->ts_gen_cntrl = 0x08; /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, &core->i2c_adap); 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, fe0->dvb.frontend, &core->i2c_adap, 0x43)) goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: fe0->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, &core->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: fe0->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, &core->i2c_adap); 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: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .scode_table = XC3028_FE_OREN538, }; 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); } break; case CX88_BOARD_PINNACLE_HYBRID_PCTV: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_pinnacle_hybrid_pctv, &core->i2c_adap); if (fe0->dvb.frontend) { fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; 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: 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: fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, &core->i2c_adap); 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: /* MFE frontend 1 */ mfe_shared = 1; dev->frontends.gate = 2; /* 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)) goto frontend_detach; } /* MFE frontend 2 */ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); if (!fe1) goto frontend_detach; /* DVB-T Init */ 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)) goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_HVR4000LITE: 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)) goto frontend_detach; } break; case CX88_BOARD_PROF_6200: case CX88_BOARD_TBS_8910: case CX88_BOARD_TEVII_S420: fe0->dvb.frontend = dvb_attach(stv0299_attach, &tevii_tuner_sharp_config, &core->i2c_adap); 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 = fe0->dvb.frontend->ops.set_voltage; fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; } else { fe0->dvb.frontend = dvb_attach(stv0288_attach, &tevii_tuner_earda_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61, &core->i2c_adap)) goto frontend_detach; 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: fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_s460_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) 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: case CX88_BOARD_SATTRADE_ST4200: fe0->dvb.frontend = dvb_attach(cx24116_attach, &hauppauge_hvr4000_config, &core->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage; break; case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII: fe0->dvb.frontend = dvb_attach(zl10353_attach, &cx88_terratec_cinergy_ht_pci_mkii_config, &core->i2c_adap); if (fe0->dvb.frontend) { fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL; if (attach_xc3028(0x61, dev) < 0) goto frontend_detach; } break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", core->name); break; } if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) { printk(KERN_ERR "%s/2: frontend initialization failed\n", core->name); goto frontend_detach; } /* define general-purpose callback pointer */ fe0->dvb.frontend->callback = cx88_tuner_callback; /* Ensure all frontends negotiate bus access */ 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 */ call_all(core, tuner, s_standby); /* register everything */ return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, &dev->pci->dev, adapter_nr, mfe_shared); frontend_detach: core->gate_ctrl = NULL; videobuf_dvb_dealloc_frontends(&dev->frontends); return -EINVAL; } /* ----------------------------------------------------------- */ /* CX8802 MPEG -> mini driver - We have been given the hardware */ static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_HVR1300: /* We arrive here with either the cx23416 or the cx22702 * on the bus. Take the bus from the cx23416 and enable the * cx22702 demod */ /* Toggle reset on cx22702 leaving i2c active */ cx_set(MO_GP0_IO, 0x00000080); udelay(1000); cx_clear(MO_GP0_IO, 0x00000080); udelay(50); cx_set(MO_GP0_IO, 0x00000080); udelay(1000); /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); udelay(1000); break; case CX88_BOARD_HAUPPAUGE_HVR3000: case CX88_BOARD_HAUPPAUGE_HVR4000: /* Toggle reset on cx22702 leaving i2c active */ cx_set(MO_GP0_IO, 0x00000080); udelay(1000); cx_clear(MO_GP0_IO, 0x00000080); udelay(50); cx_set(MO_GP0_IO, 0x00000080); udelay(1000); switch (core->dvbdev->frontends.active_fe_id) { case 1: /* DVB-S/S2 Enabled */ /* tri-state the cx22702 pins */ cx_set(MO_GP0_IO, 0x00000004); /* Take the cx24116/cx24123 out of reset */ cx_write(MO_SRST_IO, 1); core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */ break; case 2: /* DVB-T Enabled */ /* Put the cx24116/cx24123 into reset */ cx_write(MO_SRST_IO, 0); /* enable the cx22702 pins */ cx_clear(MO_GP0_IO, 0x00000004); core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */ break; } udelay(1000); break; default: err = -ENODEV; } return err; } /* CX8802 MPEG -> mini driver - We no longer have the hardware */ static int cx8802_dvb_advise_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; int err = 0; dprintk( 1, "%s\n", __func__); switch (core->boardnr) { 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; } return err; } static int cx8802_dvb_probe(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; int err; struct videobuf_dvb_frontend *fe; int i; dprintk( 1, "%s\n", __func__); dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", core->boardnr, core->name, core->pci_bus, core->pci_slot); err = -ENODEV; if (!(core->board.mpeg & CX88_MPEG_DVB)) goto fail_core; /* If vp3054 isn't enabled, a stub will just return 0 */ err = vp3054_i2c_probe(dev); if (0 != err) goto fail_core; /* dvb stuff */ printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name); dev->ts_gen_cntrl = 0x0c; err = cx8802_alloc_frontends(dev); if (err) goto fail_core; err = -ENODEV; for (i = 1; i <= core->board.num_frontends; i++) { fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); if (fe == NULL) { printk(KERN_ERR "%s() failed to get frontend(%d)\n", __func__, i); goto fail_probe; } 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) /* frontends/adapter de-allocated in dvb_register */ printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n", core->name, err); return err; fail_probe: videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends); fail_core: return err; } static int cx8802_dvb_remove(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; struct cx8802_dev *dev = drv->core->dvbdev; dprintk( 1, "%s\n", __func__); videobuf_dvb_unregister_bus(&dev->frontends); vp3054_i2c_remove(dev); core->gate_ctrl = NULL; return 0; } static struct cx8802_driver cx8802_dvb_driver = { .type_id = CX88_MPEG_DVB, .hw_access = CX8802_DRVCTL_SHARED, .probe = cx8802_dvb_probe, .remove = cx8802_dvb_remove, .advise_acquire = cx8802_dvb_advise_acquire, .advise_release = cx8802_dvb_advise_release, }; static int dvb_init(void) { printk(KERN_INFO "cx88/2: cx2388x dvb driver version %d.%d.%d loaded\n", (CX88_VERSION_CODE >> 16) & 0xff, (CX88_VERSION_CODE >> 8) & 0xff, CX88_VERSION_CODE & 0xff); #ifdef SNAPSHOT printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif return cx8802_register_driver(&cx8802_dvb_driver); } static void dvb_fini(void) { cx8802_unregister_driver(&cx8802_dvb_driver); } module_init(dvb_init); module_exit(dvb_fini);
static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL; struct videobuf_dvb_frontend *fe0; int ret; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (!fe0) return -EINVAL; /* init struct videobuf_dvb */ fe0->dvb.name = dev->name; /* init frontend */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); 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_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hauppauge_lgdt3305_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } /* FIXME: temporary hack */ /* define bridge override to set_frontend */ port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { case 1: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; } break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_OREN538, }; 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); } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1210: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1210_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1210_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_DIBCOM52, /* This is true for all demods with v36 firmware? */ .type = XC2028_D2633, }; 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); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; case CX23885_BOARD_TBS_6920: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tbs_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; break; case CX23885_BOARD_TEVII_S470: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; break; case CX23885_BOARD_DVBWORLD_2005: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: i2c_bus = &dev->i2c_bus[0]; switch (port->nr) { /* port B */ case 1: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 0); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_a, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL, LNBH24_TTX, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; /* port C */ case 2: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 1); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_b, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL, LNBH24_TTX, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; } break; case CX23885_BOARD_MYGICA_X8506: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &mygica_x8506_lgs8gl5_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config); } break; case CX23885_BOARD_MAGICPRO_PROHDTVE2: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &magicpro_prohdtve2_lgs8g75_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &magicpro_prohdtve2_xc5000_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1850: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", dev->name); break; } if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ fe0->dvb.frontend->callback = cx23885_tuner_callback; /* Put the analog decoder in standby to keep it quiet */ call_all(dev, tuner, s_standby); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0); /* init CI & MAC */ switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { static struct netup_card_info cinfo; netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); memcpy(port->frontends.adapter.proposed_mac, cinfo.port[port->nr - 1].mac, 6); printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" "%02X:%02X:%02X:%02X:%02X:%02X\n", port->nr, port->frontends.adapter.proposed_mac[0], port->frontends.adapter.proposed_mac[1], port->frontends.adapter.proposed_mac[2], port->frontends.adapter.proposed_mac[3], port->frontends.adapter.proposed_mac[4], port->frontends.adapter.proposed_mac[5]); netup_ci_init(port); break; } } return ret; } int cx23885_dvb_register(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err, i; /* Here we need to allocate the correct number of frontends, * as reflected in the cards struct. The reality is that currently * no cx23885 boards support this - yet. But, if we don't modify this * code then the second frontend would never be allocated (later) * and fail with error before the attach in dvb_register(). * Without these changes we risk an OOPS later. The changes here * are for safety, and should provide a good foundation for the * future addition of any multi-frontend cx23885 based boards. */ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, port->num_frontends); for (i = 1; i <= port->num_frontends; i++) { if (videobuf_dvb_alloc_frontend( &port->frontends, i) == NULL) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } fe0 = videobuf_dvb_get_frontend(&port->frontends, i); if (!fe0) err = -EINVAL; dprintk(1, "%s\n", __func__); dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, dev->pci_bus, dev->pci_slot); err = -ENODEV; /* dvb stuff */ /* We have to init the queue for each frontend on a port. */ printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name); 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); if (err != 0) printk(KERN_ERR "%s() dvb_register failed err = %d\n", __func__, err); return err; } int cx23885_dvb_unregister(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; /* FIXME: in an error condition where the we have * an expected number of frontends (attach problem) * then this might not clean up correctly, if 1 * is invalid. * This comment only applies to future boards IF they * implement MFE support. */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); switch (port->dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: netup_ci_exit(port); break; } return 0; }
static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL; struct videobuf_dvb_frontend *fe0; int ret; fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (!fe0) return -EINVAL; fe0->dvb.name = dev->name; switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); 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_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hauppauge_lgdt3305_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend; fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend; break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { case 1: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; } break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_OREN538, }; 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); } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1210: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1210_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1210_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = 5000, .type = XC2028_D2633, }; 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); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; case CX23885_BOARD_TBS_6920: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tbs_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; break; case CX23885_BOARD_TEVII_S470: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tevii_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = tbs_set_voltage; break; case CX23885_BOARD_DVBWORLD_2005: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: i2c_bus = &dev->i2c_bus[0]; switch (port->nr) { case 1: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 0); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_a, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL, LNBH24_TTX, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; case 2: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 1); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_b, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL, LNBH24_TTX, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; } break; case CX23885_BOARD_MYGICA_X8506: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &mygica_x8506_lgs8gl5_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config); } break; case CX23885_BOARD_MAGICPRO_PROHDTVE2: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &magicpro_prohdtve2_lgs8g75_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &magicpro_prohdtve2_xc5000_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1850: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", dev->name); break; } if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s: frontend initialization failed\n", dev->name); return -1; } fe0->dvb.frontend->callback = cx23885_tuner_callback; call_all(dev, tuner, s_standby); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0); switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { static struct netup_card_info cinfo; netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); memcpy(port->frontends.adapter.proposed_mac, cinfo.port[port->nr - 1].mac, 6); printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=" "%02X:%02X:%02X:%02X:%02X:%02X\n", port->nr, port->frontends.adapter.proposed_mac[0], port->frontends.adapter.proposed_mac[1], port->frontends.adapter.proposed_mac[2], port->frontends.adapter.proposed_mac[3], port->frontends.adapter.proposed_mac[4], port->frontends.adapter.proposed_mac[5]); netup_ci_init(port); break; } } return ret; } int cx23885_dvb_register(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err, i; printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, port->num_frontends); for (i = 1; i <= port->num_frontends; i++) { if (videobuf_dvb_alloc_frontend( &port->frontends, i) == NULL) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } fe0 = videobuf_dvb_get_frontend(&port->frontends, i); if (!fe0) err = -EINVAL; dprintk(1, "%s\n", __func__); dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, dev->pci_bus, dev->pci_slot); err = -ENODEV; printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name); 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); if (err != 0) printk(KERN_ERR "%s() dvb_register failed err = %d\n", __func__, err); return err; } int cx23885_dvb_unregister(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); switch (port->dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: netup_ci_exit(port); break; } return 0; }
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; /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (!fe0) return -EINVAL; /* init struct videobuf_dvb */ fe0->dvb.name = dev->name; /* init frontend */ switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); 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) { case 1: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; } break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .scode_table = XC3028_FE_OREN538, }; 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); } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); 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, 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]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = 5000, /* This is true for all demods with v36 firmware? */ .type = XC2028_D2633, }; 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); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", dev->name); break; } if (NULL == fe0->dvb.frontend) { printk(KERN_ERR "%s: frontend initialization failed\n", dev->name); return -1; } /* define general-purpose callback pointer */ 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 (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); /* register everything */ return videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0); } int cx23885_dvb_register(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err, i; /* Here we need to allocate the correct number of frontends, * as reflected in the cards struct. The reality is that currrently * no cx23885 boards support this - yet. But, if we don't modify this * code then the second frontend would never be allocated (later) * and fail with error before the attach in dvb_register(). * Without these changes we risk an OOPS later. The changes here * are for safety, and should provide a good foundation for the * future addition of any multi-frontend cx23885 based boards. */ printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, port->num_frontends); for (i = 1; i <= port->num_frontends; i++) { if (videobuf_dvb_alloc_frontend( &port->frontends, i) == NULL) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } fe0 = videobuf_dvb_get_frontend(&port->frontends, i); if (!fe0) err = -EINVAL; dprintk(1, "%s\n", __func__); dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, dev->pci_bus, dev->pci_slot); err = -ENODEV; /* dvb stuff */ /* We have to init the queue for each frontend on a port. */ printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name); 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); if (err != 0) printk(KERN_ERR "%s() dvb_register failed err = %d\n", __func__, err); return err; } int cx23885_dvb_unregister(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; /* FIXME: in an error condition where the we have * an expected number of frontends (attach problem) * then this might not clean up correctly, if 1 * is invalid. * This comment only applies to future boards IF they * implement MFE support. */ fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); return 0; }
static int dvb_register(struct cx23885_tsport *port) { struct cx23885_dev *dev = port->dev; struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL; struct videobuf_dvb_frontend *fe0, *fe1 = NULL; int mfe_shared = 0; int ret; fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (!fe0) return -EINVAL; fe0->dvb.name = dev->name; port->frontends.gate = 0; port->gate_ctrl = cx23885_dvb_gate_ctrl; switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); 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_HVR1270: case CX23885_BOARD_HAUPPAUGE_HVR1275: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(lgdt3305_attach, &hauppauge_lgdt3305_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr127x_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1255: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1800: i2c_bus = &dev->i2c_bus[0]; switch (alt_tuner) { case 1: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_ezqam_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); } break; case 0: default: fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_generic_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(mt2131_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &hauppauge_generic_tunerconfig, 0); break; } break; case CX23885_BOARD_HAUPPAUGE_HVR1800lp: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1800lp_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_express, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500_config, &dev->i2c_bus[0].i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_OREN538, }; 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); } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, &i2c_bus->i2c_adap); 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, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1200_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1210: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1210_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_hvr1210_tuner_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1400: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(dib7000p_attach, &i2c_bus->i2c_adap, 0x12, &hauppauge_hvr1400_dib7000_config); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x64, }; static struct xc2028_ctrl ctl = { .fname = XC3028L_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_DIBCOM52, .type = XC2028_D2633, }; 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); } break; case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP: i2c_bus = &dev->i2c_bus[port->nr - 1]; fe0->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_s5h1409_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend == NULL) fe0->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_s5h1411_config, &i2c_bus->i2c_adap); 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]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &i2c_bus->i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; } case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H: case CX23885_BOARD_COMPRO_VIDEOMATE_E650F: case CX23885_BOARD_COMPRO_VIDEOMATE_E800: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { .i2c_adap = &dev->i2c_bus[1].i2c_adap, .i2c_addr = 0x61, }; static struct xc2028_ctrl ctl = { .fname = XC2028_DEFAULT_FIRMWARE, .max_len = 64, .demod = XC3028_FE_ZARLINK456, }; 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); } break; case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc4000_config cfg = { .i2c_address = 0x61, .default_pm = 0, .dvb_amplitude = 134, .set_smoothedcvbs = 1, .if_khz = 4560 }; fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->i2c_bus[1].i2c_adap, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc4000 attach failed\n", dev->name); goto frontend_detach; } } break; case CX23885_BOARD_TBS_6920: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &tbs_cx24116_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; break; case CX23885_BOARD_TEVII_S470: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(ds3000_attach, &tevii_ds3000_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) fe0->dvb.frontend->ops.set_voltage = f300_set_voltage; break; case CX23885_BOARD_DVBWORLD_2005: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(cx24116_attach, &dvbworld_cx24116_config, &i2c_bus->i2c_adap); break; case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: i2c_bus = &dev->i2c_bus[0]; switch (port->nr) { case 1: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 0); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_a, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL | LNBH24_TTX, LNBH24_TEN, 0x09)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; case 2: fe0->dvb.frontend = dvb_attach(stv0900_attach, &netup_stv0900_config, &i2c_bus->i2c_adap, 1); if (fe0->dvb.frontend != NULL) { if (dvb_attach(stv6110_attach, fe0->dvb.frontend, &netup_stv6110_tunerconfig_b, &i2c_bus->i2c_adap)) { if (!dvb_attach(lnbh24_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, LNBH24_PCL | LNBH24_TTX, LNBH24_TEN, 0x0a)) printk(KERN_ERR "No LNBH24 found!\n"); } } break; } break; case CX23885_BOARD_MYGICA_X8506: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &mygica_x8506_lgs8gl5_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config); } break; case CX23885_BOARD_MAGICPRO_PROHDTVE2: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(lgs8gxx_attach, &magicpro_prohdtve2_lgs8g75_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus2->i2c_adap, &magicpro_prohdtve2_xc5000_config); } break; case CX23885_BOARD_HAUPPAUGE_HVR1850: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); tda18271_attach(&dev->ts1.analog_fe, 0x60, &dev->i2c_bus[1].i2c_adap, &hauppauge_tda18271_config); break; case CX23885_BOARD_HAUPPAUGE_HVR1290: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(s5h1411_attach, &hcw_s5h1411_config, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) dvb_attach(tda18271_attach, fe0->dvb.frontend, 0x60, &dev->i2c_bus[0].i2c_adap, &hauppauge_tda18271_config); break; case CX23885_BOARD_MYGICA_X8558PRO: switch (port->nr) { case 1: i2c_bus = &dev->i2c_bus[0]; fe0->dvb.frontend = dvb_attach(atbm8830_attach, &mygica_x8558pro_atbm8830_cfg1, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(max2165_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &mygic_x8558pro_max2165_cfg1); } break; case 2: i2c_bus = &dev->i2c_bus[1]; fe0->dvb.frontend = dvb_attach(atbm8830_attach, &mygica_x8558pro_atbm8830_cfg2, &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { dvb_attach(max2165_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &mygic_x8558pro_max2165_cfg2); } break; } break; case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: i2c_bus = &dev->i2c_bus[0]; mfe_shared = 1; port->frontends.gate = 0; fe0->dvb.frontend = dvb_attach(stv0367ter_attach, &netup_stv0367_config[port->nr - 1], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (NULL == dvb_attach(xc5000_attach, fe0->dvb.frontend, &i2c_bus->i2c_adap, &netup_xc5000_config[port->nr - 1])) goto frontend_detach; fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend); } fe1 = videobuf_dvb_get_frontend(&port->frontends, 2); if (fe1 == NULL) goto frontend_detach; fe1->dvb.frontend = dvb_attach(stv0367cab_attach, &netup_stv0367_config[port->nr - 1], &i2c_bus->i2c_adap); if (fe1->dvb.frontend != NULL) { fe1->dvb.frontend->id = 1; if (NULL == dvb_attach(xc5000_attach, fe1->dvb.frontend, &i2c_bus->i2c_adap, &netup_xc5000_config[port->nr - 1])) goto frontend_detach; } break; case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: i2c_bus = &dev->i2c_bus[0]; i2c_bus2 = &dev->i2c_bus[1]; switch (port->nr) { case 1: fe0->dvb.frontend = dvb_attach(drxk_attach, &terratec_drxk_config[0], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(mt2063_attach, fe0->dvb.frontend, &terratec_mt2063_config[0], &i2c_bus2->i2c_adap)) goto frontend_detach; } break; case 2: fe0->dvb.frontend = dvb_attach(drxk_attach, &terratec_drxk_config[1], &i2c_bus->i2c_adap); if (fe0->dvb.frontend != NULL) { if (!dvb_attach(mt2063_attach, fe0->dvb.frontend, &terratec_mt2063_config[1], &i2c_bus2->i2c_adap)) goto frontend_detach; } break; } break; default: printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " " isn't supported yet\n", dev->name); break; } if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) { printk(KERN_ERR "%s: frontend initialization failed\n", dev->name); goto frontend_detach; } fe0->dvb.frontend->callback = cx23885_tuner_callback; if (fe1) fe1->dvb.frontend->callback = cx23885_tuner_callback; #if 0 fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl; if (fe1) fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl; #endif call_all(dev, core, s_power, 0); if (fe0->dvb.frontend->ops.analog_ops.standby) fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend); ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, mfe_shared, NULL); if (ret) goto frontend_detach; switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: { static struct netup_card_info cinfo; netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo); memcpy(port->frontends.adapter.proposed_mac, cinfo.port[port->nr - 1].mac, 6); printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", port->nr, port->frontends.adapter.proposed_mac); netup_ci_init(port); break; } case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { struct altera_ci_config netup_ci_cfg = { .dev = dev, .adapter = &port->frontends.adapter, .demux = &fe0->dvb.demux, .fpga_rw = netup_altera_fpga_rw, }; altera_ci_init(&netup_ci_cfg, port->nr); break; } case CX23885_BOARD_TEVII_S470: { u8 eeprom[256]; if (port->nr != 1) break; dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0); memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); break; } } return ret; frontend_detach: port->gate_ctrl = NULL; videobuf_dvb_dealloc_frontends(&port->frontends); return -EINVAL; } int cx23885_dvb_register(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; struct cx23885_dev *dev = port->dev; int err, i; printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, port->num_frontends); for (i = 1; i <= port->num_frontends; i++) { if (videobuf_dvb_alloc_frontend( &port->frontends, i) == NULL) { printk(KERN_ERR "%s() failed to alloc\n", __func__); return -ENOMEM; } fe0 = videobuf_dvb_get_frontend(&port->frontends, i); if (!fe0) err = -EINVAL; dprintk(1, "%s\n", __func__); dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n", dev->board, dev->name, dev->pci_bus, dev->pci_slot); err = -ENODEV; printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name); 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, NULL); } err = dvb_register(port); if (err != 0) printk(KERN_ERR "%s() dvb_register failed err = %d\n", __func__, err); return err; } int cx23885_dvb_unregister(struct cx23885_tsport *port) { struct videobuf_dvb_frontend *fe0; fe0 = videobuf_dvb_get_frontend(&port->frontends, 1); if (fe0 && fe0->dvb.frontend) videobuf_dvb_unregister_bus(&port->frontends); switch (port->dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: netup_ci_exit(port); break; case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: altera_ci_release(port->dev, port->nr); break; } port->gate_ctrl = NULL; return 0; }