[media] tuner.h: rename TUNER_PAD_IF_OUTPUT to TUNER_PAD_OUTPUT
[deliverable/linux.git] / drivers / media / dvb-core / dvbdev.c
index 860dd7d06b601d01337d37a502883035902bc42f..a7de62ebc4157e8651ea0d8febc21b31b6e97368 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,19 @@ 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;
+       unsigned ntuner = 0, ndemod = 0;
        int ret;
+       static const char *connector_name = "Television";
 
        if (!mdev)
                return 0;
@@ -577,9 +587,11 @@ int dvb_create_media_graph(struct dvb_adapter *adap)
                switch (entity->function) {
                case MEDIA_ENT_F_TUNER:
                        tuner = entity;
+                       ntuner++;
                        break;
                case MEDIA_ENT_F_DTV_DEMOD:
                        demod = entity;
+                       ndemod++;
                        break;
                case MEDIA_ENT_F_TS_DEMUX:
                        demux = entity;
@@ -590,16 +602,80 @@ int dvb_create_media_graph(struct dvb_adapter *adap)
                }
        }
 
-       if (tuner && demod) {
-               ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT,
-                                           demod, 0, MEDIA_LNK_FL_ENABLED);
+       /*
+        * Prepare to signalize to media_create_pad_links() that multiple
+        * entities of the same type exists and a 1:n or n:1 links need to be
+        * created.
+        * NOTE: if both tuner and demod have multiple instances, it is up
+        * to the caller driver to create such links.
+        */
+       if (ntuner > 1)
+               tuner = NULL;
+       if (ndemod > 1)
+               demod = NULL;
+
+       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 (!ntuner)
+                       ret = media_create_pad_links(mdev,
+                                                    MEDIA_ENT_F_CONN_RF,
+                                                    conn, 0,
+                                                    MEDIA_ENT_F_DTV_DEMOD,
+                                                    demod, 0,
+                                                    MEDIA_LNK_FL_ENABLED,
+                                                    false);
+               else
+                       ret = media_create_pad_links(mdev,
+                                                    MEDIA_ENT_F_CONN_RF,
+                                                    conn, 0,
+                                                    MEDIA_ENT_F_TUNER,
+                                                    tuner, TUNER_PAD_RF_INPUT,
+                                                    MEDIA_LNK_FL_ENABLED,
+                                                    false);
+               if (ret)
+                       return ret;
+       }
+
+       if (ntuner && ndemod) {
+               ret = media_create_pad_links(mdev,
+                                            MEDIA_ENT_F_TUNER,
+                                            tuner, TUNER_PAD_OUTPUT,
+                                            MEDIA_ENT_F_DTV_DEMOD,
+                                            demod, 0, MEDIA_LNK_FL_ENABLED,
+                                            false);
                if (ret)
                        return ret;
        }
 
-       if (demod && demux) {
-               ret = media_create_pad_link(demod, 1, demux,
-                                           0, MEDIA_LNK_FL_ENABLED);
+       if (ndemod && demux) {
+               ret = media_create_pad_links(mdev,
+                                            MEDIA_ENT_F_DTV_DEMOD,
+                                            demod, 1,
+                                            MEDIA_ENT_F_TS_DEMUX,
+                                            demux, 0, MEDIA_LNK_FL_ENABLED,
+                                            false);
                if (ret)
                        return -ENOMEM;
        }
This page took 0.026861 seconds and 5 git commands to generate.