Esempio n. 1
0
static int __init
init_dvb(void)
{
	struct dvb_struct *dvb = &dvbs[0];

	printk("%s: %s\n", __FILE__, __FUNCTION__);
	memset(dvb, 0, sizeof(struct dvb_struct));
	dvb->num=0;

	return dvb_register(dvb);
}
Esempio n. 2
0
static int __devinit dvb_probe(struct pci_dev *pci_dev,
			       const struct pci_device_id *pci_id)
{
	struct cx8802_dev *dev;
	struct cx88_core  *core;
	int err;

	/* general setup */
	core = cx88_core_get(pci_dev);
	if (NULL == core)
		return -EINVAL;

	err = -ENODEV;
	if (!cx88_boards[core->board].dvb)
		goto fail_core;

	err = -ENOMEM;
	dev = kmalloc(sizeof(*dev),GFP_KERNEL);
	if (NULL == dev)
		goto fail_core;
	memset(dev,0,sizeof(*dev));
	dev->pci = pci_dev;
	dev->core = core;

	err = cx8802_init_common(dev);
	if (0 != err)
		goto fail_free;

	/* dvb stuff */
	printk("%s/2: cx2388x based dvb card\n", core->name);
	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
			    dev->pci, &dev->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
			    V4L2_FIELD_TOP,
			    sizeof(struct cx88_buffer),
			    dev);
	err = dvb_register(dev);
	if (0 != err)
		goto fail_fini;
	return 0;

 fail_fini:
	cx8802_fini_common(dev);
 fail_free:
	kfree(dev);
 fail_core:
	cx88_core_put(core,pci_dev);
	return err;
}
Esempio n. 3
0
/* All the DVB attach calls go here, this function get's modified
 * for each new card. No other function in this file needs
 * to change.
 */
int au0828_dvb_register(struct au0828_dev *dev)
{
	struct au0828_dvb *dvb = &dev->dvb;
	int ret;

	dprintk(1, "%s()\n", __func__);

	/* init frontend */
	switch (dev->board) {
	case AU0828_BOARD_HAUPPAUGE_HVR850:
	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
	case AU0828_BOARD_DVICO_FUSIONHDTV7:
		dvb->frontend = dvb_attach(au8522_attach,
				&hauppauge_hvr950q_config,
				&dev->i2c_adap);
		if (dvb->frontend != NULL)
			dvb_attach(xc5000_attach, dvb->frontend,
				&dev->i2c_adap,
				&hauppauge_hvr950q_tunerconfig, dev);
		break;
	default:
		printk(KERN_WARNING "The frontend of your DVB/ATSC card "
		       "isn't supported yet\n");
		break;
	}
	if (NULL == dvb->frontend) {
		printk(KERN_ERR "%s() Frontend initialization failed\n",
		       __func__);
		return -1;
	}

	/* register everything */
	ret = dvb_register(dev);
	if (ret < 0) {
		if (dvb->frontend->ops.release)
			dvb->frontend->ops.release(dvb->frontend);
		return ret;
	}

	return 0;
}
Esempio n. 4
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; /* 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;
}
Esempio n. 5
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);
Esempio n. 6
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;

	/* 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;
}
Esempio n. 7
0
/* All the DVB attach calls go here, this function get's modified
 * for each new card. No other function in this file needs
 * to change.
 */
int au0828_dvb_register(struct au0828_dev *dev)
{
	struct au0828_dvb *dvb = &dev->dvb;
	int ret;

	dprintk(1, "%s()\n", __func__);

	/* init frontend */
	switch (dev->boardnr) {
	case AU0828_BOARD_HAUPPAUGE_HVR850:
	case AU0828_BOARD_HAUPPAUGE_HVR950Q:
		dvb->frontend = dvb_attach(au8522_attach,
				&hauppauge_hvr950q_config,
				&dev->i2c_adap);
		if (dvb->frontend != NULL)
			switch (dev->board.tuner_type) {
			default:
			case TUNER_XC5000:
				dvb_attach(xc5000_attach, dvb->frontend,
					   &dev->i2c_adap,
					   &hauppauge_xc5000a_config);
				break;
			case TUNER_XC5000C:
				dvb_attach(xc5000_attach, dvb->frontend,
					   &dev->i2c_adap,
					   &hauppauge_xc5000c_config);
				break;
			}
		break;
	case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
		dvb->frontend = dvb_attach(au8522_attach,
				&hauppauge_hvr950q_config,
				&dev->i2c_adap);
		if (dvb->frontend != NULL)
			dvb_attach(mxl5007t_attach, dvb->frontend,
				   &dev->i2c_adap, 0x60,
				   &mxl5007t_hvr950q_config);
		break;
	case AU0828_BOARD_HAUPPAUGE_WOODBURY:
		dvb->frontend = dvb_attach(au8522_attach,
				&hauppauge_woodbury_config,
				&dev->i2c_adap);
		if (dvb->frontend != NULL)
			dvb_attach(tda18271_attach, dvb->frontend,
				   0x60, &dev->i2c_adap,
				   &hauppauge_woodbury_tunerconfig);
		break;
	case AU0828_BOARD_DVICO_FUSIONHDTV7:
		dvb->frontend = dvb_attach(au8522_attach,
				&fusionhdtv7usb_config,
				&dev->i2c_adap);
		if (dvb->frontend != NULL) {
			dvb_attach(xc5000_attach, dvb->frontend,
				&dev->i2c_adap,
				&hauppauge_xc5000a_config);
		}
		break;
	default:
		printk(KERN_WARNING "The frontend of your DVB/ATSC card "
		       "isn't supported yet\n");
		break;
	}
	if (NULL == dvb->frontend) {
		printk(KERN_ERR "%s() Frontend initialization failed\n",
		       __func__);
		return -1;
	}
	/* define general-purpose callback pointer */
	dvb->frontend->callback = au0828_tuner_callback;

	/* register everything */
	ret = dvb_register(dev);
	if (ret < 0) {
		if (dvb->frontend->ops.release)
			dvb->frontend->ops.release(dvb->frontend);
		return ret;
	}

	return 0;
}
Esempio n. 8
0
static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
{
	struct cx8802_dev *dev= fe->dvb->priv;

	/* this message is to set up ATC and ALC */
	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0,
		  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
	int err;

	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);
	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}

	return 0;
}

