diff options
author | Ranjani Sridharan <ranjani.sridharan@linux.intel.com> | 2023-01-27 14:00:17 +0200 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-01-27 12:14:01 +0000 |
commit | 4639029b046bcab11bd566afa2979c68edeb338a (patch) | |
tree | ef1c10ca70e2d366643fc34709d977eb01e4fe95 /sound/soc/sof/sof-audio.c | |
parent | 73ea660947b52969214473434396a33d283c5ac8 (diff) | |
download | linux-stable-4639029b046bcab11bd566afa2979c68edeb338a.tar.gz linux-stable-4639029b046bcab11bd566afa2979c68edeb338a.tar.bz2 linux-stable-4639029b046bcab11bd566afa2979c68edeb338a.zip |
ASoC: SOF: sof-audio: Only process widgets in the connected widget list
When walking the list of the widgets from the source to the sink, we
accidentally also end up preparing/setting up the widgets that are not
in the list of connected DAPM widgets associated with the PCM. Avoid
this by checking if a widget is part of the connected DAPM widget list
during widget prepare, unprepare, setup or free.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230127120031.10709-5-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof/sof-audio.c')
-rw-r--r-- | sound/soc/sof/sof-audio.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index d242a3076ed0..a72e689d5c7a 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -241,24 +241,32 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, if (!widget->dobj.private) continue; - snd_soc_dapm_widget_for_each_sink_path(widget, p) + snd_soc_dapm_widget_for_each_sink_path(widget, p) { + if (!widget_in_list(list, p->sink)) + continue; + if (p->sink->dobj.private) { ret = sof_route_setup(sdev, widget, p->sink); if (ret < 0) return ret; } + } } } else { for_each_dapm_widgets(list, i, widget) { if (!widget->dobj.private) continue; - snd_soc_dapm_widget_for_each_source_path(widget, p) + snd_soc_dapm_widget_for_each_source_path(widget, p) { + if (!widget_in_list(list, p->source)) + continue; + if (p->source->dobj.private) { ret = sof_route_setup(sdev, p->source, widget); if (ret < 0) return ret; } + } } } @@ -266,7 +274,8 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, } static void -sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget) +sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, + struct snd_soc_dapm_widget_list *list) { const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *swidget = widget->dobj.private; @@ -287,9 +296,11 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg sink_unprepare: /* unprepare all widgets in the sink paths */ snd_soc_dapm_widget_for_each_sink_path(widget, p) { + if (!widget_in_list(list, p->sink)) + continue; if (!p->walking && p->sink->dobj.private) { p->walking = true; - sof_unprepare_widgets_in_path(sdev, p->sink); + sof_unprepare_widgets_in_path(sdev, p->sink, list); p->walking = false; } } @@ -299,7 +310,8 @@ static int sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, struct snd_pcm_hw_params *fe_params, struct snd_sof_platform_stream_params *platform_params, - struct snd_pcm_hw_params *pipeline_params, int dir) + struct snd_pcm_hw_params *pipeline_params, int dir, + struct snd_soc_dapm_widget_list *list) { const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); struct snd_sof_widget *swidget = widget->dobj.private; @@ -327,10 +339,13 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget sink_prepare: /* prepare all widgets in the sink paths */ snd_soc_dapm_widget_for_each_sink_path(widget, p) { + if (!widget_in_list(list, p->sink)) + continue; if (!p->walking && p->sink->dobj.private) { p->walking = true; ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, - platform_params, pipeline_params, dir); + platform_params, pipeline_params, dir, + list); p->walking = false; if (ret < 0) { /* unprepare the source widget */ @@ -351,7 +366,7 @@ sink_prepare: * (DAI type for capture, AIF type for playback) */ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, - int dir) + int dir, struct snd_soc_dapm_widget_list *list) { struct snd_soc_dapm_path *p; int err; @@ -366,9 +381,12 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap /* free all widgets in the sink paths even in case of error to keep use counts balanced */ snd_soc_dapm_widget_for_each_sink_path(widget, p) { if (!p->walking) { + if (!widget_in_list(list, p->sink)) + continue; + p->walking = true; - err = sof_free_widgets_in_path(sdev, p->sink, dir); + err = sof_free_widgets_in_path(sdev, p->sink, dir, list); if (err < 0) ret = err; p->walking = false; @@ -384,7 +402,7 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap * The error path in this function ensures that all successfully set up widgets getting freed. */ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, - int dir) + int dir, struct snd_soc_dapm_widget_list *list) { struct snd_soc_dapm_path *p; int ret; @@ -397,9 +415,12 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d snd_soc_dapm_widget_for_each_sink_path(widget, p) { if (!p->walking) { + if (!widget_in_list(list, p->sink)) + continue; + p->walking = true; - ret = sof_set_up_widgets_in_path(sdev, p->sink, dir); + ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, list); p->walking = false; if (ret < 0) { if (widget->dobj.private) @@ -434,11 +455,11 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l switch (op) { case SOF_WIDGET_SETUP: - ret = sof_set_up_widgets_in_path(sdev, widget, dir); + ret = sof_set_up_widgets_in_path(sdev, widget, dir, list); str = "set up"; break; case SOF_WIDGET_FREE: - ret = sof_free_widgets_in_path(sdev, widget, dir); + ret = sof_free_widgets_in_path(sdev, widget, dir, list); str = "free"; break; case SOF_WIDGET_PREPARE: @@ -454,12 +475,12 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l */ memcpy(&pipeline_params, fe_params, sizeof(*fe_params)); - ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, - platform_params, &pipeline_params, dir); + ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, platform_params, + &pipeline_params, dir, list); break; } case SOF_WIDGET_UNPREPARE: - sof_unprepare_widgets_in_path(sdev, widget); + sof_unprepare_widgets_in_path(sdev, widget, list); break; default: dev_err(sdev->dev, "Invalid widget op %d\n", op); |