summaryrefslogtreecommitdiff
path: root/common/led_pwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/led_pwm.c')
-rw-r--r--common/led_pwm.c311
1 files changed, 0 insertions, 311 deletions
diff --git a/common/led_pwm.c b/common/led_pwm.c
deleted file mode 100644
index cc946ba522..0000000000
--- a/common/led_pwm.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/* Copyright 2018 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 LED control to conform to Chrome OS LED behaviour specification. */
-
-/*
- * This assumes that a single logical LED is shared between both power and
- * charging/battery status. If multiple logical LEDs are present, they all
- * follow the same patterns.
- */
-
-#include "battery.h"
-#include "charge_manager.h"
-#include "charge_state.h"
-#include "chipset.h"
-#include "common.h"
-#include "console.h"
-#include "ec_commands.h"
-#include "hooks.h"
-#include "led_common.h"
-#include "led_pwm.h"
-#include "pwm.h"
-#include "timer.h"
-#include "util.h"
-
-/* Battery percentage thresholds to blink at different rates. */
-#define CRITICAL_LOW_BATTERY_PERCENTAGE 3
-#define LOW_BATTERY_PERCENTAGE 10
-
-#define PULSE_TICK (250 * MSEC)
-
-static uint8_t led_is_pulsing;
-
-static int get_led_id_color(enum pwm_led_id id, int color)
-{
-#ifdef CONFIG_LED_PWM_ACTIVE_CHARGE_PORT_ONLY
- int active_chg_port = charge_manager_get_active_charge_port();
-
- /* We should always be able to turn off a LED. */
- if (color == -1)
- return -1;
-
- if (led_is_pulsing)
- return color;
-
- /* The inactive charge port LEDs should be off. */
- if ((int)id != active_chg_port)
- return -1;
-#endif /* CONFIG_LED_PWM_ACTIVE_CHARGE_PORT_ONLY */
- return color;
-}
-
-void set_pwm_led_color(enum pwm_led_id id, int color)
-{
- struct pwm_led duty = { 0 };
- const struct pwm_led *led = &pwm_leds[id];
-
- if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0) ||
- (color >= EC_LED_COLOR_COUNT) || (color < -1))
- return;
-
- if (color != -1) {
- duty.ch0 = led_color_map[color].ch0;
- duty.ch1 = led_color_map[color].ch1;
- duty.ch2 = led_color_map[color].ch2;
- }
-
- if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch0, duty.ch0);
- if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch1, duty.ch1);
- if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->set_duty(led->ch2, duty.ch2);
-}
-
-static void set_led_color(int color)
-{
- /*
- * We must check if auto control is enabled since the LEDs may be
- * controlled from the AP at anytime.
- */
- if ((led_auto_control_is_enabled(EC_LED_ID_POWER_LED)) ||
- (led_auto_control_is_enabled(EC_LED_ID_LEFT_LED)))
- set_pwm_led_color(PWM_LED0, get_led_id_color(PWM_LED0, color));
-
-#if CONFIG_LED_PWM_COUNT >= 2
- if (led_auto_control_is_enabled(EC_LED_ID_RIGHT_LED))
- set_pwm_led_color(PWM_LED1, get_led_id_color(PWM_LED1, color));
-#endif /* CONFIG_LED_PWM_COUNT >= 2 */
-}
-
-static void set_pwm_led_enable(enum pwm_led_id id, int enable)
-{
- const struct pwm_led *led = &pwm_leds[id];
-
- if ((id >= CONFIG_LED_PWM_COUNT) || (id < 0))
- return;
-
- if (led->ch0 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch0, enable);
- if (led->ch1 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch1, enable);
- if (led->ch2 != (enum pwm_channel)PWM_LED_NO_CHANNEL)
- led->enable(led->ch2, enable);
-}
-
-static void init_leds_off(void)
-{
- /* Turn off LEDs such that they are in a known state with zero duty. */
- set_led_color(-1);
-
- /* Enable pwm modules for each channels of LEDs */
- set_pwm_led_enable(PWM_LED0, 1);
-
-#if CONFIG_LED_PWM_COUNT >= 2
- set_pwm_led_enable(PWM_LED1, 1);
-#endif /* CONFIG_LED_PWM_COUNT >= 2 */
-}
-DECLARE_HOOK(HOOK_INIT, init_leds_off, HOOK_PRIO_INIT_PWM + 1);
-
-static uint8_t pulse_period;
-static uint8_t pulse_ontime;
-static enum ec_led_colors pulse_color;
-static void update_leds(void);
-static void pulse_leds_deferred(void);
-DECLARE_DEFERRED(pulse_leds_deferred);
-static void pulse_leds_deferred(void)
-{
- static uint8_t tick_count;
-
- if (!led_is_pulsing) {
- tick_count = 0;
- /*
- * Since we're not pulsing anymore, turn the colors off in case
- * we were in the "on" time.
- */
- set_led_color(-1);
- /* Then show the desired state. */
- update_leds();
- return;
- }
-
- if (tick_count < pulse_ontime)
- set_led_color(pulse_color);
- else
- set_led_color(-1);
-
- tick_count = (tick_count + 1) % pulse_period;
- hook_call_deferred(&pulse_leds_deferred_data, PULSE_TICK);
-}
-
-static void pulse_leds(enum ec_led_colors color, int ontime, int period)
-{
- pulse_color = color;
- pulse_ontime = ontime;
- pulse_period = period;
- led_is_pulsing = 1;
- pulse_leds_deferred();
-}
-
-static int show_charge_state(void)
-{
- enum charge_state chg_st = charge_get_state();
-
- /*
- * The colors listed below are the default, but can be overridden.
- *
- * Solid Amber == Charging
- * Solid Green == Charging (near full)
- * Fast Flash Red == Charging error or battery not present
- */
- if (chg_st == PWR_STATE_CHARGE) {
- led_is_pulsing = 0;
- set_led_color(CONFIG_LED_PWM_CHARGE_COLOR);
- } else if (chg_st == PWR_STATE_CHARGE_NEAR_FULL ||
- chg_st == PWR_STATE_DISCHARGE_FULL) {
- led_is_pulsing = 0;
- set_led_color(CONFIG_LED_PWM_NEAR_FULL_COLOR);
- } else if ((battery_is_present() != BP_YES) ||
- (chg_st == PWR_STATE_ERROR)) {
- /* 500 ms period, 50% duty cycle. */
- pulse_leds(CONFIG_LED_PWM_CHARGE_ERROR_COLOR, 1, 2);
- } else {
- /* Discharging or not charging. */
-#ifdef CONFIG_LED_PWM_CHARGE_STATE_ONLY
- /*
- * If we only show the charge state, the only reason we
- * would pulse the LEDs is if we had an error. If it no longer
- * exists, stop pulsing the LEDs.
- */
- led_is_pulsing = 0;
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
- return 0;
- }
- return 1;
-}
-
-#ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY
-static int show_battery_state(void)
-{
- int batt_percentage = charge_get_percent();
-
- /*
- * The colors listed below are the default, but can be overridden.
- *
- * Fast Flash Amber == Critical Battery
- * Slow Flash Amber == Low Battery
- */
- if (batt_percentage < CRITICAL_LOW_BATTERY_PERCENTAGE) {
- /* Flash amber faster (1 second period, 50% duty cycle) */
- pulse_leds(CONFIG_LED_PWM_LOW_BATT_COLOR, 2, 4);
- } else if (batt_percentage < LOW_BATTERY_PERCENTAGE) {
- /* Flash amber (4 second period, 50% duty cycle) */
- pulse_leds(CONFIG_LED_PWM_LOW_BATT_COLOR, 8, 16);
- } else {
- /* Sufficient charge, no need to show anything for this. */
- return 0;
- }
- return 1;
-}
-
-static int show_chipset_state(void)
-{
- /* Reflect the SoC state. */
- led_is_pulsing = 0;
- if (chipset_in_state(CHIPSET_STATE_ON)) {
- /* The LED must be on in the Active state. */
- set_led_color(CONFIG_LED_PWM_SOC_ON_COLOR);
- } else if (chipset_in_state(CHIPSET_STATE_ANY_SUSPEND)) {
- /* The power LED must pulse in the suspend state. */
- pulse_leds(CONFIG_LED_PWM_SOC_SUSPEND_COLOR, 4, 16);
- } else {
- /* Chipset is off, no need to show anything for this. */
- return 0;
- }
- return 1;
-}
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
-
-static void update_leds(void)
-{
- /* Reflecting the charge state is the highest priority. */
- if (show_charge_state())
- return;
-
-#ifndef CONFIG_LED_PWM_CHARGE_STATE_ONLY
- if (show_battery_state())
- return;
-
- if (show_chipset_state())
- return;
-#endif /* CONFIG_LED_PWM_CHARGE_STATE_ONLY */
-
- set_led_color(-1);
-}
-DECLARE_HOOK(HOOK_TICK, update_leds, HOOK_PRIO_DEFAULT);
-
-#ifdef CONFIG_CMD_LEDTEST
-int command_ledtest(int argc, char **argv)
-{
- int enable;
- int pwm_led_id;
- int led_id;
-
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
-
- pwm_led_id = atoi(argv[1]);
- if ((pwm_led_id < 0) || (pwm_led_id >= CONFIG_LED_PWM_COUNT))
- return EC_ERROR_PARAM1;
- led_id = supported_led_ids[pwm_led_id];
-
- if (argc == 2) {
- ccprintf("PWM LED %d: led_id=%d, auto_control=%d\n",
- pwm_led_id, led_id,
- led_auto_control_is_enabled(led_id) != 0);
- return EC_SUCCESS;
- }
- if (!parse_bool(argv[2], &enable))
- return EC_ERROR_PARAM2;
-
- /* Inverted because this drives auto control. */
- led_auto_control(led_id, !enable);
-
- if (argc == 4) {
- /* Set the color. */
- if (!strncmp(argv[3], "red", 3))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_RED);
- else if (!strncmp(argv[3], "green", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_GREEN);
- else if (!strncmp(argv[3], "amber", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_AMBER);
- else if (!strncmp(argv[3], "blue", 4))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_BLUE);
- else if (!strncmp(argv[3], "white", 5))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_WHITE);
- else if (!strncmp(argv[3], "yellow", 6))
- set_pwm_led_color(pwm_led_id, EC_LED_COLOR_YELLOW);
- else if (!strncmp(argv[3], "off", 3))
- set_pwm_led_color(pwm_led_id, -1);
- else
- return EC_ERROR_PARAM3;
- }
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(ledtest, command_ledtest,
- "<pwm led idx> <enable|disable> [color|off]", "");
-#endif /* defined(CONFIG_CMD_LEDTEST) */