diff options
author | Nicolas Boichat <drinkcat@chromium.org> | 2018-02-01 11:42:08 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-02-05 19:08:22 -0800 |
commit | bce23786d0bf606326b7acd752017732da896d11 (patch) | |
tree | 76412238d1c562743d8a69990c5e3a109a6e0690 | |
parent | 1af3e5362689497cbc5896cad8e907dd85c7e8ce (diff) | |
download | chrome-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>
-rw-r--r-- | driver/touchpad_elan.c | 63 |
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 |