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: Jeeja KP <jeeja.kp@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Jeeja KP 2015-10-27 09:22:52 +09:00 committed by Mark Brown
parent ce1b5551a0
commit 8724ff1752
1 changed files with 83 additions and 50 deletions

View File

@ -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;
int ret;
source = w;
src_mconfig = source->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
*/
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) {