@@ -2851,13 +2851,84 @@ static int sof_ipc4_control_setup(struct snd_sof_dev *sdev, struct snd_sof_contr
28512851 return 0 ;
28522852}
28532853
2854+ static int sof_ipc4_widget_setup_msg_payload (struct snd_sof_dev * sdev ,
2855+ struct snd_sof_widget * swidget ,
2856+ struct sof_ipc4_msg * msg ,
2857+ void * ipc_data , u32 ipc_size ,
2858+ void * * new_data , u32 * new_size )
2859+ {
2860+ struct sof_ipc4_mod_init_ext_dp_memory_data * dp_mem_data ;
2861+ struct sof_ipc4_module_init_ext_init * ext_init ;
2862+ struct sof_ipc4_module_init_ext_object * hdr ;
2863+ u32 * payload ;
2864+ u32 ext_pos ;
2865+
2866+ /* For the moment the only reason for adding init_ext_init payload is DP
2867+ * memory data. If both stack and heap size are 0 (= use default), then
2868+ * there is no need for init_ext_init payload.
2869+ */
2870+ if (swidget -> comp_domain != SOF_COMP_DOMAIN_DP ) {
2871+ msg -> extension &= ~SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK ;
2872+ return 0 ;
2873+ }
2874+
2875+ payload = kzalloc (sdev -> ipc -> max_payload_size , GFP_KERNEL );
2876+ if (!payload )
2877+ return - ENOMEM ;
2878+
2879+ /* Add ext_init first and set objects array flag to 1 */
2880+ ext_init = (struct sof_ipc4_module_init_ext_init * ) payload ;
2881+ ext_init -> word0 |= SOF_IPC4_MOD_INIT_EXT_OBJ_ARRAY_MASK ;
2882+ ext_pos = DIV_ROUND_UP (sizeof (* ext_init ), sizeof (u32 ));
2883+
2884+ /* Add object array objects after ext_init */
2885+
2886+ /* Add dp_memory_data if comp_domain indicates DP */
2887+ if (swidget -> comp_domain == SOF_COMP_DOMAIN_DP ) {
2888+ hdr = (struct sof_ipc4_module_init_ext_object * ) & payload [ext_pos ];
2889+ hdr -> header = SOF_IPC4_MOD_INIT_EXT_OBJ_LAST_MASK |
2890+ SOF_IPC4_MOD_INIT_EXT_OBJ_ID (SOF_IPC4_MOD_INIT_DATA_ID_DP_DATA ) |
2891+ SOF_IPC4_MOD_INIT_EXT_OBJ_WORDS (DIV_ROUND_UP (sizeof (* dp_mem_data ),
2892+ sizeof (u32 )));
2893+ ext_pos += DIV_ROUND_UP (sizeof (* hdr ), sizeof (u32 ));
2894+ dp_mem_data = (struct sof_ipc4_mod_init_ext_dp_memory_data * ) & payload [ext_pos ];
2895+ dp_mem_data -> domain_id = swidget -> dp_domain_id ;
2896+ dp_mem_data -> stack_bytes = swidget -> dp_stack_bytes ;
2897+ dp_mem_data -> heap_bytes = swidget -> dp_heap_bytes ;
2898+ ext_pos += DIV_ROUND_UP (sizeof (* dp_mem_data ), sizeof (u32 ));
2899+ }
2900+
2901+ /* If another array object is added, remember clear previous OBJ_LAST bit */
2902+
2903+ /* Calculate final size and check that it fits to max payload size */
2904+ * new_size = ext_pos * sizeof (u32 ) + ipc_size ;
2905+ if (* new_size > sdev -> ipc -> max_payload_size ) {
2906+ dev_err (sdev -> dev , "Max ipc payload size %lu exceeded: %u" ,
2907+ sdev -> ipc -> max_payload_size , * new_size );
2908+ kfree (payload );
2909+ return - EINVAL ;
2910+ }
2911+ * new_data = payload ;
2912+
2913+ /* Copy module specific ipc_payload to end */
2914+ memcpy (& payload [ext_pos ], ipc_data , ipc_size );
2915+
2916+ /* Update msg extension bits accoring to the payload changes */
2917+ msg -> extension |= SOF_IPC4_MOD_EXT_EXTENDED_INIT_MASK ;
2918+ msg -> extension &= ~SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK ;
2919+ msg -> extension |= SOF_IPC4_MOD_EXT_PARAM_SIZE (DIV_ROUND_UP (* new_size , sizeof (u32 )));
2920+
2921+ return 1 ;
2922+ }
2923+
28542924static int sof_ipc4_widget_setup (struct snd_sof_dev * sdev , struct snd_sof_widget * swidget )
28552925{
28562926 struct snd_sof_widget * pipe_widget = swidget -> spipe -> pipe_widget ;
28572927 struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
28582928 struct sof_ipc4_pipeline * pipeline ;
28592929 struct sof_ipc4_msg * msg ;
28602930 void * ipc_data = NULL ;
2931+ void * ext_data = NULL ;
28612932 u32 ipc_size = 0 ;
28622933 int ret ;
28632934
@@ -2982,6 +3053,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
29823053
29833054 if (swidget -> id != snd_soc_dapm_scheduler ) {
29843055 int module_id = msg -> primary & SOF_IPC4_MOD_ID_MASK ;
3056+ u32 new_size = 0 ;
29853057
29863058 ret = sof_ipc4_widget_assign_instance_id (sdev , swidget );
29873059 if (ret < 0 ) {
@@ -3002,6 +3074,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30023074 dev_dbg (sdev -> dev , "Create widget %s (pipe %d) - ID %d, instance %d, core %d\n" ,
30033075 swidget -> widget -> name , swidget -> pipeline_id , module_id ,
30043076 swidget -> instance_id , swidget -> core );
3077+
3078+ ret = sof_ipc4_widget_setup_msg_payload (sdev , swidget , msg , ipc_data , ipc_size ,
3079+ & ext_data , & new_size );
3080+ if (ret < 0 )
3081+ goto fail ;
3082+
3083+ if (ret > 0 ) {
3084+ ipc_size = new_size ;
3085+ ipc_data = ext_data ;
3086+ }
30053087 } else {
30063088 dev_dbg (sdev -> dev , "Create pipeline %s (pipe %d) - instance %d, core %d\n" ,
30073089 swidget -> widget -> name , swidget -> pipeline_id ,
@@ -3012,6 +3094,8 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30123094 msg -> data_ptr = ipc_data ;
30133095
30143096 ret = sof_ipc_tx_message_no_reply (sdev -> ipc , msg , ipc_size );
3097+
3098+ fail :
30153099 if (ret < 0 ) {
30163100 dev_err (sdev -> dev , "failed to create module %s\n" , swidget -> widget -> name );
30173101
@@ -3024,6 +3108,7 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
30243108 }
30253109 }
30263110
3111+ kfree (ext_data );
30273112 return ret ;
30283113}
30293114
0 commit comments