summaryrefslogtreecommitdiff
path: root/common/pwm_kblight.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-10-07 10:59:45 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-10-08 20:41:32 +0000
commitff8c8fee79e148567c0f2128db69563acb29ee54 (patch)
tree0d3daa52c091a36c997c0cd42be8267678a13f7f /common/pwm_kblight.c
parent99157c265c8353e166059e17d250d9991d4e7ae0 (diff)
downloadchrome-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.c130
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);