Browse Source

[media] dvbdev: create links on devices with multiple frontends

Devices like mxl111sf-based WinTV Aero-m have multiple
frontends, all linked on the same demod. Currently, the
dvb_create_graph() function is not smart enough to create
multiple links. Fix it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Mauro Carvalho Chehab 9 years ago
parent
commit
a0cce2a057
2 changed files with 51 additions and 13 deletions
  1. 44 13
      drivers/media/dvb-core/dvbdev.c
  2. 7 0
      drivers/media/dvb-core/dvbdev.h

+ 44 - 13
drivers/media/dvb-core/dvbdev.c

@@ -576,6 +576,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 	struct media_interface *intf;
 	struct media_interface *intf;
 	unsigned demux_pad = 0;
 	unsigned demux_pad = 0;
 	unsigned dvr_pad = 0;
 	unsigned dvr_pad = 0;
+	unsigned ntuner = 0, ndemod = 0;
 	int ret;
 	int ret;
 	static const char *connector_name = "Television";
 	static const char *connector_name = "Television";
 
 
@@ -586,9 +587,11 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 		switch (entity->function) {
 		switch (entity->function) {
 		case MEDIA_ENT_F_TUNER:
 		case MEDIA_ENT_F_TUNER:
 			tuner = entity;
 			tuner = entity;
+			ntuner++;
 			break;
 			break;
 		case MEDIA_ENT_F_DTV_DEMOD:
 		case MEDIA_ENT_F_DTV_DEMOD:
 			demod = entity;
 			demod = entity;
+			ndemod++;
 			break;
 			break;
 		case MEDIA_ENT_F_TS_DEMUX:
 		case MEDIA_ENT_F_TS_DEMUX:
 			demux = entity;
 			demux = entity;
@@ -599,6 +602,18 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 		}
 		}
 	}
 	}
 
 
+	/*
+	 * 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) {
 	if (create_rf_connector) {
 		conn = kzalloc(sizeof(*conn), GFP_KERNEL);
 		conn = kzalloc(sizeof(*conn), GFP_KERNEL);
 		if (!conn)
 		if (!conn)
@@ -623,28 +638,44 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 
 
-		if (!tuner)
-			ret = media_create_pad_link(conn, 0,
-						    demod, 0,
-						    MEDIA_LNK_FL_ENABLED);
+		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
 		else
-			ret = media_create_pad_link(conn, 0,
-						    tuner, TUNER_PAD_RF_INPUT,
-						    MEDIA_LNK_FL_ENABLED);
+			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)
 		if (ret)
 			return ret;
 			return ret;
 	}
 	}
 
 
-	if (tuner && demod) {
-		ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT,
-					    demod, 0, MEDIA_LNK_FL_ENABLED);
+	if (ntuner && ndemod) {
+		ret = media_create_pad_links(mdev,
+					     MEDIA_ENT_F_TUNER,
+					     tuner, TUNER_PAD_IF_OUTPUT,
+					     MEDIA_ENT_F_DTV_DEMOD,
+					     demod, 0, MEDIA_LNK_FL_ENABLED,
+					     false);
 		if (ret)
 		if (ret)
 			return 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)
 		if (ret)
 			return -ENOMEM;
 			return -ENOMEM;
 	}
 	}

+ 7 - 0
drivers/media/dvb-core/dvbdev.h

@@ -225,6 +225,13 @@ void dvb_unregister_device(struct dvb_device *dvbdev);
  *
  *
  * @adap:			pointer to struct dvb_adapter
  * @adap:			pointer to struct dvb_adapter
  * @create_rf_connector:	if true, it creates the RF connector too
  * @create_rf_connector:	if true, it creates the RF connector too
+ *
+ * This function checks all DVB-related functions at the media controller
+ * entities and creates the needed links for the media graph. It is
+ * capable of working with multiple tuners or multiple frontends, but it
+ * won't create links if the device has multiple tuners and multiple frontends
+ * or if the device has multiple muxes. In such case, the caller driver should
+ * manually create the remaining links.
  */
  */
 __must_check int dvb_create_media_graph(struct dvb_adapter *adap,
 __must_check int dvb_create_media_graph(struct dvb_adapter *adap,
 					bool create_rf_connector);
 					bool create_rf_connector);