summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-02-01 11:42:08 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-02-05 19:08:22 -0800
commitbce23786d0bf606326b7acd752017732da896d11 (patch)
tree76412238d1c562743d8a69990c5e3a109a6e0690 /driver
parent1af3e5362689497cbc5896cad8e907dd85c7e8ce (diff)
downloadchrome-ec-bce23786d0bf606326b7acd752017732da896d11.tar.gz
touchpad_elan: Power off when USB is suspended without wake
touchpad can be powered off when the USB interface is disabled without setting the remote wake feature (USB_REQ_FEATURE_DEVICE_REMOTE_WAKEUP), as events would be ignored anyway. BRANCH=none BUG=b:72683995 TEST=touchpad is disabled when lid is closed. Change-Id: I688fce16ab8c75330e588ec130fb2aa499fc0ed1 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/897069 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/touchpad_elan.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/driver/touchpad_elan.c b/driver/touchpad_elan.c
index 9c5a924239..d8bf402ea4 100644
--- a/driver/touchpad_elan.c
+++ b/driver/touchpad_elan.c
@@ -16,6 +16,7 @@
#include "touchpad.h"
#include "update_fw.h"
#include "util.h"
+#include "usb_api.h"
#include "usb_hid_touchpad.h"
/* Console output macros */
@@ -23,6 +24,9 @@
#define CPRINTF(format, args...) cprintf(CC_TOUCHPAD, format, ## args)
#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args)
+#define TASK_EVENT_POWERON TASK_EVENT_CUSTOM(1)
+#define TASK_EVENT_POWEROFF TASK_EVENT_CUSTOM(2)
+
/******************************************************************************/
/* How to talk to the controller */
/******************************************************************************/
@@ -43,10 +47,13 @@
#define ETP_I2C_RESOLUTION_CMD 0x0108
#define ETP_I2C_PRESSURE_CMD 0x010A
#define ETP_I2C_SET_CMD 0x0300
+#define ETP_I2C_POWER_CMD 0x0307
#define ETP_I2C_FW_CHECKSUM_CMD 0x030F
#define ETP_ENABLE_ABS 0x0001
+#define ETP_DISABLE_POWER 0x0001
+
#define ETP_I2C_REPORT_LEN 34
#define ETP_MAX_FINGERS 5
@@ -136,6 +143,35 @@ static int elan_tp_write_cmd(uint16_t reg, uint16_t val)
return rv;
}
+/* Power is on by default. */
+static int elan_tp_power = 1;
+
+static int elan_tp_set_power(int enable)
+{
+ int rv;
+ uint16_t val;
+
+ if ((enable && elan_tp_power) || (!enable && !elan_tp_power))
+ return EC_SUCCESS;
+
+ CPRINTS("elan TP power %s", enable ? "on" : "off");
+
+ rv = elan_tp_read_cmd(ETP_I2C_POWER_CMD, &val);
+ if (rv)
+ goto out;
+
+ if (enable)
+ val &= ~ETP_DISABLE_POWER;
+ else
+ val |= ETP_DISABLE_POWER;
+
+ rv = elan_tp_write_cmd(ETP_I2C_POWER_CMD, val);
+
+ elan_tp_power = enable;
+out:
+ return rv;
+}
+
static int finger_status[ETP_MAX_FINGERS] = {0};
/*
@@ -677,11 +713,34 @@ void touchpad_interrupt(enum gpio_signal signal)
void touchpad_task(void *u)
{
+ uint32_t event;
+
elan_tp_init();
while (1) {
- task_wait_event(-1);
+ event = task_wait_event(-1);
+
+ if (event & TASK_EVENT_WAKE)
+ elan_tp_read_report_retry();
- elan_tp_read_report_retry();
+ if (event & TASK_EVENT_POWERON)
+ elan_tp_set_power(1);
+ else if (event & TASK_EVENT_POWEROFF)
+ elan_tp_set_power(0);
}
}
+
+#ifdef CONFIG_USB_SUSPEND
+static void touchpad_usb_pm_change(void)
+{
+ /*
+ * If USB interface is suspended, and host is not asking us to do remote
+ * wakeup, we can turn off the touchpad.
+ */
+ if (usb_is_suspended() && !usb_is_remote_wakeup_enabled())
+ task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_POWEROFF, 0);
+ else
+ task_set_event(TASK_ID_TOUCHPAD, TASK_EVENT_POWERON, 0);
+}
+DECLARE_HOOK(HOOK_USB_PM_CHANGE, touchpad_usb_pm_change, HOOK_PRIO_DEFAULT);
+#endif