Unverified Commit 1b1f491d authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown
Browse files

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: default avatarPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: default avatarLiam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Reviewed-by: default avatarBard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20241107121532.3241-1-peter.ujfalusi@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 8121de33
Loading
Loading
Loading
Loading
+29 −3
Original line number Diff line number Diff line
@@ -119,10 +119,36 @@ 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);