From 17d9b2d9c096cf9112fb5c38da03b734a30c93c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= Date: Sun, 25 Apr 2021 03:16:42 +0200 Subject: [PATCH 085/464] input: goodix: Add option to power off the controller during suspend For whatever reason the controller is not suspended on Pinephone by the default procedure. It consumes quite a bit of power (~40mW) during system sleep, and more when the screen is touched. Let's power off the controller during system sleep instead. Signed-off-by: Ondrej Jirman --- drivers/input/touchscreen/goodix.c | 37 ++++++++++++++++++++++++++++++ drivers/input/touchscreen/goodix.h | 1 + 2 files changed, 38 insertions(+) diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 60e4034cf00a..fda05da2957b 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -1307,6 +1307,7 @@ static void goodix_disable_regulators(void *arg) static int goodix_ts_probe(struct i2c_client *client) { + struct device_node *np = client->dev.of_node; struct goodix_ts_data *ts; const char *cfg_name; int error; @@ -1326,6 +1327,7 @@ static int goodix_ts_probe(struct i2c_client *client) i2c_set_clientdata(client, ts); init_completion(&ts->firmware_loading_complete); ts->contact_size = GOODIX_CONTACT_SIZE; + ts->poweroff_in_suspend = of_property_read_bool(np, "poweroff-in-suspend"); error = goodix_get_gpio_config(ts); if (error) @@ -1435,6 +1437,15 @@ static int goodix_suspend(struct device *dev) if (ts->load_cfg_from_disk) wait_for_completion(&ts->firmware_loading_complete); + if (ts->poweroff_in_suspend) { + goodix_free_irq(ts); + goodix_irq_direction_output(ts, 0); + gpiod_direction_output(ts->gpiod_rst, 0); + regulator_disable(ts->avdd28); + regulator_disable(ts->vddio); + return 0; + } + /* We need gpio pins to suspend/resume */ if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) { disable_irq(client->irq); @@ -1480,6 +1491,32 @@ static int goodix_resume(struct device *dev) u8 config_ver; int error; + if (ts->poweroff_in_suspend) { + error = regulator_enable(ts->avdd28); + if (error) { + dev_err(dev, "Regulator avdd28 enable failed.\n"); + return error; + } + + error = regulator_enable(ts->vddio); + if (error) { + dev_err(dev, "Regulator vddio enable failed.\n"); + return error; + } + + error = goodix_reset(ts); + if (error) { + dev_err(dev, "Controller reset failed.\n"); + return error; + } + + error = goodix_request_irq(ts); + if (error) + return error; + + return 0; + } + if (ts->irq_pin_access_method == IRQ_PIN_ACCESS_NONE) { enable_irq(client->irq); return 0; diff --git a/drivers/input/touchscreen/goodix.h b/drivers/input/touchscreen/goodix.h index 7c44aa110ee6..db9f03149b11 100644 --- a/drivers/input/touchscreen/goodix.h +++ b/drivers/input/touchscreen/goodix.h @@ -105,6 +105,7 @@ struct goodix_ts_data { int bak_ref_len; u8 *bak_ref; struct dentry *debug_root; + bool poweroff_in_suspend; }; int goodix_i2c_read(struct i2c_client *client, u16 reg, u8 *buf, int len); -- 2.34.1