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