Input: mcs_touchkey - add support for suspend/resume
authorHeungjun Kim <riverful.kim@samsung.com>
Thu, 24 Feb 2011 05:40:11 +0000 (21:40 -0800)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Thu, 24 Feb 2011 05:43:31 +0000 (21:43 -0800)
This adds support for system-level suspend/resume to the driver.

Signed-off-by: Heungjun Kim <riverful.kim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/keyboard/mcs_touchkey.c
include/linux/i2c/mcs.h

index 63b849d7e90b0fb9d2755ed6a1e9f0bf9975959f..03fa59a0b2206525b5e56614401223f7d515da34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
+ * Touchkey driver for MELFAS MCS5000/5080 controller
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 /* MCS5000 Touchkey */
 #define MCS5000_TOUCHKEY_STATUS                0x04
@@ -45,6 +46,8 @@ struct mcs_touchkey_chip {
 };
 
 struct mcs_touchkey_data {
+       void (*poweron)(bool);
+
        struct i2c_client *client;
        struct input_dev *input_dev;
        struct mcs_touchkey_chip chip;
@@ -169,6 +172,11 @@ static int __devinit mcs_touchkey_probe(struct i2c_client *client,
        if (pdata->cfg_pin)
                pdata->cfg_pin();
 
+       if (pdata->poweron) {
+               data->poweron = pdata->poweron;
+               data->poweron(true);
+       }
+
        error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
                        IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
        if (error) {
@@ -196,12 +204,49 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client)
        struct mcs_touchkey_data *data = i2c_get_clientdata(client);
 
        free_irq(client->irq, data);
+       if (data->poweron)
+               data->poweron(false);
        input_unregister_device(data->input_dev);
        kfree(data);
 
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int mcs_touchkey_suspend(struct device *dev)
+{
+       struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+
+       /* Disable the work */
+       disable_irq(client->irq);
+
+       /* Finally turn off the power */
+       if (data->poweron)
+               data->poweron(false);
+
+       return 0;
+}
+
+static int mcs_touchkey_resume(struct device *dev)
+{
+       struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+       struct i2c_client *client = data->client;
+
+       /* Enable the device first */
+       if (data->poweron)
+               data->poweron(true);
+
+       /* Enable irq again */
+       enable_irq(client->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
+                        mcs_touchkey_suspend, mcs_touchkey_resume);
+
 static const struct i2c_device_id mcs_touchkey_id[] = {
        { "mcs5000_touchkey", MCS5000_TOUCHKEY },
        { "mcs5080_touchkey", MCS5080_TOUCHKEY },
@@ -213,6 +258,7 @@ static struct i2c_driver mcs_touchkey_driver = {
        .driver = {
                .name   = "mcs_touchkey",
                .owner  = THIS_MODULE,
+               .pm     = &mcs_touchkey_pm_ops,
        },
        .probe          = mcs_touchkey_probe,
        .remove         = __devexit_p(mcs_touchkey_remove),
index 725ae7c313ff3914ecd077df1e33b2c2a8e8b7d2..61bb18a4fd3c9946a19d90ea293f1d966042c0a4 100644 (file)
@@ -18,6 +18,7 @@
 #define MCS_KEY_CODE(v)                ((v) & 0xffff)
 
 struct mcs_platform_data {
+       void (*poweron)(bool);
        void (*cfg_pin)(void);
 
        /* touchscreen */