[media] dvbdev: Add RF connector if needed
authorMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 29 Dec 2015 13:52:23 +0000 (11:52 -0200)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Mon, 11 Jan 2016 14:19:25 +0000 (12:19 -0200)
Several pure digital TV devices have a frontend with the tuner
integrated on it. Add the RF connector when dvb_create_media_graph()
is called on such devices.

Tested with siano and dvb_usb_mxl111sf drivers.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/common/siano/smsdvb-main.c
drivers/media/dvb-core/dvbdev.c
drivers/media/dvb-core/dvbdev.h
drivers/media/usb/au0828/au0828-dvb.c
drivers/media/usb/cx231xx/cx231xx-dvb.c
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
drivers/media/usb/dvb-usb/dvb-usb-dvb.c

index 8a1ea219243944f8b397152c32cae24499b59292..d31f468830cf6de4508610bfc4086c4c27909e20 100644 (file)
@@ -1184,7 +1184,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
        if (smsdvb_debugfs_create(client) < 0)
                pr_info("failed to create debugfs node\n");
 
-       rc = dvb_create_media_graph(&client->adapter);
+       rc = dvb_create_media_graph(&client->adapter, true);
        if (rc < 0) {
                pr_err("dvb_create_media_graph failed %d\n", rc);
                goto client_error;
index 860dd7d06b601d01337d37a502883035902bc42f..28e340583edee3075e84896de2fec8567788fe90 100644 (file)
@@ -213,6 +213,13 @@ static void dvb_media_device_free(struct dvb_device *dvbdev)
                media_devnode_remove(dvbdev->intf_devnode);
                dvbdev->intf_devnode = NULL;
        }
+
+       if (dvbdev->adapter->conn) {
+               media_device_unregister_entity(dvbdev->adapter->conn);
+               dvbdev->adapter->conn = NULL;
+               kfree(dvbdev->adapter->conn_pads);
+               dvbdev->adapter->conn_pads = NULL;
+       }
 #endif
 }
 
@@ -559,16 +566,18 @@ static int dvb_create_io_intf_links(struct dvb_adapter *adap,
        return 0;
 }
 
-int dvb_create_media_graph(struct dvb_adapter *adap)
+int dvb_create_media_graph(struct dvb_adapter *adap,
+                          bool create_rf_connector)
 {
        struct media_device *mdev = adap->mdev;
-       struct media_entity *entity, *tuner = NULL, *demod = NULL;
+       struct media_entity *entity, *tuner = NULL, *demod = NULL, *conn;
        struct media_entity *demux = NULL, *ca = NULL;
        struct media_link *link;
        struct media_interface *intf;
        unsigned demux_pad = 0;
        unsigned dvr_pad = 0;
        int ret;
+       static const char *connector_name = "Television";
 
        if (!mdev)
                return 0;
@@ -590,6 +599,42 @@ int dvb_create_media_graph(struct dvb_adapter *adap)
                }
        }
 
+       if (create_rf_connector) {
+               conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+               if (!conn)
+                       return -ENOMEM;
+               adap->conn = conn;
+
+               adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads),
+                                           GFP_KERNEL);
+               if (!adap->conn_pads)
+                       return -ENOMEM;
+
+               conn->flags = MEDIA_ENT_FL_CONNECTOR;
+               conn->function = MEDIA_ENT_F_CONN_RF;
+               conn->name = connector_name;
+               adap->conn_pads->flags = MEDIA_PAD_FL_SOURCE;
+
+               ret = media_entity_pads_init(conn, 1, adap->conn_pads);
+               if (ret)
+                       return ret;
+
+               ret = media_device_register_entity(mdev, conn);
+               if (ret)
+                       return ret;
+
+               if (!tuner)
+                       ret = media_create_pad_link(conn, 0,
+                                                   demod, 0,
+                                                   MEDIA_LNK_FL_ENABLED);
+               else
+                       ret = media_create_pad_link(conn, 0,
+                                                   tuner, TUNER_PAD_RF_INPUT,
+                                                   MEDIA_LNK_FL_ENABLED);
+               if (ret)
+                       return ret;
+       }
+
        if (tuner && demod) {
                ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT,
                                            demod, 0, MEDIA_LNK_FL_ENABLED);
