diff options
| author | Azael Avalos <coproscefalo@gmail.com> | 2014-03-25 22:38:33 -0400 |
|---|---|---|
| committer | Matthew Garrett <matthew.garrett@nebula.com> | 2014-04-06 12:58:14 -0400 |
| commit | def6c4e25d31b874b939bd08e7941eaa9711653f (patch) | |
| tree | 55dad04e42107752c13681197e6137aabff1f2c3 /drivers/platform | |
| parent | 9d8658acd6be9139ef91dfe6c001796e7a03ded6 (diff) | |
toshiba_acpi: Add ECO mode led support
Newer Toshiba laptops now come with a feature called
ECO Mode, where the system is put in low power consupmtion
state and a green (world shaped with leaves) icon illuminates
indicating that the system is in such power state.
This patch adds support to turn on/off the ECO led by
creating and registering the toshiba::eco_mode led.
Signed-off-by: Azael Avalos <coproscefalo@gmail.com>
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Diffstat (limited to 'drivers/platform')
| -rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 08c53768447b..c8e8bfb78c19 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
| @@ -112,6 +112,7 @@ MODULE_LICENSE("GPL"); | |||
| 112 | #define HCI_LCD_BRIGHTNESS 0x002a | 112 | #define HCI_LCD_BRIGHTNESS 0x002a |
| 113 | #define HCI_WIRELESS 0x0056 | 113 | #define HCI_WIRELESS 0x0056 |
| 114 | #define HCI_KBD_ILLUMINATION 0x0095 | 114 | #define HCI_KBD_ILLUMINATION 0x0095 |
| 115 | #define HCI_ECO_MODE 0x0097 | ||
| 115 | #define SCI_ILLUMINATION 0x014e | 116 | #define SCI_ILLUMINATION 0x014e |
| 116 | #define SCI_KBD_ILLUM_STATUS 0x015c | 117 | #define SCI_KBD_ILLUM_STATUS 0x015c |
| 117 | #define SCI_TOUCHPAD 0x050e | 118 | #define SCI_TOUCHPAD 0x050e |
| @@ -142,6 +143,7 @@ struct toshiba_acpi_dev { | |||
| 142 | struct backlight_device *backlight_dev; | 143 | struct backlight_device *backlight_dev; |
| 143 | struct led_classdev led_dev; | 144 | struct led_classdev led_dev; |
| 144 | struct led_classdev kbd_led; | 145 | struct led_classdev kbd_led; |
| 146 | struct led_classdev eco_led; | ||
| 145 | 147 | ||
| 146 | int force_fan; | 148 | int force_fan; |
| 147 | int last_key_event; | 149 | int last_key_event; |
| @@ -159,6 +161,7 @@ struct toshiba_acpi_dev { | |||
| 159 | unsigned int kbd_illum_supported:1; | 161 | unsigned int kbd_illum_supported:1; |
| 160 | unsigned int kbd_led_registered:1; | 162 | unsigned int kbd_led_registered:1; |
| 161 | unsigned int touchpad_supported:1; | 163 | unsigned int touchpad_supported:1; |
| 164 | unsigned int eco_supported:1; | ||
| 162 | unsigned int sysfs_created:1; | 165 | unsigned int sysfs_created:1; |
| 163 | 166 | ||
| 164 | struct mutex mutex; | 167 | struct mutex mutex; |
| @@ -571,6 +574,57 @@ static int toshiba_touchpad_get(struct toshiba_acpi_dev *dev, u32 *state) | |||
| 571 | return 0; | 574 | return 0; |
| 572 | } | 575 | } |
| 573 | 576 | ||
| 577 | /* Eco Mode support */ | ||
| 578 | static int toshiba_eco_mode_available(struct toshiba_acpi_dev *dev) | ||
| 579 | { | ||
| 580 | acpi_status status; | ||
| 581 | u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; | ||
| 582 | u32 out[HCI_WORDS]; | ||
| 583 | |||
| 584 | status = hci_raw(dev, in, out); | ||
| 585 | if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { | ||
| 586 | pr_info("ACPI call to get ECO led failed\n"); | ||
| 587 | return 0; | ||
| 588 | } | ||
| 589 | |||
| 590 | return 1; | ||
| 591 | } | ||
| 592 | |||
| 593 | static enum led_brightness toshiba_eco_mode_get_status(struct led_classdev *cdev) | ||
| 594 | { | ||
| 595 | struct toshiba_acpi_dev *dev = container_of(cdev, | ||
| 596 | struct toshiba_acpi_dev, eco_led); | ||
| 597 | u32 in[HCI_WORDS] = { HCI_GET, HCI_ECO_MODE, 0, 1, 0, 0 }; | ||
| 598 | u32 out[HCI_WORDS]; | ||
| 599 | acpi_status status; | ||
| 600 | |||
| 601 | status = hci_raw(dev, in, out); | ||
| 602 | if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { | ||
| 603 | pr_err("ACPI call to get ECO led failed\n"); | ||
| 604 | return LED_OFF; | ||
| 605 | } | ||
| 606 | |||
| 607 | return out[2] ? LED_FULL : LED_OFF; | ||
| 608 | } | ||
| 609 | |||
| 610 | static void toshiba_eco_mode_set_status(struct led_classdev *cdev, | ||
| 611 | enum led_brightness brightness) | ||
| 612 | { | ||
| 613 | struct toshiba_acpi_dev *dev = container_of(cdev, | ||
| 614 | struct toshiba_acpi_dev, eco_led); | ||
| 615 | u32 in[HCI_WORDS] = { HCI_SET, HCI_ECO_MODE, 0, 1, 0, 0 }; | ||
| 616 | u32 out[HCI_WORDS]; | ||
| 617 | acpi_status status; | ||
| 618 | |||
| 619 | /* Switch the Eco Mode led on/off */ | ||
| 620 | in[2] = (brightness) ? 1 : 0; | ||
| 621 | status = hci_raw(dev, in, out); | ||
| 622 | if (ACPI_FAILURE(status) || out[0] == SCI_INPUT_DATA_ERROR) { | ||
| 623 | pr_err("ACPI call to set ECO led failed\n"); | ||
| 624 | return; | ||
| 625 | } | ||
| 626 | } | ||
| 627 | |||
| 574 | /* Bluetooth rfkill handlers */ | 628 | /* Bluetooth rfkill handlers */ |
| 575 | 629 | ||
| 576 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) | 630 | static u32 hci_get_bt_present(struct toshiba_acpi_dev *dev, bool *present) |
| @@ -1469,6 +1523,9 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev) | |||
| 1469 | 1523 | ||
| 1470 | if (dev->kbd_led_registered) | 1524 | if (dev->kbd_led_registered) |
| 1471 | led_classdev_unregister(&dev->kbd_led); | 1525 | led_classdev_unregister(&dev->kbd_led); |
| 1526 | |||
| 1527 | if (dev->eco_supported) | ||
| 1528 | led_classdev_unregister(&dev->eco_led); | ||
| 1472 | 1529 | ||
| 1473 | if (toshiba_acpi) | 1530 | if (toshiba_acpi) |
| 1474 | toshiba_acpi = NULL; | 1531 | toshiba_acpi = NULL; |
| @@ -1556,6 +1613,15 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev) | |||
| 1556 | dev->illumination_supported = 1; | 1613 | dev->illumination_supported = 1; |
| 1557 | } | 1614 | } |
| 1558 | 1615 | ||
| 1616 | if (toshiba_eco_mode_available(dev)) { | ||
| 1617 | dev->eco_led.name = "toshiba::eco_mode"; | ||
| 1618 | dev->eco_led.max_brightness = 1; | ||
| 1619 | dev->eco_led.brightness_set = toshiba_eco_mode_set_status; | ||
| 1620 | dev->eco_led.brightness_get = toshiba_eco_mode_get_status; | ||
| 1621 | if (!led_classdev_register(&dev->acpi_dev->dev, &dev->eco_led)) | ||
| 1622 | dev->eco_supported = 1; | ||
| 1623 | } | ||
| 1624 | |||
| 1559 | ret = toshiba_kbd_illum_status_get(dev, &dummy); | 1625 | ret = toshiba_kbd_illum_status_get(dev, &dummy); |
| 1560 | if (!ret) { | 1626 | if (!ret) { |
| 1561 | dev->kbd_time = dummy >> HCI_MISC_SHIFT; | 1627 | dev->kbd_time = dummy >> HCI_MISC_SHIFT; |
