Skip to content

Commit

Permalink
ASoC: SOF: sof-audio: Modify the order of widget set up
Browse files Browse the repository at this point in the history
IPC4 expects the pipelines to be triggered in the order starting from the
sink to the source. The order of triggering pipelines during start is
determined by the order in which the widgets are set up. Today, we set up
the widgets in the order from source->sink and save the pipelines that the
widgets belong to in a list. This list is later traversed in the reverse
order for triggering the pipelines. Instead of this, this patch proposes
to change the order of widget set up from sink->source so that the
pipelines will be added to the list in the same order as well. The FW
can handle widgets getting set up in any order (source->sink or
sink->source). So reversing the current order will not affect
functionality.

This change is particularly important in cases where there are 2 DAIs in
the topology connected to the same host copier as in the case of AEC with
reference capture.

SSP DAI copier (Pipeline 0) -> AEC module -> host-copier (Pipeline 2)
		   		 ^
		         	 |
			DMIC DAI copier (Pipeline 1)

In this case, we want both the DAI pipelines (0 and 1) to be started
after pipeline 2 has been started. With the order of widget setup from
source to sink, the pipelines would be added to the trigger list in the
order, pipeline 1, pipeline 2 and finally pipeline 0. This would trigger
pipeline 0 first and result in an IPC timeout during start.

Modifying the widget set up to start from the sink will guarantee that
the pipelines will be added to the trigger list in the order 2 -> 1 -> 0
or 2 -> 0 -> 1 i.e pipeline 2 will always be first. The order of trigger
between the 2 DAI pipelines does not matter and it will depend on which
order they appear in the list of connected DAPM widgets.

Signed-off-by: Ranjani Sridharan <[email protected]>
  • Loading branch information
ranj063 committed Aug 29, 2023
1 parent 59fc88f commit 0ee3d4a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 21 deletions.
4 changes: 2 additions & 2 deletions sound/soc/sof/ipc4-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,12 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
* guaranteed for each fork independently.
*/
if (state == SOF_IPC4_PIPE_RUNNING || state == SOF_IPC4_PIPE_RESET)
for (i = pipeline_list->count - 1; i >= 0; i--) {
for (i = 0; i < pipeline_list->count; i++) {
spipe = pipeline_list->pipelines[i];
sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list);
}
else
for (i = 0; i < pipeline_list->count; i++) {
for (i = pipeline_list->count - 1; i >= 0; i--) {
spipe = pipeline_list->pipelines[i];
sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list);
}
Expand Down
53 changes: 34 additions & 19 deletions sound/soc/sof/sof-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,8 +483,8 @@ sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget
}

/*
* free all widgets in the sink path starting from the source widget
* (DAI type for capture, AIF type for playback)
* free all widgets in the source path starting from the sink widget
* (AIF type for capture, DAI type for playback)
*/
static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
int dir, struct snd_sof_pcm *spcm)
Expand All @@ -503,15 +503,15 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
ret = err;
}

/* 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) {
/* free all widgets in the source paths even in case of error to keep use counts balanced */
snd_soc_dapm_widget_for_each_source_path(widget, p) {
if (!p->walking) {
if (!widget_in_list(list, p->sink))
if (!widget_in_list(list, p->source))
continue;

p->walking = true;

err = sof_free_widgets_in_path(sdev, p->sink, dir, spcm);
err = sof_free_widgets_in_path(sdev, p->source, dir, spcm);
if (err < 0)
ret = err;
p->walking = false;
Expand All @@ -522,8 +522,8 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
}

/*
* set up all widgets in the sink path starting from the source widget
* (DAI type for capture, AIF type for playback).
* set up all widgets in the source path starting from the sink widget
* (AIF type for capture, DAI type for playback).
* 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,
Expand All @@ -548,7 +548,7 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d

/* skip populating the pipe_widgets array if it is NULL */
if (!pipeline_list->pipelines)
goto sink_setup;
goto source_setup;

/*
* Add the widget's pipe_widget to the list of pipelines to be triggered if not
Expand All @@ -567,15 +567,15 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
}
}

sink_setup:
snd_soc_dapm_widget_for_each_sink_path(widget, p) {
source_setup:
snd_soc_dapm_widget_for_each_source_path(widget, p) {
if (!p->walking) {
if (!widget_in_list(list, p->sink))
if (!widget_in_list(list, p->source))
continue;

p->walking = true;

ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, spcm);
ret = sof_set_up_widgets_in_path(sdev, p->source, dir, spcm);
p->walking = false;
if (ret < 0) {
if (swidget)
Expand Down Expand Up @@ -607,13 +607,28 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
if (is_virtual_widget(sdev, widget, __func__))
continue;

/* starting widget for playback is AIF type */
if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
continue;
/*
* set up/free widgets in the order sink->source so that the pipelines will be
* added to the list in the same order as well. All other ops need to follow the
* source->sink order.
*/
if (op == SOF_WIDGET_SETUP || op == SOF_WIDGET_FREE) {
/* starting widget for playback is DAI type */
if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_dai_in)
continue;

/* starting widget for capture is DAI type */
if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out)
continue;
/* starting widget for capture is AIF type */
if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_aif_out)
continue;
} else {
/* starting widget for playback is AIF type */
if (dir == SNDRV_PCM_STREAM_PLAYBACK && widget->id != snd_soc_dapm_aif_in)
continue;

/* starting widget for capture is DAI type */
if (dir == SNDRV_PCM_STREAM_CAPTURE && widget->id != snd_soc_dapm_dai_out)
continue;
}

switch (op) {
case SOF_WIDGET_SETUP:
Expand Down

0 comments on commit 0ee3d4a

Please sign in to comment.