-
Notifications
You must be signed in to change notification settings - Fork 369
Audio: Buffers: Add support for DP-to-DP component binding #10562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1164,7 +1164,7 @@ static int module_adapter_copy_ring_buffers(struct comp_dev *dev) | |
| /* input - we need to copy data from audio_stream (as source) | ||
| * to ring_buffer (as sink) | ||
| */ | ||
| err = audio_buffer_sync_secondary_buffer(&buffer->audio_buffer, UINT_MAX); | ||
| err = audio_buffer_sync_secondary_buffer(&buffer->audio_buffer, SIZE_MAX); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. separate commit ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, done. Also I used CONFIG_DP_TO_DP_BIND to help find the code for this. |
||
|
|
||
| if (err) { | ||
| comp_err(dev, "LL to DP copy error status: %d", err); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -803,18 +803,22 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) | |
| struct mod_alloc_ctx *alloc; | ||
|
|
||
| #if CONFIG_ZEPHYR_DP_SCHEDULER | ||
| if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && | ||
| sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { | ||
| bool src_is_dp = source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP; | ||
| bool sink_is_dp = sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP; | ||
| #if CONFIG_DP_TO_DP_BIND | ||
| bool dp_to_dp = src_is_dp && sink_is_dp; | ||
| #else | ||
| if (src_is_dp && sink_is_dp) { | ||
| tr_err(&ipc_tr, "DP to DP binding is not supported: can't bind %x to %x", | ||
| src_id, sink_id); | ||
| return IPC4_INVALID_REQUEST; | ||
| } | ||
|
|
||
| #endif | ||
| struct comp_dev *dp; | ||
|
|
||
| if (sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) | ||
| if (sink_is_dp) | ||
| dp = sink; | ||
| else if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) | ||
| else if (src_is_dp) | ||
| dp = source; | ||
| else | ||
| dp = NULL; | ||
|
|
@@ -887,8 +891,8 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) | |
| * | ||
| * size = 2*max(obs of source module, ibs of destination module) | ||
| * (obs and ibs is single buffer size) | ||
| * in case of DP -> LL | ||
| * size = 2*ibs of destination (LL) module. DP queue will handle obs of DP module | ||
| * in case of DP -> LL or DP -> DP | ||
| * size = 2*ibs of destination module. DP queue will handle obs of DP module | ||
| */ | ||
| if (source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_LL) | ||
| buf_size = MAX(ibs, obs) * 2; | ||
|
|
@@ -923,12 +927,13 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) | |
| #if CONFIG_ZEPHYR_DP_SCHEDULER | ||
| struct ring_buffer *ring_buffer = NULL; | ||
|
|
||
| if (sink->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP || | ||
| source->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) { | ||
| if (src_is_dp || sink_is_dp) { | ||
| struct processing_module *srcmod = comp_mod(source); | ||
| struct module_data *src_module_data = &srcmod->priv; | ||
| struct processing_module *dstmod = comp_mod(sink); | ||
| struct module_data *dst_module_data = &dstmod->priv; | ||
| bool is_shared = audio_buffer_is_shared(&buffer->audio_buffer); | ||
| uint32_t buf_id = buf_get_id(buffer); | ||
|
|
||
| /* | ||
| * Handle cases where the size of the ring buffer depends on the | ||
|
|
@@ -940,16 +945,54 @@ __cold int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) | |
| */ | ||
| ring_buffer = ring_buffer_create(dp, MAX(ibs, dst_module_data->mpd.in_buff_size), | ||
| MAX(obs, src_module_data->mpd.out_buff_size), | ||
| audio_buffer_is_shared(&buffer->audio_buffer), | ||
| buf_get_id(buffer)); | ||
| is_shared, buf_id); | ||
| if (!ring_buffer) { | ||
| buffer_free(buffer); | ||
| return IPC4_OUT_OF_MEMORY; | ||
| } | ||
|
|
||
| #if CONFIG_DP_TO_DP_BIND | ||
| /* refcount the DP vregion for this ring_buffer (matches vregion_put in | ||
| * ring_buffer_free for DP-to-DP binding) | ||
| */ | ||
| if (ring_buffer->audio_buffer.alloc) | ||
| vregion_get(ring_buffer->audio_buffer.alloc->vreg); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This I don't fully get. Why do we need an additional vregion_get/put on the ringbuffer that we already allocated in the normal single DP case. This seems correct, but I'm puzzled why this ref is not taken in ring_buffer_create(). @lyakh any thoughts? |
||
| #endif | ||
|
|
||
| /* data destination module needs to use ring_buffer */ | ||
| audio_buffer_attach_secondary_buffer(&buffer->audio_buffer, dp == source, | ||
| &ring_buffer->audio_buffer); | ||
|
|
||
| #if CONFIG_DP_TO_DP_BIND | ||
| /* | ||
| * DP-to-DP binding: both source and sink are DP modules. | ||
| * A second ring_buffer is needed on the other side of the comp_buffer | ||
| * so each DP module has its own lock-free ring_buffer interface. | ||
| * Data flows: src_DP -> ring_buf_src -> comp_buffer -> ring_buf_sink -> sink_DP | ||
| * The comp_buffer acts as the intermediary synced during LL cycles. | ||
| */ | ||
| if (dp_to_dp) { | ||
| struct ring_buffer *ring_buffer2; | ||
|
|
||
| ring_buffer2 = | ||
| ring_buffer_create(source, | ||
| MAX(ibs, dst_module_data->mpd.in_buff_size), | ||
| MAX(obs, src_module_data->mpd.out_buff_size), | ||
| is_shared, buf_id); | ||
| if (!ring_buffer2) { | ||
| buffer_free(buffer); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about the first ring_buffer we allocated (and the vregion ref), should we free those here? |
||
| return IPC4_OUT_OF_MEMORY; | ||
| } | ||
|
|
||
| /* refcount the source DP vregion for ring_buffer2 */ | ||
| if (ring_buffer2->audio_buffer.alloc) | ||
| vregion_get(ring_buffer2->audio_buffer.alloc->vreg); | ||
|
|
||
| /* attach second ring_buffer on the source side */ | ||
| audio_buffer_attach_secondary_buffer(&buffer->audio_buffer, dp != source, | ||
| &ring_buffer2->audio_buffer); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| #endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style note, "#ifdef CONFIG_DP_TO_DP_BIND" is the usual convention. @lyakh agrees, but Linux kernel and statistics of use in SOF are on my side with this.