Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thinkpad-acpi: Add mute and mic-mute LED functionality

The LEDs are currently not visible to userspace, for security
reasons. They are exported through thinkpad_acpi.h for use by the
snd-hda-intel driver.

Thanks to Alex Hung <alex.hung@canonical.com> and Takashi Iwai
<tiwai@suse.de> for writing parts of this patch.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Acked-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

David Henningsson and committed by
Takashi Iwai
420f9739 1d198f26

+111 -3
+5 -2
Documentation/laptops/thinkpad-acpi.txt
··· 1 1 ThinkPad ACPI Extras Driver 2 2 3 - Version 0.24 4 - December 11th, 2009 3 + Version 0.25 4 + October 16th, 2013 5 5 6 6 Borislav Deianov <borislav@users.sf.net> 7 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> ··· 740 740 compiled with the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option enabled. 741 741 Distributions must never enable this option. Individual users that 742 742 are aware of the consequences are welcome to enabling it. 743 + 744 + Audio mute and microphone mute LEDs are supported, but currently not 745 + visible to userspace. They are used by the snd-hda-intel audio driver. 743 746 744 747 procfs notes: 745 748
+91 -1
drivers/platform/x86/thinkpad_acpi.c
··· 23 23 24 24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 25 25 26 - #define TPACPI_VERSION "0.24" 26 + #define TPACPI_VERSION "0.25" 27 27 #define TPACPI_SYSFS_VERSION 0x020700 28 28 29 29 /* ··· 88 88 89 89 #include <linux/pci_ids.h> 90 90 91 + #include <linux/thinkpad_acpi.h> 91 92 92 93 /* ThinkPad CMOS commands */ 93 94 #define TP_CMOS_VOLUME_DOWN 0 ··· 8351 8350 .resume = fan_resume, 8352 8351 }; 8353 8352 8353 + /************************************************************************* 8354 + * Mute LED subdriver 8355 + */ 8356 + 8357 + 8358 + struct tp_led_table { 8359 + acpi_string name; 8360 + int on_value; 8361 + int off_value; 8362 + int state; 8363 + }; 8364 + 8365 + static struct tp_led_table led_tables[] = { 8366 + [TPACPI_LED_MUTE] = { 8367 + .name = "SSMS", 8368 + .on_value = 1, 8369 + .off_value = 0, 8370 + }, 8371 + [TPACPI_LED_MICMUTE] = { 8372 + .name = "MMTS", 8373 + .on_value = 2, 8374 + .off_value = 0, 8375 + }, 8376 + }; 8377 + 8378 + static int mute_led_on_off(struct tp_led_table *t, bool state) 8379 + { 8380 + acpi_handle temp; 8381 + int output; 8382 + 8383 + if (!ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) { 8384 + pr_warn("Thinkpad ACPI has no %s interface.\n", t->name); 8385 + return -EIO; 8386 + } 8387 + 8388 + if (!acpi_evalf(hkey_handle, &output, t->name, "dd", 8389 + state ? t->on_value : t->off_value)) 8390 + return -EIO; 8391 + 8392 + t->state = state; 8393 + return state; 8394 + } 8395 + 8396 + int tpacpi_led_set(int whichled, bool on) 8397 + { 8398 + struct tp_led_table *t; 8399 + 8400 + if (whichled < 0 || whichled >= TPACPI_LED_MAX) 8401 + return -EINVAL; 8402 + 8403 + t = &led_tables[whichled]; 8404 + if (t->state < 0 || t->state == on) 8405 + return t->state; 8406 + return mute_led_on_off(t, on); 8407 + } 8408 + EXPORT_SYMBOL_GPL(tpacpi_led_set); 8409 + 8410 + static int mute_led_init(struct ibm_init_struct *iibm) 8411 + { 8412 + acpi_handle temp; 8413 + int i; 8414 + 8415 + for (i = 0; i < TPACPI_LED_MAX; i++) { 8416 + struct tp_led_table *t = &led_tables[i]; 8417 + if (ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) 8418 + mute_led_on_off(t, false); 8419 + else 8420 + t->state = -ENODEV; 8421 + } 8422 + return 0; 8423 + } 8424 + 8425 + static void mute_led_exit(void) 8426 + { 8427 + int i; 8428 + 8429 + for (i = 0; i < TPACPI_LED_MAX; i++) 8430 + tpacpi_led_set(i, false); 8431 + } 8432 + 8433 + static struct ibm_struct mute_led_driver_data = { 8434 + .name = "mute_led", 8435 + .exit = mute_led_exit, 8436 + }; 8437 + 8354 8438 /**************************************************************************** 8355 8439 **************************************************************************** 8356 8440 * ··· 8853 8767 { 8854 8768 .init = fan_init, 8855 8769 .data = &fan_driver_data, 8770 + }, 8771 + { 8772 + .init = mute_led_init, 8773 + .data = &mute_led_driver_data, 8856 8774 }, 8857 8775 }; 8858 8776
+15
include/linux/thinkpad_acpi.h
··· 1 + #ifndef __THINKPAD_ACPI_H__ 2 + #define __THINKPAD_ACPI_H__ 3 + 4 + /* These two functions return 0 if success, or negative error code 5 + (e g -ENODEV if no led present) */ 6 + 7 + enum { 8 + TPACPI_LED_MUTE, 9 + TPACPI_LED_MICMUTE, 10 + TPACPI_LED_MAX, 11 + }; 12 + 13 + int tpacpi_led_set(int whichled, bool on); 14 + 15 + #endif