From 143d6c2c999d264a47cc4d8573f95de9592d0f2f Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Thu, 21 May 2026 12:36:06 +0300 Subject: [PATCH] audio: host-zephyr: add HOST_DMA_IPC_POSITION_UPDATES Kconfig Add a built option HOST_DMA_IPC_POSITION_UPDATES to control whether functionality to send IPC stream position updates is enabled or not. Most platforms provide more efficient means for host to monitor DMA state, so this code is in most cases unncessary. The current IPC sending code (from audio context) also assume kernel context, so making this functionality user-space compatible will require extra work. Enable DMA IPC position updates by default for IPC3 as the feature can be controlled by host with sof_ipc_stream_params.no_stream_position IPC interface. Disable the feature by default for IPC4, as there is no host IPC interface to control this and copier_update_params() unconditionally disables IPC updates for IPC4 now, so this code is never used. Signed-off-by: Kai Vehmanen --- src/audio/Kconfig | 9 +++++++++ src/audio/copier/host_copier.h | 4 +++- src/audio/host-legacy.c | 12 ++++++++++++ src/audio/host-zephyr.c | 14 +++++++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/audio/Kconfig b/src/audio/Kconfig index 1f7d362ffdc2..2f2036c5a57f 100644 --- a/src/audio/Kconfig +++ b/src/audio/Kconfig @@ -42,6 +42,15 @@ config HOST_DMA_STREAM_SYNCHRONIZATION for each group, different than the default one determined by the system tick frequency. This feature will allow host lower power consumption in scenarios with deep buffering. +config HOST_DMA_IPC_POSITION_UPDATES + bool "Support for stream position updates via IPC messages" + depends on IPC_MAJOR_3 + default y + help + Support firmware functionality to report stream position updates + by sending an IPC message whenever one period of audio is transferred. + Most platforms provide more efficient ways to query the DMA status. + config COMP_CHAIN_DMA bool "Chain DMA component" depends on IPC_MAJOR_4 diff --git a/src/audio/copier/host_copier.h b/src/audio/copier/host_copier.h index 71ce89cf315b..d00907959e8f 100644 --- a/src/audio/copier/host_copier.h +++ b/src/audio/copier/host_copier.h @@ -70,7 +70,6 @@ struct host_data { /* host position reporting related */ uint32_t host_size; /**< Host buffer size (in bytes) */ - uint32_t report_pos; /**< Position in current report period */ uint32_t local_pos; /**< Local position in host buffer */ uint32_t host_period_bytes; uint16_t stream_tag; @@ -106,7 +105,10 @@ struct host_data { /* stream info */ struct sof_ipc_stream_posn posn; /* TODO: update this */ +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES + uint32_t report_pos; /**< Position in current report period */ struct ipc_msg *msg; /**< host notification */ +#endif #if CONFIG_XRUN_NOTIFICATIONS_ENABLE bool xrun_notification_sent; #endif diff --git a/src/audio/host-legacy.c b/src/audio/host-legacy.c index 3d62e271f518..e0461c4c02e2 100644 --- a/src/audio/host-legacy.c +++ b/src/audio/host-legacy.c @@ -227,7 +227,9 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt struct comp_buffer *sink; int ret; bool update_mailbox = false; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES bool send_ipc = false; +#endif if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { source = hd->dma_buffer; @@ -272,6 +274,7 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt if (hd->cont_update_posn) update_mailbox = true; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES /* Don't send stream position if no_stream_position == 1 */ if (!hd->no_stream_position) { hd->report_pos += bytes; @@ -291,13 +294,16 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt send_ipc = true; } } +#endif if (update_mailbox) { pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); mailbox_stream_write(dev->pipeline->posn_offset, &hd->posn, sizeof(hd->posn)); +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES if (send_ipc) ipc_msg_send(hd->msg, &hd->posn, false); +#endif } } @@ -553,12 +559,14 @@ int host_common_new(struct host_data *hd, struct comp_dev *dev, ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, config_id); +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, hd->posn.rhdr.hdr.size); if (!hd->msg) { comp_err(dev, "ipc_msg_init failed"); dma_put(hd->dma); return -ENOMEM; } +#endif hd->chan = NULL; hd->copy_type = COMP_COPY_NORMAL; @@ -614,7 +622,9 @@ void host_common_free(struct host_data *hd) dma_put(hd->dma); +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES ipc_msg_free(hd->msg); +#endif dma_sg_free(NULL, &hd->config.elem_array); } @@ -952,7 +962,9 @@ void host_common_reset(struct host_data *hd, uint16_t state) /* reset buffer pointers */ hd->local_pos = 0; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES hd->report_pos = 0; +#endif hd->total_data_processed = 0; hd->copy_type = COMP_COPY_NORMAL; diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index 90b0821caf5a..fcea76096f5b 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -246,7 +246,9 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt struct comp_buffer *sink; int ret; bool update_mailbox = false; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES bool send_ipc = false; +#endif if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { source = hd->dma_buffer; @@ -285,6 +287,7 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt if (hd->cont_update_posn) update_mailbox = true; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES /* Don't send stream position if no_stream_position == 1 */ if (!hd->no_stream_position) { hd->report_pos += bytes; @@ -304,13 +307,16 @@ void host_common_update(struct host_data *hd, struct comp_dev *dev, uint32_t byt send_ipc = true; } } +#endif if (update_mailbox) { pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); mailbox_stream_write(dev->pipeline->posn_offset, &hd->posn, sizeof(hd->posn)); +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES if (send_ipc) ipc_msg_send(hd->msg, &hd->posn, false); +#endif } } @@ -720,14 +726,16 @@ __cold int host_common_new(struct host_data *hd, struct comp_dev *dev, dma_sg_init(&hd->local.elem_array); ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, config_id); + hd->chan_index = -EINVAL; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, sizeof(hd->posn)); if (!hd->msg) { comp_err(dev, "ipc_msg_init failed"); sof_dma_put(hd->dma); return -ENOMEM; } - hd->chan_index = -EINVAL; +#endif hd->copy_type = COMP_COPY_NORMAL; #ifdef CONFIG_SOF_USERSPACE_LL @@ -808,7 +816,9 @@ __cold void host_common_free(struct host_data *hd) sof_dma_put(hd->dma); +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES ipc_msg_free(hd->msg); +#endif dma_sg_free(hd->alloc_ctx.heap, &hd->config.elem_array); } @@ -1212,7 +1222,9 @@ void host_common_reset(struct host_data *hd, uint16_t state) /* reset buffer pointers */ hd->local_pos = 0; +#if CONFIG_HOST_DMA_IPC_POSITION_UPDATES hd->report_pos = 0; +#endif hd->total_data_processed = 0; hd->copy_type = COMP_COPY_NORMAL;