From 985fe9a5e746db7fc2f2ad11e13ce3a77e138a4b Mon Sep 17 00:00:00 2001 From: Daisuke Nojiri Date: Thu, 7 Apr 2022 23:06:11 +0000 Subject: RGBKBD: Support backlight control via EC_CMD_PWM_SET_DUTY In a regular design, a keyboard backlight is connected to a PWM pin of an EC. With an RGB keyboard, the brightness control is part of the RGB keyboard functionality. Thus, EC_CMD_PWM_SET_DUTY with EC_PWM_TYPE_KB_LIGHT should be handled by an RGB keyboard API to control the keyboard backlight brightness. On host, run: localhost ~ # ectool pwmsetduty kb 0x8000 EC prints: RGBKBD: Set GCC to 128 BUG=b:228525798,b:226215987 BRANCH=None TEST=Taniks. See above. Signed-off-by: Daisuke Nojiri Change-Id: Id8f23ba67728f03664673834be0903e0f593e744 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3576897 Reviewed-by: Parth Malkan Reviewed-by: Zhuohao Lee --- common/pwm.c | 37 ++++++++++++++++++++++++++++--------- common/rgb_keyboard.c | 48 ++++++++++++++++++++++++++++++++++-------------- include/rgb_keyboard.h | 13 +++++++++++++ 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/common/pwm.c b/common/pwm.c index 74c079bbfd..7699405f3d 100644 --- a/common/pwm.c +++ b/common/pwm.c @@ -9,6 +9,7 @@ #include "hooks.h" #include "host_command.h" #include "pwm.h" +#include "rgb_keyboard.h" #include "util.h" #ifdef CONFIG_PWM @@ -64,11 +65,18 @@ host_command_pwm_set_duty(struct host_cmd_handler_args *args) const struct ec_params_pwm_set_duty *p = args->params; enum pwm_channel channel; - if (get_target_channel(&channel, p->pwm_type, p->index)) - return EC_RES_INVALID_PARAM; - - pwm_set_raw_duty(channel, p->duty); - pwm_enable(channel, p->duty > 0); + if (IS_ENABLED(CONFIG_RGB_KEYBOARD) && + (p->pwm_type == EC_PWM_TYPE_KB_LIGHT)) { + uint8_t gcc = DIV_ROUND_NEAREST(p->duty * RGBKBD_MAX_GCC_LEVEL, + EC_PWM_MAX_DUTY); + if (rgbkbd_set_global_brightness(gcc)) + return EC_RES_ERROR; + } else { + if (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + pwm_set_raw_duty(channel, p->duty); + pwm_enable(channel, p->duty > 0); + } return EC_RES_SUCCESS; } @@ -82,12 +90,23 @@ host_command_pwm_get_duty(struct host_cmd_handler_args *args) const struct ec_params_pwm_get_duty *p = args->params; struct ec_response_pwm_get_duty *r = args->response; - enum pwm_channel channel; + if (IS_ENABLED(CONFIG_RGB_KEYBOARD) && + (p->pwm_type == EC_PWM_TYPE_KB_LIGHT)) { + uint8_t gcc; - if (get_target_channel(&channel, p->pwm_type, p->index)) - return EC_RES_INVALID_PARAM; + if (rgbkbd_get_global_brightness(&gcc)) + return EC_RES_ERROR; + r->duty = DIV_ROUND_NEAREST(gcc * EC_PWM_MAX_DUTY, + RGBKBD_MAX_GCC_LEVEL); + } else { + enum pwm_channel channel; + + if (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->duty = pwm_get_raw_duty(channel); + } - r->duty = pwm_get_raw_duty(channel); args->response_size = sizeof(*r); return EC_RES_SUCCESS; diff --git a/common/rgb_keyboard.c b/common/rgb_keyboard.c index f581d5ae1a..0f66e6c242 100644 --- a/common/rgb_keyboard.c +++ b/common/rgb_keyboard.c @@ -233,6 +233,38 @@ void rgbkbd_init_lookup_table(void) */ } +int rgbkbd_set_global_brightness(uint8_t gcc) +{ + int e, grid; + int rv = EC_SUCCESS; + + for (grid = 0; grid < rgbkbd_count; grid++) { + struct rgbkbd *ctx = &rgbkbds[grid]; + + e = ctx->cfg->drv->set_gcc(ctx, gcc); + if (e) { + CPRINTS("Failed to set GCC to %u for grid=%d (%d)", + gcc, grid, e); + rv = e; + continue; + } + + ctx->gcc = gcc; + } + + CPRINTS("Set GCC to %u", gcc); + + /* Return EC_SUCCESS or the last error. */ + return rv; +} + +int rgbkbd_get_global_brightness(uint8_t *gcc) +{ + *gcc = rgbkbds[0].gcc; + + return EC_SUCCESS; +} + __overridable void board_enable_rgb_keyboard(bool enable) {} static int rgbkbd_init(void) @@ -307,19 +339,13 @@ static int rgbkbd_enable(int enable) void rgbkbd_task(void *u) { uint32_t event; - int i, rv; board_enable_rgb_keyboard(true); rgbkbd_init_lookup_table(); rgbkbd_init(); rgbkbd_enable(1); - for (i = 0; i < rgbkbd_count; i++) { - struct rgbkbd *ctx = &rgbkbds[i]; - rv = ctx->cfg->drv->set_gcc(ctx, 0x80); - if (rv) - CPRINTS("Failed to set GCC (%d)", rv); - } + rgbkbd_set_global_brightness(0x80); while (1) { event = task_wait_event(100 * MSEC); @@ -380,7 +406,6 @@ DECLARE_HOST_COMMAND(EC_CMD_RGBKBD, hc_rgbkbd, EC_VER_MASK(0)); test_export_static int cc_rgbk(int argc, char **argv) { - struct rgbkbd *ctx; char *end, *comma; struct rgb_s color; int gcc, x, y, val; @@ -421,12 +446,7 @@ test_export_static int cc_rgbk(int argc, char **argv) gcc = strtoi(argv[1], &end, 0); if (*end || gcc < 0 || gcc > UINT8_MAX) return EC_ERROR_PARAM1; - demo = RGBKBD_DEMO_OFF; - for (i = 0; i < rgbkbd_count; i++) { - ctx = &rgbkbds[i]; - ctx->cfg->drv->set_gcc(ctx, gcc); - } - return EC_SUCCESS; + return rgbkbd_set_global_brightness(gcc); } if (argc != 5) diff --git a/include/rgb_keyboard.h b/include/rgb_keyboard.h index 0500ce859f..f4c9540c63 100644 --- a/include/rgb_keyboard.h +++ b/include/rgb_keyboard.h @@ -12,6 +12,8 @@ /* Use this instead of '3' for readability where applicable. */ #define SIZE_OF_RGB sizeof(struct rgb_s) +#define RGBKBD_MAX_GCC_LEVEL 0xff + enum rgbkbd_demo { RGBKBD_DEMO_OFF = 0, RGBKBD_DEMO_FLOW = 1, @@ -37,6 +39,8 @@ struct rgbkbd { const struct rgbkbd_cfg * const cfg; /* Current state of the port */ enum rgbkbd_state state; + /* Global current control (a.k.a. backlight brightness) */ + uint8_t gcc; /* Buffer containing color info for each dot. */ struct rgb_s *buf; }; @@ -173,3 +177,12 @@ __override_proto void board_enable_rgb_keyboard(bool enable); */ extern const uint8_t rgbkbd_map[]; extern const size_t rgbkbd_map_size; + +/** + * Set/get global brightness of the RGB keyboard. + * + * @param gcc Brightness level 0 ~ RGBKBD_MAX_GCC_LEVEL. + * @return enum ec_error_list; + */ +int rgbkbd_set_global_brightness(uint8_t gcc); +int rgbkbd_get_global_brightness(uint8_t *gcc); -- cgit v1.2.1