summaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/st1232.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/st1232.c')
-rw-r--r--drivers/input/touchscreen/st1232.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c
index d9d05e22242..1740a249637 100644
--- a/drivers/input/touchscreen/st1232.c
+++ b/drivers/input/touchscreen/st1232.c
@@ -19,13 +19,16 @@
*/
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/of_gpio.h>
#include <linux/pm_qos.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/platform_data/st1232_pdata.h>
#define ST1232_TS_NAME "st1232-ts"
@@ -48,6 +51,7 @@ struct st1232_ts_data {
struct input_dev *input_dev;
struct st1232_ts_finger finger[MAX_FINGERS];
struct dev_pm_qos_request low_latency_req;
+ int reset_gpio;
};
static int st1232_ts_read_data(struct st1232_ts_data *ts)
@@ -139,10 +143,17 @@ end:
return IRQ_HANDLED;
}
+static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron)
+{
+ if (gpio_is_valid(ts->reset_gpio))
+ gpio_direction_output(ts->reset_gpio, poweron);
+}
+
static int st1232_ts_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct st1232_ts_data *ts;
+ struct st1232_pdata *pdata = client->dev.platform_data;
struct input_dev *input_dev;
int error;
@@ -156,17 +167,36 @@ static int st1232_ts_probe(struct i2c_client *client,
return -EINVAL;
}
+ ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
- ts = kzalloc(sizeof(struct st1232_ts_data), GFP_KERNEL);
- input_dev = input_allocate_device();
- if (!ts || !input_dev) {
- error = -ENOMEM;
- goto err_free_mem;
- }
+ input_dev = devm_input_allocate_device(&client->dev);
+ if (!input_dev)
+ return -ENOMEM;
ts->client = client;
ts->input_dev = input_dev;
+ if (pdata)
+ ts->reset_gpio = pdata->reset_gpio;
+ else if (client->dev.of_node)
+ ts->reset_gpio = of_get_gpio(client->dev.of_node, 0);
+ else
+ ts->reset_gpio = -ENODEV;
+
+ if (gpio_is_valid(ts->reset_gpio)) {
+ error = devm_gpio_request(&client->dev, ts->reset_gpio, NULL);
+ if (error) {
+ dev_err(&client->dev,
+ "Unable to request GPIO pin %d.\n",
+ ts->reset_gpio);
+ return error;
+ }
+ }
+
+ st1232_ts_power(ts, true);
+
input_dev->name = "st1232-touchscreen";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
@@ -179,31 +209,26 @@ static int st1232_ts_probe(struct i2c_client *client,
input_set_abs_params(input_dev, ABS_MT_POSITION_X, MIN_X, MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, MIN_Y, MAX_Y, 0, 0);
- error = request_threaded_irq(client->irq, NULL, st1232_ts_irq_handler,
- IRQF_ONESHOT, client->name, ts);
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, st1232_ts_irq_handler,
+ IRQF_ONESHOT,
+ client->name, ts);
if (error) {
dev_err(&client->dev, "Failed to register interrupt\n");
- goto err_free_mem;
+ return error;
}
error = input_register_device(ts->input_dev);
if (error) {
dev_err(&client->dev, "Unable to register %s input device\n",
input_dev->name);
- goto err_free_irq;
+ return error;
}
i2c_set_clientdata(client, ts);
device_init_wakeup(&client->dev, 1);
return 0;
-
-err_free_irq:
- free_irq(client->irq, ts);
-err_free_mem:
- input_free_device(input_dev);
- kfree(ts);
- return error;
}
static int st1232_ts_remove(struct i2c_client *client)
@@ -211,9 +236,7 @@ static int st1232_ts_remove(struct i2c_client *client)
struct st1232_ts_data *ts = i2c_get_clientdata(client);
device_init_wakeup(&client->dev, 0);
- free_irq(client->irq, ts);
- input_unregister_device(ts->input_dev);
- kfree(ts);
+ st1232_ts_power(ts, false);
return 0;
}
@@ -222,11 +245,14 @@ static int st1232_ts_remove(struct i2c_client *client)
static int st1232_ts_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct st1232_ts_data *ts = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev))
+ if (device_may_wakeup(&client->dev)) {
enable_irq_wake(client->irq);
- else
+ } else {
disable_irq(client->irq);
+ st1232_ts_power(ts, false);
+ }
return 0;
}
@@ -234,11 +260,14 @@ static int st1232_ts_suspend(struct device *dev)
static int st1232_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ struct st1232_ts_data *ts = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev))
+ if (device_may_wakeup(&client->dev)) {
disable_irq_wake(client->irq);
- else
+ } else {
+ st1232_ts_power(ts, true);
enable_irq(client->irq);
+ }
return 0;
}