summaryrefslogtreecommitdiff
path: root/sound/soc/sof/intel/hda-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sof/intel/hda-pcm.c')
-rw-r--r--sound/soc/sof/intel/hda-pcm.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index 1dd8d2092c3b..da6c1e7263cd 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -29,6 +29,8 @@
#define SDnFMT_BITS(x) ((x) << 4)
#define SDnFMT_CHAN(x) ((x) << 0)
+#define HDA_MAX_PERIOD_TIME_HEADROOM 10
+
static bool hda_always_enable_dmi_l1;
module_param_named(always_enable_dmi_l1, hda_always_enable_dmi_l1, bool, 0444);
MODULE_PARM_DESC(always_enable_dmi_l1, "SOF HDA always enable DMI l1");
@@ -291,19 +293,30 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
* On playback start the DMA will transfer dsp_max_burst_size_in_ms
* amount of data in one initial burst to fill up the host DMA buffer.
* Consequent DMA burst sizes are shorter and their length can vary.
- * To make sure that userspace allocate large enough ALSA buffer we need
- * to place a constraint on the buffer time.
+ * To avoid immediate xrun by the initial burst we need to place
+ * constraint on the period size (via PERIOD_TIME) to cover the size of
+ * the host buffer.
+ * We need to add headroom of max 10ms as the firmware needs time to
+ * settle to the 1ms pacing and initially it can run faster for few
+ * internal periods.
*
* On capture the DMA will transfer 1ms chunks.
- *
- * Exact dsp_max_burst_size_in_ms constraint is racy, so set the
- * constraint to a minimum of 2x dsp_max_burst_size_in_ms.
*/
- if (spcm->stream[direction].dsp_max_burst_size_in_ms)
+ if (spcm->stream[direction].dsp_max_burst_size_in_ms) {
+ unsigned int period_time = spcm->stream[direction].dsp_max_burst_size_in_ms;
+
+ /*
+ * add headroom over the maximum burst size to cover the time
+ * needed for the DMA pace to settle.
+ * Limit the headroom time to HDA_MAX_PERIOD_TIME_HEADROOM
+ */
+ period_time += min(period_time, HDA_MAX_PERIOD_TIME_HEADROOM);
+
snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_BUFFER_TIME,
- spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2,
+ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+ period_time * USEC_PER_MSEC,
UINT_MAX);
+ }
/* binding pcm substream to hda stream */
substream->runtime->private_data = &dsp_stream->hstream;