Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index fadc115..ac76cde 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -26,6 +26,12 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>
+#include <linux/pm.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#define TSC2007_SUSPEND_LEVEL 1
+#endif
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
#define TSC2007_MEASURE_AUX (0x2 << 4)
@@ -79,8 +85,17 @@
bool pendown;
int irq;
+ bool invert_x;
+ bool invert_y;
+ bool invert_z1;
+ bool invert_z2;
+
int (*get_pendown_state)(void);
void (*clear_penirq)(void);
+ int (*power_shutdown)(bool);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
};
static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
@@ -117,6 +132,18 @@
tc->z1 = tsc2007_xfer(tsc, READ_Z1);
tc->z2 = tsc2007_xfer(tsc, READ_Z2);
+ if (tsc->invert_x == true)
+ tc->x = MAX_12BIT - tc->x;
+
+ if (tsc->invert_y == true)
+ tc->y = MAX_12BIT - tc->y;
+
+ if (tsc->invert_z1 == true)
+ tc->z1 = MAX_12BIT - tc->z1;
+
+ if (tsc->invert_z2 == true)
+ tc->z2 = MAX_12BIT - tc->z2;
+
/* Prepare for next touch reading - power down ADC, enable PENIRQ */
tsc2007_xfer(tsc, PWRDOWN);
}
@@ -263,6 +290,72 @@
}
}
+#ifdef CONFIG_PM
+static int tsc2007_suspend(struct device *dev)
+{
+ int rc;
+ struct tsc2007 *ts = dev_get_drvdata(dev);
+
+ disable_irq(ts->irq);
+
+ if (cancel_delayed_work_sync(&ts->work))
+ enable_irq(ts->irq);
+
+ if (ts->power_shutdown) {
+ rc = ts->power_shutdown(true);
+ if (rc) {
+ pr_err("%s: Power off failed, suspend failed (%d)\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static int tsc2007_resume(struct device *dev)
+{
+ int rc;
+ struct tsc2007 *ts = dev_get_drvdata(dev);
+
+ if (ts->power_shutdown) {
+ rc = ts->power_shutdown(false);
+ if (rc) {
+ pr_err("%s: Power on failed, resume failed (%d)\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ enable_irq(ts->irq);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void tsc2007_early_suspend(struct early_suspend *h)
+{
+ struct tsc2007 *ts = container_of(h, struct tsc2007, early_suspend);
+
+ tsc2007_suspend(&ts->client->dev);
+}
+
+static void tsc2007_late_resume(struct early_suspend *h)
+{
+ struct tsc2007 *ts = container_of(h, struct tsc2007, early_suspend);
+
+ tsc2007_resume(&ts->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops tsc2007_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = tsc2007_suspend,
+ .resume = tsc2007_resume,
+#endif
+};
+#endif
+
static int __devinit tsc2007_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -299,6 +392,11 @@
ts->poll_period = pdata->poll_period ? : 1;
ts->get_pendown_state = pdata->get_pendown_state;
ts->clear_penirq = pdata->clear_penirq;
+ ts->invert_x = pdata->invert_x;
+ ts->invert_y = pdata->invert_y;
+ ts->invert_z1 = pdata->invert_z1;
+ ts->invert_z2 = pdata->invert_z2;
+ ts->power_shutdown = pdata->power_shutdown;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
@@ -318,7 +416,7 @@
if (pdata->init_platform_hw)
pdata->init_platform_hw();
- err = request_irq(ts->irq, tsc2007_irq, 0,
+ err = request_irq(ts->irq, tsc2007_irq, pdata->irq_flags,
client->dev.driver->name, ts);
if (err < 0) {
dev_err(&client->dev, "irq %d busy?\n", ts->irq);
@@ -334,6 +432,14 @@
if (err)
goto err_free_irq;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ TSC2007_SUSPEND_LEVEL;
+ ts->early_suspend.suspend = tsc2007_early_suspend;
+ ts->early_suspend.resume = tsc2007_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
i2c_set_clientdata(client, ts);
return 0;
@@ -358,6 +464,9 @@
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
input_unregister_device(ts->input);
kfree(ts);
@@ -374,7 +483,10 @@
static struct i2c_driver tsc2007_driver = {
.driver = {
.owner = THIS_MODULE,
- .name = "tsc2007"
+ .name = "tsc2007",
+#ifdef CONFIG_PM
+ .pm = &tsc2007_pm_ops,
+#endif
},
.id_table = tsc2007_idtable,
.probe = tsc2007_probe,