| From bace10b59624e6bd8d68bc9304357f292f1b3dcf Mon Sep 17 00:00:00 2001 |
| From: Kai Vehmanen <kai.vehmanen@linux.intel.com> |
| Date: Thu, 2 Oct 2025 10:47:16 +0300 |
| Subject: ASoC: SOF: ipc4-pcm: fix start offset calculation for chain DMA |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Kai Vehmanen <kai.vehmanen@linux.intel.com> |
| |
| commit bace10b59624e6bd8d68bc9304357f292f1b3dcf upstream. |
| |
| Assumption that chain DMA module starts the link DMA when 1ms of |
| data is available from host is not correct. Instead the firmware |
| chain DMA module fills the link DMA with initial buffer of zeroes |
| and the host and link DMAs are started at the same time. |
| |
| This results in a small error in delay calculation. This can become a |
| more severe problem if host DMA has delays that exceed 1ms. This results |
| in negative delay to be calculated and bogus values reported to |
| applications. This can confuse some applications like |
| alsa_conformance_test. |
| |
| Fix the issue by correctly calculating the firmware chain DMA |
| preamble size and initializing the start offset to this value. |
| |
| Cc: stable@vger.kernel.org |
| Fixes: a1d203d390e0 ("ASoC: SOF: ipc4-pcm: Enable delay reporting for ChainDMA streams") |
| Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> |
| Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> |
| Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> |
| Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> |
| Link: https://patch.msgid.link/20251002074719.2084-3-peter.ujfalusi@linux.intel.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| sound/soc/sof/ipc4-pcm.c | 14 ++++++++++---- |
| sound/soc/sof/ipc4-topology.c | 1 - |
| sound/soc/sof/ipc4-topology.h | 2 ++ |
| 3 files changed, 12 insertions(+), 5 deletions(-) |
| |
| --- a/sound/soc/sof/ipc4-pcm.c |
| +++ b/sound/soc/sof/ipc4-pcm.c |
| @@ -1052,7 +1052,7 @@ static int sof_ipc4_get_stream_start_off |
| return -EINVAL; |
| } else if (host_copier->data.gtw_cfg.node_id == SOF_IPC4_CHAIN_DMA_NODE_ID) { |
| /* |
| - * While the firmware does not supports time_info reporting for |
| + * While the firmware does not support time_info reporting for |
| * streams using ChainDMA, it is granted that ChainDMA can only |
| * be used on Host+Link pairs where the link position is |
| * accessible from the host side. |
| @@ -1060,10 +1060,16 @@ static int sof_ipc4_get_stream_start_off |
| * Enable delay calculation in case of ChainDMA via host |
| * accessible registers. |
| * |
| - * The ChainDMA uses 2x 1ms ping-pong buffer, dai side starts |
| - * when 1ms data is available |
| + * The ChainDMA prefills the link DMA with a preamble |
| + * of zero samples. Set the stream start offset based |
| + * on size of the preamble (driver provided fifo size |
| + * multiplied by 2.5). We add 1ms of margin as the FW |
| + * will align the buffer size to DMA hardware |
| + * alignment that is not known to host. |
| */ |
| - time_info->stream_start_offset = substream->runtime->rate / MSEC_PER_SEC; |
| + int pre_ms = SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS * 5 / 2 + 1; |
| + |
| + time_info->stream_start_offset = pre_ms * substream->runtime->rate / MSEC_PER_SEC; |
| goto out; |
| } |
| |
| --- a/sound/soc/sof/ipc4-topology.c |
| +++ b/sound/soc/sof/ipc4-topology.c |
| @@ -33,7 +33,6 @@ MODULE_PARM_DESC(ipc4_ignore_cpc, |
| |
| #define SOF_IPC4_GAIN_PARAM_ID 0 |
| #define SOF_IPC4_TPLG_ABI_SIZE 6 |
| -#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 |
| |
| static DEFINE_IDA(alh_group_ida); |
| static DEFINE_IDA(pipeline_ida); |
| --- a/sound/soc/sof/ipc4-topology.h |
| +++ b/sound/soc/sof/ipc4-topology.h |
| @@ -247,6 +247,8 @@ struct sof_ipc4_dma_stream_ch_map { |
| #define SOF_IPC4_DMA_METHOD_HDA 1 |
| #define SOF_IPC4_DMA_METHOD_GPDMA 2 /* defined for consistency but not used */ |
| |
| +#define SOF_IPC4_CHAIN_DMA_BUF_SIZE_MS 2 |
| + |
| /** |
| * struct sof_ipc4_dma_config: DMA configuration |
| * @dma_method: HDAudio or GPDMA |