Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: pcm: Split up widget prepare and setup

Widgets are set up in 2 steps, first ipc_prepare followed by the actual
IPC sent to the DSP to set up the widget. Split these 2 steps to do the
ipc_prepare during hw_params and the setting up in the prepare callback.
This will allow for future modifications to pipeline set up to be split
up between the FE and BE DAI prepare ops.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20260204081833.16630-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Ranjani Sridharan and committed by
Mark Brown
f4626976 236d5e66

+102 -34
+65 -16
sound/soc/sof/pcm.c
··· 88 88 89 89 spcm->stream[dir].list = list; 90 90 91 - ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir); 91 + ret = sof_widget_list_prepare(sdev, spcm, params, platform_params, dir); 92 92 if (ret < 0) { 93 - spcm_err(spcm, dir, "Widget list set up failed\n"); 93 + spcm_err(spcm, dir, "widget list prepare failed\n"); 94 94 spcm->stream[dir].list = NULL; 95 95 snd_soc_dapm_dai_free_widgets(&list); 96 96 return ret; ··· 100 100 return 0; 101 101 } 102 102 103 + static struct snd_sof_widget *snd_sof_find_swidget_by_comp_id(struct snd_sof_dev *sdev, 104 + int comp_id) 105 + { 106 + struct snd_sof_widget *swidget; 107 + 108 + list_for_each_entry(swidget, &sdev->widget_list, list) { 109 + if (comp_id == swidget->comp_id) 110 + return swidget; 111 + } 112 + 113 + return NULL; 114 + } 115 + 103 116 static int sof_pcm_hw_params(struct snd_soc_component *component, 104 117 struct snd_pcm_substream *substream, 105 118 struct snd_pcm_hw_params *params) 106 119 { 107 120 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 108 121 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 122 + const struct sof_ipc_tplg_ops *tplg_ops = sof_ipc_get_ops(sdev, tplg); 109 123 const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 110 - struct snd_sof_platform_stream_params platform_params = { 0 }; 124 + struct snd_sof_platform_stream_params *platform_params; 111 125 struct snd_pcm_runtime *runtime = substream->runtime; 126 + struct snd_sof_widget *host_widget; 112 127 struct snd_sof_pcm *spcm; 113 128 int ret; 114 129 ··· 159 144 spcm->prepared[substream->stream] = false; 160 145 } 161 146 162 - ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params); 147 + platform_params = &spcm->platform_params[substream->stream]; 148 + ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, platform_params); 163 149 if (ret < 0) { 164 150 spcm_err(spcm, substream->stream, "platform hw params failed\n"); 165 151 return ret; ··· 168 152 169 153 /* if this is a repeated hw_params without hw_free, skip setting up widgets */ 170 154 if (!spcm->stream[substream->stream].list) { 171 - ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, &platform_params, 155 + ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, platform_params, 172 156 substream->stream); 173 157 if (ret < 0) 174 158 return ret; 159 + } 160 + 161 + if (!sdev->dspless_mode_selected) { 162 + int host_comp_id = spcm->stream[substream->stream].comp_id; 163 + 164 + host_widget = snd_sof_find_swidget_by_comp_id(sdev, host_comp_id); 165 + if (!host_widget) { 166 + spcm_err(spcm, substream->stream, 167 + "failed to find host widget with comp_id %d\n", host_comp_id); 168 + return -EINVAL; 169 + } 170 + 171 + /* set the host DMA ID */ 172 + if (tplg_ops && tplg_ops->host_config) 173 + tplg_ops->host_config(sdev, host_widget, platform_params); 175 174 } 176 175 177 176 /* create compressed page table for audio firmware */ ··· 199 168 if (ret < 0) 200 169 return ret; 201 170 } 202 - 203 - if (pcm_ops && pcm_ops->hw_params) { 204 - ret = pcm_ops->hw_params(component, substream, params, &platform_params); 205 - if (ret < 0) 206 - return ret; 207 - } 208 - 209 - spcm->prepared[substream->stream] = true; 210 171 211 172 /* save pcm hw_params */ 212 173 memcpy(&spcm->params[substream->stream], params, sizeof(*params)); ··· 304 281 305 282 ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); 306 283 284 + /* unprepare and free the list of DAPM widgets */ 285 + sof_widget_list_unprepare(sdev, spcm, substream->stream); 286 + 307 287 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); 308 288 309 289 return ret; ··· 317 291 { 318 292 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 319 293 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); 294 + const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); 295 + struct snd_sof_platform_stream_params *platform_params; 296 + struct snd_soc_dapm_widget_list *list; 297 + struct snd_pcm_hw_params *params; 320 298 struct snd_sof_pcm *spcm; 299 + int dir = substream->stream; 321 300 int ret; 322 301 323 302 /* nothing to do for BE */ ··· 348 317 return ret; 349 318 } 350 319 351 - /* set hw_params */ 352 - ret = sof_pcm_hw_params(component, 353 - substream, &spcm->params[substream->stream]); 320 + ret = sof_pcm_hw_params(component, substream, &spcm->params[substream->stream]); 354 321 if (ret < 0) { 355 322 spcm_err(spcm, substream->stream, 356 323 "failed to set hw_params after resume\n"); 357 324 return ret; 358 325 } 326 + 327 + list = spcm->stream[dir].list; 328 + params = &spcm->params[substream->stream]; 329 + platform_params = &spcm->platform_params[substream->stream]; 330 + ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir); 331 + if (ret < 0) { 332 + dev_err(sdev->dev, "failed widget list set up for pcm %d dir %d\n", 333 + spcm->pcm.pcm_id, dir); 334 + spcm->stream[dir].list = NULL; 335 + snd_soc_dapm_dai_free_widgets(&list); 336 + return ret; 337 + } 338 + 339 + if (pcm_ops && pcm_ops->hw_params) { 340 + ret = pcm_ops->hw_params(component, substream, params, platform_params); 341 + if (ret < 0) 342 + return ret; 343 + } 344 + 345 + spcm->prepared[substream->stream] = true; 359 346 360 347 return 0; 361 348 }
+30 -18
sound/soc/sof/sof-audio.c
··· 660 660 return 0; 661 661 } 662 662 663 + int sof_widget_list_prepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 664 + struct snd_pcm_hw_params *fe_params, 665 + struct snd_sof_platform_stream_params *platform_params, 666 + int dir) 667 + { 668 + /* 669 + * Prepare widgets for set up. The prepare step is used to allocate memory, assign 670 + * instance ID and pick the widget configuration based on the runtime PCM params. 671 + */ 672 + return sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 673 + dir, SOF_WIDGET_PREPARE); 674 + } 675 + 676 + void sof_widget_list_unprepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir) 677 + { 678 + struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list; 679 + 680 + /* unprepare the widget */ 681 + sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE); 682 + 683 + snd_soc_dapm_dai_free_widgets(&list); 684 + spcm->stream[dir].list = NULL; 685 + } 686 + 663 687 int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 664 688 struct snd_pcm_hw_params *fe_params, 665 689 struct snd_sof_platform_stream_params *platform_params, ··· 694 670 struct snd_soc_dapm_widget *widget; 695 671 int i, ret; 696 672 697 - /* nothing to set up */ 698 - if (!list) 673 + /* nothing to set up or setup has been already done */ 674 + if (!list || spcm->setup_done[dir]) 699 675 return 0; 700 - 701 - /* 702 - * Prepare widgets for set up. The prepare step is used to allocate memory, assign 703 - * instance ID and pick the widget configuration based on the runtime PCM params. 704 - */ 705 - ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, 706 - dir, SOF_WIDGET_PREPARE); 707 - if (ret < 0) 708 - return ret; 709 676 710 677 /* Set up is used to send the IPC to the DSP to create the widget */ 711 678 ret = sof_walk_widgets_in_order(sdev, spcm, fe_params, platform_params, ··· 752 737 } 753 738 } 754 739 740 + spcm->setup_done[dir] = true; 741 + 755 742 return 0; 756 743 757 744 widget_free: ··· 771 754 int ret; 772 755 773 756 /* nothing to free */ 774 - if (!list) 757 + if (!list || !spcm->setup_done[dir]) 775 758 return 0; 776 759 777 760 /* send IPC to free widget in the DSP */ 778 761 ret = sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_FREE); 779 762 780 - /* unprepare the widget */ 781 - sof_walk_widgets_in_order(sdev, spcm, NULL, NULL, dir, SOF_WIDGET_UNPREPARE); 782 - 783 - snd_soc_dapm_dai_free_widgets(&list); 784 - spcm->stream[dir].list = NULL; 785 - 763 + spcm->setup_done[dir] = false; 786 764 pipeline_list->count = 0; 787 765 788 766 return ret;
+7
sound/soc/sof/sof-audio.h
··· 354 354 struct snd_sof_pcm_stream stream[2]; 355 355 struct list_head list; /* list in sdev pcm list */ 356 356 struct snd_pcm_hw_params params[2]; 357 + struct snd_sof_platform_stream_params platform_params[2]; 357 358 bool prepared[2]; /* PCM_PARAMS set successfully */ 359 + bool setup_done[2]; /* the setup of the SOF PCM device is done */ 358 360 bool pending_stop[2]; /* only used if (!pcm_ops->platform_stop_during_hw_free) */ 359 361 360 362 /* Must be last - ends in a flex-array member. */ ··· 678 676 struct snd_pcm_hw_params *fe_params, 679 677 struct snd_sof_platform_stream_params *platform_params, 680 678 int dir); 679 + int sof_widget_list_prepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, 680 + struct snd_pcm_hw_params *fe_params, 681 + struct snd_sof_platform_stream_params *platform_params, 682 + int dir); 683 + void sof_widget_list_unprepare(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); 681 684 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); 682 685 int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev, 683 686 struct snd_sof_pcm *spcm);