diff options
Diffstat (limited to '')
| -rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-dvb.c | 105 | 
1 files changed, 105 insertions, 0 deletions
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c index 4504bc6a700b..1fa79741d199 100644 --- a/drivers/media/usb/cx231xx/cx231xx-dvb.c +++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c @@ -32,7 +32,9 @@  #include "tda18271.h"  #include "s5h1411.h"  #include "lgdt3305.h" +#include "si2165.h"  #include "mb86a20s.h" +#include "si2157.h"  MODULE_DESCRIPTION("driver for cx231xx based DVB cards");  MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); @@ -67,6 +69,7 @@ struct cx231xx_dvb {  	struct dmx_frontend fe_hw;  	struct dmx_frontend fe_mem;  	struct dvb_net net; +	struct i2c_client *i2c_client_tuner;  };  static struct s5h1432_config dvico_s5h1432_config = { @@ -151,6 +154,18 @@ static struct tda18271_config pv_tda18271_config = {  	.small_i2c = TDA18271_03_BYTE_CHUNK_INIT,  }; +static const struct si2165_config hauppauge_930C_HD_1113xx_si2165_config = { +	.i2c_addr	= 0x64, +	.chip_mode	= SI2165_MODE_PLL_XTAL, +	.ref_freq_Hz	= 16000000, +}; + +static const struct si2165_config pctv_quatro_stick_1114xx_si2165_config = { +	.i2c_addr	= 0x64, +	.chip_mode	= SI2165_MODE_PLL_EXT, +	.ref_freq_Hz	= 24000000, +}; +  static inline void print_err_status(struct cx231xx *dev, int packet, int status)  {  	char *errmsg = "Unknown"; @@ -549,11 +564,18 @@ fail_adapter:  static void unregister_dvb(struct cx231xx_dvb *dvb)  { +	struct i2c_client *client;  	dvb_net_release(&dvb->net);  	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);  	dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);  	dvb_dmxdev_release(&dvb->dmxdev);  	dvb_dmx_release(&dvb->demux); +	client = dvb->i2c_client_tuner; +	/* remove I2C tuner */ +	if (client) { +		module_put(client->dev.driver->owner); +		i2c_unregister_device(client); +	}  	dvb_unregister_frontend(dvb->frontend);  	dvb_frontend_detach(dvb->frontend);  	dvb_unregister_adapter(&dvb->adapter); @@ -704,6 +726,89 @@ static int dvb_init(struct cx231xx *dev)  			   &hcw_tda18271_config);  		break; +	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: + +		dev->dvb->frontend = dvb_attach(si2165_attach, +			&hauppauge_930C_HD_1113xx_si2165_config, +			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap +			); + +		if (dev->dvb->frontend == NULL) { +			printk(DRIVER_NAME +			       ": Failed to attach SI2165 front end\n"); +			result = -EINVAL; +			goto out_free; +		} + +		dev->dvb->frontend->ops.i2c_gate_ctrl = 0; + +		/* define general-purpose callback pointer */ +		dvb->frontend->callback = cx231xx_tuner_callback; + +		dvb_attach(tda18271_attach, dev->dvb->frontend, +			0x60, +			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, +			&hcw_tda18271_config); + +		dev->cx231xx_reset_analog_tuner = NULL; +		break; + +	case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: +	{ +		struct i2c_client *client; +		struct i2c_board_info info; +		struct si2157_config si2157_config; + +		memset(&info, 0, sizeof(struct i2c_board_info)); + +		dev->dvb->frontend = dvb_attach(si2165_attach, +			&pctv_quatro_stick_1114xx_si2165_config, +			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap +			); + +		if (dev->dvb->frontend == NULL) { +			printk(DRIVER_NAME +			       ": Failed to attach SI2165 front end\n"); +			result = -EINVAL; +			goto out_free; +		} + +		dev->dvb->frontend->ops.i2c_gate_ctrl = 0; + +		/* define general-purpose callback pointer */ +		dvb->frontend->callback = cx231xx_tuner_callback; + +		/* attach tuner */ +		memset(&si2157_config, 0, sizeof(si2157_config)); +		si2157_config.fe = dev->dvb->frontend; +		si2157_config.inversion = true; +		strlcpy(info.type, "si2157", I2C_NAME_SIZE); +		info.addr = 0x60; +		info.platform_data = &si2157_config; +		request_module("si2157"); + +		client = i2c_new_device( +			&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap, +			&info); +		if (client == NULL || client->dev.driver == NULL) { +			dvb_frontend_detach(dev->dvb->frontend); +			result = -ENODEV; +			goto out_free; +		} + +		if (!try_module_get(client->dev.driver->owner)) { +			i2c_unregister_device(client); +			dvb_frontend_detach(dev->dvb->frontend); +			result = -ENODEV; +			goto out_free; +		} + +		dev->cx231xx_reset_analog_tuner = NULL; + +		dev->dvb->i2c_client_tuner = client; +		break; +	} +  	case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:  	case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:  | 
