Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/audio/copier/copier.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,8 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd)
}

buffer = comp_dev_get_first_data_producer(dai_copier);
pipe_reg.stream_start_offset = posn.dai_posn +
latency * audio_stream_period_bytes(&buffer->stream, dev->frames);
pipe_reg.stream_start_offset = posn.dai_posn + (uint64_t)latency *
audio_stream_period_bytes(&buffer->stream, dev->frames);
pipe_reg.stream_end_offset = 0;
mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg, sizeof(pipe_reg));
} else if (cmd == COMP_TRIGGER_PAUSE) {
Expand All @@ -510,15 +510,23 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd)
pipe_reg.stream_start_offset = mailbox_sw_reg_read64(cd->pipeline_reg_offset);
pipe_reg.stream_end_offset = mailbox_sw_reg_read64(cd->pipeline_reg_offset +
sizeof(pipe_reg.stream_start_offset));
pipe_reg.stream_start_offset += posn.dai_posn - pipe_reg.stream_end_offset;

/* stream_end_offset was sampled from the dai position when the pipeline
* was paused, so the current position should be ahead of it. The value
* is read back from the host visible mailbox and cannot be trusted: a
* stale or out of order one would make the unsigned subtraction wrap
* and corrupt the offset reported to the host driver.
*/
if (posn.dai_posn > pipe_reg.stream_end_offset)
pipe_reg.stream_start_offset += posn.dai_posn - pipe_reg.stream_end_offset;
Comment on lines +520 to +521

if (list_is_empty(&dai_copier->bsource_list)) {
comp_err(dev, "No source buffer bound to dai_copier");
return -EINVAL;
}

buffer = comp_dev_get_first_data_producer(dai_copier);
pipe_reg.stream_start_offset += latency *
pipe_reg.stream_start_offset += (uint64_t)latency *
audio_stream_period_bytes(&buffer->stream, dev->frames);
mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg.stream_start_offset,
sizeof(pipe_reg.stream_start_offset));
Expand Down
17 changes: 14 additions & 3 deletions src/audio/pipeline/pipeline-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,9 +699,20 @@ struct comp_dev *pipeline_get_dai_comp_latency(uint32_t pipeline_id, uint32_t *l
if (ret < 0)
return NULL;

if (input_data && output_data && input_base_cfg.ibs && output_base_cfg.obs)
*latency += input_data / input_base_cfg.ibs -
output_data / output_base_cfg.obs;
if (input_data && output_data && input_base_cfg.ibs && output_base_cfg.obs) {
uint64_t in_blocks = input_data / input_base_cfg.ibs;
uint64_t out_blocks = output_data / output_base_cfg.obs;

/* The latency is a count of blocks buffered between the
* source and the sink and cannot be negative. The sink may
* legitimately lead the source, e.g. when the dai is started
* before the host because they are in different pipelines,
* so clamp instead of letting the unsigned subtraction wrap
* into a huge value.
*/
if (in_blocks > out_blocks)
*latency += in_blocks - out_blocks;
}

/* If the component doesn't have a sink buffer, it can be a dai. */
if (list_is_empty(&ipc_sink->cd->bsink_list))
Expand Down
Loading