static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe,
					       struct dvb_frontend_parameters* params)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	u8 buf[4];
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0,
		  .buf = buf, .len = 4 };
	int err;

	/* Switch PLL to DVB mode */
	err = philips_fmd1216_pll_init(fe);
	if (err)
		return err;

	/* Tune PLL */
	dvb_pll_configure(dev->core->pll_desc, buf,
			  params->frequency,
			  params->u.ofdm.bandwidth);
	if (fe->ops.i2c_gate_ctrl)
		fe->ops.i2c_gate_ctrl(fe, 1);
	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {

		printk(KERN_WARNING "cx88-dvb: %s error "
		       "(addr %02x <- %02x, err = %i)\n",
		       __FUNCTION__, dev->core->pll_addr, buf[0], err);
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}

	return 0;
}

static struct mt352_config dntv_live_dvbt_pro_config = {
	.demod_address = 0x0f,
	.no_tuner      = 1,
	.demod_init    = dntv_live_dvbt_pro_demod_init,
};
#endif

static struct zl10353_config dvico_fusionhdtv_hybrid = {
	.demod_address = 0x0f,
	.no_tuner      = 1,
};

static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
	.demod_address = 0x0f,
};

static struct cx22702_config connexant_refboard_config = {
	.demod_address = 0x43,
	.output_mode   = CX22702_SERIAL_OUTPUT,
};

static struct cx22702_config hauppauge_hvr_config = {
	.demod_address = 0x63,
	.output_mode   = CX22702_SERIAL_OUTPUT,
};

static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
	return 0;
}

static struct or51132_config pchdtv_hd3000 = {
	.demod_address = 0x15,
	.set_ts_params = or51132_set_ts_param,
};

static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
	if (index == 0)
		cx_clear(MO_GP0_IO, 8);
	else
		cx_set(MO_GP0_IO, 8);
	return 0;
}

static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	if (is_punctured)
		dev->ts_gen_cntrl |= 0x04;
	else
		dev->ts_gen_cntrl &= ~0x04;
	return 0;
}

static struct lgdt330x_config fusionhdtv_3_gold = {
	.demod_address = 0x0e,
	.demod_chip    = LGDT3302,
	.serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
	.set_ts_params = lgdt330x_set_ts_param,
};

static struct lgdt330x_config fusionhdtv_5_gold = {
	.demod_address = 0x0e,
	.demod_chip    = LGDT3303,
	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
	.set_ts_params = lgdt330x_set_ts_param,
};

static struct lgdt330x_config pchdtv_hd5500 = {
	.demod_address = 0x59,
	.demod_chip    = LGDT3303,
	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
	.set_ts_params = lgdt330x_set_ts_param,
};

static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
	return 0;
}

static int nxt200x_set_pll_input(u8* buf, int input)
{
	if (input)
		buf[3] |= 0x08;
	else
		buf[3] &= ~0x08;
	return 0;
}

static struct nxt200x_config ati_hdtvwonder = {
	.demod_address = 0x0a,
	.set_pll_input = nxt200x_set_pll_input,
	.set_ts_params = nxt200x_set_ts_param,
};

static int cx24123_set_ts_param(struct dvb_frontend* fe,
	int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	dev->ts_gen_cntrl = 0x02;
	return 0;
}

static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
				       fe_sec_voltage_t voltage)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	if (voltage == SEC_VOLTAGE_OFF)
		cx_write(MO_GP0_IO, 0x000006fb);
	else
		cx_write(MO_GP0_IO, 0x000006f9);

	if (core->prev_set_voltage)
		return core->prev_set_voltage(fe, voltage);
	return 0;
}

static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
				      fe_sec_voltage_t voltage)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	if (voltage == SEC_VOLTAGE_OFF) {
		dprintk(1,"LNB Voltage OFF\n");
		cx_write(MO_GP0_IO, 0x0000efff);
	}

	if (core->prev_set_voltage)
		return core->prev_set_voltage(fe, voltage);
	return 0;
}

static struct cx24123_config geniatech_dvbs_config = {
	.demod_address = 0x55,
	.set_ts_params = cx24123_set_ts_param,
};

static struct cx24123_config hauppauge_novas_config = {
	.demod_address = 0x55,
	.set_ts_params = cx24123_set_ts_param,
};

static struct cx24123_config kworld_dvbs_100_config = {
	.demod_address = 0x15,
	.set_ts_params = cx24123_set_ts_param,
	.lnb_polarity  = 1,
};

static int dvb_register(struct cx8802_dev *dev)
{
	/* init struct videobuf_dvb */
	dev->dvb.name = dev->core->name;
	dev->ts_gen_cntrl = 0x0c;

	/* init frontend */
	switch (dev->core->board) {
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
		dev->dvb.frontend = dvb_attach(cx22702_attach,
					       &connexant_refboard_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap,
				   &dvb_pll_thomson_dtt759x);
		}
		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:
		dev->dvb.frontend = dvb_attach(cx22702_attach,
					       &connexant_refboard_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
				   &dev->core->i2c_adap,
				   &dvb_pll_thomson_dtt7579);
		}
		break;
	case CX88_BOARD_WINFAST_DTV2000H:
	case CX88_BOARD_HAUPPAUGE_HVR1100:
	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
		dev->dvb.frontend = dvb_attach(cx22702_attach,
					       &hauppauge_hvr_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap, &dvb_pll_fmd1216me);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
		dev->dvb.frontend = dvb_attach(mt352_attach,
					       &dvico_fusionhdtv,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
				   NULL, &dvb_pll_thomson_dtt7579);
			break;
		}
		/* ZL10353 replaces MT352 on later cards */
		dev->dvb.frontend = dvb_attach(zl10353_attach,
					       &dvico_fusionhdtv_plus_v1_1,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
				   NULL, &dvb_pll_thomson_dtt7579);
		}
		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. */
		dev->dvb.frontend = dvb_attach(mt352_attach,
					       &dvico_fusionhdtv_dual,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   NULL, &dvb_pll_thomson_dtt7579);
			break;
		}
		/* ZL10353 replaces MT352 on later cards */
		dev->dvb.frontend = dvb_attach(zl10353_attach,
					       &dvico_fusionhdtv_plus_v1_1,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   NULL, &dvb_pll_thomson_dtt7579);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
		dev->dvb.frontend = dvb_attach(mt352_attach,
					       &dvico_fusionhdtv,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   NULL, &dvb_pll_lg_z201);
		}
		break;
	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,
					       &dntv_live_dvbt_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   NULL, &dvb_pll_unknown_1);
		}
		break;
	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_fmd1216me;
		dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
			&((struct vp3054_i2c_state *)dev->card_priv)->adap);
		if (dev->dvb.frontend != NULL) {
			dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
		}
