]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
media: pvrusb2: Add multiple dvb frontend support
authorBrad Love <brad@nextdimension.cc>
Thu, 30 May 2019 20:32:25 +0000 (16:32 -0400)
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>
Thu, 13 Jun 2019 18:28:52 +0000 (14:28 -0400)
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>
drivers/media/usb/pvrusb2/pvrusb2-devattr.c
drivers/media/usb/pvrusb2/pvrusb2-dvb.c
drivers/media/usb/pvrusb2/pvrusb2-dvb.h

index 06de1c83f444ff39d529b7e709384c3d796b6b12..a4a27e071c6dc544c6b4d8adcd8d3ce981b36d7e 100644 (file)
@@ -188,10 +188,10 @@ static struct lgdt330x_config pvr2_lgdt3303_config = {
 
 static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
 {
-       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
-                             0x0e,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
+       adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
+                                0x0e,
+                                &adap->channel.hdw->i2c_adap);
+       if (adap->fe[0])
                return 0;
 
        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)
 {
-       dvb_attach(simple_tuner_attach, adap->fe,
+       dvb_attach(simple_tuner_attach, adap->fe[0],
                   &adap->channel.hdw->i2c_adap, 0x61,
                   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)
 {
-       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
-                             0x0e,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
+       adap->fe[0] = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
+                                0x0e,
+                                &adap->channel.hdw->i2c_adap);
+       if (adap->fe[0])
                return 0;
 
        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)
 {
-       dvb_attach(simple_tuner_attach, adap->fe,
+       dvb_attach(simple_tuner_attach, adap->fe[0],
                   &adap->channel.hdw->i2c_adap, 0x61,
                   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)
 {
-       adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
+       adap->fe[0] = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
+                                &adap->channel.hdw->i2c_adap);
+       if (adap->fe[0])
                return 0;
 
        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)
 {
-       dvb_attach(tda829x_attach, adap->fe,
+       dvb_attach(tda829x_attach, adap->fe[0],
                   &adap->channel.hdw->i2c_adap, 0x42,
                   &tda829x_no_probe);
-       dvb_attach(tda18271_attach, adap->fe, 0x60,
+       dvb_attach(tda18271_attach, adap->fe[0], 0x60,
                   &adap->channel.hdw->i2c_adap,
                   &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)
 {
-       adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
+       adap->fe[0] = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
+                                &adap->channel.hdw->i2c_adap);
+       if (adap->fe[0])
                return 0;
 
        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)
 {
-       adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
+       adap->fe[0] = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
+                                &adap->channel.hdw->i2c_adap);
+       if (adap->fe[0])
                return 0;
 
        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)
 {
-       dvb_attach(tda829x_attach, adap->fe,
+       dvb_attach(tda829x_attach, adap->fe[0],
                   &adap->channel.hdw->i2c_adap, 0x42,
                   &tda829x_no_probe);
-       dvb_attach(tda18271_attach, adap->fe, 0x60,
+       dvb_attach(tda18271_attach, adap->fe[0], 0x60,
                   &adap->channel.hdw->i2c_adap,
                   &hauppauge_tda18271_config);
 
index 4b32b214116959a699121ab8a3c930346f313648..f302f1e7670a0dc6b99b38818ba39eb513aca012 100644 (file)
@@ -343,26 +343,19 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
                goto done;
        }
 
-       if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
-
-               if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
+       if (dvb_props->frontend_attach(adap) == 0 && adap->fe[0]) {
+               if (dvb_register_frontend(&adap->dvb_adap, adap->fe[0])) {
                        pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                                   "frontend registration failed!");
-                       dvb_frontend_detach(adap->fe);
-                       adap->fe = NULL;
                        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)
-                       dvb_props->tuner_attach(adap);
-
-               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;
-
+               pvr2_trace(PVR2_TRACE_INFO, "transferring fe[%d] ts_bus_ctrl() to pvr2_dvb_bus_ctrl()",
+                          adap->fe[0]->id);
+               adap->fe[0]->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
        } else {
                pvr2_trace(PVR2_TRACE_ERROR_LEGS,
                           "no frontend was attached!");
@@ -370,16 +363,62 @@ static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
                return ret;
        }
 
- done:
+       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:
        pvr2_channel_limit_inputs(&adap->channel, 0);
        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)
 {
-       if (adap->fe != NULL) {
-               dvb_unregister_frontend(adap->fe);
-               dvb_frontend_detach(adap->fe);
+       if (adap->fe[1]) {
+               dvb_unregister_frontend(adap->fe[1]);
+               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;
 }
index e7f71fb94a6ee211c8d9b5654c1a39a3a9a03590..91bff573288d1bb440cc7f0f56db2005ecfd4c86 100644 (file)
@@ -18,7 +18,7 @@ struct pvr2_dvb_adapter {
        struct dmxdev           dmxdev;
        struct dvb_demux        demux;
        struct dvb_net          dvb_net;
-       struct dvb_frontend     *fe;
+       struct dvb_frontend     *fe[2];
 
        int                     feedcount;
        int                     max_feed_count;