diff options
author | David Henningsson <david.henningsson@canonical.com> | 2013-11-05 07:11:37 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-05 07:42:21 -0500 |
commit | b67ae3f1c97e2e8532ce051f0ed4365e9d796590 (patch) | |
tree | a7ac28b8c6e2cd67e14fd639566d2cfb4c06f08a /sound/pci/hda | |
parent | bbaa0d6665bc14133d7eb573d2b5ff898a06f365 (diff) |
ALSA: hda - Enable Thinkpad mute/micmute LEDs for Realtek
Same as we already have for Conexant. Right now it's only enabled
for one machine.
Tested-by: Hui Wang <hui.wang@canonical.com>
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 83 |
1 files changed, 81 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 01bf812455a2..02071a58f3f8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -829,7 +829,11 @@ static inline void alc_shutup(struct hda_codec *codec) | |||
829 | snd_hda_shutup_pins(codec); | 829 | snd_hda_shutup_pins(codec); |
830 | } | 830 | } |
831 | 831 | ||
832 | #define alc_free snd_hda_gen_free | 832 | static void alc_free(struct hda_codec *codec) |
833 | { | ||
834 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE); | ||
835 | snd_hda_gen_free(codec); | ||
836 | } | ||
833 | 837 | ||
834 | #ifdef CONFIG_PM | 838 | #ifdef CONFIG_PM |
835 | static void alc_power_eapd(struct hda_codec *codec) | 839 | static void alc_power_eapd(struct hda_codec *codec) |
@@ -3527,6 +3531,74 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec, | |||
3527 | snd_hda_override_wcaps(codec, 0x03, 0); | 3531 | snd_hda_override_wcaps(codec, 0x03, 0); |
3528 | } | 3532 | } |
3529 | 3533 | ||
3534 | #if IS_ENABLED(CONFIG_THINKPAD_ACPI) | ||
3535 | |||
3536 | #include <linux/thinkpad_acpi.h> | ||
3537 | |||
3538 | static int (*led_set_func)(int, bool); | ||
3539 | |||
3540 | static void update_tpacpi_mute_led(void *private_data, int enabled) | ||
3541 | { | ||
3542 | if (led_set_func) | ||
3543 | led_set_func(TPACPI_LED_MUTE, !enabled); | ||
3544 | } | ||
3545 | |||
3546 | static void update_tpacpi_micmute_led(struct hda_codec *codec, | ||
3547 | struct snd_ctl_elem_value *ucontrol) | ||
3548 | { | ||
3549 | if (!ucontrol || !led_set_func) | ||
3550 | return; | ||
3551 | if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) { | ||
3552 | /* TODO: How do I verify if it's a mono or stereo here? */ | ||
3553 | bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]; | ||
3554 | led_set_func(TPACPI_LED_MICMUTE, !val); | ||
3555 | } | ||
3556 | } | ||
3557 | |||
3558 | static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3559 | const struct hda_fixup *fix, int action) | ||
3560 | { | ||
3561 | struct alc_spec *spec = codec->spec; | ||
3562 | bool removefunc = false; | ||
3563 | |||
3564 | if (action == HDA_FIXUP_ACT_PROBE) { | ||
3565 | if (!led_set_func) | ||
3566 | led_set_func = symbol_request(tpacpi_led_set); | ||
3567 | if (!led_set_func) { | ||
3568 | snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); | ||
3569 | return; | ||
3570 | } | ||
3571 | |||
3572 | removefunc = true; | ||
3573 | if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { | ||
3574 | spec->gen.vmaster_mute.hook = update_tpacpi_mute_led; | ||
3575 | removefunc = false; | ||
3576 | } | ||
3577 | if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) { | ||
3578 | if (spec->gen.num_adc_nids > 1) | ||
3579 | snd_printdd("Skipping micmute LED control due to several ADCs"); | ||
3580 | else { | ||
3581 | spec->gen.cap_sync_hook = update_tpacpi_micmute_led; | ||
3582 | removefunc = false; | ||
3583 | } | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3587 | if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { | ||
3588 | symbol_put(tpacpi_led_set); | ||
3589 | led_set_func = NULL; | ||
3590 | } | ||
3591 | } | ||
3592 | |||
3593 | #else | ||
3594 | |||
3595 | static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, | ||
3596 | const struct hda_fixup *fix, int action) | ||
3597 | { | ||
3598 | } | ||
3599 | |||
3600 | #endif | ||
3601 | |||
3530 | enum { | 3602 | enum { |
3531 | ALC269_FIXUP_SONY_VAIO, | 3603 | ALC269_FIXUP_SONY_VAIO, |
3532 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 3604 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -3570,6 +3642,7 @@ enum { | |||
3570 | ALC282_FIXUP_ASUS_TX300, | 3642 | ALC282_FIXUP_ASUS_TX300, |
3571 | ALC283_FIXUP_INT_MIC, | 3643 | ALC283_FIXUP_INT_MIC, |
3572 | ALC290_FIXUP_MONO_SPEAKERS, | 3644 | ALC290_FIXUP_MONO_SPEAKERS, |
3645 | ALC269_FIXUP_THINKPAD_ACPI, | ||
3573 | }; | 3646 | }; |
3574 | 3647 | ||
3575 | static const struct hda_fixup alc269_fixups[] = { | 3648 | static const struct hda_fixup alc269_fixups[] = { |
@@ -3867,6 +3940,12 @@ static const struct hda_fixup alc269_fixups[] = { | |||
3867 | .chained = true, | 3940 | .chained = true, |
3868 | .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | 3941 | .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, |
3869 | }, | 3942 | }, |
3943 | [ALC269_FIXUP_THINKPAD_ACPI] = { | ||
3944 | .type = HDA_FIXUP_FUNC, | ||
3945 | .v.func = alc_fixup_thinkpad_acpi, | ||
3946 | .chained = true, | ||
3947 | .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST | ||
3948 | }, | ||
3870 | }; | 3949 | }; |
3871 | 3950 | ||
3872 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 3951 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
@@ -3950,7 +4029,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
3950 | SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK), | 4029 | SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK), |
3951 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4030 | SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
3952 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4031 | SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
3953 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4032 | SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI), |
3954 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4033 | SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
3955 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 4034 | SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
3956 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), | 4035 | SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC), |