#else
		printk("%s: built without vp3054 support\n", dev->core->name);
#endif
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
		dev->dvb.frontend = dvb_attach(zl10353_attach,
					       &dvico_fusionhdtv_hybrid,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap,
				   &dvb_pll_thomson_fe6600);
		}
		break;
	case CX88_BOARD_PCHDTV_HD3000:
		dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap,
				   &dvb_pll_thomson_dtt761x);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		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;
		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
					       &fusionhdtv_3_gold,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap,
				   &dvb_pll_microtune_4042);
		}
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 9);
		mdelay(200);
		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
					       &fusionhdtv_3_gold,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap,
				   &dvb_pll_thomson_dtt761x);
		}
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 1);
		mdelay(200);
		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
					       &fusionhdtv_5_gold,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(lgh06xf_attach, dev->dvb.frontend,
				   &dev->core->i2c_adap);
		}
		}
		break;
	case CX88_BOARD_PCHDTV_HD5500:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 1);
		mdelay(200);
		dev->dvb.frontend = dvb_attach(lgdt330x_attach,
					       &pchdtv_hd5500,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(lgh06xf_attach, dev->dvb.frontend,
				   &dev->core->i2c_adap);
		}
		}
		break;
	case CX88_BOARD_ATI_HDTVWONDER:
		dev->dvb.frontend = dvb_attach(nxt200x_attach,
					       &ati_hdtvwonder,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   NULL, &dvb_pll_tuv1236d);
		}
		break;
	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
		dev->dvb.frontend = dvb_attach(cx24123_attach,
					       &hauppauge_novas_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend) {
			dvb_attach(isl6421_attach, dev->dvb.frontend,
				   &dev->core->i2c_adap, 0x08, 0x00, 0x00);
		}
		break;
	case CX88_BOARD_KWORLD_DVBS_100:
		dev->dvb.frontend = dvb_attach(cx24123_attach,
					       &kworld_dvbs_100_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend) {
			dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
			dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
		}
		break;
	case CX88_BOARD_GENIATECH_DVBS:
		dev->dvb.frontend = dvb_attach(cx24123_attach,
					       &geniatech_dvbs_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend) {
			dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
			dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
		}
		break;
	case CX88_BOARD_HAUPPAUGE_HVR1300:
		dev->dvb.frontend = dvb_attach(cx22702_attach,
					       &hauppauge_hvr_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap, &dvb_pll_fmd1216me);
		}
		break;
	case CX88_BOARD_HAUPPAUGE_HVR3000:
		dev->dvb.frontend = dvb_attach(cx22702_attach,
					       &hauppauge_hvr_config,
					       &dev->core->i2c_adap);
		if (dev->dvb.frontend != NULL) {
			dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
				   &dev->core->i2c_adap, &dvb_pll_fmd1216me);
		}
		break;
	default:
		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
		       dev->core->name);
		break;
	}
	if (NULL == dev->dvb.frontend) {
		printk("%s: frontend initialization failed\n",dev->core->name);
		return -1;
	}

	if (dev->core->pll_desc) {
		dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
		dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
	}
	/* Ensure all frontends negotiate bus access */
	dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;

	/* Put the analog decoder in standby to keep it quiet */
	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);

	/* register everything */
	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
}

/* ----------------------------------------------------------- */

/* 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", __FUNCTION__);

	switch (core->board) {
	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
		 */
		cx_set(MO_GP0_IO,   0x00000080); /* cx22702 out of reset and enable */
		cx_clear(MO_GP0_IO, 0x00000004);
		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", __FUNCTION__);

	switch (core->board) {
	case CX88_BOARD_HAUPPAUGE_HVR1300:
		/* Do Nothing, leave the cx22702 on the bus. */
		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;

	dprintk( 1, "%s\n", __FUNCTION__);
	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
		core->board,
		core->name,
		core->pci_bus,
		core->pci_slot);

	err = -ENODEV;
	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
		goto fail_core;

#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
	err = vp3054_i2c_probe(dev);
	if (0 != err)
		goto fail_core;
#endif

	/* dvb stuff */
	printk("%s/2: cx2388x based dvb card\n", core->name);
	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
			    dev->pci, &dev->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
			    V4L2_FIELD_TOP,
			    sizeof(struct cx88_buffer),
			    dev);
	err = dvb_register(dev);
	if (err != 0)
		printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);

 fail_core:
	return err;
}

static int cx8802_dvb_remove(struct cx8802_driver *drv)
{
	struct cx8802_dev *dev = drv->core->dvbdev;

	/* dvb */
	videobuf_dvb_unregister(&dev->dvb);

#if defined(CONFIG_VIDEO_CX88_VP3054) || defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
	vp3054_i2c_remove(dev);
#endif

	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 "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);
Esempio n. 9
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;
}
Esempio n. 10
0
static int lgdt330x_pll_set(struct dvb_frontend* fe,
			    struct dvb_frontend_parameters* params)
{
	/* FIXME make this routine use the tuner-simple code.
	 * It could probably be shared with a number of ATSC
	 * frontends. Many share the same tuner with analog TV. */

	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;
	u8 buf[4];
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
	int err;

