input: touchscreen: panjit_i2c: fix suspend
authorGary King <gking@nvidia.com>
Mon, 6 Sep 2010 03:36:38 +0000 (20:36 -0700)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:28:30 +0000 (16:28 -0700)
the panjit touchscreen needs to be reset when returning from
deep sleep mode; add a platform data structure to specify
the reset GPIO.

perform the reset during _probe, since the code already needs
to exist for _resume

delete a bunch of unused preprocessor defines

Change-Id: I71ae65dec45710b0eab4625036edf75064d4cc2b
Signed-off-by: Gary King <gking@nvidia.com>
drivers/input/touchscreen/panjit_i2c.c
include/linux/i2c/panjit_ts.h [new file with mode: 0644]

index f636315f263bad70b2cd71f260906e0384960796..6d82cec45ed90f4e30d2fc7a98beec20574e6239 100644 (file)
 #include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/i2c/panjit_ts.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
 
-/* touch controller registers */
-#define CSR                            0x00 /* Control and Status register */
-#define C_FLAG                         0x01 /* Interrupt Clear flag */
-#define X1_H                           0x03 /* High Byte of X1 Position */
-#define X1_L                           0x04 /* Low Byte of X1 Position */
-#define Y1_H                           0x05 /* High Byte of Y1 Position */
-#define Y1_L                           0x06 /* Low Byte of Y1 Position */
-#define X2_H                           0x07 /* High Byte of X2 Position */
-#define X2_L                           0x08 /* Low Byte of X2 Position */
-#define Y2_H                           0x09 /* High Byte of Y2 Position */
-#define Y2_L                           0x0A /* Low Byte of Y2 Position */
-#define FINGERS                                0x0B /* Detected finger number */
-#define GESTURE                                0x0C /* Interpreted gesture */
-
-/* Control Status Register bit masks */
-#define CSR_SLEEP_EN                   (1 << 7)
-#define CSR_SCAN_EN                    (1 << 3)
-#define SLEEP_ENABLE                   1
-
-/* Interrupt Clear register bit masks */
-#define C_FLAG_CLEAR                   0x08
-#define INT_ASSERTED                   (1 << C_FLAG_CLEAR)
-
-#define DRIVER_NAME                    "panjit_touch"
+#define CSR            0x00
+ #define CSR_SCAN_EN   (1 << 3)
+ #define CSR_SLEEP_EN  (1 << 7)
+#define C_FLAG         0x01
+#define X1_H           0x03
+
+#define DRIVER_NAME    "panjit_touch"
 
 struct pj_data {
        struct input_dev        *input_dev;
        struct i2c_client       *client;
-       int                     chipid;
+       int                     gpio_reset;
 };
 
 struct pj_event {
@@ -74,6 +58,17 @@ union pj_buff {
        unsigned char   buff[sizeof(struct pj_data)];
 };
 
+static void pj_reset(struct pj_data *touch)
+{
+       if (touch->gpio_reset < 0)
+               return;
+
+       gpio_set_value(touch->gpio_reset, 1);
+       msleep(50);
+       gpio_set_value(touch->gpio_reset, 0);
+       msleep(50);
+}
+
 static irqreturn_t pj_irq(int irq, void *dev_id)
 {
        struct pj_data *touch = dev_id;
@@ -87,12 +82,12 @@ static irqreturn_t pj_irq(int irq, void *dev_id)
                                            sizeof(event.buff), event.buff);
        if (WARN_ON(ret < 0)) {
                dev_err(&client->dev, "error %d reading event data\n", ret);
-               return IRQ_HANDLED;
+               return IRQ_NONE;
        }
        ret = i2c_smbus_write_byte_data(client, C_FLAG, 0);
        if (WARN_ON(ret < 0)) {
                dev_err(&client->dev, "error %d clearing interrupt\n", ret);
-               return IRQ_HANDLED;
+               return IRQ_NONE;
        }
 
        input_report_key(touch->input_dev, BTN_TOUCH,
@@ -128,6 +123,7 @@ out:
 static int pj_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
 {
+       struct panjit_i2c_ts_platform_data *pdata = client->dev.platform_data;
        struct pj_data *touch = NULL;
        struct input_dev *input_dev = NULL;
        int ret = 0;
@@ -138,6 +134,22 @@ static int pj_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
+       touch->gpio_reset = -EINVAL;
+
+       if (pdata) {
+               ret = gpio_request(pdata->gpio_reset, "panjit_reset");
+               if (!ret) {
+                       ret = gpio_direction_output(pdata->gpio_reset, 1);
+                       if (ret < 0)
+                               gpio_free(pdata->gpio_reset);
+               }
+
+               if (!ret)
+                       touch->gpio_reset = pdata->gpio_reset;
+               else
+                       dev_warn(&client->dev, "unable to configure GPIO\n");
+       }
+
        input_dev = input_allocate_device();
        if (!input_dev) {
                dev_err(&client->dev, "%s: no memory\n", __func__);
@@ -148,6 +160,8 @@ static int pj_probe(struct i2c_client *client,
        touch->client = client;
        i2c_set_clientdata(client, touch);
 
+       pj_reset(touch);
+
        /* clear interrupt */
        ret = i2c_smbus_write_byte_data(touch->client, C_FLAG, 0);
        if (ret < 0) {
@@ -199,7 +213,8 @@ static int pj_probe(struct i2c_client *client,
 
        /* get the irq */
        ret = request_threaded_irq(touch->client->irq, NULL, pj_irq,
-                                  IRQF_ONESHOT, DRIVER_NAME, touch);
+                                  IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+                                  DRIVER_NAME, touch);
        if (ret) {
                dev_err(&client->dev, "%s: request_irq(%d) failed\n",
                        __func__, touch->client->irq);
@@ -213,6 +228,9 @@ fail_irq:
        input_unregister_device(touch->input_dev);
 
 fail_i2c_or_register:
+       if (touch->gpio_reset >= 0)
+               gpio_free(touch->gpio_reset);
+
        input_free_device(input_dev);
        kfree(touch);
        return ret;
@@ -223,12 +241,10 @@ static int pj_suspend(struct i2c_client *client, pm_message_t state)
        struct pj_data *touch = i2c_get_clientdata(client);
        int ret;
 
-       if (!touch) {
-               WARN_ON(1);
+       if (WARN_ON(!touch))
                return -EINVAL;
-       }
 
-       disable_irq(touch->client->irq);
+       disable_irq(client->irq);
 
        /* disable scanning and enable deep sleep */
        ret = i2c_smbus_write_byte_data(client, CSR, CSR_SLEEP_EN);
@@ -236,6 +252,7 @@ static int pj_suspend(struct i2c_client *client, pm_message_t state)
                dev_err(&client->dev, "%s: sleep enable fail\n", __func__);
                return ret;
        }
+
        return 0;
 }
 
@@ -244,18 +261,22 @@ static int pj_resume(struct i2c_client *client)
        struct pj_data *touch = i2c_get_clientdata(client);
        int ret = 0;
 
-       if (!touch) {
-               WARN_ON(1);
+       if (WARN_ON(!touch))
                return -EINVAL;
-       }
+
+       pj_reset(touch);
+
        /* enable scanning and disable deep sleep */
-       ret = i2c_smbus_write_byte_data(client, CSR, CSR_SCAN_EN);
+       ret = i2c_smbus_write_byte_data(client, C_FLAG, 0);
+       if (ret >= 0)
+               ret = i2c_smbus_write_byte_data(client, CSR, CSR_SCAN_EN);
        if (ret < 0) {
-               dev_err(&client->dev, "%s: interrupt enable fail\n", __func__);
+               dev_err(&client->dev, "%s: scan enable fail\n", __func__);
                return ret;
        }
 
-       enable_irq(touch->client->irq);
+       enable_irq(client->irq);
+
        return 0;
 }
 
@@ -267,6 +288,8 @@ static int pj_remove(struct i2c_client *client)
                return -EINVAL;
 
        free_irq(touch->client->irq, touch);
+       if (touch->gpio_reset >= 0)
+               gpio_free(touch->gpio_reset);
        input_unregister_device(touch->input_dev);
        input_free_device(touch->input_dev);
        kfree(touch);
diff --git a/include/linux/i2c/panjit_ts.h b/include/linux/i2c/panjit_ts.h
new file mode 100644 (file)
index 0000000..1dd51e1
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * include/linux/i2c/panjit_ts.h
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef _LINUX_I2C_PANJIT_TS_H
+#define _LINUX_I2C_PANJIT_TS_H
+
+struct device;
+
+struct panjit_i2c_ts_platform_data {
+       int gpio_reset;
+};
+
+#endif