summaryrefslogtreecommitdiff
path: root/board/eve/led.c
diff options
context:
space:
mode:
authorScott <scollyer@chromium.org>2016-12-15 19:12:46 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-01-31 17:07:40 -0800
commit1fdca3156233c71f51e2ffdd8758dcd53cf882cb (patch)
tree9182975aaf698fb3b3ae139ac5020b3e5d70dec3 /board/eve/led.c
parenta4bddf7f2144a4a42e67260fa274da64d79fb2c7 (diff)
downloadchrome-ec-1fdca3156233c71f51e2ffdd8758dcd53cf882cb.tar.gz
eve: Add support for 3 color PWM controlled LEDs
Eve has two 3 color PWM controlled LEDs. This CL adds basic support for these LEDs so that they can be set to off, red, green, or blue. In addition, the LED policy from Kevin is appropriated. In S0 the LEDs will be blue. In S3/S5 if no charger is connected, then the LEDs are off If a charger is connected and the charge level is less than a threshold, both LEDs are set to red. When the charge level gets above a certain level or if the charge state is idle, then the LEDs are set to green. BRANCH=none BUG=chrome-os-partner:60797 TEST=manual Turn the system on so it's in S0, verify both LEDs are blue. Close the lid with no external charger and verify that the LEDs are both off. Connect the charger, and using battfake <> EC command verify that when the charge level is less than the threshold the LEDs are red, otherwise they are green. Set battfake to 0, and verified flashing red. Change-Id: I556ccdafde03cd5f5205e8948d5737dcbdc09d6d Signed-off-by: Scott <scollyer@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/434146 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@google.com> Reviewed-by: Todd Broch <tbroch@chromium.org>
Diffstat (limited to 'board/eve/led.c')
-rw-r--r--board/eve/led.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/board/eve/led.c b/board/eve/led.c
new file mode 100644
index 0000000000..1e7f4222d4
--- /dev/null
+++ b/board/eve/led.c
@@ -0,0 +1,194 @@
+/* Copyright 2017 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.
+ *
+ * Power/Battery LED control for Eve
+ */
+
+#include "charge_state.h"
+#include "chipset.h"
+#include "console.h"
+#include "extpower.h"
+#include "gpio.h"
+#include "hooks.h"
+#include "led_common.h"
+#include "pwm.h"
+#include "registers.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_PWM, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_PWM, format, ## args)
+
+#define LED_TOTAL_TICKS 16
+#define LED_ON_TICKS 8
+
+static int led_debug;
+
+const enum ec_led_id supported_led_ids[] = {
+ EC_LED_ID_POWER_LED, EC_LED_ID_BATTERY_LED};
+const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
+
+enum led_color {
+ LED_OFF = 0,
+ LED_RED,
+ LED_GREEN,
+ LED_BLUE,
+
+ /* Number of colors, not a color itself */
+ LED_COLOR_COUNT
+};
+
+/* Brightness vs. color, in the order of off, red, green and blue */
+static const uint8_t color_brightness[LED_COLOR_COUNT][3] = {
+ /* {Red, Green, Blue}, */
+ [LED_OFF] = {100, 100, 100},
+ [LED_RED] = {20, 100, 100},
+ [LED_GREEN] = {100, 20, 100},
+ [LED_BLUE] = {100, 100, 20},
+};
+
+/**
+ * Set LED color
+ *
+ * @param color Enumerated color value
+ */
+static void set_color(enum led_color color)
+{
+ /* Set color for left LED */
+ pwm_set_duty(PWM_CH_LED_L_RED, color_brightness[color][0]);
+ pwm_set_duty(PWM_CH_LED_L_GREEN, color_brightness[color][1]);
+ pwm_set_duty(PWM_CH_LED_L_BLUE, color_brightness[color][2]);
+
+ /* Set color for right LED */
+ pwm_set_duty(PWM_CH_LED_R_RED, color_brightness[color][0]);
+ pwm_set_duty(PWM_CH_LED_R_GREEN, color_brightness[color][1]);
+ pwm_set_duty(PWM_CH_LED_R_BLUE, color_brightness[color][2]);
+}
+
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+{
+ brightness_range[EC_LED_COLOR_RED] = 100;
+ brightness_range[EC_LED_COLOR_BLUE] = 100;
+ brightness_range[EC_LED_COLOR_GREEN] = 100;
+}
+
+int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
+{
+ /* Set brightness for left LED */
+ pwm_set_duty(PWM_CH_LED_L_RED, brightness[EC_LED_COLOR_RED]);
+ pwm_set_duty(PWM_CH_LED_L_BLUE, brightness[EC_LED_COLOR_BLUE]);
+ pwm_set_duty(PWM_CH_LED_L_GREEN, brightness[EC_LED_COLOR_GREEN]);
+
+ /* Set brightness for right LED */
+ pwm_set_duty(PWM_CH_LED_R_RED, brightness[EC_LED_COLOR_RED]);
+ pwm_set_duty(PWM_CH_LED_R_BLUE, brightness[EC_LED_COLOR_BLUE]);
+ pwm_set_duty(PWM_CH_LED_R_GREEN, brightness[EC_LED_COLOR_GREEN]);
+ return EC_SUCCESS;
+}
+
+static void eve_led_set_power_battery(void)
+{
+ static int power_ticks;
+ enum charge_state chg_state = charge_get_state();
+
+ if (chipset_in_state(CHIPSET_STATE_ON)) {
+ set_color(LED_BLUE);
+ return;
+ }
+
+ /* Flash red on critical battery, which usually inhibits AP power-on. */
+ if (battery_is_present() != BP_YES ||
+ charge_get_percent() < CONFIG_CHARGER_MIN_BAT_PCT_FOR_POWER_ON) {
+ set_color(((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ?
+ LED_RED : LED_OFF);
+ return;
+ }
+
+ /* CHIPSET_STATE_OFF */
+ switch (chg_state) {
+ case PWR_STATE_DISCHARGE:
+ set_color(LED_OFF);
+ break;
+ case PWR_STATE_CHARGE:
+ set_color(LED_RED);
+ break;
+ case PWR_STATE_ERROR:
+ set_color(((power_ticks++ % LED_TOTAL_TICKS)
+ < LED_ON_TICKS) ? LED_RED : LED_GREEN);
+ break;
+ case PWR_STATE_CHARGE_NEAR_FULL:
+ case PWR_STATE_IDLE: /* External power connected in IDLE. */
+ set_color(LED_GREEN);
+ break;
+ default:
+ set_color(LED_RED);
+ break;
+ }
+ if (chg_state != PWR_STATE_ERROR)
+ power_ticks = 0;
+}
+
+static void led_init(void)
+{
+ /*
+ * Enable PWMs and set to 0% duty cycle. If they're disabled,
+ * seems to ground the pins instead of letting them float.
+ */
+ /* Initialize PWM channels for left LED */
+ pwm_enable(PWM_CH_LED_L_RED, 1);
+ pwm_enable(PWM_CH_LED_L_GREEN, 1);
+ pwm_enable(PWM_CH_LED_L_BLUE, 1);
+
+ /* Initialize PWM channels for right LED */
+ pwm_enable(PWM_CH_LED_R_RED, 1);
+ pwm_enable(PWM_CH_LED_R_GREEN, 1);
+ pwm_enable(PWM_CH_LED_R_BLUE, 1);
+
+ set_color(LED_OFF);
+}
+/* After pwm_pin_init() */
+DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT);
+
+/**
+ * Called by hook task every 250 ms
+ */
+static void led_tick(void)
+{
+ if (led_debug)
+ return;
+
+ if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED) &&
+ led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) {
+ eve_led_set_power_battery();
+ return;
+ }
+}
+DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT);
+
+/******************************************************************/
+/* Console commands */
+static int command_led(int argc, char **argv)
+{
+ if (argc > 1) {
+ ccprintf("cmd led %s\n", argv[1]);
+ if (!strcasecmp(argv[1], "debug")) {
+ led_debug ^= 1;
+ CPRINTF("led_debug = %d\n", led_debug);
+ } else if (!strcasecmp(argv[1], "off")) {
+ set_color(LED_OFF);
+ } else if (!strcasecmp(argv[1], "red")) {
+ set_color(LED_RED);
+ } else if (!strcasecmp(argv[1], "green")) {
+ set_color(LED_GREEN);
+ } else if (!strcasecmp(argv[1], "blue")) {
+ set_color(LED_BLUE);
+ } else {
+ /* maybe handle charger_discharge_on_ac() too? */
+ return EC_ERROR_PARAM1;
+ }
+ }
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(led, command_led,
+ "[debug|red|green|blue|off]",
+ "Change LED color");