Linux Audio

Check our new training course

Loading...
v5.9
 1// SPDX-License-Identifier: GPL-2.0
 2/* Helper functions for Thinkpad LED control;
 3 * to be included from codec driver
 4 */
 5
 6#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
 7
 8#include <linux/acpi.h>
 9#include <linux/leds.h>
 
 
 
 
 
 
 
 
 
 
 
10
11static bool is_thinkpad(struct hda_codec *codec)
12{
13	return (codec->core.subsystem_id >> 16 == 0x17aa) &&
14	       (acpi_dev_found("LEN0068") || acpi_dev_found("LEN0268") ||
15		acpi_dev_found("IBM0068"));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16}
17
18static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
19				    const struct hda_fixup *fix, int action)
20{
 
 
 
21	if (action == HDA_FIXUP_ACT_PROBE) {
22		if (!is_thinkpad(codec))
23			return;
24		snd_hda_gen_add_mute_led_cdev(codec, NULL);
25		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26	}
27}
28
29#else /* CONFIG_THINKPAD_ACPI */
30
31static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
32				    const struct hda_fixup *fix, int action)
33{
34}
35
36#endif /* CONFIG_THINKPAD_ACPI */
v3.15
 
  1/* Helper functions for Thinkpad LED control;
  2 * to be included from codec driver
  3 */
  4
  5#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
  6
  7#include <linux/acpi.h>
  8#include <linux/thinkpad_acpi.h>
  9
 10static int (*led_set_func)(int, bool);
 11static void (*old_vmaster_hook)(void *, int);
 12
 13static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
 14				 void **rv)
 15{
 16	bool *found = context;
 17	*found = true;
 18	return AE_OK;
 19}
 20
 21static bool is_thinkpad(struct hda_codec *codec)
 22{
 23	bool found = false;
 24	if (codec->subsystem_id >> 16 != 0x17aa)
 25		return false;
 26	if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
 27		return true;
 28	found = false;
 29	return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
 30}
 31
 32static void update_tpacpi_mute_led(void *private_data, int enabled)
 33{
 34	if (old_vmaster_hook)
 35		old_vmaster_hook(private_data, enabled);
 36
 37	if (led_set_func)
 38		led_set_func(TPACPI_LED_MUTE, !enabled);
 39}
 40
 41static void update_tpacpi_micmute_led(struct hda_codec *codec,
 42				      struct snd_kcontrol *kcontrol,
 43				      struct snd_ctl_elem_value *ucontrol)
 44{
 45	if (!ucontrol || !led_set_func)
 46		return;
 47	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
 48		/* TODO: How do I verify if it's a mono or stereo here? */
 49		bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
 50		led_set_func(TPACPI_LED_MICMUTE, !val);
 51	}
 52}
 53
 54static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
 55				    const struct hda_fixup *fix, int action)
 56{
 57	struct hda_gen_spec *spec = codec->spec;
 58	bool removefunc = false;
 59
 60	if (action == HDA_FIXUP_ACT_PROBE) {
 61		if (!is_thinkpad(codec))
 62			return;
 63		if (!led_set_func)
 64			led_set_func = symbol_request(tpacpi_led_set);
 65		if (!led_set_func) {
 66			codec_warn(codec,
 67				   "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
 68			return;
 69		}
 70
 71		removefunc = true;
 72		if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
 73			old_vmaster_hook = spec->vmaster_mute.hook;
 74			spec->vmaster_mute.hook = update_tpacpi_mute_led;
 75			removefunc = false;
 76		}
 77		if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
 78			if (spec->num_adc_nids > 1)
 79				codec_dbg(codec,
 80					  "Skipping micmute LED control due to several ADCs");
 81			else {
 82				spec->cap_sync_hook = update_tpacpi_micmute_led;
 83				removefunc = false;
 84			}
 85		}
 86	}
 87
 88	if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
 89		symbol_put(tpacpi_led_set);
 90		led_set_func = NULL;
 91		old_vmaster_hook = NULL;
 92	}
 93}
 94
 95#else /* CONFIG_THINKPAD_ACPI */
 96
 97static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
 98				    const struct hda_fixup *fix, int action)
 99{
100}
101
102#endif /* CONFIG_THINKPAD_ACPI */