summaryrefslogtreecommitdiff
path: root/board/halvor
diff options
context:
space:
mode:
Diffstat (limited to 'board/halvor')
-rw-r--r--board/halvor/board.c50
-rw-r--r--board/halvor/board.h15
-rw-r--r--board/halvor/build.mk1
-rw-r--r--board/halvor/led.c103
4 files changed, 168 insertions, 1 deletions
diff --git a/board/halvor/board.c b/board/halvor/board.c
index a242c2431d..8bf58af26a 100644
--- a/board/halvor/board.c
+++ b/board/halvor/board.c
@@ -17,6 +17,8 @@
#include "lid_switch.h"
#include "power.h"
#include "power_button.h"
+#include "pwm.h"
+#include "pwm_chip.h"
#include "switch.h"
#include "system.h"
#include "task.h"
@@ -29,7 +31,9 @@
static void board_init(void)
{
- /* TODO */
+ /* Illuminate motherboard and daughter board LEDs equally to start. */
+ pwm_enable(PWM_CH_LED4_SIDESEL, 1);
+ pwm_set_duty(PWM_CH_LED4_SIDESEL, 50);
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
@@ -114,6 +118,50 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* PWM configuration */
+const struct pwm_t pwm_channels[] = {
+ [PWM_CH_LED1_BLUE] = {
+ .channel = 2,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ .freq = 2400,
+ },
+ [PWM_CH_LED2_GREEN] = {
+ .channel = 0,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ .freq = 2400,
+ },
+ [PWM_CH_LED3_RED] = {
+ .channel = 1,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ .freq = 2400,
+ },
+ [PWM_CH_LED4_SIDESEL] = {
+ .channel = 7,
+ .flags = PWM_CONFIG_ACTIVE_LOW | PWM_CONFIG_DSLEEP,
+ /* Run at a higher frequency than the color PWM signals to avoid
+ * timing-based color shifts.
+ */
+ .freq = 4800,
+ },
+ [PWM_CH_FAN] = {
+ .channel = 5,
+ .flags = PWM_CONFIG_OPEN_DRAIN,
+ .freq = 25000
+ },
+ [PWM_CH_KBLIGHT] = {
+ .channel = 3,
+ .flags = 0,
+ /*
+ * Set PWM frequency to multiple of 50 Hz and 60 Hz to prevent
+ * flicker. Higher frequencies consume similar average power to
+ * lower PWM frequencies, but higher frequencies record a much
+ * lower maximum power.
+ */
+ .freq = 2400,
+ },
+};
+BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
+
/******************************************************************************/
void halvor_tcpc_alert_event(enum gpio_signal signal)
{
diff --git a/board/halvor/board.h b/board/halvor/board.h
index c10447dba4..2b1ef9b176 100644
--- a/board/halvor/board.h
+++ b/board/halvor/board.h
@@ -19,6 +19,11 @@
#undef CONFIG_UART_TX_BUF_SIZE
#define CONFIG_UART_TX_BUF_SIZE 4096
+/* LED defines */
+#define CONFIG_LED_PWM
+/* Although there are 2 LEDs, they are both controlled by the same lines. */
+#define CONFIG_LED_PWM_COUNT 1
+
/* Keyboard features */
/* Sensors */
@@ -114,6 +119,16 @@ enum battery_type {
BATTERY_TYPE_COUNT,
};
+enum pwm_channel {
+ PWM_CH_LED1_BLUE = 0,
+ PWM_CH_LED2_GREEN,
+ PWM_CH_LED3_RED,
+ PWM_CH_LED4_SIDESEL,
+ PWM_CH_FAN,
+ PWM_CH_KBLIGHT,
+ PWM_CH_COUNT
+};
+
enum sensor_id {
LID_ACCEL = 0,
CLEAR_ALS,
diff --git a/board/halvor/build.mk b/board/halvor/build.mk
index d9d20ff7c7..f16b1520c0 100644
--- a/board/halvor/build.mk
+++ b/board/halvor/build.mk
@@ -29,5 +29,6 @@ ENV_VARS := VOLTEER_POWER_SEQUENCE
board-y=board.o
board-y+=battery.o
+board-y+=led.o
board-$(VOLTEER_POWER_SEQUENCE)+=power_sequence.o
board-y+=sensors.o
diff --git a/board/halvor/led.c b/board/halvor/led.c
new file mode 100644
index 0000000000..4e99b66579
--- /dev/null
+++ b/board/halvor/led.c
@@ -0,0 +1,103 @@
+/* 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 Halvor
+ */
+
+#include "charge_manager.h"
+#include "common.h"
+#include "ec_commands.h"
+#include "hooks.h"
+#include "led_common.h"
+#include "led_pwm.h"
+#include "pwm.h"
+
+const enum ec_led_id supported_led_ids[] = {
+ EC_LED_ID_POWER_LED,
+};
+const int supported_led_ids_count = ARRAY_SIZE(supported_led_ids);
+
+struct pwm_led led_color_map[] = {
+ /* Red, Green, Blue */
+ [EC_LED_COLOR_RED] = { 100, 0, 0 },
+ [EC_LED_COLOR_GREEN] = { 0, 100, 0 },
+ [EC_LED_COLOR_BLUE] = { 0, 0, 100 },
+ /* The green LED seems to be brighter than the others, so turn down
+ * green from its natural level for these secondary colors.
+ */
+ [EC_LED_COLOR_YELLOW] = { 100, 70, 0 },
+ [EC_LED_COLOR_WHITE] = { 100, 70, 100 },
+ [EC_LED_COLOR_AMBER] = { 100, 20, 0 },
+};
+
+struct pwm_led pwm_leds[] = {
+ /* 2 RGB diffusers controlled by 1 set of 3 channels. */
+ [PWM_LED0] = {
+ .ch0 = PWM_CH_LED3_RED,
+ .ch1 = PWM_CH_LED2_GREEN,
+ .ch2 = PWM_CH_LED1_BLUE,
+ .enable = &pwm_enable,
+ .set_duty = &pwm_set_duty,
+ },
+};
+
+void led_get_brightness_range(enum ec_led_id led_id, uint8_t *brightness_range)
+{
+ brightness_range[EC_LED_COLOR_RED] = 255;
+ brightness_range[EC_LED_COLOR_GREEN] = 255;
+ brightness_range[EC_LED_COLOR_BLUE] = 255;
+}
+
+int led_set_brightness(enum ec_led_id led_id, const uint8_t *brightness)
+{
+ enum pwm_led_id pwm_id;
+
+ /* Convert ec_led_id to pwm_led_id. */
+ if (led_id == EC_LED_ID_POWER_LED)
+ pwm_id = PWM_LED0;
+ else
+ return EC_ERROR_UNKNOWN;
+
+ if (brightness[EC_LED_COLOR_RED])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_RED);
+ else if (brightness[EC_LED_COLOR_GREEN])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_GREEN);
+ else if (brightness[EC_LED_COLOR_BLUE])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_BLUE);
+ else if (brightness[EC_LED_COLOR_YELLOW])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_YELLOW);
+ else if (brightness[EC_LED_COLOR_WHITE])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_WHITE);
+ else if (brightness[EC_LED_COLOR_AMBER])
+ set_pwm_led_color(pwm_id, EC_LED_COLOR_AMBER);
+ else
+ /* Otherwise, the "color" is "off". */
+ set_pwm_led_color(pwm_id, -1);
+
+ return EC_SUCCESS;
+}
+
+/* Illuminates the LED on the side of the active charging port. If not charging,
+ * illuminates both LEDs.
+ */
+static void led_set_charge_port_tick(void)
+{
+ int port;
+ int side_select_duty;
+
+ port = charge_manager_get_active_charge_port();
+ switch (port) {
+ case 0:
+ side_select_duty = 100;
+ break;
+ case 1:
+ side_select_duty = 0;
+ break;
+ default:
+ side_select_duty = 50;
+ }
+
+ pwm_set_duty(PWM_CH_LED4_SIDESEL, side_select_duty);
+}
+DECLARE_HOOK(HOOK_TICK, led_set_charge_port_tick, HOOK_PRIO_DEFAULT);