@@ -78,6 +78,9 @@ static const struct sof_ipc4_fw_status {
7878 {165 , "Reserved (ADSP_IPC_PIPELINE_ALREADY_EXISTS removed)" },
7979};
8080
81+ typedef void (* ipc4_notification_handler )(struct snd_sof_dev * sdev ,
82+ struct sof_ipc4_msg * msg );
83+
8184static int sof_ipc4_check_reply_status (struct snd_sof_dev * sdev , u32 status )
8285{
8386 int i , ret ;
@@ -610,9 +613,55 @@ static int ipc4_fw_ready(struct snd_sof_dev *sdev, struct sof_ipc4_msg *ipc4_msg
610613 return sof_ipc4_init_msg_memory (sdev );
611614}
612615
616+ static void sof_ipc4_module_notification_handler (struct snd_sof_dev * sdev ,
617+ struct sof_ipc4_msg * ipc4_msg )
618+ {
619+ struct sof_ipc4_notify_module_data * data = ipc4_msg -> data_ptr ;
620+
621+ /*
622+ * If the notification includes additional, module specific data, then
623+ * we need to re-allocate the buffer and re-read the whole payload,
624+ * including the event_data
625+ */
626+ if (data -> event_data_size ) {
627+ void * new ;
628+ int ret ;
629+
630+ ipc4_msg -> data_size += data -> event_data_size ;
631+
632+ new = krealloc (ipc4_msg -> data_ptr , ipc4_msg -> data_size , GFP_KERNEL );
633+ if (!new ) {
634+ ipc4_msg -> data_size -= data -> event_data_size ;
635+ return ;
636+ }
637+
638+ /* re-read the whole payload */
639+ ipc4_msg -> data_ptr = new ;
640+ ret = snd_sof_ipc_msg_data (sdev , NULL , ipc4_msg -> data_ptr ,
641+ ipc4_msg -> data_size );
642+ if (ret < 0 ) {
643+ dev_err (sdev -> dev ,
644+ "Failed to read the full module notification: %d\n" ,
645+ ret );
646+ return ;
647+ }
648+ data = ipc4_msg -> data_ptr ;
649+ }
650+
651+ /* Handle ALSA kcontrol notification */
652+ if ((data -> event_id & SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_MASK ) ==
653+ SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL ) {
654+ const struct sof_ipc_tplg_ops * tplg_ops = sdev -> ipc -> ops -> tplg ;
655+
656+ if (tplg_ops -> control -> update )
657+ tplg_ops -> control -> update (sdev , ipc4_msg );
658+ }
659+ }
660+
613661static void sof_ipc4_rx_msg (struct snd_sof_dev * sdev )
614662{
615663 struct sof_ipc4_msg * ipc4_msg = sdev -> ipc -> msg .rx_data ;
664+ ipc4_notification_handler handler_func = NULL ;
616665 size_t data_size = 0 ;
617666 int err ;
618667
@@ -648,6 +697,10 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev)
648697 case SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT :
649698 snd_sof_dsp_panic (sdev , 0 , true);
650699 break ;
700+ case SOF_IPC4_NOTIFY_MODULE_NOTIFICATION :
701+ data_size = sizeof (struct sof_ipc4_notify_module_data );
702+ handler_func = sof_ipc4_module_notification_handler ;
703+ break ;
651704 default :
652705 dev_dbg (sdev -> dev , "Unhandled DSP message: %#x|%#x\n" ,
653706 ipc4_msg -> primary , ipc4_msg -> extension );
@@ -663,6 +716,10 @@ static void sof_ipc4_rx_msg(struct snd_sof_dev *sdev)
663716 snd_sof_ipc_msg_data (sdev , NULL , ipc4_msg -> data_ptr , ipc4_msg -> data_size );
664717 }
665718
719+ /* Handle notifications with payload */
720+ if (handler_func )
721+ handler_func (sdev , ipc4_msg );
722+
666723 sof_ipc4_log_header (sdev -> dev , "ipc rx done " , ipc4_msg , true);
667724
668725 if (data_size ) {
0 commit comments