Commit 4639029b authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown

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: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: default avatarPéter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230127120031.10709-5-peter.ujfalusi@linux.intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 73ea6609
...@@ -241,19 +241,26 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, ...@@ -241,19 +241,26 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
if (!widget->dobj.private) if (!widget->dobj.private)
continue; 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) { if (p->sink->dobj.private) {
ret = sof_route_setup(sdev, widget, p->sink); ret = sof_route_setup(sdev, widget, p->sink);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
} }
}
} else { } else {
for_each_dapm_widgets(list, i, widget) { for_each_dapm_widgets(list, i, widget) {
if (!widget->dobj.private) if (!widget->dobj.private)
continue; 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) { if (p->source->dobj.private) {
ret = sof_route_setup(sdev, p->source, widget); ret = sof_route_setup(sdev, p->source, widget);
if (ret < 0) if (ret < 0)
...@@ -261,12 +268,14 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev, ...@@ -261,12 +268,14 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
} }
} }
} }
}
return 0; return 0;
} }
static void 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); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
struct snd_sof_widget *swidget = widget->dobj.private; 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 ...@@ -287,9 +296,11 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
sink_unprepare: sink_unprepare:
/* unprepare all widgets in the sink paths */ /* unprepare all widgets in the sink paths */
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->walking && p->sink->dobj.private) { if (!p->walking && p->sink->dobj.private) {
p->walking = true; p->walking = true;
sof_unprepare_widgets_in_path(sdev, p->sink); sof_unprepare_widgets_in_path(sdev, p->sink, list);
p->walking = false; p->walking = false;
} }
} }
...@@ -299,7 +310,8 @@ static int ...@@ -299,7 +310,8 @@ static int
sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget, 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_pcm_hw_params *fe_params,
struct snd_sof_platform_stream_params *platform_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); const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
struct snd_sof_widget *swidget = widget->dobj.private; 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 ...@@ -327,10 +339,13 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
sink_prepare: sink_prepare:
/* prepare all widgets in the sink paths */ /* prepare all widgets in the sink paths */
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->walking && p->sink->dobj.private) { if (!p->walking && p->sink->dobj.private) {
p->walking = true; p->walking = true;
ret = sof_prepare_widgets_in_path(sdev, p->sink, fe_params, 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; p->walking = false;
if (ret < 0) { if (ret < 0) {
/* unprepare the source widget */ /* unprepare the source widget */
...@@ -351,7 +366,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget ...@@ -351,7 +366,7 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
* (DAI type for capture, AIF type for playback) * (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, 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; struct snd_soc_dapm_path *p;
int err; int err;
...@@ -366,9 +381,12 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap ...@@ -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 */ /* 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) { snd_soc_dapm_widget_for_each_sink_path(widget, p) {
if (!p->walking) { if (!p->walking) {
if (!widget_in_list(list, p->sink))
continue;
p->walking = true; 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) if (err < 0)
ret = err; ret = err;
p->walking = false; p->walking = false;
...@@ -384,7 +402,7 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap ...@@ -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. * 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, 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; struct snd_soc_dapm_path *p;
int ret; int ret;
...@@ -397,9 +415,12 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d ...@@ -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) { snd_soc_dapm_widget_for_each_sink_path(widget, p) {
if (!p->walking) { if (!p->walking) {
if (!widget_in_list(list, p->sink))
continue;
p->walking = true; 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; p->walking = false;
if (ret < 0) { if (ret < 0) {
if (widget->dobj.private) if (widget->dobj.private)
...@@ -434,11 +455,11 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l ...@@ -434,11 +455,11 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l
switch (op) { switch (op) {
case SOF_WIDGET_SETUP: 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"; str = "set up";
break; break;
case SOF_WIDGET_FREE: 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"; str = "free";
break; break;
case SOF_WIDGET_PREPARE: case SOF_WIDGET_PREPARE:
...@@ -454,12 +475,12 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_l ...@@ -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)); memcpy(&pipeline_params, fe_params, sizeof(*fe_params));
ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, ret = sof_prepare_widgets_in_path(sdev, widget, fe_params, platform_params,
platform_params, &pipeline_params, dir); &pipeline_params, dir, list);
break; break;
} }
case SOF_WIDGET_UNPREPARE: case SOF_WIDGET_UNPREPARE:
sof_unprepare_widgets_in_path(sdev, widget); sof_unprepare_widgets_in_path(sdev, widget, list);
break; break;
default: default:
dev_err(sdev->dev, "Invalid widget op %d\n", op); dev_err(sdev->dev, "Invalid widget op %d\n", op);
......
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