summaryrefslogtreecommitdiff
path: root/drivers/input/keyboard/stmpe-keypad.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/keyboard/stmpe-keypad.c')
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c89
1 files changed, 88 insertions, 1 deletions
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index ab7610ca10e..c1de4d77ca1 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -108,10 +108,52 @@ struct stmpe_keypad {
unsigned int rows;
unsigned int cols;
+ bool enable;
unsigned short keymap[STMPE_KEYPAD_KEYMAP_SIZE];
};
+static ssize_t stmpe_show_attr_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
+ return sprintf(buf, "%d\n", keypad->enable);
+}
+
+static ssize_t stmpe_store_attr_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
+ struct stmpe *stmpe = keypad->stmpe;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 0, &val))
+ return -EINVAL;
+
+ if (keypad->enable != val) {
+ keypad->enable = val;
+ if (!val)
+ stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD);
+ else
+ stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD);
+ }
+ return count;
+}
+
+static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
+ stmpe_show_attr_enable, stmpe_store_attr_enable);
+
+static struct attribute *stmpe_keypad_attrs[] = {
+ &dev_attr_enable.attr,
+ NULL,
+};
+
+static struct attribute_group stmpe_attr_group = {
+ .attrs = stmpe_keypad_attrs,
+};
+
static int stmpe_keypad_read_data(struct stmpe_keypad *keypad, u8 *data)
{
const struct stmpe_keypad_variant *variant = keypad->variant;
@@ -285,7 +327,7 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
goto out_freekeypad;
}
- input->name = "STMPE keypad";
+ input->name = "STMPE-keypad";
input->id.bustype = BUS_I2C;
input->dev.parent = &pdev->dev;
@@ -332,10 +374,20 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
goto out_unregisterinput;
}
+ /* sysfs implementation for dynamic enable/disable the input event */
+ ret = sysfs_create_group(&pdev->dev.kobj, &stmpe_attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to create sysfs entries\n");
+ goto out_free_irq;
+ }
+
+ keypad->enable = true;
platform_set_drvdata(pdev, keypad);
return 0;
+out_free_irq:
+ free_irq(irq, keypad);
out_unregisterinput:
input_unregister_device(input);
input = NULL;
@@ -354,6 +406,7 @@ static int __devexit stmpe_keypad_remove(struct platform_device *pdev)
stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD);
+ sysfs_remove_group(&pdev->dev.kobj, &stmpe_attr_group);
free_irq(irq, keypad);
input_unregister_device(keypad->input);
platform_set_drvdata(pdev, NULL);
@@ -362,9 +415,43 @@ static int __devexit stmpe_keypad_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int stmpe_keypad_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
+ struct stmpe *stmpe = keypad->stmpe;
+
+ if (!device_may_wakeup(stmpe->dev))
+ stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD);
+
+ return 0;
+}
+
+static int stmpe_keypad_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct stmpe_keypad *keypad = platform_get_drvdata(pdev);
+ struct stmpe *stmpe = keypad->stmpe;
+
+ if (!device_may_wakeup(stmpe->dev))
+ stmpe_enable(stmpe, STMPE_BLOCK_KEYPAD);
+
+ return 0;
+}
+
+static const struct dev_pm_ops stmpe_keypad_dev_pm_ops = {
+ .suspend = stmpe_keypad_suspend,
+ .resume = stmpe_keypad_resume,
+};
+#endif
+
static struct platform_driver stmpe_keypad_driver = {
.driver.name = "stmpe-keypad",
.driver.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .driver.pm = &stmpe_keypad_dev_pm_ops,
+#endif
.probe = stmpe_keypad_probe,
.remove = __devexit_p(stmpe_keypad_remove),
};