diff options
Diffstat (limited to 'board/lindar/led.c')
-rw-r--r-- | board/lindar/led.c | 793 |
1 files changed, 0 insertions, 793 deletions
diff --git a/board/lindar/led.c b/board/lindar/led.c deleted file mode 100644 index 6d602d5c4e..0000000000 --- a/board/lindar/led.c +++ /dev/null @@ -1,793 +0,0 @@ -/* Copyright 2020 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 for Malefor - */ - -#include "cbi_ssfc.h" -#include "charge_state.h" -#include "common.h" -#include "cros_board_info.h" -#include "extpower.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "ktd20xx.h" -#include "led_common.h" -#include "led_onoff_states.h" -#include "lid_switch.h" -#include "stdbool.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_CHARGER, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args) - -#define LED_OFF_LVL 1 -#define LED_ON_LVL 0 - -__override const int led_charge_lvl_1 = 5; - -__override const int led_charge_lvl_2 = 97; - -__override struct led_descriptor - led_bat_state_table[LED_NUM_STATES][LED_NUM_PHASES] = { - [STATE_CHARGING_LVL_1] = {{EC_LED_COLOR_RED, LED_INDEFINITE} }, - [STATE_CHARGING_LVL_2] = {{EC_LED_COLOR_AMBER, LED_INDEFINITE} }, - [STATE_CHARGING_FULL_CHARGE] = {{EC_LED_COLOR_GREEN, LED_INDEFINITE} }, - [STATE_DISCHARGE_S0] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S3] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_DISCHARGE_S5] = {{LED_OFF, LED_INDEFINITE} }, - [STATE_BATTERY_ERROR] = {{EC_LED_COLOR_RED, 1 * LED_ONE_SEC}, - {LED_OFF, 1 * LED_ONE_SEC} }, - [STATE_FACTORY_TEST] = {{EC_LED_COLOR_RED, 2 * LED_ONE_SEC}, - {EC_LED_COLOR_GREEN, 2 * LED_ONE_SEC} }, -}; - -__override const struct led_descriptor - led_pwr_state_table[PWR_LED_NUM_STATES][LED_NUM_PHASES] = { - [PWR_LED_STATE_ON] = {{EC_LED_COLOR_WHITE, LED_INDEFINITE} }, - [PWR_LED_STATE_SUSPEND_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_SUSPEND_NO_AC] = {{EC_LED_COLOR_WHITE, 1 * LED_ONE_SEC}, - {LED_OFF, 3 * LED_ONE_SEC} }, - [PWR_LED_STATE_OFF] = {{LED_OFF, LED_INDEFINITE} }, -}; - -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); - -__override void led_set_color_power(enum ec_led_colors color) -{ - if (color == EC_LED_COLOR_WHITE) - gpio_set_level(GPIO_LED_3_L, LED_ON_LVL); - else - /* LED_OFF and unsupported colors */ - gpio_set_level(GPIO_LED_3_L, LED_OFF_LVL); -} - -__override void led_set_color_battery(enum ec_led_colors color) -{ - switch (color) { - case EC_LED_COLOR_AMBER: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_RED: - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_ON_LVL); - break; - case EC_LED_COLOR_GREEN: - gpio_set_level(GPIO_LED_1_L, LED_ON_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - default: /* LED_OFF and other unsupported colors */ - gpio_set_level(GPIO_LED_1_L, LED_OFF_LVL); - gpio_set_level(GPIO_LED_2_L, LED_OFF_LVL); - break; - } -} - -void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - brightness_range[EC_LED_COLOR_RED] = 1; - brightness_range[EC_LED_COLOR_AMBER] = 1; - brightness_range[EC_LED_COLOR_GREEN] = 1; - } else if (led_id == EC_LED_ID_POWER_LED) { - brightness_range[EC_LED_COLOR_WHITE] = 1; - } -} - -int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness) -{ - if (led_id == EC_LED_ID_BATTERY_LED) { - if (brightness[EC_LED_COLOR_RED] != 0) - led_set_color_battery(EC_LED_COLOR_RED); - else if (brightness[EC_LED_COLOR_AMBER] != 0) - led_set_color_battery(EC_LED_COLOR_AMBER); - else if (brightness[EC_LED_COLOR_GREEN] != 0) - led_set_color_battery(EC_LED_COLOR_GREEN); - else - led_set_color_battery(LED_OFF); - } else if (led_id == EC_LED_ID_POWER_LED) { - if (brightness[EC_LED_COLOR_WHITE] != 0) - led_set_color_power(EC_LED_COLOR_WHITE); - else - led_set_color_power(LED_OFF); - } - - return EC_SUCCESS; -} - -static const uint16_t ktd2061_i2c_addr = 0x68; -static void controller_write(uint8_t reg, uint8_t val) -{ - uint8_t buf[2]; - - buf[0] = reg; - buf[1] = val; - - i2c_xfer_unlocked(I2C_PORT_LIGHTBAR, ktd2061_i2c_addr, - buf, 2, 0, 0, - I2C_XFER_SINGLE); -} - -enum lightbar_states { - LB_STATE_OFF, - LB_STATE_LID_CLOSE, - LB_STATE_SLEEP_AC_ONLY, - LB_STATE_SLEEP_AC_BAT_LOW, - LB_STATE_SLEEP_AC_BAT_LV1, - LB_STATE_SLEEP_AC_BAT_LV2, - LB_STATE_SLEEP_AC_BAT_LV3, - LB_STATE_SLEEP_AC_BAT_LV4, - LB_STATE_SLEEP_BAT_LOW, - LB_STATE_SLEEP_BAT_ONLY, - LB_STATE_S0_AC_ONLY, - LB_STATE_S0_BAT_LOW, - LB_STATE_S0_BAT_LV1, - LB_STATE_S0_BAT_LV2, - LB_STATE_S0_BAT_LV3, - LB_STATE_S0_BAT_LV4, - LB_NUM_STATES -}; - -/* - * All lightbar states should have one phase defined, - * and an additional phase can be defined for blinking - */ -enum lightbar_phase { - LIGHTBAR_PHASE_0 = 0, - LIGHTBAR_PHASE_1 = 1, - LIGHTBAR_NUM_PHASES -}; - -enum ec_lightbar_colors { - BAR_RESET, - BAR_OFF, - BAR_COLOR_ORG_20_PERCENT, - BAR_COLOR_GRN_40_PERCENT, - BAR_COLOR_GRN_60_PERCENT, - BAR_COLOR_GRN_80_PERCENT, - BAR_COLOR_GRN_FULL, - BAR_COLOR_ORG_FULL, - LIGHTBAR_COLOR_TOTAL -}; - -struct lightbar_descriptor { - enum ec_lightbar_colors color; - uint8_t ticks; -}; - -#define BAR_INFINITE UINT8_MAX -#define LIGHTBAR_ONE_SEC (1000 / HOOK_TICK_INTERVAL_MS) -#define LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP (3 * LIGHTBAR_ONE_SEC) -int lightbar_resume_tick; - -const struct lightbar_descriptor - lb_table[LB_NUM_STATES][LIGHTBAR_NUM_PHASES] = { - [LB_STATE_OFF] = {{BAR_OFF, BAR_INFINITE} }, - [LB_STATE_LID_CLOSE] = {{BAR_OFF, BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_ONLY] = {{BAR_OFF, BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_BAT_LOW] = {{BAR_COLOR_ORG_20_PERCENT, - BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_BAT_LV1] = {{BAR_COLOR_GRN_40_PERCENT, - BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_BAT_LV2] = {{BAR_COLOR_GRN_60_PERCENT, - BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_BAT_LV3] = {{BAR_COLOR_GRN_80_PERCENT, - BAR_INFINITE} }, - [LB_STATE_SLEEP_AC_BAT_LV4] = {{BAR_COLOR_GRN_FULL, BAR_INFINITE} }, - [LB_STATE_SLEEP_BAT_LOW] = {{BAR_OFF, 5 * LIGHTBAR_ONE_SEC}, - {BAR_COLOR_ORG_FULL, LIGHTBAR_ONE_SEC} }, - [LB_STATE_SLEEP_BAT_ONLY] = {{BAR_OFF, BAR_INFINITE} }, - [LB_STATE_S0_AC_ONLY] = {{BAR_OFF, BAR_INFINITE} }, - [LB_STATE_S0_BAT_LOW] = {{BAR_COLOR_ORG_20_PERCENT, - BAR_INFINITE} }, - [LB_STATE_S0_BAT_LV1] = {{BAR_COLOR_GRN_40_PERCENT, - BAR_INFINITE} }, - [LB_STATE_S0_BAT_LV2] = {{BAR_COLOR_GRN_60_PERCENT, - BAR_INFINITE} }, - [LB_STATE_S0_BAT_LV3] = {{BAR_COLOR_GRN_80_PERCENT, - BAR_INFINITE} }, - [LB_STATE_S0_BAT_LV4] = {{BAR_COLOR_GRN_FULL, BAR_INFINITE} }, -}; - -#define DISABLE_LIGHTBAR 0x00 -#define ENABLE_LIGHTBAR 0x80 -#define I_OFF 0x00 -#define GRN_I_ON 0x1E -#define ORG_I_ON 0x28 -#define SEL_OFF 0x00 -#define SEL_1ST_LED BIT(7) -#define SEL_2ND_LED BIT(3) -#define SEL_BOTH (SEL_1ST_LED | SEL_2ND_LED) -#define SKU_ID_NONE 0x00 -#define SKU_ID_INVALID 0x01 -#define LB_SUPPORTED_SKUID_LOWER 458700 -#define LB_SUPPORTED_SKUID_UPPER 458800 - -static bool lightbar_is_supported(void) -{ - static uint32_t skuid = SKU_ID_NONE; - bool result; - - /* lindar add SSFC tag to cbi image from "board_id = 3". */ - if (get_board_id() >= 3) { - if (get_cbi_ssfc_lightbar() == SSFC_LIGHTBAR_NONE) - return false; - return true; - } - - if (skuid == SKU_ID_NONE) { - if (cbi_get_sku_id(&skuid)) { - CPRINTS("Cannot get skuid for lightbar supported"); - skuid = SKU_ID_INVALID; - } - } - - /* - * If board_id = 1 or 2, it needs to check sku_id to know - * if system support lightbar or not. - */ - if (skuid >= LB_SUPPORTED_SKUID_LOWER && - skuid <= LB_SUPPORTED_SKUID_UPPER) - result = true; - else - result = false; - - return result; -} - -/* - * lightbar_enter_s0ix_s3: - * This flag is used to know if system ever enter S0ix/S3. - * Lightbar V9 SPEC define lightbar resuming behavior, "S0ix/S3 -> S0", - * but not include "G3/S5/S4 -> S0". "G3/S5/S4 -> S0" need to keep off. - */ -static bool lightbar_enter_s0ix_s3; - -/* - * lightbar_auto_control: - * We need some command for testing lightbar in factory. - * So, create this flag to stop regular action in lightbar_update(). - * - * lightbar_demo_state: - * It's used for testing lightbar via executing command under - * console. - */ -static bool lightbar_auto_control; -static enum lightbar_states lightbar_demo_state; - -static void lightbar_set_auto_control(bool state) -{ - lightbar_auto_control = state; -} - -static bool lightbar_is_auto_control(void) -{ - return lightbar_auto_control; -} - -static void lightbar_set_demo_state(enum lightbar_states tmp_state) -{ - if (tmp_state >= LB_NUM_STATES || tmp_state < LB_STATE_OFF) { - lightbar_demo_state = LB_NUM_STATES; - lightbar_resume_tick = 0; - } else { - lightbar_demo_state = tmp_state; - - if (lightbar_demo_state >= LB_STATE_S0_AC_ONLY) - lightbar_resume_tick = - LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP; - } - ccprintf("lightbar_demo_state = %d; lightbar_resume_tick %d.\n", - lightbar_demo_state, - lightbar_resume_tick); -} - -static enum lightbar_states lightbar_get_demo_state(void) -{ - /* - * Once tick count to zero, it needs to return LB_STATE_OFF to - * simulate lightbar off. - */ - if ((lightbar_demo_state != LB_NUM_STATES) && - (lightbar_demo_state >= LB_STATE_S0_AC_ONLY) && - (lightbar_resume_tick == 0)) - return LB_STATE_OFF; - - return lightbar_demo_state; -} - -static bool lightbar_is_enabled(void) -{ - if (!lightbar_is_supported()) - return false; - - /* - * Lightbar's I2C is powered by PP3300_A, and its power will be turn - * when system enter S4/S5. It may get I2C error if EC keep polling - * lightbar. We should stop it when EC doesn't turn on PP330_A. - */ - if (!board_is_i2c_port_powered(I2C_PORT_LIGHTBAR)) - return false; - - return true; -} - -/* - * From "board_id = 3", HW change lightbar circuit, and it only support - * two colors, orange (amber) and green. It connects KTD20xx's red-channel - * green color led, and green-channel to orange color led. - * Blue-channel is unused. - * - * The configuration format of lightbar_xx_led_cfg's is as below. - * ID_DAT, STATUS_REG, CTRL_CFG - * IRED_SET0, IGRN_SET0, IBLU_SET0, IRED_SET1, IGRN_SET1, IBLU_SET1 - * ISEL_A12, ISEL_A34, ISEL_B12, ISEL_B34, ISEL_C12, ISEL_C34 - */ -const uint8_t lightbar_10_led_cfg[LIGHTBAR_COLOR_TOTAL][KTD20XX_TOTOAL_REG] = { - [BAR_RESET] = { - 0x00, 0x00, DISABLE_LIGHTBAR, - I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_OFF] = { - 0x00, 0x00, DISABLE_LIGHTBAR, - I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_ORG_20_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - I_OFF, ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_OFF, SEL_BOTH, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_40_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_60_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_BOTH, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_80_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_FULL] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF - }, - [BAR_COLOR_ORG_FULL] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - I_OFF, ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF - } -}; - -const uint8_t lightbar_12_led_cfg[LIGHTBAR_COLOR_TOTAL][KTD20XX_TOTOAL_REG] = { - [BAR_RESET] = { - 0x00, 0x00, DISABLE_LIGHTBAR, - I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_OFF] = { - 0x00, 0x00, DISABLE_LIGHTBAR, - I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_ORG_20_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - I_OFF, ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_2ND_LED, SEL_BOTH, SEL_OFF, SEL_OFF, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_40_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_2ND_LED, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_60_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_2ND_LED, SEL_BOTH, SEL_OFF, SEL_OFF - }, - [BAR_COLOR_GRN_80_PERCENT] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_OFF, SEL_2ND_LED - }, - [BAR_COLOR_GRN_FULL] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - GRN_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH - }, - [BAR_COLOR_ORG_FULL] = { - 0x00, 0x00, ENABLE_LIGHTBAR, - I_OFF, ORG_I_ON, I_OFF, I_OFF, I_OFF, I_OFF, - SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH, SEL_BOTH - } -}; - -/* - * lightbar_ctrl is a pointer to 2-dimension lightbar configuration. It's used - * to base on DUT type to load different cfg. - * Default is lightbar_10_led_cfg. - */ -const uint8_t (*lightbar_ctrl)[KTD20XX_TOTOAL_REG] = lightbar_10_led_cfg; - -static void lightbar_set_color(enum ec_lightbar_colors color) -{ - enum ktd20xx_register i; - - if (color >= LIGHTBAR_COLOR_TOTAL) { - CPRINTS("Lightbar Error! Incorrect lightbard color %d", color); - color = BAR_RESET; - } - - i2c_lock(I2C_PORT_LIGHTBAR, 1); - for (i = KTD20XX_IRED_SET0; i <= KTD20XX_ISEL_C34; i++) - controller_write(i, lightbar_ctrl[color][i]); - - controller_write(KTD20XX_CTRL_CFG, - lightbar_ctrl[color][KTD20XX_CTRL_CFG]); - - i2c_lock(I2C_PORT_LIGHTBAR, 0); -} - -static void lightbar_init(void) -{ - if (!lightbar_is_enabled()) - return; - - if (get_cbi_ssfc_lightbar() == SSFC_LIGHTBAR_12_LED) - lightbar_ctrl = lightbar_12_led_cfg; - else - lightbar_ctrl = lightbar_10_led_cfg; - - /* Clear this flag if system doesn't enter S0ix/S3 */ - lightbar_enter_s0ix_s3 = false; - lightbar_resume_tick = 0; - - lightbar_set_color(BAR_RESET); -} - -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, lightbar_init, HOOK_PRIO_DEFAULT); - -static void lightbar_sleep_entry(void) -{ - if (!lightbar_is_enabled()) - return; - - lightbar_set_auto_control(true); - /* - * Set this flag, then EC'll base on it to set resume tick after - * S0ix/S3 exit. - */ - lightbar_enter_s0ix_s3 = true; - lightbar_resume_tick = 0; - - lightbar_set_color(BAR_RESET); -} - -DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, lightbar_sleep_entry, HOOK_PRIO_DEFAULT); - -static void lightbar_sleep_exit(void) -{ - if (!lightbar_is_enabled()) - return; - - lightbar_set_auto_control(true); - if (lightbar_enter_s0ix_s3) - lightbar_resume_tick = LIGHTBAR_COUNT_FOR_RESUME_FROM_SLEEP; - else - lightbar_resume_tick = 0; - lightbar_enter_s0ix_s3 = false; -} - -DECLARE_HOOK(HOOK_CHIPSET_RESUME, lightbar_sleep_exit, HOOK_PRIO_DEFAULT); - -#define LB_BAT_THRESHOLD_1 16 -#define LB_BAT_THRESHOLD_2 40 -#define LB_BAT_THRESHOLD_3 60 -#define LB_BAT_THRESHOLD_4 80 - -static enum lightbar_states lightbar_get_state(void) -{ - enum lightbar_states new_state = LB_NUM_STATES; - int cur_bat_percent; - - cur_bat_percent = charge_get_percent(); - - if (!lid_is_open()) - return LB_STATE_LID_CLOSE; - - if (lightbar_resume_tick) { - if ((battery_is_present() == BP_YES) && - charge_get_display_charge()) { - if (cur_bat_percent < LB_BAT_THRESHOLD_1) - new_state = LB_STATE_S0_BAT_LOW; - else if (cur_bat_percent < LB_BAT_THRESHOLD_2) - new_state = LB_STATE_S0_BAT_LV1; - else if (cur_bat_percent < LB_BAT_THRESHOLD_3) - new_state = LB_STATE_S0_BAT_LV2; - else if (cur_bat_percent < LB_BAT_THRESHOLD_4) - new_state = LB_STATE_S0_BAT_LV3; - else - new_state = LB_STATE_S0_BAT_LV4; - } else - new_state = LB_STATE_S0_AC_ONLY; - return new_state; - } - - if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) - return LB_STATE_OFF; - - if (extpower_is_present()) { - if ((battery_is_present() == BP_YES) && - charge_get_display_charge()) { - if (cur_bat_percent < LB_BAT_THRESHOLD_1) - new_state = LB_STATE_SLEEP_AC_BAT_LOW; - else if (cur_bat_percent < LB_BAT_THRESHOLD_2) - new_state = LB_STATE_SLEEP_AC_BAT_LV1; - else if (cur_bat_percent < LB_BAT_THRESHOLD_3) - new_state = LB_STATE_SLEEP_AC_BAT_LV2; - else if (cur_bat_percent < LB_BAT_THRESHOLD_4) - new_state = LB_STATE_SLEEP_AC_BAT_LV3; - else - new_state = LB_STATE_SLEEP_AC_BAT_LV4; - } else - new_state = LB_STATE_SLEEP_AC_ONLY; - } else { - if (cur_bat_percent < LB_BAT_THRESHOLD_1) - new_state = LB_STATE_SLEEP_BAT_LOW; - else - new_state = LB_STATE_SLEEP_BAT_ONLY; - } - - return new_state; -} - -#define LIGHTBAR_DEBOUNCE_TICKS 1 -static void lightbar_update(void) -{ - static uint8_t ticks, period; - static enum lightbar_states lb_cur_state = LB_NUM_STATES; - static int debounce_lightbar_state_update; - enum lightbar_states desired_state; - int phase; - - if (!lightbar_is_enabled()) - return; - - if (lightbar_is_auto_control()) - desired_state = lightbar_get_state(); - else { - desired_state = lightbar_get_demo_state(); - /* - * Stop to update lb_cur_state if desired_state is equal to - * LB_NUM_STATES. - */ - if (desired_state == LB_NUM_STATES) - return; - } - - if (lightbar_resume_tick) - lightbar_resume_tick--; - - if (desired_state != lb_cur_state && - desired_state < LB_NUM_STATES) { - /* State is changing */ - lb_cur_state = desired_state; - /* Reset ticks and period when state changes */ - ticks = 0; - - period = lb_table[lb_cur_state][LIGHTBAR_PHASE_0].ticks + - lb_table[lb_cur_state][LIGHTBAR_PHASE_1].ticks; - - /* - * System will be waken up when AC status change in S0ix. Due to - * EC may be late to update chipset state and cause lightbar - * flash a while when system transfer to S0. We add to debounce - * for any lightbar status change. - * It can make sure lightbar state is ready to to update. - */ - debounce_lightbar_state_update = LIGHTBAR_DEBOUNCE_TICKS; - } - - /* If this state is undefined, turn lightbar off */ - if (period == 0) { - CPRINTS("Undefined lightbar behavior for lightbar state %d," - "turning off lightbar", lb_cur_state); - lightbar_set_color(BAR_OFF); - return; - } - - if (debounce_lightbar_state_update != 0) { - debounce_lightbar_state_update--; - return; - } - - /* - * Determine which phase of the state table to use. The phase is - * determined if it falls within first phase time duration. - */ - phase = ticks < lb_table[lb_cur_state][LIGHTBAR_PHASE_0].ticks ? 0 : 1; - ticks = (ticks + 1) % period; - - /* Set the color for the given state and phase */ - lightbar_set_color(lb_table[lb_cur_state][phase].color); - -} - -DECLARE_HOOK(HOOK_TICK, lightbar_update, HOOK_PRIO_DEFAULT); - -/****************************************************************************/ -/* EC console commands for lightbar */ -/****************************************************************************/ -static void lightbar_dump_status(void) -{ - uint32_t cbi_bid, cbi_skuid; - int cbi_ssfc_lightbar; - - ccprintf("lightbar is %ssupported, %sabled, auto_control: %sabled\n", - lightbar_is_supported()?"":"un-", - lightbar_is_enabled()?"en":"dis", - lightbar_is_auto_control()?"en":"dis"); - - cbi_bid = get_board_id(); - cbi_get_sku_id(&cbi_skuid); - cbi_ssfc_lightbar = get_cbi_ssfc_lightbar(); - ccprintf("board id = %d, skuid = %d, ssfc_lightbar = %d\n", - cbi_bid, - cbi_skuid, - cbi_ssfc_lightbar); -} - -#ifdef CONFIG_CONSOLE_CMDHELP -static int help(const char *cmd) -{ - ccprintf("Usage:\n"); - ccprintf(" %s - dump lightbar status\n", cmd); - ccprintf(" %s on - set on lightbar auto control\n", - cmd); - ccprintf(" %s off - set off lightbar auto control\n", - cmd); - ccprintf(" %s demo [%x - %x] - demo lightbar state\n", - cmd, LB_STATE_OFF, (LB_NUM_STATES - 1)); - return EC_SUCCESS; -} -#endif - -static int command_lightbar(int argc, char **argv) -{ - /* no args = dump lightbar status */ - if (argc == 1) { - lightbar_dump_status(); - return EC_SUCCESS; - } - - if (!strcasecmp(argv[1], "help")) { - #ifdef CONFIG_CONSOLE_CMDHELP - help(argv[0]); - #endif - return EC_SUCCESS; - } - - if (!lightbar_is_enabled()) { - lightbar_dump_status(); - return EC_ERROR_UNIMPLEMENTED; - } - - if (!strcasecmp(argv[1], "on")) { - lightbar_set_auto_control(true); - return EC_SUCCESS; - } - - if (!strcasecmp(argv[1], "off")) { - lightbar_set_auto_control(false); - lightbar_set_demo_state(LB_NUM_STATES); - return EC_SUCCESS; - } - - if (!strcasecmp(argv[1], "demo")) { - int lb_demo_state; - char *e; - - /* Need to disable auto_control before demo */ - if (lightbar_is_auto_control()) { - ccprintf("Please set off auto control before demo.\n"); - return EC_ERROR_ACCESS_DENIED; - } - - lb_demo_state = 0xff & strtoi(argv[2], &e, 16); - lightbar_set_demo_state(lb_demo_state); - return EC_SUCCESS; - } - -#ifdef CONFIG_CONSOLE_CMDHELP - help(argv[0]); -#endif - - return EC_ERROR_INVAL; -} - -DECLARE_CONSOLE_COMMAND(lightbar, command_lightbar, - "[help | on | off | demo]", - "get/set lightbar status"); - -/****************************************************************************/ -/* EC host commands (ectool) for lightbar */ -/****************************************************************************/ -static enum ec_status lpc_cmd_lightbar(struct host_cmd_handler_args *args) -{ - const struct ec_params_lightbar *in = args->params; - int lb_demo_state; - - /* - * HOST_CMD is binded with ectool. From ectool.c, it already define - * command format. - * We only base on "off", "on", and "seq" to do what we can do - * now. - * Originally, I expect to use "demo", but it limit "in->demo.num" - * within 0~1. So, adopt "seq" command for basic testing. - */ - switch (in->cmd) { - case LIGHTBAR_CMD_OFF: - lightbar_set_auto_control(false); - lightbar_set_demo_state(LB_NUM_STATES); - break; - case LIGHTBAR_CMD_ON: - lightbar_set_auto_control(true); - break; - case LIGHTBAR_CMD_SEQ: - lb_demo_state = in->seq.num; - if (lightbar_is_auto_control()) { - CPRINTS("Please set off auto control before demo."); - return EC_RES_ACCESS_DENIED; - } - lightbar_set_demo_state(lb_demo_state); - break; - default: - CPRINTS("LB bad cmd 0x%x", in->cmd); - return EC_RES_INVALID_PARAM; - } - - return EC_RES_SUCCESS; -} - -DECLARE_HOST_COMMAND(EC_CMD_LIGHTBAR_CMD, - lpc_cmd_lightbar, - EC_VER_MASK(0)); |