Skip to content

Commit

Permalink
ASoC: SOF: ipc4-pcm: Correct delay reporting
Browse files Browse the repository at this point in the history
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: 3937a76 ("ASoC: SOF: ipc4-pcm: add delay function support")
Link: thesofproject#4781
Reported-by: Kai Vehmanen <[email protected]>
Signed-off-by: Peter Ujfalusi <[email protected]>
  • Loading branch information
ujfalusi committed Jan 17, 2024
1 parent 7a4106a commit 3d7c4c4
Showing 1 changed file with 6 additions and 11 deletions.
17 changes: 6 additions & 11 deletions sound/soc/sof/ipc4-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down

1 comment on commit 3d7c4c4

@RanderWang
Copy link

@RanderWang RanderWang commented on 3d7c4c4 Jan 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to spec : stream_start_offset is in number of bytes, not frames. We need to align with windows driver.
So in fw we build it in bytes

struct ipc4_pipeline_registers {
	/**
	 * Stream start offset (LPIB) reported by mixin module allocated on pipeline attached
	 * to Host Output Gateway when first data is being mixed to mixout module. When data
	 * is not mixed (right after creation/after reset) value "(uint64_t)-1" is reported.
	 * In number of bytes.
	 * */
	uint64_t stream_start_offset;
	/**
	 * Stream end offset (LPIB) reported by mixin module allocated on pipeline attached
	 * to Host Output Gateway during transition from RUNNING to PAUSED. When data
	 * is not mixed (right after creation/after reset) value "(uint64_t)-1" is reported. When
	 * first data is mixed then value "0"is reported.
	 * In number of bytes.
	 * */
	uint64_t stream_end_offset;
} __attribute__((packed, aligned(8)));

Please sign in to comment.