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 | /************************************************************************* |
