linux/sound/pci/hda/dell_wmi_helper.c
<<
>>
Prefs
   1/* Helper functions for Dell Mic Mute LED control;
   2 * to be included from codec driver
   3 */
   4
   5#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
   6#include <linux/dell-led.h>
   7
   8static int dell_led_value;
   9static int (*dell_led_set_func)(int, int);
  10static void (*dell_old_cap_hook)(struct hda_codec *,
  11                                 struct snd_kcontrol *,
  12                                 struct snd_ctl_elem_value *);
  13
  14static void update_dell_wmi_micmute_led(struct hda_codec *codec,
  15                                        struct snd_kcontrol *kcontrol,
  16                                        struct snd_ctl_elem_value *ucontrol)
  17{
  18        if (dell_old_cap_hook)
  19                dell_old_cap_hook(codec, kcontrol, ucontrol);
  20
  21        if (!ucontrol || !dell_led_set_func)
  22                return;
  23        if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
  24                /* TODO: How do I verify if it's a mono or stereo here? */
  25                int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
  26                if (val == dell_led_value)
  27                        return;
  28                dell_led_value = val;
  29                if (dell_led_set_func)
  30                        dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
  31        }
  32}
  33
  34
  35static void alc_fixup_dell_wmi(struct hda_codec *codec,
  36                               const struct hda_fixup *fix, int action)
  37{
  38        struct alc_spec *spec = codec->spec;
  39        bool removefunc = false;
  40
  41        if (action == HDA_FIXUP_ACT_PROBE) {
  42                if (!dell_led_set_func)
  43                        dell_led_set_func = symbol_request(dell_app_wmi_led_set);
  44                if (!dell_led_set_func) {
  45                        codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
  46                        return;
  47                }
  48
  49                removefunc = true;
  50                if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
  51                        dell_led_value = 0;
  52                        if (spec->gen.num_adc_nids > 1)
  53                                codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
  54                        else {
  55                                dell_old_cap_hook = spec->gen.cap_sync_hook;
  56                                spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
  57                                removefunc = false;
  58                        }
  59                }
  60
  61        }
  62
  63        if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
  64                symbol_put(dell_app_wmi_led_set);
  65                dell_led_set_func = NULL;
  66                dell_old_cap_hook = NULL;
  67        }
  68}
  69
  70#else /* CONFIG_LEDS_DELL_NETBOOKS */
  71static void alc_fixup_dell_wmi(struct hda_codec *codec,
  72                               const struct hda_fixup *fix, int action)
  73{
  74}
  75
  76#endif /* CONFIG_LEDS_DELL_NETBOOKS */
  77