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.
Unified · Split
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #define SKL_CONTROL_TYPE_BYTE_TLV 0x100 |
| 20 | 20 | #define SKL_CONTROL_TYPE_MIC_SELECT 0x102 |
| 21 | 21 | #define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103 |
| 22 | +#define SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC 0x104 | |
| 22 | 23 | |
| 23 | 24 | #define HDA_SST_CFG_MAX 900 /* size of copier cfg*/ |
| 24 | 25 | #define MAX_IN_QUEUE 8 |
| @@ -1405,6 +1405,18 @@ static int skl_tplg_multi_config_set(struct snd_kcontrol *kcontrol, · 1404 unmodified lines | ||
| 1405 | 1405 | return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); |
| 1406 | 1406 | } |
| 1407 | 1407 | |
| 1408 | +static int skl_tplg_multi_config_get_dmic(struct snd_kcontrol *kcontrol, | |
| 1409 | + struct snd_ctl_elem_value *ucontrol) | |
| 1410 | +{ | |
| 1411 | + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, false); | |
| 1412 | +} | |
| 1413 | + | |
| 1414 | +static int skl_tplg_multi_config_set_dmic(struct snd_kcontrol *kcontrol, | |
| 1415 | + struct snd_ctl_elem_value *ucontrol) | |
| 1416 | +{ | |
| 1417 | + return skl_tplg_multi_config_set_get(kcontrol, ucontrol, true); | |
| 1418 | +} | |
| 1419 | + | |
| 1408 | 1420 | static int skl_tplg_tlv_control_get(struct snd_kcontrol *kcontrol, |
| 1409 | 1421 | unsigned int __user *data, unsigned int size) |
| 1410 | 1422 | { |
| @@ -1949,6 +1961,11 @@ static const struct snd_soc_tplg_kcontrol_ops skl_tplg_kcontrol_ops[] = { · 538 unmodified lines | ||
| 1949 | 1961 | .get = skl_tplg_multi_config_get, |
| 1950 | 1962 | .put = skl_tplg_multi_config_set, |
| 1951 | 1963 | }, |
| 1964 | + { | |
| 1965 | + .id = SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC, | |
| 1966 | + .get = skl_tplg_multi_config_get_dmic, | |
| 1967 | + .put = skl_tplg_multi_config_set_dmic, | |
| 1968 | + } | |
| 1952 | 1969 | }; |
| 1953 | 1970 | |
| 1954 | 1971 | 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, · 1154 unmodified lines | ||
| 3109 | 3126 | case SND_SOC_TPLG_CTL_ENUM: |
| 3110 | 3127 | tplg_ec = container_of(hdr, |
| 3111 | 3128 | struct snd_soc_tplg_enum_control, hdr); |
| 3112 | − if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READWRITE) { | |
| 3129 | + if (kctl->access & SNDRV_CTL_ELEM_ACCESS_READ) { | |
| 3113 | 3130 | se = (struct soc_enum *)kctl->private_value; |
| 3114 | 3131 | if (tplg_ec->priv.size) |
| 3115 | − return skl_init_enum_data(bus->dev, se, | |
| 3116 | − tplg_ec); | |
| 3132 | + skl_init_enum_data(bus->dev, se, tplg_ec); | |
| 3117 | 3133 | } |
| 3134 | + | |
| 3135 | + /* | |
| 3136 | + * now that the control initializations are done, remove | |
| 3137 | + * write permission for the DMIC configuration enums to | |
| 3138 | + * avoid conflicts between NHLT settings and user interaction | |
| 3139 | + */ | |
| 3140 | + | |
| 3141 | + if (hdr->ops.get == SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC) | |
| 3142 | + kctl->access = SNDRV_CTL_ELEM_ACCESS_READ; | |
| 3143 | + | |
| 3118 | 3144 | break; |
| 3119 | 3145 | |
| 3120 | 3146 | default: |
| @@ -3584,6 +3610,37 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, · 463 unmodified lines | ||
| 3584 | 3610 | return 0; |
| 3585 | 3611 | } |
| 3586 | 3612 | |
| 3613 | +static void skl_tplg_complete(struct snd_soc_component *component) | |
| 3614 | +{ | |
| 3615 | + struct snd_soc_dobj *dobj; | |
| 3616 | + struct snd_soc_acpi_mach *mach = | |
| 3617 | + dev_get_platdata(component->card->dev); | |
| 3618 | + int i; | |
| 3619 | + | |
| 3620 | + list_for_each_entry(dobj, &component->dobj_list, list) { | |
| 3621 | + struct snd_kcontrol *kcontrol = dobj->control.kcontrol; | |
| 3622 | + struct soc_enum *se = | |
| 3623 | + (struct soc_enum *)kcontrol->private_value; | |
| 3624 | + char **texts = dobj->control.dtexts; | |
| 3625 | + char chan_text[4]; | |
| 3626 | + | |
| 3627 | + if (dobj->type != SND_SOC_DOBJ_ENUM || | |
| 3628 | + dobj->control.kcontrol->put != | |
| 3629 | + skl_tplg_multi_config_set_dmic) | |
| 3630 | + continue; | |
| 3631 | + sprintf(chan_text, "c%d", mach->mach_params.dmic_num); | |
| 3632 | + | |
| 3633 | + for (i = 0; i < se->items; i++) { | |
| 3634 | + struct snd_ctl_elem_value val; | |
| 3635 | + | |
| 3636 | + if (strstr(texts[i], chan_text)) { | |
| 3637 | + val.value.enumerated.item[0] = i; | |
| 3638 | + kcontrol->put(kcontrol, &val); | |
| 3639 | + } | |
| 3640 | + } | |
| 3641 | + } | |
| 3642 | +} | |
| 3643 | + | |
| 3587 | 3644 | static struct snd_soc_tplg_ops skl_tplg_ops = { |
| 3588 | 3645 | .widget_load = skl_tplg_widget_load, |
| 3589 | 3646 | .control_load = skl_tplg_control_load, |
| @@ -3593,6 +3650,7 @@ static struct snd_soc_tplg_ops skl_tplg_ops = { · 3 unmodified lines | ||
| 3593 | 3650 | .io_ops_count = ARRAY_SIZE(skl_tplg_kcontrol_ops), |
| 3594 | 3651 | .manifest = skl_manifest_load, |
| 3595 | 3652 | .dai_load = skl_dai_load, |
| 3653 | + .complete = skl_tplg_complete, | |
| 3596 | 3654 | }; |
| 3597 | 3655 | |
| 3598 | 3656 | /* |