	/* Put the analog decoder in standby to keep it quiet */
	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);

	dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
	if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
		printk(KERN_WARNING "cx88-dvb: %s error "
			   "(addr %02x <- %02x, err = %i)\n",
			   __FUNCTION__, buf[0], buf[1], err);
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}
	if (core->tuner_type == TUNER_LG_TDVS_H062F) {
		/* Set the Auxiliary Byte. */
		buf[2] &= ~0x20;
		buf[2] |= 0x18;
		buf[3] = 0x50;
		i2c_transfer(&core->i2c_adap, &msg, 1);
	}
	return 0;
}

static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
	if (index == 0)
		cx_clear(MO_GP0_IO, 8);
	else
		cx_set(MO_GP0_IO, 8);
	return 0;
}

static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	if (is_punctured)
		dev->ts_gen_cntrl |= 0x04;
	else
		dev->ts_gen_cntrl &= ~0x04;
	return 0;
}

static struct lgdt330x_config fusionhdtv_3_gold = {
	.demod_address    = 0x0e,
	.demod_chip       = LGDT3302,
	.serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
	.pll_set          = lgdt330x_pll_set,
	.set_ts_params    = lgdt330x_set_ts_param,
};

static struct lgdt330x_config fusionhdtv_5_gold = {
	.demod_address    = 0x0e,
	.demod_chip       = LGDT3303,
	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
	.pll_set          = lgdt330x_pll_set,
	.set_ts_params    = lgdt330x_set_ts_param,
};
#endif

static int dvb_register(struct cx8802_dev *dev)
{
	/* init struct videobuf_dvb */
	dev->dvb.name = dev->core->name;
	dev->ts_gen_cntrl = 0x0c;

	/* init frontend */
	switch (dev->core->board) {
#ifdef HAVE_CX22702
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
		dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
						   &dev->core->i2c_adap);
		break;
	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
	case CX88_BOARD_CONEXANT_DVB_T1:
		dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
						   &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_MT352
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_lg_z201;
		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
						 &dev->core->i2c_adap);
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
		dev->core->pll_addr = 0x60;
		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
						 &dev->core->i2c_adap);
		break;
	case CX88_BOARD_KWORLD_DVB_T:
	case CX88_BOARD_DNTV_LIVE_DVB_T:
	case CX88_BOARD_ADSTECH_DVB_T_PCI:
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_unknown_1;
		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
						 &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_OR51132
	case CX88_BOARD_PCHDTV_HD3000:
		dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
						 &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_LGDT330X
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		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;
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_microtune_4042;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
						    &dev->core->i2c_adap);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 9);
		mdelay(200);
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_thomson_dtt7611;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
						    &dev->core->i2c_adap);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 1);
		mdelay(200);
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
						    &dev->core->i2c_adap);
		}
		break;
#endif
	default:
		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
		       dev->core->name);
		break;
	}
	if (NULL == dev->dvb.frontend) {
		printk("%s: frontend initialization failed\n",dev->core->name);
		return -1;
	}

	if (dev->core->pll_desc) {
		dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
		dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
	}

	/* Put the analog decoder in standby to keep it quiet */
	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);

	/* register everything */
	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}

/* ----------------------------------------------------------- */

static int __devinit dvb_probe(struct pci_dev *pci_dev,
			       const struct pci_device_id *pci_id)
{
	struct cx8802_dev *dev;
	struct cx88_core  *core;
	int err;

	/* general setup */
	core = cx88_core_get(pci_dev);
	if (NULL == core)
		return -EINVAL;

	err = -ENODEV;
	if (!cx88_boards[core->board].dvb)
		goto fail_core;

	err = -ENOMEM;
	dev = kmalloc(sizeof(*dev),GFP_KERNEL);
	if (NULL == dev)
		goto fail_core;
	memset(dev,0,sizeof(*dev));
	dev->pci = pci_dev;
	dev->core = core;

	err = cx8802_init_common(dev);
	if (0 != err)
		goto fail_free;

	/* dvb stuff */
	printk("%s/2: cx2388x based dvb card\n", core->name);
	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
			    dev->pci, &dev->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
			    V4L2_FIELD_TOP,
			    sizeof(struct cx88_buffer),
			    dev);
	err = dvb_register(dev);
	if (0 != err)
		goto fail_fini;
	return 0;

 fail_fini:
	cx8802_fini_common(dev);
 fail_free:
	kfree(dev);
 fail_core:
	cx88_core_put(core,pci_dev);
	return err;
}

static void __devexit dvb_remove(struct pci_dev *pci_dev)
{
        struct cx8802_dev *dev = pci_get_drvdata(pci_dev);

	/* dvb */
	videobuf_dvb_unregister(&dev->dvb);

	/* common */
	cx8802_fini_common(dev);
	cx88_core_put(dev->core,dev->pci);
	kfree(dev);
}

static struct pci_device_id cx8802_pci_tbl[] = {
	{
		.vendor       = 0x14f1,
		.device       = 0x8802,
                .subvendor    = PCI_ANY_ID,
                .subdevice    = PCI_ANY_ID,
	},{
		/* --- end of list --- */
	}
};
Esempio n. 11
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;
}
Esempio n. 12
0
int cx18_dvb_register(struct cx18_stream *stream)
{
	struct cx18 *cx = stream->cx;
	struct cx18_dvb *dvb = stream->dvb;
	struct dvb_adapter *dvb_adapter;
	struct dvb_demux *dvbdemux;
	struct dmx_demux *dmx;
	int ret;

	if (!dvb)
		return -EINVAL;

	dvb->enabled = 0;
	dvb->stream = stream;

	ret = dvb_register_adapter(&dvb->dvb_adapter,
			CX18_DRIVER_NAME,
			THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
	if (ret < 0)
		goto err_out;

	dvb_adapter = &dvb->dvb_adapter;

	dvbdemux = &dvb->demux;

	dvbdemux->priv = (void *)stream;

	dvbdemux->filternum = 256;
	dvbdemux->feednum = 256;
	dvbdemux->start_feed = cx18_dvb_start_feed;
	dvbdemux->stop_feed = cx18_dvb_stop_feed;
	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
		DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
	ret = dvb_dmx_init(dvbdemux);
	if (ret < 0)
		goto err_dvb_unregister_adapter;

	dmx = &dvbdemux->dmx;

	dvb->hw_frontend.source = DMX_FRONTEND_0;
	dvb->mem_frontend.source = DMX_MEMORY_FE;
	dvb->dmxdev.filternum = 256;
	dvb->dmxdev.demux = dmx;

	ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
	if (ret < 0)
		goto err_dvb_dmx_release;

	ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
	if (ret < 0)
		goto err_dvb_dmxdev_release;

	ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
	if (ret < 0)
		goto err_remove_hw_frontend;

	ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
	if (ret < 0)
		goto err_remove_mem_frontend;

	ret = dvb_register(stream);
	if (ret < 0)
		goto err_disconnect_frontend;

	dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);

	CX18_INFO("DVB Frontend registered\n");
	CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
		  stream->dvb->dvb_adapter.num, stream->name,
		  stream->buffers, stream->buf_size/1024,
		  (stream->buf_size * 100 / 1024) % 100);

	mutex_init(&dvb->feedlock);
	dvb->enabled = 1;
	return ret;

