/* 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 and battery LED control. */ #include "battery.h" #include "charge_manager.h" #include "charge_state.h" #include "chipset.h" #include "ec_commands.h" #include "gpio.h" #include "hooks.h" #include "host_command.h" #include "led_common.h" #include "system.h" #include "util.h" #define BAT_LED_ON 1 #define BAT_LED_OFF 0 #define LED_TOTAL_TICKS 16 #define LED_ON_TICKS 8 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 }; /** * Set LED color * * @param color Enumerated color value */ static void set_color(enum led_color color) { gpio_set_level(GPIO_POWER_LED, !(color == LED_BLUE)); gpio_set_level(GPIO_LED_ACIN, !(color == LED_GREEN)); gpio_set_level(GPIO_LED_CHARGE, !(color == LED_RED)); } void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) { brightness_range[EC_LED_COLOR_RED] = 1; brightness_range[EC_LED_COLOR_BLUE] = 1; brightness_range[EC_LED_COLOR_GREEN] = 1; } int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) { gpio_set_level(GPIO_POWER_LED, !brightness[EC_LED_COLOR_BLUE]); gpio_set_level(GPIO_LED_ACIN, !brightness[EC_LED_COLOR_GREEN]); gpio_set_level(GPIO_LED_CHARGE, !brightness[EC_LED_COLOR_RED]); return EC_SUCCESS; } static void nautilus_led_set_power_battery(void) { static unsigned int power_ticks; enum led_color cur_led_color = LED_RED; enum charge_state chg_state = charge_get_state(); int charge_percent = charge_get_percent(); 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_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: if ((charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) && charge_percent >= BATTERY_LEVEL_NEAR_FULL) cur_led_color = LED_GREEN; else cur_led_color = LED_OFF; break; case PWR_STATE_CHARGE: cur_led_color = LED_RED; break; case PWR_STATE_ERROR: cur_led_color = ((power_ticks++ % LED_TOTAL_TICKS) < LED_ON_TICKS) ? LED_RED : LED_GREEN; break; case PWR_STATE_CHARGE_NEAR_FULL: case PWR_STATE_IDLE: if(charge_get_flags() & CHARGE_FLAG_EXTERNAL_POWER) cur_led_color = LED_GREEN; else cur_led_color = LED_OFF; break; default: cur_led_color = LED_RED; break; } set_color(cur_led_color); if (chg_state != PWR_STATE_ERROR) power_ticks = 0; } /** * Called by hook task every 250 ms */ static void led_tick(void) { if (led_auto_control_is_enabled(EC_LED_ID_POWER_LED) && led_auto_control_is_enabled(EC_LED_ID_BATTERY_LED)) { nautilus_led_set_power_battery(); } } DECLARE_HOOK(HOOK_TICK, led_tick, HOOK_PRIO_DEFAULT);