summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2014-12-16 10:22:09 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-06 01:19:06 +0000
commit6fec4e4a69729cc715ceddaf9e8c6fad4ddacc80 (patch)
tree7b1d7253e07cbd22f7d5e775e830448ea2d77406
parent23fa3236aef2f4fe32d3368d439ee93a5b2a4577 (diff)
downloadchrome-ec-6fec4e4a69729cc715ceddaf9e8c6fad4ddacc80.tar.gz
lightbar: Pulse lightbar in S5 if power-up is inhibited
Add a lightbar indicator if a charger is attached and we refuse to power-up the AP due to battery level. BUG=chrome-os-partner:31127 TEST=Manual on Samus. Attach charger with depleted battery, verify that lightbar pulses red. Remove charger and verify that lightbar stops pulsing. Also verify the same with missing battery. BRANCH=Samus Change-Id: Icddd543dc34e36ac04957ea07bde0e2d5709f74b Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/236023 Reviewed-by: Alec Berg <alecaberg@chromium.org>
-rw-r--r--common/lightbar.c78
-rw-r--r--include/ec_commands.h5
2 files changed, 79 insertions, 4 deletions
diff --git a/common/lightbar.c b/common/lightbar.c
index ab9bfa8985..ea9ce9b6d4 100644
--- a/common/lightbar.c
+++ b/common/lightbar.c
@@ -55,6 +55,9 @@ static struct p_state {
/* It's either charging or discharging. */
int battery_is_charging;
+ /* Is power-on prevented due to battery level? */
+ int battery_is_power_on_prevented;
+
/* Pattern variables for state S0. */
uint16_t w0; /* primary phase */
uint8_t ramp; /* ramp-in for S3->S0 */
@@ -75,6 +78,8 @@ static const struct lightbar_params_v1 default_params = {
.s3_sleep_for = 5 * SECOND, /* between checks */
.s3_ramp_up = 2500,
.s3_ramp_down = 10000,
+ .s5_ramp_up = 2500,
+ .s5_ramp_down = 10000,
.tap_tick_delay = 5000, /* oscillation step time */
.tap_gate_delay = 200 * MSEC, /* segment gating delay */
.tap_display_time = 3 * SECOND, /* total sequence time */
@@ -103,6 +108,7 @@ static const struct lightbar_params_v1 default_params = {
{ 5, 0xff, 0xff, 0xff }, /* battery: 0 = red, else off */
{ 0xff, 0xff, 0xff, 0xff } /* AC: do nothing */
},
+ .s5_idx = 5, /* flash red */
.color = {
/*
* These values have been optically calibrated for the
@@ -187,6 +193,7 @@ static void get_battery_level(void)
#ifdef HAS_TASK_CHARGER
st.battery_percent = pct = charge_get_percent();
st.battery_is_charging = (PWR_STATE_DISCHARGE != charge_get_state());
+ st.battery_is_power_on_prevented = charge_prevent_power_on();
#endif
/* Find the new battery level */
@@ -647,13 +654,76 @@ static uint32_t sequence_S3S5(void)
return LIGHTBAR_S5;
}
-/* CPU is off. The lightbar loses power when the CPU is in S5, so there's
- * nothing to do. We'll just wait here until the state changes. */
+/* Pulse S5 color to indicate that the battery is so critically low that it
+ * must charge first before the system can power on. */
+static uint32_t pulse_s5_color(void)
+{
+ int r, g, b;
+ int f;
+ int w;
+ struct rgb_s *color = &st.p.color[st.p.s5_idx];
+
+ for (w = 0; w < 128; w += 2) {
+ f = cycle_010(w);
+ r = color->r * f / FP_SCALE;
+ g = color->g * f / FP_SCALE;
+ b = color->b * f / FP_SCALE;
+ lb_set_rgb(NUM_LEDS, r, g, b);
+ WAIT_OR_RET(st.p.s5_ramp_up);
+ }
+ for (w = 128; w <= 256; w++) {
+ f = cycle_010(w);
+ r = color->r * f / FP_SCALE;
+ g = color->g * f / FP_SCALE;
+ b = color->b * f / FP_SCALE;
+ lb_set_rgb(NUM_LEDS, r, g, b);
+ WAIT_OR_RET(st.p.s5_ramp_down);
+ }
+
+ return 0;
+}
+
+/* CPU is off. Pulse the lightbar if a charger is attached and the battery is
+ * so low that the system cannot power on. Otherwise, the lightbar loses power
+ * when the CPU is in S5, so there's nothing to do. We'll just wait here until
+ * the state changes. */
static uint32_t sequence_S5(void)
{
+ int initialized = 0;
+ uint32_t res = 0;
+
+ while (1) {
+ get_battery_level();
+ if (!st.battery_is_power_on_prevented ||
+ !st.battery_is_charging)
+ break;
+
+ if (!initialized) {
+#ifdef CONFIG_LIGHTBAR_POWER_RAILS
+ /* Request that lightbar power rails be turned on. */
+ if (lb_power(1)) {
+ lb_init();
+ lb_set_rgb(NUM_LEDS, 0, 0, 0);
+ }
+#endif
+ lb_on();
+ initialized = 1;
+ }
+
+ res = pulse_s5_color();
+ if (res)
+ break;
+ }
+
+#ifdef CONFIG_LIGHTBAR_POWER_RAILS
+ if (initialized)
+ /* Suggest that the lightbar power rails can be shut down. */
+ lb_power(0);
+#endif
lb_off();
- WAIT_OR_RET(-1);
- return 0;
+ if (!res)
+ WAIT_OR_RET(-1);
+ return res;
}
/* The AP is going to poke at the lightbar directly, so we don't want the EC
diff --git a/include/ec_commands.h b/include/ec_commands.h
index d10cd62d1d..0a6858e2f2 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1017,6 +1017,8 @@ struct lightbar_params_v1 {
int32_t s3_sleep_for;
int32_t s3_ramp_up;
int32_t s3_ramp_down;
+ int32_t s5_ramp_up;
+ int32_t s5_ramp_down;
int32_t tap_tick_delay;
int32_t tap_gate_delay;
int32_t tap_display_time;
@@ -1046,6 +1048,9 @@ struct lightbar_params_v1 {
uint8_t s0_idx[2][LB_BATTERY_LEVELS]; /* AP is running */
uint8_t s3_idx[2][LB_BATTERY_LEVELS]; /* AP is sleeping */
+ /* s5: single color pulse on inhibited power-up */
+ uint8_t s5_idx;
+
/* Color palette */
struct rgb_s color[8]; /* 0-3 are Google colors */
} __packed;