Commit 8724ff17 authored by Jeeja KP's avatar Jeeja KP Committed by Mark Brown

ASoC: Intel: Skylake: Add support for virtual dsp widgets

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: default avatarJeeja KP <jeeja.kp@intel.com>
Signed-off-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ce1b5551
...@@ -397,40 +397,24 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, ...@@ -397,40 +397,24 @@ static int skl_tplg_mixer_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
/* static int skl_tplg_bind_sinks(struct snd_soc_dapm_widget *w,
* A PGA represents a module in a pipeline. So in the Pre-PMU event of PGA struct skl *skl,
* we need to do following: struct skl_module_cfg *src_mconfig)
* - 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 snd_soc_dapm_path *p; struct snd_soc_dapm_path *p;
struct snd_soc_dapm_widget *source, *sink; struct snd_soc_dapm_widget *sink = NULL;
struct skl_module_cfg *src_mconfig, *sink_mconfig; struct skl_module_cfg *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst; struct skl_sst *ctx = skl->skl_sst;
int ret = 0; int ret;
source = w;
src_mconfig = source->priv;
/* snd_soc_dapm_widget_for_each_sink_path(w, p) {
* 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) {
if (!p->connect) if (!p->connect)
continue; continue;
dev_dbg(ctx->dev, "%s: src widget=%s\n", __func__, w->name); 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); 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 * here we will check widgets in sink pipelines, so that
* can be any widgets type and we are only interested if * 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, ...@@ -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)) { is_skl_dsp_widget_type(p->sink)) {
sink = p->sink; sink = p->sink;
src_mconfig = source->priv;
sink_mconfig = sink->priv; sink_mconfig = sink->priv;
/* Bind source to sink, mixin is always source */ /* 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, ...@@ -454,10 +437,43 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
if (ret) if (ret)
return 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 */ /* Start source pipe last after starting all sinks */
ret = skl_run_pipe(ctx, src_mconfig->pipe); ret = skl_run_pipe(ctx, src_mconfig->pipe);
if (ret) if (ret)
...@@ -466,6 +482,38 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w, ...@@ -466,6 +482,38 @@ static int skl_tplg_pga_dapm_pre_pmu_event(struct snd_soc_dapm_widget *w,
return 0; 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: * in the Post-PMU event of mixer we need to do following:
* - Check if this pipe is running * - 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, ...@@ -479,7 +527,6 @@ static int skl_tplg_mixer_dapm_post_pmu_event(struct snd_soc_dapm_widget *w,
struct skl *skl) struct skl *skl)
{ {
int ret = 0; int ret = 0;
struct snd_soc_dapm_path *p;
struct snd_soc_dapm_widget *source, *sink; struct snd_soc_dapm_widget *source, *sink;
struct skl_module_cfg *src_mconfig, *sink_mconfig; struct skl_module_cfg *src_mconfig, *sink_mconfig;
struct skl_sst *ctx = skl->skl_sst; 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, ...@@ -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 * one more sink before this sink got connected, Since source is
* started, bind this sink to source and start this pipe. * started, bind this sink to source and start this pipe.
*/ */
snd_soc_dapm_widget_for_each_sink_path(w, p) { source = skl_get_src_dsp_widget(w, skl);
if (!p->connect) if (source != NULL) {
continue; src_mconfig = source->priv;
sink_mconfig = sink->priv;
dev_dbg(ctx->dev, "sink widget=%s\n", w->name); src_pipe_started = 1;
dev_dbg(ctx->dev, "src widget=%s\n", p->source->name);
/* /*
* here we will check widgets in sink pipelines, so that * check pipe state, then no need to bind or start the
* can be any widgets type and we are only interested if * pipe
* they are ones used for SKL so check that first
*/ */
if ((p->source->priv != NULL) && if (src_mconfig->pipe->state != SKL_PIPE_STARTED)
is_skl_dsp_widget_type(p->source)) { src_pipe_started = 0;
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_pipe_started) { if (src_pipe_started) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment