diff mbox

[09/17] ASoC: Intel: Skylake: Add support for virtual dsp widgets

Message ID 1445905380-18167-10-git-send-email-vinod.koul@intel.com (mailing list archive)
State Accepted
Commit 8724ff17521a91a87971027cf78631030091bc52
Headers show

Commit Message

Vinod Koul Oct. 27, 2015, 12:22 a.m. UTC
From: Jeeja KP <jeeja.kp@intel.com>

In SKL topology routes, some paths can be connected by a widget
which are not a DSP FW widget and virtual with respect to
firmware. In these case when module has to bind, then the
virtual DSP modules needs to skipped till a actual DSP module is
found which connects the pipelines.

So we need to walk the graph and find a widget which is real in
nature. This patch adds that support and splits
skl_tplg_pga_dapm_pre_pmu_event() fn with parsing code to
skl_tplg_bind_sinks() fn and call that recursively as well as
while parsing

The patch moves code a bit while splitting so diffstat doesn't
tell real picture

Signed-off-by: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
---
 sound/soc/intel/skylake/skl-topology.c | 133 ++++++++++++++++++++-------------
 1 file changed, 83 insertions(+), 50 deletions(-)
diff mbox

Patch

diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index abbf8e7eb3e7..0c6e7833e652 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -397,40 +397,24 @@  static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-/*
- * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
- * we need to do following:
- *   - Bind to sink pipeline
- *      Since the sink pipes can be running and we don't get mixer event on
- *      connect for already running mixer, we need to find the sink pipes
- *      here and bind to them. This way dynamic connect works.
- *   - Start sink pipeline, if not running
- *   - Then run current pipe
- */
-static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
-							struct skl *skl)
+static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
+				struct skl *skl,
+				struct skl_module_cfg *src_mconfig)
 {
 	struct snd_soc_dapm_path *p;
-	struct snd_soc_dapm_widget *source, *sink;
-	struct skl_module_cfg *src_mconfig, *sink_mconfig;
+	struct snd_soc_dapm_widget *sink = NULL;
+	struct skl_module_cfg *sink_mconfig;
 	struct skl_sst *ctx = skl->skl_sst;
-	int ret = 0;
-
-	source = w;
-	src_mconfig = source->priv;
+	int ret;
 
-	/*
-	 * find which sink it is connected to, bind with the sink,
-	 * if sink is not started, start sink pipe first, then start
-	 * this pipe
-	 */
-	snd_soc_dapm_widget_for_each_source_path(w, p) {
+	snd_soc_dapm_widget_for_each_sink_path(w, p) {
 		if (!p->connect)
 			continue;
 
 		dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name);
 		dev_dbg(ctx->dev, "%s: sink widget=%s\n", __func__, p->sink->name);
 
+		sink = p->sink;
 		/*
 		 * here we will check widgets in sink pipelines, so that
 		 * can be any widgets type and we are only interested if
@@ -440,7 +424,6 @@  static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
 					is_skl_dsp_widget_type(p->sink)) {
 
 			sink = p->sink;
-			src_mconfig = source->priv;
 			sink_mconfig = sink->priv;
 
 			/* Bind source to sink, mixin is always source */
@@ -454,10 +437,43 @@  static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
 				if (ret)
 					return ret;
 			}
-			break;
 		}
 	}
 
+	if (!sink)
+		return skl_tplg_bind_sinks(sink, skl, src_mconfig);
+
+	return 0;
+}
+
+/*
+ * A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA
+ * we need to do following:
+ *   - Bind to sink pipeline
+ *      Since the sink pipes can be running and we don't get mixer event on
+ *      connect for already running mixer, we need to find the sink pipes
+ *      here and bind to them. This way dynamic connect works.
+ *   - Start sink pipeline, if not running
+ *   - Then run current pipe
+ */
+static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
+								struct skl *skl)
+{
+	struct skl_module_cfg *src_mconfig;
+	struct skl_sst *ctx = skl->skl_sst;
+	int ret = 0;
+
+	src_mconfig = w->priv;
+
+	/*
+	 * find which sink it is connected to, bind with the sink,
+	 * if sink is not started, start sink pipe first, then start
+	 * this pipe
+	 */
+	ret = skl_tplg_bind_sinks(w, skl, src_mconfig);
+	if (ret)
+		return ret;
+
 	/* Start source pipe last after starting all sinks */
 	ret = skl_run_pipe(ctx, src_mconfig->pipe);
 	if (ret)
@@ -466,6 +482,38 @@  static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static struct snd_soc_dapm_widget *skl_get_src_dsp_widget(
+		struct snd_soc_dapm_widget *w, struct skl *skl)
+{
+	struct snd_soc_dapm_path *p;
+	struct snd_soc_dapm_widget *src_w = NULL;
+	struct skl_sst *ctx = skl->skl_sst;
+
+	snd_soc_dapm_widget_for_each_source_path(w, p) {
+		src_w = p->source;
+		if (!p->connect)
+			continue;
+
+		dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
+		dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+
+		/*
+		 * here we will check widgets in sink pipelines, so that can
+		 * be any widgets type and we are only interested if they are
+		 * ones used for SKL so check that first
+		 */
+		if ((p->source->priv != NULL) &&
+					is_skl_dsp_widget_type(p->source)) {
+			return p->source;
+		}
+	}
+
+	if (src_w != NULL)
+		return skl_get_src_dsp_widget(src_w, skl);
+
+	return NULL;
+}
+
 /*
  * in the Post-PMU event of mixer we need to do following:
  *   - Check if this pipe is running
@@ -479,7 +527,6 @@  static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
 							struct skl *skl)
 {
 	int ret = 0;
-	struct snd_soc_dapm_path *p;
 	struct snd_soc_dapm_widget *source, *sink;
 	struct skl_module_cfg *src_mconfig, *sink_mconfig;
 	struct skl_sst *ctx = skl->skl_sst;
@@ -493,32 +540,18 @@  static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
 	 * one more sink before this sink got connected, Since source is
 	 * started, bind this sink to source and start this pipe.
 	 */
-	snd_soc_dapm_widget_for_each_sink_path(w, p) {
-		if (!p->connect)
-			continue;
-
-		dev_dbg(ctx->dev, "sink widget=%s\n", w->name);
-		dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
+	source = skl_get_src_dsp_widget(w, skl);
+	if (source != NULL) {
+		src_mconfig = source->priv;
+		sink_mconfig = sink->priv;
+		src_pipe_started = 1;
 
 		/*
-		 * here we will check widgets in sink pipelines, so that
-		 * can be any widgets type and we are only interested if
-		 * they are ones used for SKL so check that first
+		 * check pipe state, then no need to bind or start the
+		 * pipe
 		 */
-		if ((p->source->priv != NULL) &&
-					is_skl_dsp_widget_type(p->source)) {
-			source = p->source;
-			src_mconfig = source->priv;
-			sink_mconfig = sink->priv;
-			src_pipe_started = 1;
-
-			/*
-			 * check pipe state, then no need to bind or start
-			 * the pipe
-			 */
-			if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
-				src_pipe_started = 0;
-		}
+		if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
+			src_pipe_started = 0;
 	}
 
 	if (src_pipe_started) {