diff options
| -rw-r--r-- | Documentation/laptops/thinkpad-acpi.txt | 7 | ||||
| -rw-r--r-- | drivers/platform/x86/thinkpad_acpi.c | 92 | ||||
| -rw-r--r-- | include/linux/thinkpad_acpi.h | 15 |
3 files changed, 111 insertions, 3 deletions
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 86c52360ffe7..fc04c14de4bb 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | ThinkPad ACPI Extras Driver | 1 | ThinkPad ACPI Extras Driver |
| 2 | 2 | ||
| 3 | Version 0.24 | 3 | Version 0.25 |
| 4 | December 11th, 2009 | 4 | October 16th, 2013 |
| 5 | 5 | ||
| 6 | Borislav Deianov <borislav@users.sf.net> | 6 | Borislav Deianov <borislav@users.sf.net> |
| 7 | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 7 | Henrique de Moraes Holschuh <hmh@hmh.eng.br> |
| @@ -741,6 +741,9 @@ compiled with the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option enabled. | |||
| 741 | Distributions must never enable this option. Individual users that | 741 | Distributions must never enable this option. Individual users that |
| 742 | are aware of the consequences are welcome to enabling it. | 742 | are aware of the consequences are welcome to enabling it. |
| 743 | 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. | ||
| 746 | |||
| 744 | procfs notes: | 747 | procfs notes: |
| 745 | 748 | ||
| 746 | The available commands are: | 749 | The available commands are: |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 03ca6c139f1a..0b7efb269cf1 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 25 | 25 | ||
| 26 | #define TPACPI_VERSION "0.24" | 26 | #define TPACPI_VERSION "0.25" |
| 27 | #define TPACPI_SYSFS_VERSION 0x020700 | 27 | #define TPACPI_SYSFS_VERSION 0x020700 |
| 28 | 28 | ||
| 29 | /* | 29 | /* |
| @@ -88,6 +88,7 @@ | |||
| 88 | 88 | ||
| 89 | #include <linux/pci_ids.h> | 89 | #include <linux/pci_ids.h> |
| 90 | 90 | ||
| 91 | #include <linux/thinkpad_acpi.h> | ||
| 91 | 92 | ||
| 92 | /* ThinkPad CMOS commands */ | 93 | /* ThinkPad CMOS commands */ |
| 93 | #define TP_CMOS_VOLUME_DOWN 0 | 94 | #define TP_CMOS_VOLUME_DOWN 0 |
| @@ -8350,6 +8351,91 @@ static struct ibm_struct fan_driver_data = { | |||
| 8350 | .resume = fan_resume, | 8351 | .resume = fan_resume, |
| 8351 | }; | 8352 | }; |
| 8352 | 8353 | ||
| 8354 | /************************************************************************* | ||
| 8355 | * Mute LED subdriver | ||
| 8356 | */ | ||
| 8357 | |||
| 8358 | |||
| 8359 | struct tp_led_table { | ||
| 8360 | acpi_string name; | ||
| 8361 | int on_value; | ||
| 8362 | int off_value; | ||
| 8363 | int state; | ||
| 8364 | }; | ||
| 8365 | |||
| 8366 | static struct tp_led_table led_tables[] = { | ||
| 8367 | [TPACPI_LED_MUTE] = { | ||
| 8368 | .name = "SSMS", | ||
| 8369 | .on_value = 1, | ||
| 8370 | .off_value = 0, | ||
| 8371 | }, | ||
| 8372 | [TPACPI_LED_MICMUTE] = { | ||
| 8373 | .name = "MMTS", | ||
| 8374 | .on_value = 2, | ||
| 8375 | .off_value = 0, | ||
| 8376 | }, | ||
| 8377 | }; | ||
| 8378 | |||
| 8379 | static int mute_led_on_off(struct tp_led_table *t, bool state) | ||
| 8380 | { | ||
| 8381 | acpi_handle temp; | ||
| 8382 | int output; | ||
| 8383 | |||
| 8384 | if (!ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) { | ||
| 8385 | pr_warn("Thinkpad ACPI has no %s interface.\n", t->name); | ||
| 8386 | return -EIO; | ||
| 8387 | } | ||
| 8388 | |||
| 8389 | if (!acpi_evalf(hkey_handle, &output, t->name, "dd", | ||
| 8390 | state ? t->on_value : t->off_value)) | ||
| 8391 | return -EIO; | ||
| 8392 | |||
| 8393 | t->state = state; | ||
| 8394 | return state; | ||
| 8395 | } | ||
| 8396 | |||
| 8397 | int tpacpi_led_set(int whichled, bool on) | ||
| 8398 | { | ||
| 8399 | struct tp_led_table *t; | ||
| 8400 | |||
| 8401 | if (whichled < 0 || whichled >= TPACPI_LED_MAX) | ||
| 8402 | return -EINVAL; | ||
| 8403 | |||
| 8404 | t = &led_tables[whichled]; | ||
| 8405 | if (t->state < 0 || t->state == on) | ||
| 8406 | return t->state; | ||
| 8407 | return mute_led_on_off(t, on); | ||
| 8408 | } | ||
| 8409 | EXPORT_SYMBOL_GPL(tpacpi_led_set); | ||
| 8410 | |||
| 8411 | static int mute_led_init(struct ibm_init_struct *iibm) | ||
| 8412 | { | ||
| 8413 | acpi_handle temp; | ||
| 8414 | int i; | ||
| 8415 | |||
| 8416 | for (i = 0; i < TPACPI_LED_MAX; i++) { | ||
| 8417 | struct tp_led_table *t = &led_tables[i]; | ||
| 8418 | if (ACPI_SUCCESS(acpi_get_handle(hkey_handle, t->name, &temp))) | ||
| 8419 | mute_led_on_off(t, false); | ||
| 8420 | else | ||
| 8421 | t->state = -ENODEV; | ||
| 8422 | } | ||
| 8423 | return 0; | ||
| 8424 | } | ||
| 8425 | |||
| 8426 | static void mute_led_exit(void) | ||
| 8427 | { | ||
| 8428 | int i; | ||
| 8429 | |||
| 8430 | for (i = 0; i < TPACPI_LED_MAX; i++) | ||
| 8431 | tpacpi_led_set(i, false); | ||
| 8432 | } | ||
| 8433 | |||
| 8434 | static struct ibm_struct mute_led_driver_data = { | ||
| 8435 | .name = "mute_led", | ||
| 8436 | .exit = mute_led_exit, | ||
| 8437 | }; | ||
| 8438 | |||
| 8353 | /**************************************************************************** | 8439 | /**************************************************************************** |
| 8354 | **************************************************************************** | 8440 | **************************************************************************** |
| 8355 | * | 8441 | * |
| @@ -8768,6 +8854,10 @@ static struct ibm_init_struct ibms_init[] __initdata = { | |||
| 8768 | .init = fan_init, | 8854 | .init = fan_init, |
| 8769 | .data = &fan_driver_data, | 8855 | .data = &fan_driver_data, |
| 8770 | }, | 8856 | }, |
| 8857 | { | ||
| 8858 | .init = mute_led_init, | ||
| 8859 | .data = &mute_led_driver_data, | ||
| 8860 | }, | ||
| 8771 | }; | 8861 | }; |
| 8772 | 8862 | ||
| 8773 | static int __init set_ibm_param(const char *val, struct kernel_param *kp) | 8863 | static int __init set_ibm_param(const char *val, struct kernel_param *kp) |
diff --git a/include/linux/thinkpad_acpi.h b/include/linux/thinkpad_acpi.h new file mode 100644 index 000000000000..361de59a2285 --- /dev/null +++ b/include/linux/thinkpad_acpi.h | |||
| @@ -0,0 +1,15 @@ | |||
| 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 | ||
