Skip to content

Commit 528ca61

Browse files
author
Jyri Sarha
committed
ASoC: sof: ipc4-control: Global mixers and capture hw mute indicator
Implement global kcontrol concept and add capture hw mute indicator implementation in it. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent 137ee12 commit 528ca61

5 files changed

Lines changed: 154 additions & 3 deletions

File tree

sound/soc/sof/ipc4-control.c

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
843979
const 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
};

sound/soc/sof/ipc4-loader.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev)
411411
case SOF_IPC4_FW_CONTEXT_SAVE:
412412
ipc4_data->fw_context_save = *tuple->value;
413413
break;
414+
case SOF_IPC4_FW_GLOBAL_KCONTROL_MASK:
415+
ipc4_data->global_kcontrol_mask = *tuple->value;
416+
break;
414417
default:
415418
break;
416419
}

sound/soc/sof/ipc4-priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ struct sof_ipc4_fw_data {
8686
int max_num_pipelines;
8787
u32 max_libs_count;
8888
bool fw_context_save;
89+
u32 global_kcontrol_mask;
90+
void *global_kcontrol_priv;
8991

9092
int (*load_library)(struct snd_sof_dev *sdev,
9193
struct sof_ipc4_fw_library *fw_lib, bool reload);

sound/soc/sof/sof-audio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ struct sof_ipc_tplg_control_ops {
166166
/* mandatory callback to set up volume table for volume kcontrols */
167167
int (*set_up_volume_table)(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS],
168168
int size);
169+
int (*create_non_topology_controls)(struct snd_sof_dev *sdev,
170+
struct snd_soc_component *scomp);
169171
};
170172

171173
/**

sound/soc/sof/topology.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,8 +2251,15 @@ static int sof_complete(struct snd_soc_component *scomp)
22512251
}
22522252

22532253
/* set up static pipelines */
2254-
if (tplg_ops && tplg_ops->set_up_all_pipelines)
2255-
return tplg_ops->set_up_all_pipelines(sdev, false);
2254+
if (tplg_ops && tplg_ops->set_up_all_pipelines) {
2255+
ret = tplg_ops->set_up_all_pipelines(sdev, false);
2256+
if (ret < 0)
2257+
return ret;
2258+
}
2259+
2260+
/* set up non topology mixers */
2261+
if (tplg_ops && tplg_ops->control && tplg_ops->control->create_non_topology_controls)
2262+
return tplg_ops->control->create_non_topology_controls(sdev, scomp);
22562263

22572264
return 0;
22582265
}

0 commit comments

Comments
 (0)