Skip to content

Commit f596c38

Browse files
committed
ASoC: SOF: pcm: Split up widget prepare and setup
In preparation for refacting pipeline management, split the widget prepare and set up between the hw_params and prepare ioctls. This is required to ensure that the BE pipeline widgets can be set up during the BE DAI prepare and the remaining widgets will be set up during the FE DAI prepare. The widget's ipc_prepare op for all widgets in both the BE and FE pipelines are handled during the FE DAI hw_params to make sure that the pipeline params can be propagated all the way from the source widget to the sink widget. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
1 parent 714ad3f commit f596c38

File tree

3 files changed

+95
-31
lines changed

3 files changed

+95
-31
lines changed

sound/soc/sof/pcm.c

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run
106106

107107
spcm->stream[dir].list = list;
108108

109-
ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
109+
ret = sof_widget_list_prepare(sdev, spcm, params, platform_params, dir);
110110
if (ret < 0) {
111-
spcm_err(spcm, dir, "Widget list set up failed\n");
111+
spcm_err(spcm, dir, "widget list prepare failed\n");
112112
spcm->stream[dir].list = NULL;
113113
snd_soc_dapm_dai_free_widgets(&list);
114114
return ret;
@@ -118,15 +118,30 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run
118118
return 0;
119119
}
120120

121+
static struct snd_sof_widget *snd_sof_find_swidget_by_comp_id(struct snd_sof_dev *sdev,
122+
int comp_id)
123+
{
124+
struct snd_sof_widget *swidget;
125+
126+
list_for_each_entry(swidget, &sdev->widget_list, list) {
127+
if (comp_id == swidget->comp_id)
128+
return swidget;
129+
}
130+
131+
return NULL;
132+
}
133+
121134
static int sof_pcm_hw_params(struct snd_soc_component *component,
122135
struct snd_pcm_substream *substream,
123136
struct snd_pcm_hw_params *params)
124137
{
125138
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
126139
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
140+
const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg);
127141
const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
128-
struct snd_sof_platform_stream_params platform_params = { 0 };
142+
struct snd_sof_platform_stream_params *platform_params;
129143
struct snd_pcm_runtime *runtime = substream->runtime;
144+
struct snd_sof_widget *host_widget;
130145
struct snd_sof_pcm *spcm;
131146
int ret;
132147

@@ -152,20 +167,36 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
152167
spcm->prepared[substream->stream] = false;
153168
}
154169

155-
ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params);
170+
platform_params = &spcm->platform_params[substream->stream];
171+
ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, platform_params);
156172
if (ret < 0) {
157173
spcm_err(spcm, substream->stream, "platform hw params failed\n");
158174
return ret;
159175
}
160176

161177
/* if this is a repeated hw_params without hw_free, skip setting up widgets */
162178
if (!spcm->stream[substream->stream].list) {
163-
ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, &platform_params,
179+
ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, platform_params,
164180
substream->stream);
165181
if (ret < 0)
166182
return ret;
167183
}
168184

185+
if (!sdev->dspless_mode_selected) {
186+
int host_comp_id = spcm->stream[substream->stream].comp_id;
187+
188+
host_widget = snd_sof_find_swidget_by_comp_id(sdev, host_comp_id);
189+
if (!host_widget) {
190+
spcm_err(spcm, substream->stream,
191+
"failed to find host widget with comp_id %d\n", host_comp_id);
192+
return -EINVAL;
193+
}
194+
195+
/* set the host DMA ID */
196+
if (tplg_ops && tplg_ops->host_config)
197+
tplg_ops->host_config(sdev, host_widget, platform_params);
198+
}
199+
169200
/* create compressed page table for audio firmware */
170201
if (runtime->buffer_changed) {
171202
ret = create_page_table(component, substream, runtime->dma_area,
@@ -175,14 +206,6 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
175206
return ret;
176207
}
177208

178-
if (pcm_ops && pcm_ops->hw_params) {
179-
ret = pcm_ops->hw_params(component, substream, params, &platform_params);
180-
if (ret < 0)
181-
return ret;
182-
}
183-
184-
spcm->prepared[substream->stream] = true;
185-
186209
/* save pcm hw_params */
187210
memcpy(&spcm->params[substream->stream], params, sizeof(*params));
188211

@@ -287,6 +310,9 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
287310

288311
ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true);
289312

313+
/* unprepare and free the list of DAPM widgets */
314+
sof_widget_list_unprepare(sdev, spcm, substream->stream);
315+
290316
cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
291317

