Skip to content

Commit

Permalink
src: dai-zephyr: copy data to all available sinks
Browse files Browse the repository at this point in the history
In the case where the copier has more than one output and,
additionally, we will be using a pin other than pin 0
(for example, when we want to copy data from pin 1 of
a gateway-type copier to the next pipeline), it is necessary
to copy data in playback path from the source to the output
for all possible sinks.

Signed-off-by: Damian Nikodem <[email protected]>
  • Loading branch information
dnikodem committed Jun 6, 2024
1 parent 0bda13d commit 2649bd8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 17 deletions.
8 changes: 4 additions & 4 deletions posix/include/sof/lib/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,13 +538,13 @@ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source,
dma_process_func process, uint32_t sink_bytes);

/*
* Used when copying DMA buffer bytes into multiple sink buffers, one at a time using the provided
* Used when copying stream audio into multiple sink buffers, one at a time using the provided
* conversion function. DMA buffer consume should be performed after the data has been copied
* to all sinks.
*/
int dma_buffer_copy_from_no_consume(struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process, uint32_t source_bytes);
int stream_copy_from_no_consume(struct comp_buffer __sparse_cache *source,
struct comp_buffer __sparse_cache *sink,
dma_process_func process, uint32_t source_bytes);

/* generic DMA DSP <-> Host copier */

Expand Down
52 changes: 46 additions & 6 deletions src/audio/dai-zephyr.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,55 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
}

if (dev->direction == SOF_IPC_STREAM_PLAYBACK) {
#if CONFIG_IPC_MAJOR_4
struct list_item *sink_list;
/*
* copy from local buffer to all sinks that are not gateway buffers
* using the right PCM converter function.
*/
list_for_item(sink_list, &dev->bsink_list) {
struct comp_dev *sink_dev;
struct comp_buffer *sink;
int j;

sink = container_of(sink_list, struct comp_buffer, source_list);

if (sink == dd->dma_buffer)
continue;

sink_dev = sink->sink;

j = IPC4_SRC_QUEUE_ID(buf_get_id(sink));

if (j >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) {
comp_err(dev, "Sink queue ID: %d >= max output pin count: %d\n",
j, IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT);
ret = -EINVAL;
continue;
}

if (!converter[j]) {
comp_err(dev, "No PCM converter for sink queue %d\n", j);
ret = -EINVAL;
continue;
}

if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE) {
ret = stream_copy_from_no_consume(dd->local_buffer, sink,
converter[j], bytes);
}
}
#endif
ret = dma_buffer_copy_to(dd->local_buffer, dd->dma_buffer,
dd->process, bytes);
} else {
audio_stream_invalidate(&dd->dma_buffer->stream, bytes);
/*
* The PCM converter functions used during DMA buffer copy can never fail,
* so no need to check the return value of dma_buffer_copy_from_no_consume().
* so no need to check the return value of stream_copy_from_no_consume().
*/
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer, dd->local_buffer,
dd->process, bytes);
ret = stream_copy_from_no_consume(dd->dma_buffer, dd->local_buffer,
dd->process, bytes);
#if CONFIG_IPC_MAJOR_4
struct list_item *sink_list;
/* Skip in case of endpoint DAI devices created by the copier */
Expand Down Expand Up @@ -315,9 +354,9 @@ dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes,
}

if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE)
ret = dma_buffer_copy_from_no_consume(dd->dma_buffer,
sink, converter[j],
bytes);
ret = stream_copy_from_no_consume(dd->dma_buffer,
sink, converter[j],
bytes);
}
}
#endif
Expand Down Expand Up @@ -1520,6 +1559,7 @@ int dai_common_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_fun

/* calculate minimum size to copy */
if (dev->direction == SOF_IPC_STREAM_PLAYBACK) {
struct list_item *sink_list;
src_samples = audio_stream_get_avail_samples(&dd->local_buffer->stream);
sink_samples = free_bytes / sampling;
samples = MIN(src_samples, sink_samples);
Expand Down
6 changes: 3 additions & 3 deletions src/lib/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,9 @@ int dma_buffer_copy_to(struct comp_buffer *source,
return ret;
}

int dma_buffer_copy_from_no_consume(struct comp_buffer *source,
struct comp_buffer *sink,
dma_process_func process, uint32_t source_bytes)
int stream_copy_from_no_consume(struct comp_buffer *source,
struct comp_buffer *sink,
dma_process_func process, uint32_t source_bytes)
{
struct audio_stream *istream = &source->stream;
uint32_t samples = source_bytes /
Expand Down
8 changes: 4 additions & 4 deletions xtos/include/sof/lib/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -538,13 +538,13 @@ int dma_buffer_copy_from(struct comp_buffer *source,
dma_process_func process, uint32_t source_bytes);

/*
* Used when copying DMA buffer bytes into multiple sink buffers, one at a time using the provided
* Used when copying stream audio into multiple sink buffers, one at a time using the provided
* conversion function. DMA buffer consume should be performed after the data has been copied
* to all sinks.
*/
int dma_buffer_copy_from_no_consume(struct comp_buffer *source,
struct comp_buffer *sink,
dma_process_func process, uint32_t source_bytes);
int stream_copy_from_no_consume(struct comp_buffer *source,
struct comp_buffer *sink,
dma_process_func process, uint32_t source_bytes);

/* copies data to DMA buffer using provided processing function */
int dma_buffer_copy_to(struct comp_buffer *source,
Expand Down

0 comments on commit 2649bd8

Please sign in to comment.