Skip to content

Commit

Permalink
dai-zephyr: use frames aligned for multi-endpoint copy
Browse files Browse the repository at this point in the history
When aggregating streams using dai_zephyr_multi_endpoint_copy()
multiple glitches observed in audio streams with odd number of channels.
Use audio_stream_avail_frames_aligned() for every dai in a loop
to correctly calcualte processing frames.

Signed-off-by: Ievgen Ganakov <[email protected]>
  • Loading branch information
iganakov committed Jun 4, 2024
1 parent 0bda13d commit fc9ad55
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/audio/copier/copier_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ int create_endpoint_buffer(struct comp_dev *dev,
audio_stream_set_buffer_fmt(&buffer->stream,
copier_cfg->base.audio_fmt.interleaving_style);

audio_stream_set_align(1, 1, &buffer->stream);

for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++)
buffer->chmap[i] = (chan_map >> i * 4) & 0xf;

Expand Down
43 changes: 19 additions & 24 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1332,19 +1332,15 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
struct comp_buffer *multi_endpoint_buffer,
int num_endpoints)
{
uint32_t avail_bytes = UINT32_MAX;
uint32_t free_bytes = UINT32_MAX;
uint32_t frames;
uint32_t src_frames, sink_frames;
uint32_t frame_bytes;
uint32_t frames_aligned;
uint32_t frames = UINT32_MAX;
int ret, i;
int direction;

if (!num_endpoints || !dd || !multi_endpoint_buffer)
return 0;

frame_bytes = audio_stream_frame_bytes(&dd[0]->dma_buffer->stream);

direction = dev->direction;

/* calculate min available/free from all endpoint DMA buffers */
Expand All @@ -1359,37 +1355,36 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
case -EPIPE:
/* DMA status can return -EPIPE and current status content if xrun occurs */
if (direction == SOF_IPC_STREAM_PLAYBACK)
comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(): dma_get_status() underrun occurred, endpoint: %d ret = %u",
i, ret);
comp_dbg(dev, "dma_get_status() underrun occurred "
"endpoint: %d ret = %u", i, ret);
else
comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(): dma_get_status() overrun occurred, enpdoint: %d ret = %u",
i, ret);
comp_dbg(dev, "dma_get_status() overrun occurred, "
"enpdoint: %d ret = %u", i, ret);
break;
default:
return ret;
}

avail_bytes = MIN(avail_bytes, stat.pending_length);
free_bytes = MIN(free_bytes, stat.free);
}

/* calculate minimum size to copy */
if (direction == SOF_IPC_STREAM_PLAYBACK) {
src_frames = audio_stream_get_avail_frames(&multi_endpoint_buffer->stream);
sink_frames = free_bytes / frame_bytes;
} else {
src_frames = avail_bytes / frame_bytes;
sink_frames = audio_stream_get_free_frames(&multi_endpoint_buffer->stream);
if (direction == SOF_IPC_STREAM_PLAYBACK) {
frames_aligned = audio_stream_avail_frames_aligned(
&multi_endpoint_buffer->stream, &dd[i]->dma_buffer->stream);
frames = MIN(frames, frames_aligned);
} else {
frames_aligned = audio_stream_avail_frames_aligned(
&dd[i]->dma_buffer->stream, &multi_endpoint_buffer->stream);
frames = MIN(frames, frames_aligned);
}
}

frames = MIN(src_frames, sink_frames);

/* limit bytes per copy to one period for the whole pipeline in order to avoid high load
* spike if FAST_MODE is enabled, then one period limitation is omitted. All dd's have the
* same period_bytes, so use the period_bytes from dd[0]
*/
if (!(dd[0]->ipc_config.feature_mask & BIT(IPC4_COPIER_FAST_MODE)))
if (!dd[0]->fast_mode) {
frame_bytes = audio_stream_frame_bytes(&dd[0]->dma_buffer->stream);
frames = MIN(frames, dd[0]->period_bytes / frame_bytes);
}

comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(), dir: %d copy frames= 0x%x",
dev->direction, frames);

Expand Down

0 comments on commit fc9ad55

Please sign in to comment.