From 7413ce2ef4e31060b15413118bb0b3f9b066f1d0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 17 Jan 2024 15:12:46 +0200 Subject: [PATCH] ASoC: SOF: ipc4-pcm: Correct delay reporting The link start offset and link position is in frames from the hardware, there is no need for conversion. At the start of the stream the link position can be lower than the start offset as the firmware provides a calculated estimate of it by taking the link DMA position and adding a calculated latency through the audio processing. Fixes: 3937a76c6493 ("ASoC: SOF: ipc4-pcm: add delay function support") Link: https://github.com/thesofproject/linux/issues/4781 Reported-by: Kai Vehmanen Signed-off-by: Peter Ujfalusi --- sound/soc/sof/ipc4-pcm.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 07eb5c6d4adf32..2afd4d4ac5c7cc 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -818,9 +818,7 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev, struct sof_ipc4_copier *host_copier = time_info->host_copier; struct sof_ipc4_copier *dai_copier = time_info->dai_copier; struct sof_ipc4_pipeline_registers ppl_reg; - u64 stream_start_position; - u32 dai_sample_size; - u32 ch, node_index; + u32 node_index; u32 offset; if (!host_copier || !dai_copier) @@ -835,13 +833,7 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev, if (ppl_reg.stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) return -EINVAL; - stream_start_position = ppl_reg.stream_start_offset; - ch = dai_copier->data.out_format.fmt_cfg; - ch = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(ch); - dai_sample_size = (dai_copier->data.out_format.bit_depth >> 3) * ch; - /* convert offset to sample count */ - do_div(stream_start_position, dai_sample_size); - time_info->stream_start_offset = stream_start_position; + time_info->stream_start_offset = ppl_reg.stream_start_offset; return 0; } @@ -899,7 +891,10 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component, * Firmware calculates correct stream_start_offset for all cases including above two. * Driver subtracts stream_start_offset from dai dma position to get accurate one */ - tmp_ptr -= time_info->stream_start_offset; + if (tmp_ptr > time_info->stream_start_offset) + tmp_ptr -= time_info->stream_start_offset; + else + tmp_ptr = 0; /* Calculate the delay taking into account that both pointer can wrap */ div64_u64_rem(tmp_ptr, substream->runtime->boundary, &tmp_ptr);