index abee18a402e1e4ceffd145453df447b65ce9153f..b622d6a3b95e00d10492dfa9e336a789df1092a0 100644 (file)
@@ -75,6 +75,9 @@ struct dvb_frontend;
  *                     used.
  * @mdev:              pointer to struct media_device, used when the media
  *                     controller is used.
+ * @conn:              RF connector. Used only if the device has no separate
+ *                     tuner.
+ * @conn_pads:         pointer to struct media_pad associated with @conn;
  */
 struct dvb_adapter {
        int num;
@@ -94,6 +97,8 @@ struct dvb_adapter {
 
 #if defined(CONFIG_MEDIA_CONTROLLER_DVB)
        struct media_device *mdev;
+       struct media_entity *conn;
+       struct media_pad *conn_pads;
 #endif
 };
 
@@ -214,7 +219,16 @@ int dvb_register_device(struct dvb_adapter *adap,
 void dvb_unregister_device(struct dvb_device *dvbdev);
 
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
-__must_check int dvb_create_media_graph(struct dvb_adapter *adap);
+/**
+ * dvb_create_media_graph - Creates media graph for the Digital TV part of the
+ *                             device.
+ *
+ * @adap:                      pointer to struct dvb_adapter
+ * @create_rf_connector:       if true, it creates the RF connector too
+ */
+__must_check int dvb_create_media_graph(struct dvb_adapter *adap,
+                                       bool create_rf_connector);
+
 static inline void dvb_register_media_controller(struct dvb_adapter *adap,
                                                 struct media_device *mdev)
 {
@@ -222,7 +236,9 @@ static inline void dvb_register_media_controller(struct dvb_adapter *adap,
 }
 
 #else
-static inline int dvb_create_media_graph(struct dvb_adapter *adap)
+static inline
+int dvb_create_media_graph(struct dvb_adapter *adap,
+                          bool create_rf_connector)
 {
        return 0;
 };
index cd542b49a6c2bdab211bc49776bd1a1d01a00f8d..94363a3ba400a3ccdcaa3d6ec88ebc082d1ecdf2 100644 (file)
@@ -486,7 +486,7 @@ static int dvb_register(struct au0828_dev *dev)
        dvb->start_count = 0;
        dvb->stop_count = 0;
 
-       result = dvb_create_media_graph(&dvb->adapter);
+       result = dvb_create_media_graph(&dvb->adapter, false);
        if (result < 0)
                goto fail_create_graph;
 
index b7552d20ebdb5594699bc28bf152604911b5af8f..b8d5b2be92937ccbb0dc7a3a0ed01f544e7644bb 100644 (file)
@@ -551,7 +551,7 @@ static int register_dvb(struct cx231xx_dvb *dvb,
 
        /* register network adapter */
        dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
-       result = dvb_create_media_graph(&dvb->adapter);
+       result = dvb_create_media_graph(&dvb->adapter, false);
        if (result < 0)
                goto fail_create_graph;
 
index 0fa2c45917b029f86270c4e4d3767642796c9103..e8491f73c0d9a0e2bcad8e06735bc72cd2684a1b 100644 (file)
@@ -706,7 +706,7 @@ static int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
                }
        }
 
-       ret = dvb_create_media_graph(&adap->dvb_adap);
+       ret = dvb_create_media_graph(&adap->dvb_adap, true);
        if (ret < 0)
                goto err_dvb_unregister_frontend;
 
index 241463ef631e003b290b4e5e6b469428e9450b9e..9ddfcab268be9c797e7ce6a276dc4168fe0651df 100644 (file)
@@ -330,7 +330,7 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
        if (ret)
                return ret;
 
-       ret = dvb_create_media_graph(&adap->dvb_adap);
+       ret = dvb_create_media_graph(&adap->dvb_adap, true);
        if (ret)
                return ret;