err_disconnect_frontend:
	dmx->disconnect_frontend(dmx);
err_remove_mem_frontend:
	dmx->remove_frontend(dmx, &dvb->mem_frontend);
err_remove_hw_frontend:
	dmx->remove_frontend(dmx, &dvb->hw_frontend);
err_dvb_dmxdev_release:
	dvb_dmxdev_release(&dvb->dmxdev);
err_dvb_dmx_release:
	dvb_dmx_release(dvbdemux);
err_dvb_unregister_adapter:
	dvb_unregister_adapter(dvb_adapter);
err_out:
	return ret;
}
Esempio n. 13
0
static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
{
	struct cx8802_dev *dev= fe->dvb->priv;

	/* this message is to set up ATC and ALC */
	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0,
		  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
	int err;

	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}

	return 0;
}

static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
				      struct dvb_frontend_parameters* params,
				      u8* pllbuf)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0,
		  .buf = pllbuf+1, .len = 4 };
	int err;

	/* Switch PLL to DVB mode */
	err = philips_fmd1216_pll_init(fe);
	if (err)
		return err;

	/* Tune PLL */
	pllbuf[0] = dev->core->pll_addr << 1;
	dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
			  params->frequency,
			  params->u.ofdm.bandwidth);
	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
		printk(KERN_WARNING "cx88-dvb: %s error "
			   "(addr %02x <- %02x, err = %i)\n",
			   __FUNCTION__, pllbuf[0], pllbuf[1], err);
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}

	return 0;
}

static struct mt352_config dntv_live_dvbt_pro_config = {
	.demod_address = 0x0f,
	.no_tuner      = 1,
	.demod_init    = dntv_live_dvbt_pro_demod_init,
	.pll_set       = dntv_live_dvbt_pro_pll_set,
};
#endif
#endif

#ifdef HAVE_CX22702
static struct cx22702_config connexant_refboard_config = {
	.demod_address = 0x43,
	.output_mode   = CX22702_SERIAL_OUTPUT,
	.pll_address   = 0x60,
	.pll_desc      = &dvb_pll_thomson_dtt7579,
};

static struct cx22702_config hauppauge_novat_config = {
	.demod_address = 0x43,
	.output_mode   = CX22702_SERIAL_OUTPUT,
	.pll_address   = 0x61,
	.pll_desc      = &dvb_pll_thomson_dtt759x,
};
static struct cx22702_config hauppauge_hvr1100_config = {
	.demod_address = 0x63,
	.output_mode   = CX22702_SERIAL_OUTPUT,
	.pll_address   = 0x61,
	.pll_desc      = &dvb_pll_fmd1216me,
};
#endif

#ifdef HAVE_OR51132
static int or51132_set_ts_param(struct dvb_frontend* fe,
				int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
	return 0;
}

static struct or51132_config pchdtv_hd3000 = {
	.demod_address    = 0x15,
	.pll_address      = 0x61,
	.pll_desc         = &dvb_pll_thomson_dtt7610,
	.set_ts_params    = or51132_set_ts_param,
};
#endif

#ifdef HAVE_LGDT330X
static int lgdt330x_pll_set(struct dvb_frontend* fe,
			    struct dvb_frontend_parameters* params)
{
	/* FIXME make this routine use the tuner-simple code.
	 * It could probably be shared with a number of ATSC
	 * frontends. Many share the same tuner with analog TV. */

	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;
	u8 buf[4];
	struct i2c_msg msg =
		{ .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
	int err;

	/* Put the analog decoder in standby to keep it quiet */
	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);

	dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
	if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
		printk(KERN_WARNING "cx88-dvb: %s error "
			   "(addr %02x <- %02x, err = %i)\n",
			   __FUNCTION__, buf[0], buf[1], err);
		if (err < 0)
			return err;
		else
			return -EREMOTEIO;
	}
	if (core->tuner_type == TUNER_LG_TDVS_H062F) {
		/* Set the Auxiliary Byte. */
		buf[2] &= ~0x20;
		buf[2] |= 0x18;
		buf[3] = 0x50;
		i2c_transfer(&core->i2c_adap, &msg, 1);
	}
	return 0;
}

static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	dprintk(1, "%s: index = %d\n", __FUNCTION__, index);
	if (index == 0)
		cx_clear(MO_GP0_IO, 8);
	else
		cx_set(MO_GP0_IO, 8);
	return 0;
}

static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	if (is_punctured)
		dev->ts_gen_cntrl |= 0x04;
	else
		dev->ts_gen_cntrl &= ~0x04;
	return 0;
}

static struct lgdt330x_config fusionhdtv_3_gold = {
	.demod_address    = 0x0e,
	.demod_chip       = LGDT3302,
	.serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
	.pll_set          = lgdt330x_pll_set,
	.set_ts_params    = lgdt330x_set_ts_param,
};

static struct lgdt330x_config fusionhdtv_5_gold = {
	.demod_address    = 0x0e,
	.demod_chip       = LGDT3303,
	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
	.pll_set          = lgdt330x_pll_set,
	.set_ts_params    = lgdt330x_set_ts_param,
};
#endif

