in usb/cx231xx/cx231xx-dvb.c [616:1139]
static int dvb_init(struct cx231xx *dev)
{
int result;
struct cx231xx_dvb *dvb;
struct i2c_adapter *tuner_i2c;
struct i2c_adapter *demod_i2c;
struct i2c_client *client;
struct i2c_adapter *adapter;
if (!dev->board.has_dvb) {
/* This device does not support the extension */
return 0;
}
dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
if (dvb == NULL) {
dev_info(dev->dev,
"cx231xx_dvb: memory allocation failed\n");
return -ENOMEM;
}
dev->dvb = dvb;
dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);
mutex_lock(&dev->lock);
cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
cx231xx_demod_reset(dev);
/* init frontend */
switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250:
dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,
&dvico_s5h1432_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach s5h1432 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],
tuner_i2c,
&cnxt_rde250_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250:
dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,
&xc5000_s5h1411_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach s5h1411 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
if (!dvb_attach(xc5000_attach, dev->dvb->frontend[0],
tuner_i2c,
&cnxt_rdu250_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_CNXT_RDE_253S:
dev->dvb->frontend[0] = dvb_attach(s5h1432_attach,
&dvico_s5h1432_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach s5h1432 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],
dev->board.tuner_addr, tuner_i2c,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_KWORLD_UB445_USB_HYBRID:
dev->dvb->frontend[0] = dvb_attach(s5h1411_attach,
&tda18271_s5h1411_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach s5h1411 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend[0],
dev->board.tuner_addr, tuner_i2c,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_HAUPPAUGE_EXETER:
dev_info(dev->dev,
"%s: looking for tuner / demod on i2c bus: %d\n",
__func__, i2c_adapter_id(tuner_i2c));
dev->dvb->frontend[0] = dvb_attach(lgdt3305_attach,
&hcw_lgdt3305_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach LG3305 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
dvb_attach(tda18271_attach, dev->dvb->frontend[0],
dev->board.tuner_addr, tuner_i2c,
&hcw_tda18271_config);
break;
case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
{
struct si2165_platform_data si2165_pdata = {};
/* attach demod */
si2165_pdata.fe = &dev->dvb->frontend[0];
si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL;
si2165_pdata.ref_freq_hz = 16000000;
/* perform probe/init/attach */
client = dvb_module_probe("si2165", NULL, demod_i2c,
dev->board.demod_addr,
&si2165_pdata);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
dvb_attach(tda18271_attach, dev->dvb->frontend[0],
dev->board.tuner_addr, tuner_i2c,
&hcw_tda18271_config);
dev->cx231xx_reset_analog_tuner = NULL;
break;
}
case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
{
struct si2165_platform_data si2165_pdata = {};
struct si2157_config si2157_config = {};
/* attach demod */
si2165_pdata.fe = &dev->dvb->frontend[0];
si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT;
si2165_pdata.ref_freq_hz = 24000000;
/* perform probe/init/attach */
client = dvb_module_probe("si2165", NULL, demod_i2c,
dev->board.demod_addr,
&si2165_pdata);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
/* attach tuner */
si2157_config.fe = dev->dvb->frontend[0];
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
si2157_config.mdev = dev->media_dev;
#endif
si2157_config.if_port = 1;
si2157_config.inversion = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2157", NULL, tuner_i2c,
dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client;
break;
}
case CX231XX_BOARD_HAUPPAUGE_955Q:
{
struct si2157_config si2157_config = {};
struct lgdt3306a_config lgdt3306a_config = {};
lgdt3306a_config = hauppauge_955q_lgdt3306a_config;
lgdt3306a_config.fe = &dev->dvb->frontend[0];
lgdt3306a_config.i2c_adapter = &adapter;
/* perform probe/init/attach */
client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,
dev->board.demod_addr,
&lgdt3306a_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
/* attach tuner */
si2157_config.fe = dev->dvb->frontend[0];
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
si2157_config.mdev = dev->media_dev;
#endif
si2157_config.if_port = 1;
si2157_config.inversion = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2157", NULL, tuner_i2c,
dev->board.tuner_addr,
&si2157_config);
if (!client) {
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:
dev_info(dev->dev,
"%s: looking for demod on i2c bus: %d\n",
__func__, i2c_adapter_id(tuner_i2c));
dev->dvb->frontend[0] = dvb_attach(mb86a20s_attach,
&pv_mb86a20s_config,
demod_i2c);
if (!dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach mb86a20s demod\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
dvb_attach(tda18271_attach, dev->dvb->frontend[0],
dev->board.tuner_addr, tuner_i2c,
&pv_tda18271_config);
break;
case CX231XX_BOARD_EVROMEDIA_FULL_HYBRID_FULLHD:
{
struct si2157_config si2157_config = {};
struct si2168_config si2168_config = {};
/* attach demodulator chip */
si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */
si2168_config.fe = &dev->dvb->frontend[0];
si2168_config.i2c_adapter = &adapter;
si2168_config.ts_clock_inv = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2168", NULL, demod_i2c,
dev->board.demod_addr,
&si2168_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
/* attach tuner chip */
si2157_config.fe = dev->dvb->frontend[0];
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
si2157_config.mdev = dev->media_dev;
#endif
si2157_config.if_port = 1;
si2157_config.inversion = false;
/* perform probe/init/attach */
client = dvb_module_probe("si2157", NULL, tuner_i2c,
dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client;
break;
}
case CX231XX_BOARD_ASTROMETA_T2HYBRID:
{
struct mn88473_config mn88473_config = {};
/* attach demodulator chip */
mn88473_config.i2c_wr_max = 16;
mn88473_config.xtal = 25000000;
mn88473_config.fe = &dev->dvb->frontend[0];
/* perform probe/init/attach */
client = dvb_module_probe("mn88473", NULL, demod_i2c,
dev->board.demod_addr,
&mn88473_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
/* attach tuner chip */
dvb_attach(r820t_attach, dev->dvb->frontend[0],
tuner_i2c,
&astrometa_t2hybrid_r820t_config);
break;
}
case CX231XX_BOARD_HAUPPAUGE_935C:
{
struct si2157_config si2157_config = {};
struct si2168_config si2168_config = {};
/* attach demodulator chip */
si2168_config.ts_mode = SI2168_TS_SERIAL;
si2168_config.fe = &dev->dvb->frontend[0];
si2168_config.i2c_adapter = &adapter;
si2168_config.ts_clock_inv = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2168", NULL, demod_i2c,
dev->board.demod_addr,
&si2168_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
/* attach tuner */
si2157_config.fe = dev->dvb->frontend[0];
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
si2157_config.mdev = dev->media_dev;
#endif
si2157_config.if_port = 1;
si2157_config.inversion = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2157", NULL, tuner_i2c,
dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client;
break;
}
case CX231XX_BOARD_HAUPPAUGE_975:
{
struct i2c_adapter *adapter2;
struct si2157_config si2157_config = {};
struct lgdt3306a_config lgdt3306a_config = {};
struct si2168_config si2168_config = {};
/* attach first demodulator chip */
lgdt3306a_config = hauppauge_955q_lgdt3306a_config;
lgdt3306a_config.fe = &dev->dvb->frontend[0];
lgdt3306a_config.i2c_adapter = &adapter;
/* perform probe/init/attach */
client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,
dev->board.demod_addr,
&lgdt3306a_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client;
/* attach second demodulator chip */
si2168_config.ts_mode = SI2168_TS_SERIAL;
si2168_config.fe = &dev->dvb->frontend[1];
si2168_config.i2c_adapter = &adapter2;
si2168_config.ts_clock_inv = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2168", NULL, adapter,
dev->board.demod_addr2,
&si2168_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[1] = client;
dvb->frontend[1]->id = 1;
/* define general-purpose callback pointer */
dvb->frontend[0]->callback = cx231xx_tuner_callback;
dvb->frontend[1]->callback = cx231xx_tuner_callback;
/* attach tuner */
si2157_config.fe = dev->dvb->frontend[0];
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
si2157_config.mdev = dev->media_dev;
#endif
si2157_config.if_port = 1;
si2157_config.inversion = true;
/* perform probe/init/attach */
client = dvb_module_probe("si2157", NULL, adapter,
dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV;
goto out_free;
}
dev->cx231xx_reset_analog_tuner = NULL;
dvb->i2c_client_tuner = client;
dvb->frontend[1]->tuner_priv = dvb->frontend[0]->tuner_priv;
memcpy(&dvb->frontend[1]->ops.tuner_ops,
&dvb->frontend[0]->ops.tuner_ops,
sizeof(struct dvb_tuner_ops));
break;
}
default:
dev_err(dev->dev,
"%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
dev->name);
break;
}
if (!dvb->frontend[0]) {
dev_err(dev->dev,
"%s/2: frontend initialization failed\n", dev->name);
result = -EINVAL;
goto out_free;
}
/* register everything */
result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);
if (result < 0)
goto out_free;
dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");
ret:
cx231xx_set_mode(dev, CX231XX_SUSPEND);
mutex_unlock(&dev->lock);
return result;
out_free:
/* remove I2C tuner */
dvb_module_release(dvb->i2c_client_tuner);
dvb->i2c_client_tuner = NULL;
/* remove I2C demod(s) */
dvb_module_release(dvb->i2c_client_demod[1]);
dvb->i2c_client_demod[1] = NULL;
dvb_module_release(dvb->i2c_client_demod[0]);
dvb->i2c_client_demod[0] = NULL;
kfree(dvb);
dev->dvb = NULL;
goto ret;
}