292318
return ret;
@@ -297,7 +323,12 @@ static int sof_pcm_prepare(struct snd_soc_component *component,
297323
{
298324
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
299325
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
326+
const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
327+
struct snd_sof_platform_stream_params *platform_params;
328+
struct snd_soc_dapm_widget_list *list;
329+
struct snd_pcm_hw_params *params;
300330
struct snd_sof_pcm *spcm;
331+
int dir = substream->stream;
301332
int ret;
302333

303334
/* nothing to do for BE */
@@ -323,15 +354,33 @@ static int sof_pcm_prepare(struct snd_soc_component *component,
323354
return ret;
324355
}
325356

326-
/* set hw_params */
327-
ret = sof_pcm_hw_params(component,
328-
substream, &spcm->params[substream->stream]);
357+
ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]);
329358
if (ret < 0) {
330359
spcm_err(spcm, substream->stream,
331360
"failed to set hw_params after resume\n");
332361
return ret;
333362
}
334363

364+
list = spcm->stream[dir].list;
365+
params = &spcm->params[substream->stream];
366+
platform_params = &spcm->platform_params[substream->stream];
367+
ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
368+
if (ret < 0) {
369+
dev_err(sdev->dev, "failed widget list set up for pcm %d dir %d\n",
370+
spcm->pcm.pcm_id, dir);
371+
spcm->stream[dir].list = NULL;
372+
snd_soc_dapm_dai_free_widgets(&list);
373+
return ret;
374+
}
375+
376+
if (pcm_ops && pcm_ops->hw_params) {
377+
ret = pcm_ops->hw_params(component, substream, params, platform_params);
378+
if (ret < 0)
379+
return ret;
380+
}
381+
382+
spcm->prepared[substream->stream] = true;
383+
335384
return 0;
336385
}
337386

sound/soc/sof/sof-audio.c

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,30 @@ sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
672672
return 0;
673673
}
674674

675+
int sof_widget_list_prepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
676+
struct snd_pcm_hw_params *fe_params,
677+
struct snd_sof_platform_stream_params *platform_params,
678+
int dir)
679+
{
680+
/*
681+
* Prepare widgets for set up. The prepare step is used to allocate memory, assign
682+
* instance ID and pick the widget configuration based on the runtime PCM params.
683+
*/
684+
return sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
685+
dir, SOF_WIDGET_PREPARE);
686+
}
687+
688+
void sof_widget_list_unprepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir)
689+
{
690+
struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
691+
692+
/* unprepare the widget */
693+
sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
694+
695+
snd_soc_dapm_dai_free_widgets(&list);
696+
spcm->stream[dir].list = NULL;
697+
}
698+
675699
int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
676700
struct snd_pcm_hw_params *fe_params,
677701
struct snd_sof_platform_stream_params *platform_params,
@@ -686,15 +710,6 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
686710
if (!list)
687711
return 0;
688712

689-
/*
690-
* Prepare widgets for set up. The prepare step is used to allocate memory, assign
691-
* instance ID and pick the widget configuration based on the runtime PCM params.
692-
*/
693-
ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
694-
dir, SOF_WIDGET_PREPARE);
695-
if (ret < 0)
696-
return ret;
697-
698713
/* Set up is used to send the IPC to the DSP to create the widget */
699714
ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params,
700715
dir, SOF_WIDGET_SETUP);
@@ -772,12 +787,6 @@ int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int
772787
/* send IPC to free widget in the DSP */
773788
ret = sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_FREE);
774789

775-
/* unprepare the widget */
776-
sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
777-
778-
snd_soc_dapm_dai_free_widgets(&list);
779-
spcm->stream[dir].list = NULL;
780-
781790
pipeline_list->count = 0;
782791

783792
return ret;

sound/soc/sof/sof-audio.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ struct snd_sof_pcm {
354354
struct snd_sof_pcm_stream stream[2];
355355
struct list_head list; /* list in sdev pcm list */
356356
struct snd_pcm_hw_params params[2];
357+
struct snd_sof_platform_stream_params platform_params[2];
357358
bool prepared[2]; /* PCM_PARAMS set successfully */
358359
bool pending_stop[2]; /* only used if (!pcm_ops->platform_stop_during_hw_free) */
359360

@@ -663,6 +664,11 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
663664
struct snd_pcm_hw_params *fe_params,
664665
struct snd_sof_platform_stream_params *platform_params,
665666
int dir);
667+
int sof_widget_list_prepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
668+
struct snd_pcm_hw_params *fe_params,
669+
struct snd_sof_platform_stream_params *platform_params,
670+
int dir);
671+
void sof_widget_list_unprepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
666672
int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
667673
int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev,
668674
struct snd_sof_pcm *spcm);

0 commit comments

Comments
 (0)