]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/input/touchscreen/st1232.c
Merge remote-tracking branch 'workqueues/for-next'
[karo-tx-linux.git] / drivers / input / touchscreen / st1232.c
index d9d05e222428ccab1dd3967d544d20bcd0ae974c..2f03b2f289dd365fe3053338d09d049b7d724244 100644 (file)
  */
 
 #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.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 +52,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 +144,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 +168,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 +210,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 +237,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 +246,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 +261,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;
 }