summaryrefslogtreecommitdiff
path: root/sound/soc/intel
diff options
context:
space:
mode:
authorMateusz Gorski <mateusz.gorski@linux.intel.com>2020-11-29 12:41:48 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-12-02 08:49:57 +0100
commitcd734398737641a6dc13f09a4d9357174c879df6 (patch)
tree41ef557a9e2d80f45f2609ce344593c602320fb5 /sound/soc/intel
parent6ebb6af62721767a437a4ac76736682631157985 (diff)
ASoC: Intel: Skylake: Automatic DMIC format configuration according to information from NHLT
commit 2d744ecf2b98405723a2138a547e5c75009bc4e5 upstream. Automatically choose DMIC pipeline format configuration depending on information included in NHLT. Change the access rights of appropriate kcontrols to read-only in order to prevent user interference. Signed-off-by: Mateusz Gorski <mateusz.gorski@linux.intel.com> Reviewed-by: Cezary Rojewski <cezary.rojewski@intel.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20200427132727.24942-4-mateusz.gorski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org> Cc: <stable@vger.kernel.org> # 5.4.x Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/soc/intel')
-rw-r--r--sound/soc/intel/skylake/skl-topology.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index c9cd6d60d57b..aa5833001fde 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -1405,6 +1405,18 @@ static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol,
return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
}
+static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false);
+}
+
+static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true);
+}
+
static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol,
unsigned int __user *data, unsigned int size)
{
@@ -1949,6 +1961,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = {
.get = skl_tplg_multi_config_get,
.put = skl_tplg_multi_config_set,
},
+ {
+ .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC,
+ .get = skl_tplg_multi_config_get_dmic,
+ .put = skl_tplg_multi_config_set_dmic,
+ }
};
static int skl_tplg_fill_pipe_cfg(struct device *dev,
@@ -3109,12 +3126,21 @@ static int skl_tplg_control_load(struct snd_soc_component *cmpnt,
case SND_SOC_TPLG_CTL_ENUM:
tplg_ec = container_of(hdr,
struct snd_soc_tplg_enum_control, hdr);
- if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) {
+ if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) {
se = (struct soc_enum *)kctl->private_value;
if (tplg_ec->priv.size)
- return skl_init_enum_data(bus->dev, se,
- tplg_ec);
+ skl_init_enum_data(bus->dev, se, tplg_ec);
}
+
+ /*
+ * now that the control initializations are done, remove
+ * write permission for the DMIC configuration enums to
+ * avoid conflicts between NHLT settings and user interaction
+ */
+
+ if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC)
+ kctl->access = SNDRV_CTL_ELEM_ACCESS_READ;
+
break;
default:
@@ -3584,6 +3610,37 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index,
return 0;
}
+static void skl_tplg_complete(struct snd_soc_component *component)
+{
+ struct snd_soc_dobj *dobj;
+ struct snd_soc_acpi_mach *mach =
+ dev_get_platdata(component->card->dev);
+ int i;
+
+ list_for_each_entry(dobj, &component->dobj_list, list) {
+ struct snd_kcontrol *kcontrol = dobj->control.kcontrol;
+ struct soc_enum *se =
+ (struct soc_enum *)kcontrol->private_value;
+ char **texts = dobj->control.dtexts;
+ char chan_text[4];
+
+ if (dobj->type != SND_SOC_DOBJ_ENUM ||
+ dobj->control.kcontrol->put !=
+ skl_tplg_multi_config_set_dmic)
+ continue;
+ sprintf(chan_text, "c%d", mach->mach_params.dmic_num);
+
+ for (i = 0; i < se->items; i++) {
+ struct snd_ctl_elem_value val;
+
+ if (strstr(texts[i], chan_text)) {
+ val.value.enumerated.item[0] = i;
+ kcontrol->put(kcontrol, &val);
+ }
+ }
+ }
+}
+
static struct snd_soc_tplg_ops skl_tplg_ops = {
.widget_load = skl_tplg_widget_load,
.control_load = skl_tplg_control_load,
@@ -3593,6 +3650,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = {
.io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops),
.manifest = skl_manifest_load,
.dai_load = skl_dai_load,
+ .complete = skl_tplg_complete,
};
/*