input: synaptics_i2c_rmi4: Allow GPIOs to suspend during sleep
In order to save power, enable GPIOs to go into suspened mode
during sleep by freeing them, and re-requesting on wake.
Change-Id: I5b1839f5a15fff0bad13b636be35079a8687fa6a
Signed-off-by: Amy Maloche <amaloche@codeaurora.org>
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 438f701..0b234ce 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1058,6 +1058,8 @@
"synaptics,i2c-pull-up");
rmi4_pdata->power_down_enable = of_property_read_bool(np,
"synaptics,power-down");
+ rmi4_pdata->disable_gpios = of_property_read_bool(np,
+ "synaptics,disable-gpios");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
@@ -2022,6 +2024,85 @@
return 0;
}
+static int synaptics_rmi4_gpio_configure(struct synaptics_rmi4_data *rmi4_data,
+ bool on)
+{
+ int retval = 0;
+
+ if (on) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(rmi4_data->board->irq_gpio,
+ "rmi4_irq_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_req;
+ }
+ retval = gpio_direction_input(rmi4_data->board->\
+ irq_gpio);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_dir;
+ }
+ } else {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(rmi4_data->board->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(rmi4_data->board->reset_gpio,
+ "rmi4_reset_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->reset_gpio);
+ goto err_irq_gpio_dir;
+ }
+
+ retval = gpio_direction_output(rmi4_data->board->\
+ reset_gpio, 1);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->reset_gpio);
+ goto err_reset_gpio_dir;
+ }
+
+ gpio_set_value(rmi4_data->board->reset_gpio, 0);
+ usleep(RMI4_GPIO_SLEEP_LOW_US);
+ gpio_set_value(rmi4_data->board->reset_gpio, 1);
+ msleep(RESET_DELAY);
+ } else
+ synaptics_rmi4_reset_command(rmi4_data);
+
+ return 0;
+ } else {
+ if (rmi4_data->board->disable_gpios) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ }
+
+ return 0;
+ }
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_irq_gpio_req:
+ return retval;
+}
+
/**
* synaptics_rmi4_probe()
*
@@ -2151,52 +2232,12 @@
goto err_power_device;
}
- if (gpio_is_valid(platform_data->irq_gpio)) {
- /* configure touchscreen irq gpio */
- retval = gpio_request(platform_data->irq_gpio, "rmi4_irq_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_req;
- }
- retval = gpio_direction_input(platform_data->irq_gpio);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_dir;
- }
- } else {
- dev_err(&client->dev, "irq gpio not provided\n");
- goto err_irq_gpio_req;
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&client->dev, "Failed to configure gpios\n");
+ goto err_gpio_config;
}
- if (gpio_is_valid(platform_data->reset_gpio)) {
- /* configure touchscreen reset out gpio */
- retval = gpio_request(platform_data->reset_gpio,
- "rmi4_reset_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_irq_gpio_dir;
- }
-
- retval = gpio_direction_output(platform_data->reset_gpio, 1);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_reset_gpio_dir;
- }
-
- gpio_set_value(platform_data->reset_gpio, 0);
- usleep(RMI4_GPIO_SLEEP_LOW_US);
- gpio_set_value(platform_data->reset_gpio, 1);
- msleep(RESET_DELAY);
- } else
- synaptics_rmi4_reset_command(rmi4_data);
-
-
init_waitqueue_head(&rmi4_data->wait);
mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
@@ -2205,7 +2246,7 @@
dev_err(&client->dev,
"%s: Failed to query device\n",
__func__);
- goto err_reset_gpio_dir;
+ goto err_free_gpios;
}
input_set_abs_params(rmi4_data->input_dev,
@@ -2348,13 +2389,12 @@
kfree(fhandler);
}
}
-err_reset_gpio_dir:
- if (gpio_is_valid(platform_data->reset_gpio))
- gpio_free(platform_data->reset_gpio);
-err_irq_gpio_dir:
- if (gpio_is_valid(platform_data->irq_gpio))
- gpio_free(platform_data->irq_gpio);
-err_irq_gpio_req:
+err_free_gpios:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_gpio_config:
synaptics_rmi4_power_on(rmi4_data, false);
err_power_device:
synaptics_rmi4_regulator_configure(rmi4_data, false);
@@ -2685,16 +2725,6 @@
}
}
- if (rmi4_data->board->power_down_enable) {
- retval = synaptics_rmi4_reset_device(rmi4_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to issue reset command, rc = %d\n",
- __func__, retval);
- return retval;
- }
- }
-
return 0;
fail_regulator_lpm:
@@ -2755,6 +2785,13 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in suspend state\n");
+ return retval;
+ }
+ }
rmi4_data->suspended = true;
return 0;
@@ -2780,6 +2817,14 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in active state\n");
+ return retval;
+ }
+ }
+
retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
if (retval < 0) {
dev_err(dev, "failed to enter active power mode\n");
@@ -2790,6 +2835,17 @@
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
+ if (rmi4_data->board->power_down_enable ||
+ rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_reset_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to issue reset command, " \
+ "rc = %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
rmi4_data->suspended = false;
return 0;