Skip to content

Commit

Permalink
ASoC: SOF: Refactor pipeline management
Browse files Browse the repository at this point in the history
Invoke the set_up_be_pipeline and free_be_pipeline ops in the BE DAI
prepare and hw_free to ensure that all the widgets and routes belonging
to the BE pipeline are handled in the BE DAI ops. Add a new field in
struct snd_sof_pipeline to identify BE pipelines i.e. those that contain
the DAI widget. Modify the FE ops to make sure that the widgets/routes
belonging to these pipelines are skipped during setup/free/unprepare.

Signed-off-by: Ranjani Sridharan <[email protected]>
  • Loading branch information
ranj063 committed Dec 4, 2024
1 parent 1fc0c72 commit 3d36fa1
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 12 deletions.
12 changes: 8 additions & 4 deletions sound/soc/sof/intel/hda-dai-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,11 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
/*
* STOP/SUSPEND trigger is invoked only once when all users of this pipeline have
* been stopped. So, clear the started_count so that the pipeline can be reset
*/
ret = sof_ipc4_set_pipeline_state(sdev, pipe_widget->instance_id,
SOF_IPC4_PIPE_RESET);
if (ret < 0)
goto out;
pipeline->state = SOF_IPC4_PIPE_RESET;
swidget->spipe->started_count = 0;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
Expand Down Expand Up @@ -638,6 +639,9 @@ static int hda_ipc4_set_up_be_pipeline(struct snd_soc_dapm_widget *w, int dir)
struct snd_sof_dev *sdev = widget_to_sdev(w);
int ret;

/* set the be_pipeline flag true for the pipeline */
swidget->spipe->be_pipeline = true;

/* set up the widgets in the BE pipeline */
ret = hda_dai_set_up_widgets_in_pipeline(w, swidget->spipe, dir);
if (ret < 0) {
Expand Down
17 changes: 16 additions & 1 deletion sound/soc/sof/intel/hda-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_st
struct snd_soc_dai *cpu_dai)
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
struct sof_intel_hda_stream *hda_stream;
struct hdac_ext_link *hlink;
struct snd_sof_dev *sdev;
Expand Down Expand Up @@ -137,6 +138,9 @@ int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_st
hda_stream = hstream_to_sof_hda_stream(hext_stream);
hda_stream->host_reserved = 0;

if (ops->free_be_pipeline)
return ops->free_be_pipeline(w, substream->stream);

return 0;
}

Expand Down Expand Up @@ -322,9 +326,20 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
static int hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai);
struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream);
int stream = substream->stream;
int ret;

ret = hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai);
if (ret < 0)
return ret;

if (ops && ops->set_up_be_pipeline)
return ops->set_up_be_pipeline(w, substream->stream);

return ret;

return hda_dai_hw_params(substream, &rtd->dpcm[stream].hw_params, dai);
}

