@@ -2952,13 +2952,85 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
29522952 return 0 ;
29532953}
29542954
2955+ static int sof_ipc4_widget_setup_msg_payload (struct snd_sof_dev * sdev ,
2956+ struct snd_sof_widget * swidget ,
2957+ struct sof_ipc4_msg * msg ,
2958+ void * ipc_data , u32 ipc_size ,
2959+ void * * new_data )
2960+ {
2961+ struct sof_ipc4_mod_init_ext_dp_memory_data * dp_mem_data ;
2962+ struct sof_ipc4_module_init_ext_init * ext_init ;
2963+ struct sof_ipc4_module_init_ext_object * hdr ;
2964+ int new_size ;
2965+ u32 * payload ;
2966+ u32 ext_pos ;
2967+
2968+ /* For the moment the only reason for adding init_ext_init payload is DP
2969+ * memory data. If both stack and heap size are 0 (= use default), then
2970+ * there is no need for init_ext_init payload.
2971+ */
2972+ if (swidget -> comp_domain != SOF_COMP_DOMAIN_DP ) {
2973+ msg -> extension &= ~SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK ;
2974+ return 0 ;
2975+ }
2976+
2977+ payload = kzalloc (sdev -> ipc -> max_payload_size , GFP_KERNEL );
2978+ if (!payload )
2979+ return - ENOMEM ;
2980+
2981+ /* Add ext_init first and set objects array flag to 1 */
2982+ ext_init = (struct sof_ipc4_module_init_ext_init * )payload ;
2983+ ext_init -> word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK ;
2984+ ext_pos = DIV_ROUND_UP (sizeof (* ext_init ), sizeof (u32 ));
2985+
2986+ /* Add object array objects after ext_init */
2987+
2988+ /* Add dp_memory_data if comp_domain indicates DP */
2989+ if (swidget -> comp_domain == SOF_COMP_DOMAIN_DP ) {
2990+ hdr = (struct sof_ipc4_module_init_ext_object * )& payload [ext_pos ];
2991+ hdr -> header = SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK |
2992+ SOF_IPC4_MOD_INIT_EXT_OBJ_ID (SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA ) |
2993+ SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS (DIV_ROUND_UP (sizeof (* dp_mem_data ),
2994+ sizeof (u32 )));
2995+ ext_pos += DIV_ROUND_UP (sizeof (* hdr ), sizeof (u32 ));
2996+ dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data * )& payload [ext_pos ];
2997+ dp_mem_data -> domain_id = swidget -> dp_domain_id ;
2998+ dp_mem_data -> stack_bytes = swidget -> dp_stack_bytes ;
2999+ dp_mem_data -> heap_bytes = swidget -> dp_heap_bytes ;
3000+ ext_pos += DIV_ROUND_UP (sizeof (* dp_mem_data ), sizeof (u32 ));
3001+ }
3002+
3003+ /* If another array object is added, remember clear previous OBJ_LAST bit */
3004+
3005+ /* Calculate final size and check that it fits to max payload size */
3006+ new_size = ext_pos * sizeof (u32 ) + ipc_size ;
3007+ if (new_size > sdev -> ipc -> max_payload_size ) {
3008+ dev_err (sdev -> dev , "Max ipc payload size %lu exceeded: %u" ,
3009+ sdev -> ipc -> max_payload_size , new_size );
3010+ kfree (payload );
3011+ return - EINVAL ;
3012+ }
3013+ * new_data = payload ;
3014+
3015+ /* Copy module specific ipc_payload to end */
3016+ memcpy (& payload [ext_pos ], ipc_data , ipc_size );
3017+
3018+ /* Update msg extension bits according to the payload changes */
3019+ msg -> extension |= SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK ;
3020+ msg -> extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK ;
3021+ msg -> extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE (DIV_ROUND_UP (new_size , sizeof (u32 )));
3022+
3023+ return new_size ;
3024+ }
3025+
29553026static int sof_ipc4_widget_setup (struct snd_sof_dev * sdev , struct snd_sof_widget * swidget )
29563027{
29573028 struct snd_sof_widget * pipe_widget = swidget -> spipe -> pipe_widget ;
29583029 struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
29593030 struct sof_ipc4_pipeline * pipeline ;
29603031 struct sof_ipc4_msg * msg ;
29613032 void * ipc_data = NULL ;
3033+ void * ext_data = NULL ;
29623034 u32 ipc_size = 0 ;
29633035 int ret ;
29643036
@@ -3103,6 +3175,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
31033175 dev_dbg (sdev -> dev , "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n" ,
31043176 swidget -> widget -> name , swidget -> pipeline_id , module_id ,
31053177 swidget -> instance_id , swidget -> core );
3178+
3179+ ret = sof_ipc4_widget_setup_msg_payload (sdev , swidget , msg , ipc_data , ipc_size ,
3180+ & ext_data );
3181+ if (ret < 0 )
3182+ goto fail ;
3183+
3184+ if (ret > 0 ) {
3185+ ipc_size = ret ;
3186+ ipc_data = ext_data ;
3187+ }
31063188 } else {
31073189 dev_dbg (sdev -> dev , "Create pipeline %s (pipe %d) - instance %d, core %d\n" ,
31083190 swidget -> widget -> name , swidget -> pipeline_id ,
@@ -3113,6 +3195,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
31133195 msg -> data_ptr = ipc_data ;
31143196
31153197 ret = sof_ipc_tx_message_no_reply (sdev -> ipc , msg , ipc_size );
3198+
3199+ fail :
31163200 if (ret < 0 ) {
31173201 dev_err (sdev -> dev , "failed to create module %s\n" , swidget -> widget -> name );
31183202
@@ -3125,6 +3209,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
31253209 }
31263210 }
31273211
3212+ kfree (ext_data );
31283213 return ret ;
31293214}
31303215
0 commit comments