Commit | Line | Data |
---|---|---|
00ef9940 HW |
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 | ||
8 | static int dell_led_value; | |
9 | static int (*dell_led_set_func)(int, int); | |
10 | static void (*dell_old_cap_hook)(struct hda_codec *, | |
11 | struct snd_kcontrol *, | |
12 | struct snd_ctl_elem_value *); | |
13 | ||
14 | static 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 | ||
35 | static 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 */ | |
71 | static 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 */ |