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>
This commit is contained in:
parent
73ea660947
commit
4639029b04
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user