#ifdef HAVE_NXT200X
static int nxt200x_set_ts_param(struct dvb_frontend* fe,
				int is_punctured)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
	return 0;
}

static int nxt200x_set_pll_input(u8* buf, int input)
{
	if (input)
		buf[3] |= 0x08;
	else
		buf[3] &= ~0x08;
	return 0;
}

static struct nxt200x_config ati_hdtvwonder = {
	.demod_address    = 0x0a,
	.pll_address      = 0x61,
	.pll_desc         = &dvb_pll_tuv1236d,
	.set_pll_input    = nxt200x_set_pll_input,
	.set_ts_params    = nxt200x_set_ts_param,
};
#endif

#ifdef HAVE_CX24123
static int cx24123_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 void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
{
	struct cx8802_dev *dev= fe->dvb->priv;
	struct cx88_core *core = dev->core;

	if (on)
		cx_write(MO_GP0_IO, 0x000006f9);
	else
		cx_write(MO_GP0_IO, 0x000006fB);
}

static struct cx24123_config hauppauge_novas_config = {
	.demod_address		= 0x55,
	.use_isl6421		= 1,
	.set_ts_params		= cx24123_set_ts_param,
};

static struct cx24123_config kworld_dvbs_100_config = {
	.demod_address		= 0x15,
	.use_isl6421		= 0,
	.set_ts_params		= cx24123_set_ts_param,
	.enable_lnb_voltage	= cx24123_enable_lnb_voltage,
};
#endif

static int dvb_register(struct cx8802_dev *dev)
{
	/* init struct videobuf_dvb */
	dev->dvb.name = dev->core->name;
	dev->ts_gen_cntrl = 0x0c;

	/* init frontend */
	switch (dev->core->board) {
#ifdef HAVE_CX22702
	case CX88_BOARD_HAUPPAUGE_DVB_T1:
		dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
						   &dev->core->i2c_adap);
		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:
		dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
						   &dev->core->i2c_adap);
		break;
	case CX88_BOARD_HAUPPAUGE_HVR1100:
	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
		dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
						   &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_MT352
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_lg_z201;
		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
						 &dev->core->i2c_adap);
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
		dev->core->pll_addr = 0x60;
		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
						 &dev->core->i2c_adap);
		break;
	case CX88_BOARD_KWORLD_DVB_T:
	case CX88_BOARD_DNTV_LIVE_DVB_T:
	case CX88_BOARD_ADSTECH_DVB_T_PCI:
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_unknown_1;
		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
						 &dev->core->i2c_adap);
		break;
	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
#ifdef HAVE_VP3054_I2C
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_fmd1216me;
		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
			&((struct vp3054_i2c_state *)dev->card_priv)->adap);
#else
		printk("%s: built without vp3054 support\n", dev->core->name);
#endif
		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. */
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
						 &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_OR51132
	case CX88_BOARD_PCHDTV_HD3000:
		dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
						 &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_LGDT330X
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		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;
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_microtune_4042;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
						    &dev->core->i2c_adap);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 9);
		mdelay(200);
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
						    &dev->core->i2c_adap);
		}
		break;
	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
		dev->ts_gen_cntrl = 0x08;
		{
		/* Do a hardware reset of chip before using it. */
		struct cx88_core *core = dev->core;

		cx_clear(MO_GP0_IO, 1);
		mdelay(100);
		cx_set(MO_GP0_IO, 1);
		mdelay(200);
		dev->core->pll_addr = 0x61;
		dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
						    &dev->core->i2c_adap);
		}
		break;
#endif
#ifdef HAVE_NXT200X
	case CX88_BOARD_ATI_HDTVWONDER:
		dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder,
						 &dev->core->i2c_adap);
		break;
#endif
#ifdef HAVE_CX24123
	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
		dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
			&dev->core->i2c_adap);
		break;
	case CX88_BOARD_KWORLD_DVBS_100:
		dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
			&dev->core->i2c_adap);
		break;
#endif
	default:
		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
		       dev->core->name);
		break;
	}
	if (NULL == dev->dvb.frontend) {
		printk("%s: frontend initialization failed\n",dev->core->name);
		return -1;
	}

	if (dev->core->pll_desc) {
		dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
		dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
	}

	/* Put the analog decoder in standby to keep it quiet */
	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);

	/* register everything */
	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}

/* ----------------------------------------------------------- */

static int __devinit dvb_probe(struct pci_dev *pci_dev,
			       const struct pci_device_id *pci_id)
{
	struct cx8802_dev *dev;
	struct cx88_core  *core;
	int err;

	/* general setup */
	core = cx88_core_get(pci_dev);
	if (NULL == core)
		return -EINVAL;

	err = -ENODEV;
	if (!cx88_boards[core->board].dvb)
		goto fail_core;

	err = -ENOMEM;
	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
	if (NULL == dev)
		goto fail_core;
	dev->pci = pci_dev;
	dev->core = core;

	err = cx8802_init_common(dev);
	if (0 != err)
		goto fail_free;

#ifdef HAVE_VP3054_I2C
	err = vp3054_i2c_probe(dev);
	if (0 != err)
		goto fail_free;
#endif

	/* dvb stuff */
	printk("%s/2: cx2388x based dvb card\n", core->name);
	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
			    dev->pci, &dev->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
			    V4L2_FIELD_TOP,
			    sizeof(struct cx88_buffer),
			    dev);
	err = dvb_register(dev);
	if (0 != err)
		goto fail_fini;

	/* Maintain a reference to cx88-video can query the 8802 device. */
	core->dvbdev = dev;
	return 0;

 fail_fini:
	cx8802_fini_common(dev);
 fail_free:
	kfree(dev);
 fail_core:
	cx88_core_put(core,pci_dev);
	return err;
}

static void __devexit dvb_remove(struct pci_dev *pci_dev)
{
	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);

	/* Destroy any 8802 reference. */
	dev->core->dvbdev = NULL;

	/* dvb */
	videobuf_dvb_unregister(&dev->dvb);

