@@ -208,6 +208,105 @@ __cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_i
208208 return dev ;
209209}
210210
211+ #ifdef CONFIG_SOF_USERSPACE_LL
212+ /**
213+ * comp_new_ipc4_user - Create component in user-space IPC thread context.
214+ *
215+ * Called from the user-space IPC thread. Receives a pre-resolved driver
216+ * pointer from the kernel handler. Performs IPC4 message parsing, HOSTBOX
217+ * data read, and calls drv->ops.create() in user-space context.
218+ *
219+ * @param ipc4 IPC4 message request (reconstructed from ipc_user pri/ext words)
220+ * @param drv Component driver resolved by kernel via ipc4_get_comp_drv()
221+ * @return Created component device, or NULL on failure
222+ */
223+ __cold struct comp_dev * comp_new_ipc4_user (struct ipc4_message_request * ipc4 ,
224+ const struct comp_driver * drv )
225+ {
226+ struct ipc4_module_init_instance module_init ;
227+ struct comp_ipc_config ipc_config ;
228+ struct comp_dev * dev ;
229+ uint32_t comp_id ;
230+ char * data ;
231+ int ret ;
232+
233+ assert_can_be_cold ();
234+
235+ ret = memcpy_s (& module_init , sizeof (module_init ), ipc4 , sizeof (* ipc4 ));
236+ if (ret < 0 )
237+ return NULL ;
238+
239+ comp_id = IPC4_COMP_ID (module_init .primary .r .module_id ,
240+ module_init .primary .r .instance_id );
241+
242+ if (ipc4_get_comp_dev (comp_id )) {
243+ tr_err (& ipc_tr , "comp 0x%x exists" , comp_id );
244+ return NULL ;
245+ }
246+
247+ if (module_init .extension .r .core_id >= CONFIG_CORE_COUNT ) {
248+ tr_err (& ipc_tr , "ipc: comp->core = %u" ,
249+ (uint32_t )module_init .extension .r .core_id );
250+ return NULL ;
251+ }
252+
253+ memset (& ipc_config , 0 , sizeof (ipc_config ));
254+ ipc_config .id = comp_id ;
255+ ipc_config .pipeline_id = module_init .extension .r .ppl_instance_id ;
256+ ipc_config .core = module_init .extension .r .core_id ;
257+ ipc_config .ipc_config_size =
258+ module_init .extension .r .param_block_size * sizeof (uint32_t );
259+ ipc_config .ipc_extended_init = module_init .extension .r .extended_init ;
260+ if (ipc_config .ipc_config_size > MAILBOX_HOSTBOX_SIZE ) {
261+ tr_err (& ipc_tr ,
262+ "IPC payload size %u too big for the message window" ,
263+ ipc_config .ipc_config_size );
264+ return NULL ;
265+ }
266+ #ifdef CONFIG_DCACHE_LINE_SIZE
267+ if (!IS_ENABLED (CONFIG_LIBRARY ))
268+ sys_cache_data_invd_range (
269+ (__sparse_force void __sparse_cache * )MAILBOX_HOSTBOX_BASE ,
270+ ALIGN_UP (ipc_config .ipc_config_size ,
271+ CONFIG_DCACHE_LINE_SIZE ));
272+ #endif
273+ data = ipc4_get_comp_new_data ();
274+
275+ #if CONFIG_ZEPHYR_DP_SCHEDULER
276+ if (module_init .extension .r .proc_domain )
277+ ipc_config .proc_domain = COMP_PROCESSING_DOMAIN_DP ;
278+ else
279+ ipc_config .proc_domain = COMP_PROCESSING_DOMAIN_LL ;
280+ #else
281+ if (module_init .extension .r .proc_domain ) {
282+ tr_err (& ipc_tr ,
283+ "ipc: DP scheduling is disabled, cannot create comp 0x%x" ,
284+ comp_id );
285+ return NULL ;
286+ }
287+ ipc_config .proc_domain = COMP_PROCESSING_DOMAIN_LL ;
288+ #endif
289+
290+ if (drv -> type == SOF_COMP_MODULE_ADAPTER ) {
291+ const struct ipc_config_process spec = {
292+ .data = (const unsigned char * )data ,
293+ .size = ipc_config .ipc_config_size ,
294+ };
295+
296+ dev = drv -> ops .create (drv , & ipc_config , (const void * )& spec );
297+ } else {
298+ dev = drv -> ops .create (drv , & ipc_config , (const void * )data );
299+ }
300+ if (!dev )
301+ return NULL ;
302+
303+ list_init (& dev -> bsource_list );
304+ list_init (& dev -> bsink_list );
305+
306+ return dev ;
307+ }
308+ #endif /* CONFIG_SOF_USERSPACE_LL */
309+
211310/* Called from ipc4_set_pipeline_state(), so cannot be cold */
212311struct ipc_comp_dev * ipc_get_comp_by_ppl_id (struct ipc * ipc , uint16_t type ,
213312 uint32_t ppl_id ,
0 commit comments