aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt7
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c92
-rw-r--r--include/linux/thinkpad_acpi.h15
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.
741Distributions must never enable this option. Individual users that 741Distributions must never enable this option. Individual users that
742are aware of the consequences are welcome to enabling it. 742are aware of the consequences are welcome to enabling it.
743 743
744Audio mute and microphone mute LEDs are supported, but currently not
745visible to userspace. They are used by the snd-hda-intel audio driver.
746
744procfs notes: 747procfs notes:
745 748
746The available commands are: 749The 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
8359struct tp_led_table {
8360 acpi_string name;
8361 int on_value;
8362 int off_value;
8363 int state;
8364};
8365
8366static 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
8379static 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
8397int 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}
8409EXPORT_SYMBOL_GPL(tpacpi_led_set);
8410
8411static 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
8426static 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
8434static 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
8773static int __init set_ibm_param(const char *val, struct kernel_param *kp) 8863static 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
7enum {
8 TPACPI_LED_MUTE,
9 TPACPI_LED_MICMUTE,
10 TPACPI_LED_MAX,
11};
12
13int tpacpi_led_set(int whichled, bool on);
14
15#endif