summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2016-05-10 13:24:51 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-05-11 18:24:30 -0700
commit9494fc0dd10f1e6b59084c691f1f9f1499e401f1 (patch)
tree163ff88a7b731abfbdedc9852269ecd88b44a10a
parent3e9490031bbf5cd48c2acc314c38b201d50cb748 (diff)
downloadchrome-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.c2
-rw-r--r--board/kevin/board.h3
-rw-r--r--common/pwm.c68
-rw-r--r--include/config.h3
-rw-r--r--include/ec_commands.h31
-rw-r--r--util/ectool.c85
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},