@@ -649,6 +649,10 @@ sof_ipc4_volsw_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
649649 return sof_ipc4_set_volume_data (sdev , swidget , scontrol , false);
650650}
651651
652+
653+ static void snd_ipc4_handle_global_event (struct snd_sof_dev * sdev ,
654+ struct sof_ipc4_control_msg_payload * msg_data );
655+
652656#define PARAM_ID_FROM_EXTENSION (_ext ) (((_ext) & SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK) \
653657 >> SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT)
654658
@@ -673,6 +677,7 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
673677 ndata -> event_data_size );
674678 return ;
675679 }
680+ msg_data = (struct sof_ipc4_control_msg_payload * )ndata -> event_data ;
676681
677682 event_param_id = ndata -> event_id & SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK ;
678683 switch (event_param_id ) {
@@ -690,6 +695,14 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
690695 return ;
691696 }
692697
698+ if (ndata -> module_id == SOF_IPC4_MOD_INIT_BASEFW_MOD_ID &&
699+ ndata -> instance_id == SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID ) {
700+ dev_info (sdev -> dev , "Received global notifier event_id %#x" ,
701+ event_param_id );
702+ snd_ipc4_handle_global_event (sdev , msg_data );
703+ return ;
704+ }
705+
693706 /* Find the swidget based on ndata->module_id and ndata->instance_id */
694707 swidget = sof_ipc4_find_swidget_by_ids (sdev , ndata -> module_id ,
695708 ndata -> instance_id );
@@ -700,7 +713,6 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
700713 }
701714
702715 /* Find the scontrol which is the source of the notification */
703- msg_data = (struct sof_ipc4_control_msg_payload * )ndata -> event_data ;
704716 list_for_each_entry (scontrol , & sdev -> kcontrol_list , list ) {
705717 if (scontrol -> comp_id == swidget -> comp_id ) {
706718 u32 local_param_id ;
@@ -840,6 +852,130 @@ sof_ipc4_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_I
840852 return 0 ;
841853}
842854
855+ struct sof_ipc4_kcontrol_global_priv {
856+ struct snd_card * snd_card ;
857+ struct snd_kcontrol * capture_hw_mute ;
858+ };
859+
860+ static int sof_ipc4_capture_hw_mute_get (struct snd_kcontrol * kcontrol ,
861+ struct snd_ctl_elem_value * ucontrol )
862+ {
863+ ucontrol -> value .integer .value [0 ] = kcontrol -> private_value ;
864+ return 0 ;
865+ }
866+
867+ static const struct snd_kcontrol_new sof_ipc4_capture_hw_mute = {
868+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER ,
869+ .access = SNDRV_CTL_ELEM_ACCESS_READ ,
870+ .name = "Global capture HW mute indicator" ,
871+ .info = snd_ctl_boolean_mono_info ,
872+ .get = sof_ipc4_capture_hw_mute_get ,
873+ };
874+
875+ static struct snd_card * sof_scomp_get_card (struct snd_soc_component * scomp )
876+ {
877+ struct device * dev = scomp -> dev ;
878+
879+ if (!scomp -> card ) {
880+ dev_err (dev , "%s: No snd_soc_card" , __func__ );
881+ return NULL ;
882+ }
883+
884+ return scomp -> card -> snd_card ;
885+ }
886+
887+ static int sof_ipc4_create_non_topology_controls (struct snd_sof_dev * sdev ,
888+ struct snd_soc_component * scomp )
889+ {
890+ struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
891+ struct snd_card * snd_card = sof_scomp_get_card (scomp );
892+ struct device * dev = sdev -> dev ;
893+ struct sof_ipc4_kcontrol_global_priv * priv ;
894+ int ret ;
895+
896+ if (!snd_card ) {
897+ dev_err (dev , "%s: Card not found!" , __func__ );
898+ return - ENODEV ;
899+ }
900+
901+ if (!ipc4_data -> global_kcontrol_mask )
902+ return 0 ;
903+
904+ priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
905+ if (!priv )
906+ return - ENOMEM ;
907+
908+ priv -> snd_card = snd_card ;
909+
910+ if (ipc4_data -> global_kcontrol_mask &
911+ BIT (SOF_IPC4_KCONTROL_GLOBAL_CAPTURE_HW_MUTE )) {
912+ struct snd_kcontrol * kctl ;
913+
914+ kctl = snd_ctl_new1 (& sof_ipc4_capture_hw_mute , NULL );
915+ if (!kctl ) {
916+ dev_err (dev , "%s: snd_ctl_new1(): failed" , __func__ );
917+ return - EINVAL ;
918+ }
919+
920+ kctl -> private_value = 0 ;
921+
922+ ret = snd_ctl_add (snd_card , kctl );
923+ if (ret < 0 )
924+ dev_err (dev , "%s: snd_ctl_add(): failed" , __func__ );
925+ else
926+ priv -> capture_hw_mute = kctl ;
927+ }
928+
929+ ipc4_data -> global_kcontrol_priv = priv ;
930+
931+ return 0 ;
932+ }
933+
934+ static void snd_ipc4_global_capture_hw_mute_report (struct snd_sof_dev * sdev ,
935+ bool status )
936+ {
937+ struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
938+ struct sof_ipc4_kcontrol_global_priv * priv = ipc4_data -> global_kcontrol_priv ;
939+ struct device * dev = sdev -> dev ;
940+ struct snd_kcontrol * kctl ;
941+
942+ if (!priv || !priv -> capture_hw_mute )
943+ return ;
944+
945+ kctl = priv -> capture_hw_mute ;
946+
947+ dev_dbg (dev , "%s: reporting %u, old %lu" , __func__ ,
948+ status , kctl -> private_value );
949+
950+ if (kctl -> private_value == status )
951+ return ;
952+
953+ kctl -> private_value = status ;
954+ snd_ctl_notify (priv -> snd_card , SNDRV_CTL_EVENT_MASK_VALUE , & kctl -> id );
955+ }
956+
957+ static void snd_ipc4_handle_global_event (struct snd_sof_dev * sdev ,
958+ struct sof_ipc4_control_msg_payload * msg_data )
959+ {
960+ struct device * dev = sdev -> dev ;
961+
962+ dev_dbg (dev , "%s: got msg id %u num_elems %u" , __func__ ,
963+ msg_data -> id , msg_data -> num_elems );
964+
965+ switch (msg_data -> id ) {
966+ case SOF_IPC4_KCONTROL_GLOBAL_CAPTURE_HW_MUTE :
967+ if (msg_data -> num_elems == 1 || msg_data -> chanv [0 ].channel == 0 )
968+ snd_ipc4_global_capture_hw_mute_report (sdev , msg_data -> chanv [0 ].value );
969+ else
970+ dev_warn (dev , "%s: bad data for id %u chan 0 %u" , __func__ ,
971+ msg_data -> id , msg_data -> chanv [0 ].channel );
972+ break ;
973+ default :
974+ dev_warn (dev , "%s: unknown global control elem id %u" , __func__ ,
975+ msg_data -> id );
976+ }
977+ }
978+
843979const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = {
844980 .volume_put = sof_ipc4_volume_put ,
845981 .volume_get = sof_ipc4_volume_get ,
@@ -855,4 +991,5 @@ const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops = {
855991 .update = sof_ipc4_control_update ,
856992 .widget_kcontrol_setup = sof_ipc4_widget_kcontrol_setup ,
857993 .set_up_volume_table = sof_ipc4_set_up_volume_table ,
994+ .create_non_topology_controls = sof_ipc4_create_non_topology_controls ,
858995};
0 commit comments