media: pvrusb2: Add multiple dvb frontend support
All changes are equivalent and backwards compatible. All current devices have been changed to use fe[0] Code has been added to dvb init to support cleanup after failure. Multiple frontends are required by Hauppauge HVR-1975, which is in a later commit. Signed-off-by: Brad Love <brad@nextdimension.cc> Reviewed-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:

committed by
Mauro Carvalho Chehab

parent
d5cb82b01a
commit
cac821d2ea
@@ -188,10 +188,10 @@ static struct lgdt330x_config pvr2_lgdt3303_config = {
|
|||||||
|
|
||||||
static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
|
adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
|
||||||
0x0e,
|
0x0e,
|
||||||
&adap->channel.hdw->i2c_adap);
|
&adap->channel.hdw->i2c_adap);
|
||||||
if (adap->fe)
|
if (adap->fe[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -199,7 +199,7 @@ static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
|
|||||||
|
|
||||||
static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
dvb_attach(simple_tuner_attach, adap->fe,
|
dvb_attach(simple_tuner_attach, adap->fe[0],
|
||||||
&adap->channel.hdw->i2c_adap, 0x61,
|
&adap->channel.hdw->i2c_adap, 0x61,
|
||||||
TUNER_LG_TDVS_H06XF);
|
TUNER_LG_TDVS_H06XF);
|
||||||
|
|
||||||
@@ -248,10 +248,10 @@ static struct lgdt330x_config pvr2_lgdt3302_config = {
|
|||||||
|
|
||||||
static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
|
adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
|
||||||
0x0e,
|
0x0e,
|
||||||
&adap->channel.hdw->i2c_adap);
|
&adap->channel.hdw->i2c_adap);
|
||||||
if (adap->fe)
|
if (adap->fe[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -259,7 +259,7 @@ static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
|
|||||||
|
|
||||||
static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
dvb_attach(simple_tuner_attach, adap->fe,
|
dvb_attach(simple_tuner_attach, adap->fe[0],
|
||||||
&adap->channel.hdw->i2c_adap, 0x61,
|
&adap->channel.hdw->i2c_adap, 0x61,
|
||||||
TUNER_PHILIPS_FCV1236D);
|
TUNER_PHILIPS_FCV1236D);
|
||||||
|
|
||||||
@@ -335,9 +335,9 @@ static struct tda18271_config hauppauge_tda18271_dvb_config = {
|
|||||||
|
|
||||||
static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
|
adap->fe[0] = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
|
||||||
&adap->channel.hdw->i2c_adap);
|
&adap->channel.hdw->i2c_adap);
|
||||||
if (adap->fe)
|
if (adap->fe[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -345,10 +345,10 @@ static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
|
|||||||
|
|
||||||
static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
dvb_attach(tda829x_attach, adap->fe,
|
dvb_attach(tda829x_attach, adap->fe[0],
|
||||||
&adap->channel.hdw->i2c_adap, 0x42,
|
&adap->channel.hdw->i2c_adap, 0x42,
|
||||||
&tda829x_no_probe);
|
&tda829x_no_probe);
|
||||||
dvb_attach(tda18271_attach, adap->fe, 0x60,
|
dvb_attach(tda18271_attach, adap->fe[0], 0x60,
|
||||||
&adap->channel.hdw->i2c_adap,
|
&adap->channel.hdw->i2c_adap,
|
||||||
&hauppauge_tda18271_dvb_config);
|
&hauppauge_tda18271_dvb_config);
|
||||||
|
|
||||||
@@ -433,9 +433,9 @@ static struct tda18271_config hauppauge_tda18271_config = {
|
|||||||
|
|
||||||
static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
|
adap->fe[0] = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
|
||||||
&adap->channel.hdw->i2c_adap);
|
&adap->channel.hdw->i2c_adap);
|
||||||
if (adap->fe)
|
if (adap->fe[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -443,9 +443,9 @@ static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
|
|||||||
|
|
||||||
static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
|
adap->fe[0] = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
|
||||||
&adap->channel.hdw->i2c_adap);
|
&adap->channel.hdw->i2c_adap);
|
||||||
if (adap->fe)
|
if (adap->fe[0])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -453,10 +453,10 @@ static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
|
|||||||
|
|
||||||
static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
|
static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
dvb_attach(tda829x_attach, adap->fe,
|
dvb_attach(tda829x_attach, adap->fe[0],
|
||||||
&adap->channel.hdw->i2c_adap, 0x42,
|
&adap->channel.hdw->i2c_adap, 0x42,
|
||||||
&tda829x_no_probe);
|
&tda829x_no_probe);
|
||||||
dvb_attach(tda18271_attach, adap->fe, 0x60,
|
dvb_attach(tda18271_attach, adap->fe[0], 0x60,
|
||||||
&adap->channel.hdw->i2c_adap,
|
&adap->channel.hdw->i2c_adap,
|
||||||
&hauppauge_tda18271_config);
|
&hauppauge_tda18271_config);
|
||||||
|
|
||||||
|
@@ -343,26 +343,19 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
|
if (dvb_props->frontend_attach(adap) == 0 && adap->fe[0]) {
|
||||||
|
if (dvb_register_frontend(&adap->dvb_adap, adap->fe[0])) {
|
||||||
if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
|
|
||||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||||
"frontend registration failed!");
|
"frontend registration failed!");
|
||||||
dvb_frontend_detach(adap->fe);
|
|
||||||
adap->fe = NULL;
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto done;
|
goto fail_frontend0;
|
||||||
}
|
}
|
||||||
|
if (adap->fe[0]->ops.analog_ops.standby)
|
||||||
|
adap->fe[0]->ops.analog_ops.standby(adap->fe[0]);
|
||||||
|
|
||||||
if (dvb_props->tuner_attach)
|
pvr2_trace(PVR2_TRACE_INFO, "transferring fe[%d] ts_bus_ctrl() to pvr2_dvb_bus_ctrl()",
|
||||||
dvb_props->tuner_attach(adap);
|
adap->fe[0]->id);
|
||||||
|
adap->fe[0]->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
|
||||||
if (adap->fe->ops.analog_ops.standby)
|
|
||||||
adap->fe->ops.analog_ops.standby(adap->fe);
|
|
||||||
|
|
||||||
/* Ensure all frontends negotiate bus access */
|
|
||||||
adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||||
"no frontend was attached!");
|
"no frontend was attached!");
|
||||||
@@ -370,16 +363,62 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dvb_props->tuner_attach && dvb_props->tuner_attach(adap)) {
|
||||||
|
pvr2_trace(PVR2_TRACE_ERROR_LEGS, "tuner attach failed");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto fail_tuner;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adap->fe[1]) {
|
||||||
|
adap->fe[1]->id = 1;
|
||||||
|
adap->fe[1]->tuner_priv = adap->fe[0]->tuner_priv;
|
||||||
|
memcpy(&adap->fe[1]->ops.tuner_ops,
|
||||||
|
&adap->fe[0]->ops.tuner_ops,
|
||||||
|
sizeof(struct dvb_tuner_ops));
|
||||||
|
|
||||||
|
if (dvb_register_frontend(&adap->dvb_adap, adap->fe[1])) {
|
||||||
|
pvr2_trace(PVR2_TRACE_ERROR_LEGS,
|
||||||
|
"frontend registration failed!");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto fail_frontend1;
|
||||||
|
}
|
||||||
|
/* MFE lock */
|
||||||
|
adap->dvb_adap.mfe_shared = 1;
|
||||||
|
|
||||||
|
if (adap->fe[1]->ops.analog_ops.standby)
|
||||||
|
adap->fe[1]->ops.analog_ops.standby(adap->fe[1]);
|
||||||
|
|
||||||
|
pvr2_trace(PVR2_TRACE_INFO, "transferring fe[%d] ts_bus_ctrl() to pvr2_dvb_bus_ctrl()",
|
||||||
|
adap->fe[1]->id);
|
||||||
|
adap->fe[1]->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
|
||||||
|
}
|
||||||
done:
|
done:
|
||||||
pvr2_channel_limit_inputs(&adap->channel, 0);
|
pvr2_channel_limit_inputs(&adap->channel, 0);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
fail_frontend1:
|
||||||
|
dvb_frontend_detach(adap->fe[1]);
|
||||||
|
adap->fe[1] = NULL;
|
||||||
|
fail_tuner:
|
||||||
|
dvb_unregister_frontend(adap->fe[0]);
|
||||||
|
fail_frontend0:
|
||||||
|
dvb_frontend_detach(adap->fe[0]);
|
||||||
|
adap->fe[0] = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
|
static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
|
||||||
{
|
{
|
||||||
if (adap->fe != NULL) {
|
if (adap->fe[1]) {
|
||||||
dvb_unregister_frontend(adap->fe);
|
dvb_unregister_frontend(adap->fe[1]);
|
||||||
dvb_frontend_detach(adap->fe);
|
dvb_frontend_detach(adap->fe[1]);
|
||||||
|
adap->fe[1] = NULL;
|
||||||
|
}
|
||||||
|
if (adap->fe[0]) {
|
||||||
|
dvb_unregister_frontend(adap->fe[0]);
|
||||||
|
dvb_frontend_detach(adap->fe[0]);
|
||||||
|
adap->fe[0] = NULL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ struct pvr2_dvb_adapter {
|
|||||||
struct dmxdev dmxdev;
|
struct dmxdev dmxdev;
|
||||||
struct dvb_demux demux;
|
struct dvb_demux demux;
|
||||||
struct dvb_net dvb_net;
|
struct dvb_net dvb_net;
|
||||||
struct dvb_frontend *fe;
|
struct dvb_frontend *fe[2];
|
||||||
|
|
||||||
int feedcount;
|
int feedcount;
|
||||||
int max_feed_count;
|
int max_feed_count;
|
||||||
|
Reference in New Issue
Block a user