diff options
Diffstat (limited to 'board/kip/led.c')
-rw-r--r-- | board/kip/led.c | 205 |
1 files changed, 131 insertions, 74 deletions
diff --git a/board/kip/led.c b/board/kip/led.c index f0eda1c57a..4de1735e51 100644 --- a/board/kip/led.c +++ b/board/kip/led.c @@ -7,115 +7,172 @@ #include "charge_state.h" #include "chipset.h" +#include "extpower.h" #include "gpio.h" #include "hooks.h" #include "led_common.h" -#include "pwm.h" #include "util.h" -const enum ec_led_id supported_led_ids[] = {EC_LED_ID_BATTERY_LED}; +const enum ec_led_id supported_led_ids[] = { + EC_LED_ID_BATTERY_LED, EC_LED_ID_POWER_LED}; const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids); enum led_color { LED_OFF = 0, - LED_RED, - LED_ORANGE, - LED_YELLOW, - LED_GREEN, - - /* Number of colors, not a color itself */ - LED_COLOR_COUNT + LED_WHITE, + LED_AMBER, + LED_COLOR_COUNT /* Number of colors, not a color itself */ }; -/* Brightness vs. color, for {red, green} LEDs */ -static const uint8_t color_brightness[LED_COLOR_COUNT][2] = { - {0, 0}, - {100, 0}, - {30, 45}, - {20, 60}, - {0, 100}, -}; +static int bat_led_set_color(enum led_color color) +{ + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_BAT_LED0, 1); + gpio_set_level(GPIO_BAT_LED1, 1); + break; + case LED_WHITE: + gpio_set_level(GPIO_BAT_LED0, 1); + gpio_set_level(GPIO_BAT_LED1, 0); + break; + case LED_AMBER: + gpio_set_level(GPIO_BAT_LED0, 0); + gpio_set_level(GPIO_BAT_LED1, 1); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; +} -/** - * Set LED color - * - * @param color Enumerated color value - */ -static void set_color(enum led_color color) +static int pwr_led_set_color(enum led_color color) { - pwm_set_duty(PWM_CH_LED_RED, color_brightness[color][0]); - pwm_set_duty(PWM_CH_LED_GREEN, color_brightness[color][1]); + switch (color) { + case LED_OFF: + gpio_set_level(GPIO_PWR_LED_L, 1); + break; + case LED_WHITE: + gpio_set_level(GPIO_PWR_LED_L, 0); + break; + default: + return EC_ERROR_UNKNOWN; + } + return EC_SUCCESS; } 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_GREEN] = 100; + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + brightness_range[EC_LED_COLOR_WHITE] = 100; + brightness_range[EC_LED_COLOR_YELLOW] = 100; + break; + case EC_LED_ID_POWER_LED: + brightness_range[EC_LED_COLOR_WHITE] = 100; + break; + default: + /* Nothing to do */ + break; + } } int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { - pwm_set_duty(PWM_CH_LED_RED, brightness[EC_LED_COLOR_RED]); - pwm_set_duty(PWM_CH_LED_GREEN, brightness[EC_LED_COLOR_GREEN]); + switch (led_id) { + case EC_LED_ID_BATTERY_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + bat_led_set_color(LED_WHITE); + else if (brightness[EC_LED_COLOR_YELLOW] != 0) + bat_led_set_color(LED_AMBER); + else + bat_led_set_color(LED_OFF); + break; + case EC_LED_ID_POWER_LED: + if (brightness[EC_LED_COLOR_WHITE] != 0) + pwr_led_set_color(LED_WHITE); + else + pwr_led_set_color(LED_OFF); + break; + default: + break; + } return EC_SUCCESS; } -static void led_init(void) +static void kip_led_set_power(void) { - /* Configure GPIOs */ - gpio_config_module(MODULE_PWM_LED, 1); - - /* - * Enable PWMs and set to 0% duty cycle. If they're disabled, the LM4 - * seems to ground the pins instead of letting them float. - */ - pwm_enable(PWM_CH_LED_RED, 1); - pwm_enable(PWM_CH_LED_GREEN, 1); - set_color(LED_OFF); -} -DECLARE_HOOK(HOOK_INIT, led_init, HOOK_PRIO_DEFAULT); + static int power_ticks; + static int previous_state_suspend; -/** - * Called by hook task every 250 ms - */ -static void led_tick(void) -{ - static unsigned ticks; - int chstate = charge_get_state(); + power_ticks++; - ticks++; + if (chipset_in_state(CHIPSET_STATE_SUSPEND)) { + /* Reset ticks if entering suspend so LED turns amber + * as soon as possible. */ + if (!previous_state_suspend) + power_ticks = 0; - /* If we don't control the LED, nothing to do */ - if (!led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) - return; + /* Blink once every one second. */ + pwr_led_set_color((power_ticks & 0x4) ? LED_WHITE : LED_OFF); - /* If charging error, blink orange, 25% duty cycle, 4 sec period */ - if (chstate == PWR_STATE_ERROR) { - set_color((ticks % 16) < 4 ? LED_ORANGE : LED_OFF); + previous_state_suspend = 1; return; } - /* If charge-force-idle, blink green, 50% duty cycle, 2 sec period */ - if (chstate == PWR_STATE_IDLE && - (charge_get_flags() & CHARGE_FLAG_FORCE_IDLE)) { - set_color((ticks & 0x4) ? LED_GREEN : LED_OFF); - return; - } + previous_state_suspend = 0; - /* If the system is charging, solid orange */ - if (chstate == PWR_STATE_CHARGE) { - set_color(LED_ORANGE); - return; - } + if (chipset_in_state(CHIPSET_STATE_ANY_OFF)) + pwr_led_set_color(LED_OFF); + else if (chipset_in_state(CHIPSET_STATE_ON)) + pwr_led_set_color(LED_WHITE); +} - /* If AC connected and fully charged (or close to it), solid green */ - if (chstate == PWR_STATE_CHARGE_NEAR_FULL || - chstate == PWR_STATE_IDLE) { - set_color(LED_GREEN); - return; +static void kip_led_set_battery(void) +{ + static int battery_ticks; + uint32_t chflags = charge_get_flags(); + + battery_ticks++; + + /* Battery LED is solid white if AC connected, unless the battery is + * is charging or there is an error. */ + bat_led_set_color(extpower_is_present() ? LED_WHITE : LED_OFF); + + switch (charge_get_state()) { + case PWR_STATE_CHARGE: + bat_led_set_color(LED_AMBER); + break; + case PWR_STATE_DISCHARGE: + /* See crosbug.com/p/22159. There's a 3% difference + * between the battery level seen by the kernel and what's + * really going on, so if they want to see 12%, we use 15%. + * Hard code this number here, because this only affects the + * LED color, not the battery charge state. */ + if (charge_get_percent() < 15) + bat_led_set_color( + (battery_ticks & 0x4) ? LED_WHITE : LED_OFF); + break; + case PWR_STATE_ERROR: + bat_led_set_color((battery_ticks & 0x2) ? LED_WHITE : LED_OFF); + break; + case PWR_STATE_IDLE: + if (chflags & CHARGE_FLAG_FORCE_IDLE) + bat_led_set_color( + (battery_ticks & 0x4) ? LED_AMBER : LED_OFF); + break; + default: + /* Other states don't alter LED behavior */ + break; } +} + +/* Called by hook task every 250mSec */ +static void led_tick(void) +{ + if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) + kip_led_set_power(); - /* Otherwise, system is off and AC not connected, LED off */ - set_color(LED_OFF); + if (led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) + kip_led_set_battery(); } DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT); |