Merge tag 'sound-5.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[sfrench/cifs-2.6.git] / sound / pci / hda / hda_generic.c
index f5cba7afd1c662e2e5ced46397ef1924f26cb91b..3998e17718057e2db4027d40a218f15a6b251884 100644 (file)
@@ -981,6 +981,8 @@ add_control(struct hda_gen_spec *spec, int type, const char *name,
        knew->index = cidx;
        if (get_amp_nid_(val))
                knew->subdevice = HDA_SUBDEV_AMP_FLAG;
+       if (knew->access == 0)
+               knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
        knew->private_value = val;
        return knew;
 }
@@ -3618,8 +3620,11 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
                           amp_val_replace_channels(ctl, chs));
        if (!knew)
                return -ENOMEM;
-       if (is_switch)
+       if (is_switch) {
                knew->put = cap_single_sw_put;
+               if (spec->mic_mute_led)
+                       knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
+       }
        if (!inv_dmic)
                return 0;
 
@@ -3634,8 +3639,11 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
                           amp_val_replace_channels(ctl, 2));
        if (!knew)
                return -ENOMEM;
-       if (is_switch)
+       if (is_switch) {
                knew->put = cap_single_sw_put;
+               if (spec->mic_mute_led)
+                       knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
+       }
        return 0;
 }
 
@@ -3676,6 +3684,8 @@ static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
                knew->index = idx;
                knew->private_value = sw_ctl;
                knew->subdevice = HDA_SUBDEV_AMP_FLAG;
+               if (spec->mic_mute_led)
+                       knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
        }
        return 0;
 }
@@ -3917,11 +3927,6 @@ static int create_mute_led_cdev(struct hda_codec *codec,
        return devm_led_classdev_register(&codec->core.dev, cdev);
 }
 
-static void vmaster_update_mute_led(void *private_data, int enabled)
-{
-       ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
-}
-
 /**
  * snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
  * @codec: the HDA codec
@@ -3945,134 +3950,11 @@ int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
        if (spec->vmaster_mute.hook)
                codec_err(codec, "vmaster hook already present before cdev!\n");
 
-       spec->vmaster_mute.hook = vmaster_update_mute_led;
-       spec->vmaster_mute_enum = 1;
+       spec->vmaster_mute_led = 1;
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
 
-/*
- * mic mute LED hook helpers
- */
-enum {
-       MICMUTE_LED_ON,
-       MICMUTE_LED_OFF,
-       MICMUTE_LED_FOLLOW_CAPTURE,
-       MICMUTE_LED_FOLLOW_MUTE,
-};
-
-static void call_micmute_led_update(struct hda_codec *codec)
-{
-       struct hda_gen_spec *spec = codec->spec;
-       unsigned int val;
-
-       switch (spec->micmute_led.led_mode) {
-       case MICMUTE_LED_ON:
-               val = 1;
-               break;
-       case MICMUTE_LED_OFF:
-               val = 0;
-               break;
-       case MICMUTE_LED_FOLLOW_CAPTURE:
-               val = !!spec->micmute_led.capture;
-               break;
-       case MICMUTE_LED_FOLLOW_MUTE:
-       default:
-               val = !spec->micmute_led.capture;
-               break;
-       }
-
-       if (val == spec->micmute_led.led_value)
-               return;
-       spec->micmute_led.led_value = val;
-       ledtrig_audio_set(LED_AUDIO_MICMUTE,
-                         spec->micmute_led.led_value ? LED_ON : LED_OFF);
-}
-
-static void update_micmute_led(struct hda_codec *codec,
-                              struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_gen_spec *spec = codec->spec;
-       unsigned int mask;
-
-       if (spec->micmute_led.old_hook)
-               spec->micmute_led.old_hook(codec, kcontrol, ucontrol);
-
-       if (!ucontrol)
-               return;
-       mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-       if (!strcmp("Capture Switch", ucontrol->id.name)) {
-               /* TODO: How do I verify if it's a mono or stereo here? */
-               if (ucontrol->value.integer.value[0] ||
-                   ucontrol->value.integer.value[1])
-                       spec->micmute_led.capture |= mask;
-               else
-                       spec->micmute_led.capture &= ~mask;
-               call_micmute_led_update(codec);
-       }
-}
-
-static int micmute_led_mode_info(struct snd_kcontrol *kcontrol,
-                                struct snd_ctl_elem_info *uinfo)
-{
-       static const char * const texts[] = {
-               "On", "Off", "Follow Capture", "Follow Mute",
-       };
-
-       return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
-}
-
-static int micmute_led_mode_get(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_gen_spec *spec = codec->spec;
-
-       ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode;
-       return 0;
-}
-
-static int micmute_led_mode_put(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_value *ucontrol)
-{
-       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct hda_gen_spec *spec = codec->spec;
-       unsigned int mode;
-
-       mode = ucontrol->value.enumerated.item[0];
-       if (mode > MICMUTE_LED_FOLLOW_MUTE)
-               mode = MICMUTE_LED_FOLLOW_MUTE;
-       if (mode == spec->micmute_led.led_mode)
-               return 0;
-       spec->micmute_led.led_mode = mode;
-       call_micmute_led_update(codec);
-       return 1;
-}
-
-static const struct snd_kcontrol_new micmute_led_mode_ctl = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Mic Mute-LED Mode",
-       .info = micmute_led_mode_info,
-       .get = micmute_led_mode_get,
-       .put = micmute_led_mode_put,
-};
-
-/* Set up the capture sync hook for controlling the mic-mute LED */
-static int add_micmute_led_hook(struct hda_codec *codec)
-{
-       struct hda_gen_spec *spec = codec->spec;
-
-       spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
-       spec->micmute_led.capture = 0;
-       spec->micmute_led.led_value = -1;
-       spec->micmute_led.old_hook = spec->cap_sync_hook;
-       spec->cap_sync_hook = update_micmute_led;
-       if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
-               return -ENOMEM;
-       return 0;
-}
-
 /**
  * snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
  * @codec: the HDA codec
@@ -4091,6 +3973,7 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
                                     int (*callback)(struct led_classdev *,
                                                     enum led_brightness))
 {
+       struct hda_gen_spec *spec = codec->spec;
        int err;
 
        if (callback) {
@@ -4101,7 +3984,8 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
                }
        }
 
-       return add_micmute_led_hook(codec);
+       spec->mic_mute_led = 1;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
 #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
@@ -5060,6 +4944,9 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
 
        parse_user_hints(codec);
 
+       if (spec->vmaster_mute_led || spec->mic_mute_led)
+               snd_ctl_led_request();
+
        if (spec->mixer_nid && !spec->mixer_merge_nid)
                spec->mixer_merge_nid = spec->mixer_nid;
 
@@ -5291,7 +5178,7 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
            !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
                err = snd_hda_add_vmaster(codec, "Master Playback Volume",
                                          spec->vmaster_tlv, follower_pfxs,
-                                         "Playback Volume");
+                                         "Playback Volume", 0);
                if (err < 0)
                        return err;
        }
@@ -5299,13 +5186,14 @@ int snd_hda_gen_build_controls(struct hda_codec *codec)
            !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
                err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
                                            NULL, follower_pfxs,
-                                           "Playback Switch",
-                                           true, &spec->vmaster_mute.sw_kctl);
+                                           "Playback Switch", true,
+                                           spec->vmaster_mute_led ?
+                                               SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
+                                           &spec->vmaster_mute.sw_kctl);
                if (err < 0)
                        return err;
                if (spec->vmaster_mute.hook) {
-                       snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
-                                                spec->vmaster_mute_enum);
+                       snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
                        snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
                }
        }