diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2016-05-10 13:24:51 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-05-11 18:24:30 -0700 |
commit | 9494fc0dd10f1e6b59084c691f1f9f1499e401f1 (patch) | |
tree | 163ff88a7b731abfbdedc9852269ecd88b44a10a | |
parent | 3e9490031bbf5cd48c2acc314c38b201d50cb748 (diff) | |
download | chrome-ec-9494fc0dd10f1e6b59084c691f1f9f1499e401f1.tar.gz |
pwm: Add generic PWM control host commands
Add generic PWM host commands for setting + getting duty cycle. PWMs can
be controlled through index (board-specific meaning) or by type
(currently KB backlight and display backlight are supported, more can be
added as needed).
BUG=chrome-os-partner:52002
BRANCH=None
TEST=Manual on chell.
`ectool pwmsetduty kb 100` - Verify KB backlight goes to 100%
`ectool pwmgetduty kb` - Prints 100
`ectool pwmgetduty 0` - Prints 100
`ectool pwmsetduty 0 0` - Verify KB backlight goes to 0%
`ectool pwmgetduty kb` - Prints 0
`ectool pwmgetduty disp` - Error res 3 (unsupported PWM type)
`ectool pwmsetduty 1` - Error res 3 (non-existent PWM index)
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Change-Id: I607c92a291e6c2e3af8238eaf22ad2bb81ffc805
Reviewed-on: https://chromium-review.googlesource.com/344012
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r-- | board/kevin/board.c | 2 | ||||
-rw-r--r-- | board/kevin/board.h | 3 | ||||
-rw-r--r-- | common/pwm.c | 68 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/ec_commands.h | 31 | ||||
-rw-r--r-- | util/ectool.c | 85 |
6 files changed, 189 insertions, 3 deletions
diff --git a/board/kevin/board.c b/board/kevin/board.c index 75bf2b0302..e4a822fee6 100644 --- a/board/kevin/board.c +++ b/board/kevin/board.c @@ -72,7 +72,7 @@ const struct pwm_t pwm_channels[] = { #ifdef BOARD_KEVIN [PWM_CH_LED_GREEN] = { 0, PWM_CONFIG_DSLEEP, 100 }, #endif - [PWM_CH_BKLIGHT] = { 2, 0, 10000 }, + [PWM_CH_DISPLIGHT] = { 2, 0, 10000 }, [PWM_CH_LED_RED] = { 3, PWM_CONFIG_DSLEEP, 100 }, #ifdef BOARD_KEVIN [PWM_CH_LED_BLUE] = { 4, PWM_CONFIG_DSLEEP, 100 }, diff --git a/board/kevin/board.h b/board/kevin/board.h index 7f5e742a86..18c801ec99 100644 --- a/board/kevin/board.h +++ b/board/kevin/board.h @@ -14,6 +14,7 @@ #define CONFIG_HOSTCMD_SPS #define CONFIG_POWER_COMMON #define CONFIG_PWM +#define CONFIG_PWM_DISPLIGHT #ifdef BOARD_KEVIN #define CONFIG_LED_COMMON #endif @@ -132,7 +133,7 @@ enum pwm_channel { #ifdef BOARD_KEVIN PWM_CH_LED_GREEN, #endif - PWM_CH_BKLIGHT, + PWM_CH_DISPLIGHT, PWM_CH_LED_RED, #ifdef BOARD_KEVIN PWM_CH_LED_BLUE, diff --git a/common/pwm.c b/common/pwm.c index 7377d1d170..c689b0acac 100644 --- a/common/pwm.c +++ b/common/pwm.c @@ -7,10 +7,78 @@ #include "console.h" #include "gpio.h" #include "hooks.h" +#include "host_command.h" #include "pwm.h" #include "util.h" #ifdef CONFIG_PWM + +/* + * Get target channel based on type / index host command parameters. + * Returns 0 if a valid channel is selected, -1 on error. + */ +static int get_target_channel(enum pwm_channel *channel, int type, int index) +{ + switch (type) { + case EC_PWM_TYPE_GENERIC: + *channel = index; + break; +#ifdef CONFIG_PWM_KBLIGHT + case EC_PWM_TYPE_KB_LIGHT: + *channel = PWM_CH_KBLIGHT; + break; +#endif +#ifdef CONFIG_PWM_DISPLIGHT + case EC_PWM_TYPE_DISPLAY_LIGHT: + *channel = PWM_CH_DISPLIGHT; + break; +#endif + default: + return -1; + } + + return *channel >= PWM_CH_COUNT; +} + +static int 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 (p->percent > 100) + return EC_RES_INVALID_PARAM; + + if (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + pwm_set_duty(channel, p->percent); + pwm_enable(channel, p->percent > 0); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_SET_DUTY, + host_command_pwm_set_duty, + EC_VER_MASK(0)); + +static int 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 (get_target_channel(&channel, p->pwm_type, p->index)) + return EC_RES_INVALID_PARAM; + + r->percent = pwm_get_duty(channel); + args->response_size = sizeof(*r); + + return EC_RES_SUCCESS; +} +DECLARE_HOST_COMMAND(EC_CMD_PWM_GET_DUTY, + host_command_pwm_get_duty, + EC_VER_MASK(0)); + /** * Print status of a PWM channel. * diff --git a/include/config.h b/include/config.h index 19a51cd194..d80737d677 100644 --- a/include/config.h +++ b/include/config.h @@ -1475,6 +1475,9 @@ #undef CONFIG_PWM_INPUT_LFCLK /*****************************************************************************/ +/* Support PWM output to display backlight */ +#undef CONFIG_PWM_DISPLIGHT + /* Support PWM output to keyboard backlight */ #undef CONFIG_PWM_KBLIGHT diff --git a/include/ec_commands.h b/include/ec_commands.h index a205878bec..faeeb412fb 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1173,6 +1173,7 @@ struct ec_params_pwm_set_fan_target_rpm_v1 { } __packed; /* Get keyboard backlight */ +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ #define EC_CMD_PWM_GET_KEYBOARD_BACKLIGHT 0x22 struct ec_response_pwm_get_keyboard_backlight { @@ -1181,6 +1182,7 @@ struct ec_response_pwm_get_keyboard_backlight { } __packed; /* Set keyboard backlight */ +/* OBSOLETE - Use EC_CMD_PWM_SET_DUTY */ #define EC_CMD_PWM_SET_KEYBOARD_BACKLIGHT 0x23 struct ec_params_pwm_set_keyboard_backlight { @@ -1201,6 +1203,35 @@ struct ec_params_pwm_set_fan_duty_v1 { uint8_t fan_idx; } __packed; +#define EC_CMD_PWM_SET_DUTY 0x25 + +enum ec_pwm_type { + /* All types, indexed by board-specific enum pwm_channel */ + EC_PWM_TYPE_GENERIC = 0, + /* Keyboard backlight */ + EC_PWM_TYPE_KB_LIGHT, + /* Display backlight */ + EC_PWM_TYPE_DISPLAY_LIGHT, + EC_PWM_TYPE_COUNT, +}; + +struct ec_params_pwm_set_duty { + uint8_t percent; /* Duty cycle percent on [0, 100] */ + uint8_t pwm_type; /* ec_pwm_type */ + uint8_t index; /* Type-specific index, or 0 if unique */ +} __packed; + +#define EC_CMD_PWM_GET_DUTY 0x26 + +struct ec_params_pwm_get_duty { + uint8_t pwm_type; /* ec_pwm_type */ + uint8_t index; /* Type-specific index, or 0 if unique */ +} __packed; + +struct ec_response_pwm_get_duty { + uint8_t percent; +} __packed; + /*****************************************************************************/ /* * Lightbar commands. This looks worse than it is. Since we only use one HOST diff --git a/util/ectool.c b/util/ectool.c index 59793e21d6..0e3c1ee596 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -173,10 +173,14 @@ const char help_str[] = " Prints current keyboard backlight percent\n" " pwmgetnumfans\n" " Prints the number of fans present\n" + " pwmgetduty\n" + " Prints the current duty cycle for given PWM\n" " pwmsetfanrpm <targetrpm>\n" " Set target fan RPM\n" " pwmsetkblight <percent>\n" " Set keyboard backlight in percent\n" + " pwmsetduty\n" + " Set duty cycle of given PWM in percent\n" " readtest <patternoffset> <size>\n" " Reads a pattern from the EC via LPC\n" " reboot_ec <RO|RW|cold|hibernate|disable-jump> [at-shutdown]\n" @@ -1858,7 +1862,6 @@ int cmd_pwm_set_fan_rpm(int argc, char *argv[]) return 0; } - int cmd_pwm_get_keyboard_backlight(int argc, char *argv[]) { struct ec_response_pwm_get_keyboard_backlight r; @@ -1903,6 +1906,84 @@ int cmd_pwm_set_keyboard_backlight(int argc, char *argv[]) return 0; } +int cmd_pwm_get_duty(int argc, char *argv[]) +{ + struct ec_params_pwm_get_duty p; + struct ec_response_pwm_get_duty r; + char *e; + int rv; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <pwm_idx> | kb | disp\n", argv[0]); + return -1; + } + + if (!strcmp(argv[1], "kb")) { + p.pwm_type = EC_PWM_TYPE_KB_LIGHT; + p.index = 0; + } else if (!strcmp(argv[1], "disp")) { + p.pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT; + p.index = 0; + } else { + p.pwm_type = EC_PWM_TYPE_GENERIC; + p.index = strtol(argv[1], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad pwm_idx\n"); + return -1; + } + } + + rv = ec_command(EC_CMD_PWM_GET_DUTY, 0, &p, sizeof(p), &r, sizeof(r)); + if (rv < 0) + return rv; + + printf("Current PWM duty: %d\n", r.percent); + return 0; +} + + +int cmd_pwm_set_duty(int argc, char *argv[]) +{ + struct ec_params_pwm_set_duty p; + char *e; + int rv; + + if (argc != 3) { + fprintf(stderr, "Usage: %s <pwm_idx> | kb | disp <percent>\n", + argv[0]); + return -1; + } + + if (!strcmp(argv[1], "kb")) { + p.pwm_type = EC_PWM_TYPE_KB_LIGHT; + p.index = 0; + } else if (!strcmp(argv[1], "disp")) { + p.pwm_type = EC_PWM_TYPE_DISPLAY_LIGHT; + p.index = 0; + } else { + p.pwm_type = EC_PWM_TYPE_GENERIC; + p.index = strtol(argv[1], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad pwm_idx\n"); + return -1; + } + } + + p.percent = strtol(argv[2], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad percent.\n"); + return -1; + } + + rv = ec_command(EC_CMD_PWM_SET_DUTY, 0, + &p, sizeof(p), NULL, 0); + if (rv < 0) + return rv; + + printf("PWM set.\n"); + return 0; +} + int cmd_fanduty(int argc, char *argv[]) { struct ec_params_pwm_set_fan_duty_v1 p_v1; @@ -6602,8 +6683,10 @@ const struct command commands[] = { {"pwmgetfanrpm", cmd_pwm_get_fan_rpm}, {"pwmgetkblight", cmd_pwm_get_keyboard_backlight}, {"pwmgetnumfans", cmd_pwm_get_num_fans}, + {"pwmgetduty", cmd_pwm_get_duty}, {"pwmsetfanrpm", cmd_pwm_set_fan_rpm}, {"pwmsetkblight", cmd_pwm_set_keyboard_backlight}, + {"pwmsetduty", cmd_pwm_set_duty}, {"readtest", cmd_read_test}, {"reboot_ec", cmd_reboot_ec}, {"rtcget", cmd_rtc_get}, |