From a37bd1b48a3a56123658468cb9a7fc1e5c1c0475 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 8 Mar 2024 15:12:38 +0200 Subject: [PATCH 1/3] ASoC: SOF: Add dsp_buffer_time_ms member to snd_sof_pcm_stream The dsp_buffer_time_ms can be used to save the length of the DSP host buffer for platform code to place constraint using it to avoid user space requesting for smaller period size than the DMA burst between DSP and host. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/sof-audio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 72af874499f9ab..1c0df518dc3aac 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -325,6 +325,7 @@ struct snd_sof_pcm_stream { struct work_struct period_elapsed_work; struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */ bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */ + unsigned int dsp_buffer_time_ms; /* The size of the DSP pcm buffer in ms */ /* * flag to indicate that the DSP pipelines should be kept * active or not while suspending the stream From b75fef17a079a3117f1d39f5e1f16a027113f2dc Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 8 Mar 2024 15:14:22 +0200 Subject: [PATCH 2/3] ASoC: SOF: ipc4-topology: Save the DMA buffer time for playback PCMs When setting up the pcm widget, save the DSP buffer size (in ms) for platform code to place a constraint on playback. On playback the DMA will fill the buffer on start and if the period size is smaller it will immediately overrun. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/ipc4-topology.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f935a5820d7a09..e9439e31a64b18 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -412,8 +412,9 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) struct sof_ipc4_available_audio_format *available_fmt; struct snd_soc_component *scomp = swidget->scomp; struct sof_ipc4_copier *ipc4_copier; + struct snd_sof_pcm *spcm; int node_type = 0; - int ret; + int ret, dir; ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL); if (!ipc4_copier) @@ -447,6 +448,19 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) } dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type); + spcm = snd_sof_find_spcm_comp(scomp, swidget->comp_id, &dir); + if (spcm && dir == SNDRV_PCM_STREAM_PLAYBACK) { + struct snd_sof_pcm_stream *sps = &spcm->stream[dir]; + + sof_update_ipc_object(scomp, &sps->dsp_buffer_time_ms, + SOF_COPIER_DEEP_BUFFER_TOKENS, + swidget->tuples, + swidget->num_tuples, sizeof(u32), 1); + /* Set default DMA buffer size if it is not specified in topology */ + if (!sps->dsp_buffer_time_ms) + sps->dsp_buffer_time_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE; + } + skip_gtw_cfg: ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL); if (!ipc4_copier->gtw_attr) { From da9054cbb20308e620428d5281daefdb5fec5870 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 8 Mar 2024 15:16:26 +0200 Subject: [PATCH 3/3] ASoC: SOF: Intel: hda-pcm: Use dsp_buffer_time_ms to place constraint If the PCM have the dsp_buffer_time_ms set then place a constraint to limit the minimum period time to avoid smaller period sizes than the DMA burst. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/intel/hda-pcm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index 9847d749d09f45..2905415b3644a0 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -263,6 +263,18 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32); + /* + * Set constraint on the period time to make sure that it is larger than + * the DSP buffer size. This is the maximum DMA burst size that can + * happen on stream start for example. + * The period size must not be smaller than this. + */ + if (spcm->stream[substream->stream].dsp_buffer_time_ms) + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIOD_TIME, + spcm->stream[substream->stream].dsp_buffer_time_ms * USEC_PER_MSEC, + UINT_MAX); + /* binding pcm substream to hda stream */ substream->runtime->private_data = &dsp_stream->hstream; return 0;