@@ -37,6 +37,9 @@
#define WORK_REGISTER_NUM_X 0x33
#define WORK_REGISTER_NUM_Y 0x34
+#define PMOD_REGISTER_ACTIVE 0x00
+#define PMOD_REGISTER_HIBERNATE 0x03
+
#define M09_REGISTER_THRESHOLD 0x80
#define M09_REGISTER_GAIN 0x92
#define M09_REGISTER_OFFSET 0x93
@@ -52,6 +55,7 @@
#define WORK_REGISTER_OPMODE 0x3c
#define FACTORY_REGISTER_OPMODE 0x01
+#define PMOD_REGISTER_OPMODE 0xa5
#define TOUCH_EVENT_DOWN 0x00
#define TOUCH_EVENT_UP 0x01
@@ -1204,19 +1208,51 @@ static int edt_ft5x06_ts_remove(struct i2c_client *client)
static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
+ int ret;
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
enable_irq_wake(client->irq);
+ return 0;
+ }
- return 0;
+ /*
+ * Hibernate mode requires reset or wake signal to recover to active
+ * state.
+ */
+ if (!tsdata->wake_gpio && !tsdata->reset_gpio)
+ return 0;
+
+ ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE,
+ PMOD_REGISTER_HIBERNATE);
+ if (ret)
+ dev_err(dev, "Failed to set hibernate mode\n");
+
+ return ret;
}
static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
disable_irq_wake(client->irq);
+ return 0;
+ }
+
+ /* Recover from hibernate mode if hardware supports it */
+ if (tsdata->wake_gpio) {
+ gpiod_set_value_cansleep(tsdata->wake_gpio, 0);
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
+ msleep(300);
+ } else if (tsdata->reset_gpio) {
+ gpiod_set_value_cansleep(tsdata->reset_gpio, 1);
+ usleep_range(5000, 6000);
+ gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
+ msleep(300);
+ }
return 0;
}
It is possible to bring the device into a deep sleep state. To exit this state the reset or wakeup pin must be toggeled as documented in [1]. Because of the poor documentation I used the several downstream kernels [2] and other applications notes [3] to indentify the related registers. [1] https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/ \ FT5x26.pdf [2] https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-3.4/drivers/ \ input/touchscreen/ft5x_ts.c https://github.com/Pablito2020/focaltech-touch-driver/blob/master/ \ ft5336_driver.c [3] https://www.newhavendisplay.com/appnotes/datasheets/touchpanel/ \ FT5x16_registers.pdf Signed-off-by: Marco Felsch <m.felsch@pengutronix.de> --- drivers/input/touchscreen/edt-ft5x06.c | 42 ++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-)