Skip to content

Commit

Permalink
fujitsu-laptop: Add support for eco LED
Browse files Browse the repository at this point in the history
There is an indicator LED signaling activated power saving mode
on certain Fujitsu laptop models. This has currently no use on Linux.
Export it to userspace.

Signed-off-by: Matej Groma <matejgroma@gmail.com>
Acked-by: Jonathan Woithe <jwoithe@just42.net>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
  • Loading branch information
Matej Groma authored and Darren Hart committed Jun 29, 2016
1 parent 1879e69 commit d6b88f6
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions drivers/platform/x86/fujitsu-laptop.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@
#define LOGOLAMP_POWERON 0x2000
#define LOGOLAMP_ALWAYS 0x4000
#define RADIO_LED_ON 0x20
#define ECO_LED 0x10000
#define ECO_LED_ON 0x80000
#endif

/* Hotkey details */
Expand Down Expand Up @@ -166,6 +168,7 @@ struct fujitsu_hotkey_t {
int logolamp_registered;
int kblamps_registered;
int radio_led_registered;
int eco_led_registered;
};

static struct fujitsu_hotkey_t *fujitsu_hotkey;
Expand Down Expand Up @@ -202,6 +205,17 @@ static struct led_classdev radio_led = {
.brightness_get = radio_led_get,
.brightness_set = radio_led_set
};

static enum led_brightness eco_led_get(struct led_classdev *cdev);
static void eco_led_set(struct led_classdev *cdev,
enum led_brightness brightness);

static struct led_classdev eco_led = {
.name = "fujitsu::eco_led",
.max_brightness = 1,
.brightness_get = eco_led_get,
.brightness_set = eco_led_set
};
#endif

#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
Expand Down Expand Up @@ -286,6 +300,18 @@ static void radio_led_set(struct led_classdev *cdev,
call_fext_func(FUNC_RFKILL, 0x5, RADIO_LED_ON, 0x0);
}

static void eco_led_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
int curr;

curr = call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0);
if (brightness)
call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr | ECO_LED_ON);
else
call_fext_func(FUNC_LEDS, 0x1, ECO_LED, curr & ~ECO_LED_ON);
}

static enum led_brightness logolamp_get(struct led_classdev *cdev)
{
enum led_brightness brightness = LED_OFF;
Expand Down Expand Up @@ -320,6 +346,16 @@ static enum led_brightness radio_led_get(struct led_classdev *cdev)

return brightness;
}

static enum led_brightness eco_led_get(struct led_classdev *cdev)
{
enum led_brightness brightness = LED_OFF;

if (call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) & ECO_LED_ON)
brightness = cdev->max_brightness;

return brightness;
}
#endif

/* Hardware access for LCD brightness control */
Expand Down Expand Up @@ -934,6 +970,23 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
result);
}
}

/* Support for eco led is not always signaled in bit corresponding
* to the bit used to control the led. According to the DSDT table,
* bit 14 seems to indicate presence of said led as well.
* Confirm by testing the status.
*/
if ((call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & BIT(14)) &&
(call_fext_func(FUNC_LEDS, 0x2, ECO_LED, 0x0) != UNSUPPORTED_CMD)) {
result = led_classdev_register(&fujitsu->pf_device->dev,
&eco_led);
if (result == 0) {
fujitsu_hotkey->eco_led_registered = 1;
} else {
pr_err("Could not register LED handler for eco LED, error %i\n",
result);
}
}
#endif

return result;
Expand Down Expand Up @@ -963,6 +1016,9 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device)

if (fujitsu_hotkey->radio_led_registered)
led_classdev_unregister(&radio_led);

if (fujitsu_hotkey->eco_led_registered)
led_classdev_unregister(&eco_led);
#endif

input_unregister_device(input);
Expand Down

0 comments on commit d6b88f6

Please sign in to comment.