diff options
-rw-r--r-- | Documentation/thinkpad-acpi.txt | 23 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 33 |
2 files changed, 44 insertions, 12 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index 339ce21e59df..352e8aee63fe 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
@@ -378,23 +378,19 @@ supported. Use "eject2" instead of "eject" for the second bay. | |||
378 | Note: the UltraBay eject support on the 600e/x, A22p and A3x is | 378 | Note: the UltraBay eject support on the 600e/x, A22p and A3x is |
379 | EXPERIMENTAL and may not work as expected. USE WITH CAUTION! | 379 | EXPERIMENTAL and may not work as expected. USE WITH CAUTION! |
380 | 380 | ||
381 | CMOS control -- /proc/acpi/ibm/cmos | 381 | CMOS control |
382 | ----------------------------------- | 382 | ------------ |
383 | |||
384 | procfs: /proc/acpi/ibm/cmos | ||
385 | sysfs device attribute: cmos_command | ||
383 | 386 | ||
384 | This feature is used internally by the ACPI firmware to control the | 387 | This feature is used internally by the ACPI firmware to control the |
385 | ThinkLight on most newer ThinkPad models. It may also control LCD | 388 | ThinkLight on most newer ThinkPad models. It may also control LCD |
386 | brightness, sounds volume and more, but only on some models. | 389 | brightness, sounds volume and more, but only on some models. |
387 | 390 | ||
388 | The commands are non-negative integer numbers: | 391 | The range of valid cmos command numbers is 0 to 21, but not all have an |
389 | 392 | effect and the behavior varies from model to model. Here is the behavior | |
390 | echo 0 >/proc/acpi/ibm/cmos | 393 | on the X40 (tpb is the ThinkPad Buttons utility): |
391 | echo 1 >/proc/acpi/ibm/cmos | ||
392 | echo 2 >/proc/acpi/ibm/cmos | ||
393 | ... | ||
394 | |||
395 | The range of valid numbers is 0 to 21, but not all have an effect and | ||
396 | the behavior varies from model to model. Here is the behavior on the | ||
397 | X40 (tpb is the ThinkPad Buttons utility): | ||
398 | 394 | ||
399 | 0 - no effect but tpb reports "Volume down" | 395 | 0 - no effect but tpb reports "Volume down" |
400 | 1 - no effect but tpb reports "Volume up" | 396 | 1 - no effect but tpb reports "Volume up" |
@@ -407,6 +403,9 @@ X40 (tpb is the ThinkPad Buttons utility): | |||
407 | 13 - ThinkLight off | 403 | 13 - ThinkLight off |
408 | 14 - no effect but tpb reports ThinkLight status change | 404 | 14 - no effect but tpb reports ThinkLight status change |
409 | 405 | ||
406 | The cmos command interface is prone to firmware split-brain problems, as | ||
407 | in newer ThinkPads it is just a compatibility layer. | ||
408 | |||
410 | LED control -- /proc/acpi/ibm/led | 409 | LED control -- /proc/acpi/ibm/led |
411 | --------------------------------- | 410 | --------------------------------- |
412 | 411 | ||
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 79abc6841e30..ba749df189ab 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -1743,8 +1743,30 @@ static struct ibm_struct bay_driver_data = { | |||
1743 | * CMOS subdriver | 1743 | * CMOS subdriver |
1744 | */ | 1744 | */ |
1745 | 1745 | ||
1746 | /* sysfs cmos_command -------------------------------------------------- */ | ||
1747 | static ssize_t cmos_command_store(struct device *dev, | ||
1748 | struct device_attribute *attr, | ||
1749 | const char *buf, size_t count) | ||
1750 | { | ||
1751 | unsigned long cmos_cmd; | ||
1752 | int res; | ||
1753 | |||
1754 | if (parse_strtoul(buf, 21, &cmos_cmd)) | ||
1755 | return -EINVAL; | ||
1756 | |||
1757 | res = issue_thinkpad_cmos_command(cmos_cmd); | ||
1758 | return (res)? res : count; | ||
1759 | } | ||
1760 | |||
1761 | static struct device_attribute dev_attr_cmos_command = | ||
1762 | __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store); | ||
1763 | |||
1764 | /* --------------------------------------------------------------------- */ | ||
1765 | |||
1746 | static int __init cmos_init(struct ibm_init_struct *iibm) | 1766 | static int __init cmos_init(struct ibm_init_struct *iibm) |
1747 | { | 1767 | { |
1768 | int res; | ||
1769 | |||
1748 | vdbg_printk(TPACPI_DBG_INIT, | 1770 | vdbg_printk(TPACPI_DBG_INIT, |
1749 | "initializing cmos commands subdriver\n"); | 1771 | "initializing cmos commands subdriver\n"); |
1750 | 1772 | ||
@@ -1752,9 +1774,19 @@ static int __init cmos_init(struct ibm_init_struct *iibm) | |||
1752 | 1774 | ||
1753 | vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n", | 1775 | vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n", |
1754 | str_supported(cmos_handle != NULL)); | 1776 | str_supported(cmos_handle != NULL)); |
1777 | |||
1778 | res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); | ||
1779 | if (res) | ||
1780 | return res; | ||
1781 | |||
1755 | return (cmos_handle)? 0 : 1; | 1782 | return (cmos_handle)? 0 : 1; |
1756 | } | 1783 | } |
1757 | 1784 | ||
1785 | static void cmos_exit(void) | ||
1786 | { | ||
1787 | device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); | ||
1788 | } | ||
1789 | |||
1758 | static int cmos_read(char *p) | 1790 | static int cmos_read(char *p) |
1759 | { | 1791 | { |
1760 | int len = 0; | 1792 | int len = 0; |
@@ -1795,6 +1827,7 @@ static struct ibm_struct cmos_driver_data = { | |||
1795 | .name = "cmos", | 1827 | .name = "cmos", |
1796 | .read = cmos_read, | 1828 | .read = cmos_read, |
1797 | .write = cmos_write, | 1829 | .write = cmos_write, |
1830 | .exit = cmos_exit, | ||
1798 | }; | 1831 | }; |
1799 | 1832 | ||
1800 | /************************************************************************* | 1833 | /************************************************************************* |