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: Intel: hda-stream: Always use at least two BDLE for transfers

The HDA specification states that the SDnLVI (Last Valid Index) must be at
least 1 (two BDLE entry).

Update the debug prints as well to provide better information.

While the LVI=0 worked so far without issues, it is better to align with
the specification to avoid unforeseen issues with FW loading.

Notes:
- The LVI > 0 rules is valid and honored for audio use cases
- LVI == 0 is used with software controlled (SPIB) transfers only for
firmware and library loading, which is permitted by the hardware
- This is not spelled out in the specification and it is better to avoid
cases

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20241107121532.3241-1-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Peter Ujfalusi and committed by
Mark Brown
1b1f491d 8121de33

+29 -3
+29 -3
sound/soc/sof/intel/hda-stream.c
··· 119 119 int remain, ioc; 120 120 121 121 period_bytes = hstream->period_bytes; 122 - dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes); 123 - if (!period_bytes) 122 + dev_dbg(sdev->dev, "period_bytes: %#x, bufsize: %#x\n", period_bytes, 123 + hstream->bufsize); 124 + 125 + if (!period_bytes) { 126 + unsigned int chunk_size; 127 + 128 + chunk_size = snd_sgbuf_get_chunk_size(dmab, 0, hstream->bufsize); 129 + 124 130 period_bytes = hstream->bufsize; 131 + 132 + /* 133 + * HDA spec demands that the LVI value must be at least one 134 + * before the DMA operation can begin. This means that there 135 + * must be at least two BDLE present for the transfer. 136 + * 137 + * If the buffer is not a single continuous area then the 138 + * hda_setup_bdle() will create multiple BDLEs for each segment. 139 + * If the memory is a single continuous area, force it to be 140 + * split into two 'periods', otherwise the transfer will be 141 + * split to multiple BDLE for each chunk in hda_setup_bdle() 142 + * 143 + * Note: period_bytes == 0 can only happen for firmware or 144 + * library loading. The data size is 4K aligned, which ensures 145 + * that the second chunk's start address will be 128-byte 146 + * aligned. 147 + */ 148 + if (chunk_size == hstream->bufsize) 149 + period_bytes /= 2; 150 + } 125 151 126 152 periods = hstream->bufsize / period_bytes; 127 153 128 - dev_dbg(sdev->dev, "periods:%d\n", periods); 154 + dev_dbg(sdev->dev, "periods: %d\n", periods); 129 155 130 156 remain = hstream->bufsize % period_bytes; 131 157 if (remain)