#ifdef HAVE_VP3054_I2C
	vp3054_i2c_remove(dev);
#endif

	/* common */
	cx8802_fini_common(dev);
	cx88_core_put(dev->core,dev->pci);
	kfree(dev);
}

static struct pci_device_id cx8802_pci_tbl[] = {
	{
		.vendor       = 0x14f1,
		.device       = 0x8802,
		.subvendor    = PCI_ANY_ID,
		.subdevice    = PCI_ANY_ID,
	},{
		/* --- end of list --- */
	}
};
MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);

static struct pci_driver dvb_pci_driver = {
	.name     = "cx88-dvb",
	.id_table = cx8802_pci_tbl,
	.probe    = dvb_probe,
	.remove   = __devexit_p(dvb_remove),
	.suspend  = cx8802_suspend_common,
	.resume   = cx8802_resume_common,
};

static int dvb_init(void)
{
	printk(KERN_INFO "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 pci_register_driver(&dvb_pci_driver);
}

static void dvb_fini(void)
{
	pci_unregister_driver(&dvb_pci_driver);
}

module_init(dvb_init);
module_exit(dvb_fini);
Esempio n. 14
0
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
    struct dvb_frontend *fe;
    struct xc2028_ctrl ctl;
    struct xc2028_config cfg = {
        .i2c_adap  = &dev->core->i2c_adap,
        .i2c_addr  = addr,
        .ctrl      = &ctl,
        .callback  = cx88_tuner_callback,
    };

    if (!dev->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, dev->dvb.frontend, &cfg);
    if (!fe) {
        printk(KERN_ERR "%s/2: xc3028 attach failed\n",
               dev->core->name);
        return -EINVAL;
    }

    printk(KERN_INFO "%s/2: xc3028 attached\n",
           dev->core->name);

    return 0;
}

static int dvb_register(struct cx8802_dev *dev)
{
    struct cx88_core *core = dev->core;

    /* init struct videobuf_dvb */
    dev->dvb.name = core->name;
    dev->ts_gen_cntrl = 0x0c;

    /* init frontend */
    switch (core->boardnr) {
    case CX88_BOARD_HAUPPAUGE_DVB_T1:
        dev->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,
                    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:
        dev->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,
                    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:
    case CX88_BOARD_HAUPPAUGE_HVR3000:
        dev->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,
                   &core->i2c_adap, 0x61,
                   TUNER_PHILIPS_FMD1216ME_MK3))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
        dev->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,
                    0x60, NULL, DVB_PLL_THOMSON_DTT7579))
                goto frontend_detach;
            break;
        }
        /* ZL10353 replaces MT352 on later cards */
        dev->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,
                    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. */
        dev->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,
                    0x61, NULL, DVB_PLL_THOMSON_DTT7579))
                goto frontend_detach;
            break;
        }
        /* ZL10353 replaces MT352 on later cards */
        dev->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,
                    0x61, NULL, DVB_PLL_THOMSON_DTT7579))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
        dev->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,
                    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:
        dev->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,
                    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 */
        dev->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,
                    &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:
        dev->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,
                   &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,
                           &dvico_fusionhdtv_xc3028,
                           &core->i2c_adap);
        if (dev->dvb.frontend == NULL)
            dev->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 (dev->dvb.frontend)
            dev->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,
                           &core->i2c_adap);
        if (dev->dvb.frontend != NULL) {
            if (!dvb_attach(simple_tuner_attach, dev->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;
        dev->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,
                    &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);
        dev->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,
                    &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);
        dev->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,
                    &core->i2c_adap, 0x61,
                    TUNER_LG_TDVS_H06XF))
                goto frontend_detach;
            if (!dvb_attach(tda9887_attach, dev->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);
        dev->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,
                    &core->i2c_adap, 0x61,
                    TUNER_LG_TDVS_H06XF))
                goto frontend_detach;
            if (!dvb_attach(tda9887_attach, dev->dvb.frontend,
                   &core->i2c_adap, 0x43))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_ATI_HDTVWONDER:
        dev->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,
                    &core->i2c_adap, 0x61,
                    TUNER_PHILIPS_TUV1236D))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
    case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
        dev->dvb.frontend = dvb_attach(cx24123_attach,
                           &hauppauge_novas_config,
                           &core->i2c_adap);
        if (dev->dvb.frontend) {
            if (!dvb_attach(isl6421_attach, dev->dvb.frontend,
                    &core->i2c_adap, 0x08, 0x00, 0x00))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_KWORLD_DVBS_100:
        dev->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;
        }
        break;
    case CX88_BOARD_GENIATECH_DVBS:
        dev->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;
        }
        break;
    case CX88_BOARD_PINNACLE_PCTV_HD_800i:
        dev->dvb.frontend = dvb_attach(s5h1409_attach,
                           &pinnacle_pctv_hd_800i_config,
                           &core->i2c_adap);
        if (dev->dvb.frontend != NULL) {
            /* tuner_config.video_dev must point to
             * i2c_adap.algo_data
             */
            if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
                    &core->i2c_adap,
                    &pinnacle_pctv_hd_800i_tuner_config,
                    core->i2c_adap.algo_data))
                goto frontend_detach;
        }
        break;
    case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
        dev->dvb.frontend = dvb_attach(s5h1409_attach,
                        &dvico_hdtv5_pci_nano_config,
                        &core->i2c_adap);
        if (dev->dvb.frontend != NULL) {
            struct dvb_frontend *fe;
            struct xc2028_config cfg = {
                .i2c_adap  = &core->i2c_adap,
                .i2c_addr  = 0x61,
                .callback  = cx88_pci_nano_callback,
            };
            static struct xc2028_ctrl ctl = {
                .fname       = "xc3028-v27.fw",
                .max_len     = 64,
                .scode_table = XC3028_FE_OREN538,
            };

            fe = dvb_attach(xc2028_attach,
                    dev->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,
                           &cx88_geniatech_x8000_mt,
                           &core->i2c_adap);
        if (attach_xc3028(0x61, dev) < 0)
            goto frontend_detach;
        break;
     case CX88_BOARD_GENIATECH_X8000_MT:
        dev->ts_gen_cntrl = 0x00;

        dev->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,
                           &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,
                           &dvico_fusionhdtv7_config,
                           &core->i2c_adap);
        if (dev->dvb.frontend != NULL) {
            /* tuner_config.video_dev must point to
             * i2c_adap.algo_data
             */
            if (!dvb_attach(xc5000_attach, dev->dvb.frontend,
                    &core->i2c_adap,
                    &dvico_fusionhdtv7_tuner_config,
                    core->i2c_adap.algo_data))
                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 == dev->dvb.frontend) {
        printk(KERN_ERR
               "%s/2: frontend initialization failed\n",
               core->name);
        return -EINVAL;
    }

    /* Ensure all frontends negotiate bus access */
    dev->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);

