diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-10-07 10:59:45 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2013-10-08 20:41:32 +0000 |
commit | ff8c8fee79e148567c0f2128db69563acb29ee54 (patch) | |
tree | 0d3daa52c091a36c997c0cd42be8267678a13f7f /common/pwm_kblight.c | |
parent | 99157c265c8353e166059e17d250d9991d4e7ae0 (diff) | |
download | chrome-ec-ff8c8fee79e148567c0f2128db69563acb29ee54.tar.gz |
rambi: Control LEDs using PWM
Rambi has a pair of LEDs which are attached to the PWM fan controller.
Add support for them. Also add a generic 'pwmduty' command which can
be used to get/set the duty cycle for any PWM channel.
Also fix rounding errors in pwm module, so that set/get duty doesn't
keep rounding down.
BUG=chrome-os-partner:22895
BRANCH=none
TEST=Boot rambi. LEDs are off.
pwmduty -> both are 0%
pwmduty 0 10 -> green LED on dimly
pwmduty 1 10 -> red LED on dimly
pwmduty 0 99 -> green LED on brightly
pwmduty 1 100 -> red LED on brightly
pwmduty 1 0 -> red LED off
pwmduty 1 -1 -> red LED turns back on because fan controller is disabled
pwmduty -> channel 0 at 99%, channel 1 disabled
Build all platforms. Pass all unit tests.
Change-Id: Ib0a6289a757554e696a9a0153a85bdc34e2ee2ae
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/172094
Diffstat (limited to 'common/pwm_kblight.c')
-rw-r--r-- | common/pwm_kblight.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/common/pwm_kblight.c b/common/pwm_kblight.c new file mode 100644 index 0000000000..41448ce7e8 --- /dev/null +++ b/common/pwm_kblight.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* PWM control module for Chromebook keyboard backlight. */ + +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "host_command.h" +#include "lid_switch.h" +#include "pwm.h" +#include "system.h" +#include "util.h" + +#define PWMKBD_SYSJUMP_TAG 0x504b /* "PK" */ +#define PWM_HOOK_VERSION 1 +/* Saved PWM state across sysjumps */ +struct pwm_kbd_state { + uint8_t kblight_en; + uint8_t kblight_percent; + uint8_t pad0, pad1; /* Pad to multiple of 4 bytes. */ +}; + +/*****************************************************************************/ +/* Console commands */ + +static int command_kblight(int argc, char **argv) +{ + if (argc >= 2) { + char *e; + int i = strtoi(argv[1], &e, 0); + if (*e) + return EC_ERROR_PARAM1; + pwm_set_duty(PWM_CH_KBLIGHT, i); + } + + ccprintf("Keyboard backlight: %d%%\n", pwm_get_duty(PWM_CH_KBLIGHT)); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(kblight, command_kblight, + "percent", + "Set keyboard backlight", + NULL); + +/*****************************************************************************/ +/* Host commands */ + +int pwm_command_get_keyboard_backlight(struct host_cmd_handler_args *args) +{ + struct ec_response_pwm_get_keyboard_backlight *r = args->response; + + r->percent = pwm_get_duty(PWM_CH_KBLIGHT); + r->enabled = pwm_get_enabled(PWM_CH_KBLIGHT); + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT, + pwm_command_get_keyboard_backlight, + EC_VER_MASK(0)); + +int pwm_command_set_keyboard_backlight(struct host_cmd_handler_args *args) +{ + const struct ec_params_pwm_set_keyboard_backlight *p = args->params; + + pwm_set_duty(PWM_CH_KBLIGHT, p->percent); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT, + pwm_command_set_keyboard_backlight, + EC_VER_MASK(0)); + +/*****************************************************************************/ +/* Hooks */ + +static void pwm_kblight_init(void) +{ + const struct pwm_kbd_state *prev; + int version, size; + + /* Configure GPIO */ + gpio_config_module(MODULE_PWM_KBLIGHT, 1); + + prev = (const struct pwm_kbd_state *) + system_get_jump_tag(PWMKBD_SYSJUMP_TAG, &version, &size); + if (prev && version == PWM_HOOK_VERSION && size == sizeof(*prev)) { + /* Restore previous state. */ + pwm_enable(PWM_CH_KBLIGHT, prev->kblight_en); + pwm_set_duty(PWM_CH_KBLIGHT, prev->kblight_percent); + } else { + /* Enable keyboard backlight control, turned down */ + pwm_set_duty(PWM_CH_KBLIGHT, 0); + pwm_enable(PWM_CH_KBLIGHT, 1); + } +} +DECLARE_HOOK(HOOK_INIT, pwm_kblight_init, HOOK_PRIO_DEFAULT); + +static void pwm_kblight_preserve_state(void) +{ + struct pwm_kbd_state state; + + state.kblight_en = pwm_get_enabled(PWM_CH_KBLIGHT); + state.kblight_percent = pwm_get_duty(PWM_CH_KBLIGHT); + + system_add_jump_tag(PWMKBD_SYSJUMP_TAG, PWM_HOOK_VERSION, + sizeof(state), &state); +} +DECLARE_HOOK(HOOK_SYSJUMP, pwm_kblight_preserve_state, HOOK_PRIO_DEFAULT); + +static void pwm_kblight_suspend(void) +{ + pwm_set_duty(PWM_CH_KBLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, pwm_kblight_suspend, HOOK_PRIO_DEFAULT); + +static void pwm_kblight_shutdown(void) +{ + pwm_set_duty(PWM_CH_KBLIGHT, 0); +} +DECLARE_HOOK(HOOK_CHIPSET_SHUTDOWN, pwm_kblight_shutdown, HOOK_PRIO_DEFAULT); + +static void pwm_kblight_lid_change(void) +{ + pwm_enable(PWM_CH_KBLIGHT, lid_is_open()); +} +DECLARE_HOOK(HOOK_LID_CHANGE, pwm_kblight_lid_change, HOOK_PRIO_DEFAULT); |