static const struct snd_soc_dai_ops hda_dai_ops = {
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/sof/ipc4-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ sof_ipc4_add_pipeline_to_trigger_list(struct snd_sof_dev *sdev, int state,
struct snd_sof_widget *pipe_widget = spipe->pipe_widget;
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;

if (pipeline->skip_during_fe_trigger && state != SOF_IPC4_PIPE_RESET)
if (pipeline->skip_during_fe_trigger)
return;

switch (state) {
Expand Down Expand Up @@ -177,7 +177,7 @@ sof_ipc4_update_pipeline_state(struct snd_sof_dev *sdev, int state, int cmd,
struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
int i;

if (pipeline->skip_during_fe_trigger && state != SOF_IPC4_PIPE_RESET)
if (pipeline->skip_during_fe_trigger)
return;

/* set state for pipeline if it was just triggered */
Expand Down
38 changes: 33 additions & 5 deletions sound/soc/sof/sof-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,17 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc
}
EXPORT_SYMBOL(sof_route_setup);

/* helper function to check if the widget belong to the BE pipeline */
static bool sof_is_be_pipeline_widget(struct snd_soc_dapm_widget *w)
{
struct snd_sof_widget *swidget = w->dobj.private;

if (swidget->spipe->be_pipeline)
return true;

return false;
}

static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
struct snd_soc_dapm_widget_list *list, int dir)
{
Expand All @@ -319,6 +330,12 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
continue;

if (p->sink->dobj.private) {
/*
* skip routes between widgets belonging to the BE pipeline
*/
if (sof_is_be_pipeline_widget(widget) &&
sof_is_be_pipeline_widget(p->sink))
continue;
ret = sof_route_setup(sdev, widget, p->sink);
if (ret < 0)
return ret;
Expand All @@ -335,6 +352,11 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
continue;

if (p->source->dobj.private) {
/*
* skip routes between widgets belonging to the BE pipeline
*/
if (sof_is_be_pipeline_widget(widget) &&
sof_is_be_pipeline_widget(p->source))
ret = sof_route_setup(sdev, p->source, widget);
if (ret < 0)
return ret;
Expand Down Expand Up @@ -415,8 +437,12 @@ sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widg
if (is_virtual_widget(sdev, widget, __func__))
return;

/* skip if the widget is in use or if it is already unprepared */
if (!swidget || !swidget->prepared || swidget->use_count > 0)
/*
* skip if the widget is in use or if it is already unprepared or
* if it belongs to a BE pipeline.
*/
if (!swidget || !swidget->prepared || swidget->use_count > 0 ||
swidget->spipe->be_pipeline)
goto sink_unprepare;

widget_ops = tplg_ops ? tplg_ops->widget : NULL;
Expand Down Expand Up @@ -506,14 +532,16 @@ static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dap
int dir, struct snd_sof_pcm *spcm)
{
struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
struct snd_sof_widget *swidget = widget->dobj.private;
struct snd_soc_dapm_path *p;
int err;
int ret = 0;

if (is_virtual_widget(sdev, widget, __func__))
return 0;

if (widget->dobj.private) {
/* only free widgets that aren't part of the BE pipeline */
if (swidget && !swidget->spipe->be_pipeline) {
err = sof_widget_free(sdev, widget->dobj.private);
if (err < 0)
ret = err;
Expand Down Expand Up @@ -555,7 +583,7 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
if (is_virtual_widget(sdev, widget, __func__))
return 0;

if (swidget) {
if (swidget && !swidget->spipe->be_pipeline) {
int i;

ret = sof_widget_setup(sdev, widget->dobj.private);
Expand Down Expand Up @@ -594,7 +622,7 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
ret = sof_set_up_widgets_in_path(sdev, p->sink, dir, spcm);
p->walking = false;
if (ret < 0) {
if (swidget)
if (swidget && !swidget->spipe->be_pipeline)
sof_widget_free(sdev, swidget);
return ret;
}
Expand Down
2 changes: 2 additions & 0 deletions sound/soc/sof/sof-audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ struct snd_sof_widget {
pipeline
* @complete: flag used to indicate that pipeline set up is complete.
* @core_mask: Mask containing target cores for all modules in the pipeline
* @be_pipeline: Flag indicating if the pipeline contains a BE DAI widget
* @list: List item in sdev pipeline_list
*/
struct snd_sof_pipeline {
Expand All @@ -507,6 +508,7 @@ struct snd_sof_pipeline {
int paused_count;
int complete;
unsigned long core_mask;
bool be_pipeline;
struct list_head list;
};

Expand Down
4 changes: 4 additions & 0 deletions sound/soc/sof/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,10 @@ static int sof_set_widget_pipeline(struct snd_sof_dev *sdev, struct snd_sof_pipe
swidget->spipe = spipe;
swidget->dynamic_pipeline_widget = pipe_widget->dynamic_pipeline_widget;

/* set the be_pipeline flag true for the pipeline if the widget is a DAI */
if (WIDGET_IS_DAI(swidget->id))
spipe->be_pipeline = true;

return 0;
}

Expand Down

0 comments on commit 3d36fa1

Please sign in to comment.