frontend_detach:
    if (dev->dvb.frontend) {
        dvb_frontend_detach(dev->dvb.frontend);
        dev->dvb.frontend = NULL;
    }
    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
         */
        cx_set(MO_GP0_IO,   0x00000080); /* cx22702 out of reset and enable */
        cx_clear(MO_GP0_IO, 0x00000004);
        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;
    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;

    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);
    videobuf_queue_sg_init(&dev->dvb.dvbq, &dvb_qops,
                &dev->pci->dev, &dev->slock,
                V4L2_BUF_TYPE_VIDEO_CAPTURE,
                V4L2_FIELD_TOP,
                sizeof(struct cx88_buffer),
                dev);
    err = dvb_register(dev);
    if (err != 0)
        printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
               core->name, err);

 fail_core:
    return err;
}

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);

    vp3054_i2c_remove(dev);

    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, *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;
}
static int dvb_register(struct cx23885_tsport *port)
{
	struct cx23885_dev *dev = port->dev;
	struct cx23885_i2c *i2c_bus = NULL;

	/* init struct videobuf_dvb */
	port->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,
						&hauppauge_generic_config,
						&i2c_bus->i2c_adap);
		if (port->dvb.frontend != NULL) {
			dvb_attach(mt2131_attach, port->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:
			port->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,
					   &dev->i2c_bus[1].i2c_adap, 0x42,
					   &tda829x_no_probe);
				dvb_attach(tda18271_attach, port->dvb.frontend,
					   0x60, &dev->i2c_bus[1].i2c_adap,
					   &hauppauge_tda18271_config);
			}
			break;
		case 0:
		default:
			port->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,
					   &i2c_bus->i2c_adap,
					   &hauppauge_generic_tunerconfig, 0);
			break;
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
		i2c_bus = &dev->i2c_bus[0];
		port->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,
				   &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,
						&fusionhdtv_5_express,
						&i2c_bus->i2c_adap);
		if (port->dvb.frontend != NULL) {
			dvb_attach(simple_tuner_attach, port->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,
						&hauppauge_hvr1500q_config,
						&dev->i2c_bus[0].i2c_adap);
		if (port->dvb.frontend != NULL)
			dvb_attach(xc5000_attach, port->dvb.frontend,
				&i2c_bus->i2c_adap,
				&hauppauge_hvr1500q_tunerconfig, i2c_bus);
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1500:
		i2c_bus = &dev->i2c_bus[1];
		port->dvb.frontend = dvb_attach(s5h1409_attach,
						&hauppauge_hvr1500_config,
						&dev->i2c_bus[0].i2c_adap);
		if (port->dvb.frontend != NULL) {
			struct dvb_frontend *fe;
			struct xc2028_config cfg = {
				.i2c_adap  = &i2c_bus->i2c_adap,
				.i2c_addr  = 0x61,
				.callback  = cx23885_hvr1500_xc3028_callback,
			};
			static struct xc2028_ctrl ctl = {
				.fname       = "xc3028-v27.fw",
				.max_len     = 64,
				.scode_table = XC3028_FE_OREN538,
			};

			fe = dvb_attach(xc2028_attach,
					port->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];
		port->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,
				&dev->i2c_bus[1].i2c_adap, 0x42,
				&tda829x_no_probe);
			dvb_attach(tda18271_attach, port->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,
			&i2c_bus->i2c_adap,
			0x12, &hauppauge_hvr1400_dib7000_config);
		if (port->dvb.frontend != NULL) {
			struct dvb_frontend *fe;
			struct xc2028_config cfg = {
				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
				.i2c_addr  = 0x64,
				.callback  = cx23885_hvr1500_xc3028_callback,
			};
			static struct xc2028_ctrl ctl = {
				.fname   = "xc3028L-v36.fw",
				.max_len = 64,
				.demod   = 5000,
				.d2633   = 1
			};

			fe = dvb_attach(xc2028_attach,
					port->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];

		port->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,
							&dvico_s5h1411_config,
							&i2c_bus->i2c_adap);
		if (port->dvb.frontend != NULL)
			dvb_attach(xc5000_attach, port->dvb.frontend,
				&i2c_bus->i2c_adap,
				&dvico_xc5000_tunerconfig, i2c_bus);
		break;
	default:
		printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
		       dev->name);
		break;
	}
	if (NULL == port->dvb.frontend) {
		printk("%s: frontend initialization failed\n", dev->name);
		return -1;
	}

	/* 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);

	/* register everything */
	return videobuf_dvb_register(&port->dvb, THIS_MODULE, port,
				     &dev->pci->dev, adapter_nr);
}

int cx23885_dvb_register(struct cx23885_tsport *port)
{
	struct cx23885_dev *dev = port->dev;
	int err;

	dprintk(1, "%s\n", __func__);
	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
		dev->board,
		dev->name,
		dev->pci_bus,
		dev->pci_slot);

	err = -ENODEV;

	/* 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,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
			    sizeof(struct cx23885_buffer), port);
	err = dvb_register(port);
	if (err != 0)
		printk("%s() dvb_register failed err = %d\n", __func__, err);

	return err;
}

int cx23885_dvb_unregister(struct cx23885_tsport *port)
{
	/* dvb */
	if(port->dvb.frontend)
		videobuf_dvb_unregister(&port->dvb);

	return 0;
}