dai-zephyr: handle dynamic disconnect of one sink

In IPC4 mode, the DAI supports writing data to multiple sinks.
It is possible one of the sinks to be on a different pipeline,
which can be disconnected while the DAI is still running.

Depending on the order of pipeline setup, the disconnected sink
might have been chosen as the local_buffer.

Handle this case by reconfiguring the local buffer after
disconnect in the copy function.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
This commit is contained in:
Kai Vehmanen 2023-05-23 12:36:02 +03:00 committed by Kai Vehmanen
parent e2f66c65ab
commit aeda64b61c
1 changed files with 38 additions and 2 deletions

View File

@ -1465,6 +1465,37 @@ int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev,
return 0;
}
static void set_new_local_buffer(struct dai_data *dd, struct comp_dev *dev)
{
struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer);
struct comp_buffer __sparse_cache *local_buf;
uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream);
uint32_t local_fmt;
buffer_release(dma_buf);
if (dev->direction == SOF_IPC_STREAM_PLAYBACK)
dd->local_buffer = list_first_item(&dev->bsource_list,
struct comp_buffer,
sink_list);
else
dd->local_buffer = list_first_item(&dev->bsink_list,
struct comp_buffer,
source_list);
local_buf = buffer_acquire(dd->local_buffer);
local_fmt = audio_stream_get_frm_fmt(&local_buf->stream);
buffer_release(local_buf);
dd->process = pcm_get_conversion_function(local_fmt, dma_fmt);
if (!dd->process) {
comp_err(dev, "converter function NULL: local fmt %d dma fmt %d\n",
local_fmt, dma_fmt);
dd->local_buffer = NULL;
}
}
/* copy and process stream data from source to sink buffers */
int dai_zephyr_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter)
{
@ -1508,9 +1539,14 @@ int dai_zephyr_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_fun
buffer_release(buf_c);
/* handle module runtime unbind */
if (!dd->local_buffer) {
comp_warn(dev, "dai_zephyr_copy(): local buffer unbound, cannot copy");
return 0;
set_new_local_buffer(dd, dev);
if (!dd->local_buffer) {
comp_warn(dev, "dai_zephyr_copy(): local buffer unbound, cannot copy");
return 0;
}
}
/* calculate minimum size to copy */