summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>2024-11-07 14:15:32 +0200
committerMark Brown <broonie@kernel.org>2024-11-07 13:03:36 +0000
commit1b1f491dac4f6ee88ec7c36c4fd27880b0a89f41 (patch)
tree3ad3b716fddd33bd48c656d2b8b6477460ba1b44
parent8121de33460d0f1441e75b6e52dae9317efd0656 (diff)
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>
-rw-r--r--sound/soc/sof/intel/hda-stream.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 3ac63ce67ab1..519bafd3b947 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -119,13 +119,39 @@ int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev,
int remain, ioc;
period_bytes = hstream->period_bytes;
- dev_dbg(sdev->dev, "period_bytes:0x%x\n", period_bytes);
- if (!period_bytes)
+ dev_dbg(sdev->dev, "period_bytes: %#x, bufsize: %#x\n", period_bytes,
+ hstream->bufsize);
+
+ if (!period_bytes) {
+ unsigned int chunk_size;
+
+ chunk_size = snd_sgbuf_get_chunk_size(dmab, 0, hstream->bufsize);
+
period_bytes = hstream->bufsize;
+ /*
+ * HDA spec demands that the LVI value must be at least one
+ * before the DMA operation can begin. This means that there
+ * must be at least two BDLE present for the transfer.
+ *
+ * If the buffer is not a single continuous area then the
+ * hda_setup_bdle() will create multiple BDLEs for each segment.
+ * If the memory is a single continuous area, force it to be
+ * split into two 'periods', otherwise the transfer will be
+ * split to multiple BDLE for each chunk in hda_setup_bdle()
+ *
+ * Note: period_bytes == 0 can only happen for firmware or
+ * library loading. The data size is 4K aligned, which ensures
+ * that the second chunk's start address will be 128-byte
+ * aligned.
+ */
+ if (chunk_size == hstream->bufsize)
+ period_bytes /= 2;
+ }
+
periods = hstream->bufsize / period_bytes;
- dev_dbg(sdev->dev, "periods:%d\n", periods);
+ dev_dbg(sdev->dev, "periods: %d\n", periods);
remain = hstream->bufsize % period_bytes;
if (remain)