summaryrefslogtreecommitdiff
path: root/drivers/platform/chrome/cros_ec_lightbar.c
diff options
context:
space:
mode:
authorEric Caruso <ejcaruso@chromium.org>2017-05-16 18:46:48 +0300
committerBenson Leung <bleung@chromium.org>2017-06-24 02:12:18 +0300
commit405c84308c4335ee7cb58b9304b77b85e61f7129 (patch)
tree1b487ce422a157890aed2ddacbb9cd5ecb18a83e /drivers/platform/chrome/cros_ec_lightbar.c
parentbe3ebebf4377fe924f0419f78fc82cf01a31e692 (diff)
downloadlinux-405c84308c4335ee7cb58b9304b77b85e61f7129.tar.xz
platform/chrome: cros_ec_lightbar - Control of suspend/resume lightbar sequence
Don't let EC control suspend/resume sequence. If the EC controls the lightbar and sets the sequence when it notices the chipset transitioning between states, we can't make exceptions for cases where we don't want to activate the lightbar. Instead, let's move the suspend/resume notifications into the kernel so we can selectively play the sequences. Signed-off-by: Eric Caruso <ejcaruso@chromium.org> Signed-off-by: Guenter Roeck <groeck@chromium.org> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> Acked-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Benson Leung <bleung@chromium.org>
Diffstat (limited to 'drivers/platform/chrome/cros_ec_lightbar.c')
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c85
1 files changed, 82 insertions, 3 deletions
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c
index 26675059707e..4df379dc4bb9 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -341,6 +341,80 @@ exit:
return ret;
}
+static int lb_send_empty_cmd(struct cros_ec_dev *ec, uint8_t cmd)
+{
+ struct ec_params_lightbar *param;
+ struct cros_ec_command *msg;
+ int ret;
+
+ msg = alloc_lightbar_cmd_msg(ec);
+ if (!msg)
+ return -ENOMEM;
+
+ param = (struct ec_params_lightbar *)msg->data;
+ param->cmd = cmd;
+
+ ret = lb_throttle();
+ if (ret)
+ goto error;
+
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0)
+ goto error;
+ if (msg->result != EC_RES_SUCCESS) {
+ ret = -EINVAL;
+ goto error;
+ }
+ ret = 0;
+error:
+ kfree(msg);
+
+ return ret;
+}
+
+int lb_manual_suspend_ctrl(struct cros_ec_dev *ec, uint8_t enable)
+{
+ struct ec_params_lightbar *param;
+ struct cros_ec_command *msg;
+ int ret;
+
+ msg = alloc_lightbar_cmd_msg(ec);
+ if (!msg)
+ return -ENOMEM;
+
+ param = (struct ec_params_lightbar *)msg->data;
+
+ param->cmd = LIGHTBAR_CMD_MANUAL_SUSPEND_CTRL;
+ param->manual_suspend_ctrl.enable = enable;
+
+ ret = lb_throttle();
+ if (ret)
+ goto error;
+
+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+ if (ret < 0)
+ goto error;
+ if (msg->result != EC_RES_SUCCESS) {
+ ret = -EINVAL;
+ goto error;
+ }
+ ret = 0;
+error:
+ kfree(msg);
+
+ return ret;
+}
+
+int lb_suspend(struct cros_ec_dev *ec)
+{
+ return lb_send_empty_cmd(ec, LIGHTBAR_CMD_SUSPEND);
+}
+
+int lb_resume(struct cros_ec_dev *ec)
+{
+ return lb_send_empty_cmd(ec, LIGHTBAR_CMD_RESUME);
+}
+
static ssize_t sequence_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -473,6 +547,11 @@ static struct attribute *__lb_cmds_attrs[] = {
NULL,
};
+bool ec_has_lightbar(struct cros_ec_dev *ec)
+{
+ return !!get_lightbar_version(ec, NULL, NULL);
+}
+
static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
@@ -489,10 +568,10 @@ static umode_t cros_ec_lightbar_attrs_are_visible(struct kobject *kobj,
return 0;
/* Only instantiate this stuff if the EC has a lightbar */
- if (get_lightbar_version(ec, NULL, NULL))
+ if (ec_has_lightbar(ec))
return a->mode;
- else
- return 0;
+
+ return 0;
}
struct attribute_group cros_ec_lightbar_attr_group = {