Skip to content

Commit 5fcdbb2

Browse files
ranj063broonie
authored andcommitted
ASoC: SOF: Add support for dynamic pipelines
Add support for dynamic pipelines by modifying the PCM hw_params ioctl implementation to determine the widgets required for a PCM stream by querying the list of connected DAPM widgets. This list is saved as part of snd_sof_pcm_stream struct and will be used to setup the widgets. The sof_widget_list_setup/free routines setup and free connected DAPM widgets when a PCM is opened/closed. These routines accept a list of connected DAPM widgets as input and determine the SOF widgets, their corresponding pipeline widgets and connections between them that need to be setup before the PCM is triggered. Please note that the dynamic pipeline feature will only be enabled for those pipelines whose dynamic_pipeline_widget flag is set in topologies. Add a new token called SOF_TKN_SCHED_DYNAMIC_PIPELINE that when set in topology will be applied to the dynamic_pipeline_widget flag of the pipeline widget. Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://lore.kernel.org/r/20210927120517.20505-12-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 0acb48d commit 5fcdbb2

File tree

4 files changed

+390
-54
lines changed

4 files changed

+390
-54
lines changed

sound/soc/sof/intel/hda.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,6 @@
4141
#define EXCEPT_MAX_HDR_SIZE 0x400
4242
#define HDA_EXT_ROM_STATUS_SIZE 8
4343

44-
static const struct sof_intel_dsp_desc
45-
*get_chip_info(struct snd_sof_pdata *pdata)
46-
{
47-
const struct sof_dev_desc *desc = pdata->desc;
48-
const struct sof_intel_dsp_desc *chip_info;
49-
50-
chip_info = desc->chip_info;
51-
52-
return chip_info;
53-
}
54-
5544
int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w)
5645
{
5746
struct snd_sof_widget *swidget = w->dobj.private;
@@ -132,6 +121,17 @@ int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w)
132121
return sof_widget_free(sdev, swidget);
133122
}
134123

124+
static const struct sof_intel_dsp_desc
125+
*get_chip_info(struct snd_sof_pdata *pdata)
126+
{
127+
const struct sof_dev_desc *desc = pdata->desc;
128+
const struct sof_intel_dsp_desc *chip_info;
129+
130+
chip_info = desc->chip_info;
131+
132+
return chip_info;
133+
}
134+
135135
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
136136

137137
/*

sound/soc/sof/pcm.c

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,40 @@ static int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream,
116116
return ret;
117117
}
118118

119+
static int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev,
120+
struct snd_soc_pcm_runtime *rtd,
121+
struct snd_sof_pcm *spcm, int dir)
122+
{
123+
struct snd_soc_dai *dai;
124+
int ret, j;
125+
126+
/* query DAPM for list of connected widgets and set them up */
127+
for_each_rtd_cpu_dais(rtd, j, dai) {
128+
struct snd_soc_dapm_widget_list *list;
129+
130+
ret = snd_soc_dapm_dai_get_connected_widgets(dai, dir, &list,
131+
dpcm_end_walk_at_be);
132+
if (ret < 0) {
133+
dev_err(sdev->dev, "error: dai %s has no valid %s path\n", dai->name,
134+
dir == SNDRV_PCM_STREAM_PLAYBACK ? "playback" : "capture");
135+
return ret;
136+
}
137+
138+
spcm->stream[dir].list = list;
139+
140+
ret = sof_widget_list_setup(sdev, spcm, dir);
141+
if (ret < 0) {
142+
dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n",
143+
spcm->pcm.pcm_id, dir);
144+
spcm->stream[dir].list = NULL;
145+
snd_soc_dapm_dai_free_widgets(&list);
146+
return ret;
147+
}
148+
}
149+
150+
return 0;
151+
}
152+
119153
static int sof_pcm_hw_params(struct snd_soc_component *component,
120154
struct snd_pcm_substream *substream,
121155
struct snd_pcm_hw_params *params)
@@ -213,7 +247,14 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
213247

214248
dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
215249

216-
/* send IPC to the DSP */
250+
/* if this is a repeated hw_params without hw_free, skip setting up widgets */
251+
if (!spcm->stream[substream->stream].list) {
252+
ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream);
253+
if (ret < 0)
254+
return ret;
255+
}
256+
257+
/* send hw_params IPC to the DSP */
217258
ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
218259
&ipc_params_reply, sizeof(ipc_params_reply));
219260
if (ret < 0) {
@@ -259,6 +300,10 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
259300
err = ret;
260301
}
261302

303+
ret = sof_widget_list_free(sdev, spcm, substream->stream);
304+
if (ret < 0)
305+
err = ret;
306+
262307
cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
263308

264309
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
@@ -316,6 +361,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
316361
struct sof_ipc_stream stream;
317362
struct sof_ipc_reply reply;
318363
bool reset_hw_params = false;
364+
bool free_widget_list = false;
319365
bool ipc_first = false;
320366
int ret;
321367

@@ -386,6 +432,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
386432
spcm->stream[substream->stream].suspend_ignored = true;
387433
return 0;
388434
}
435+
free_widget_list = true;
389436
fallthrough;
390437
case SNDRV_PCM_TRIGGER_STOP:
391438
stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
@@ -414,8 +461,15 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
414461
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
415462

416463
/* free PCM if reset_hw_params is set and the STOP IPC is successful */
417-
if (!ret && reset_hw_params)
464+
if (!ret && reset_hw_params) {
418465
ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
466+
if (ret < 0)
467+
return ret;
468+
469+
/* free widget list only for SUSPEND trigger */
470+
if (free_widget_list)
471+
ret = sof_widget_list_free(sdev, spcm, substream->stream);
472+
}
419473

420474
return ret;
421475
}

0 commit comments

Comments
 (0)