0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/device.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/input.h>
0017 #include <linux/slab.h>
0018
0019 #include <linux/mfd/pcf50633/core.h>
0020
0021 #define PCF50633_OOCSTAT_ONKEY 0x01
0022 #define PCF50633_REG_OOCSTAT 0x12
0023 #define PCF50633_REG_OOCMODE 0x10
0024
0025 struct pcf50633_input {
0026 struct pcf50633 *pcf;
0027 struct input_dev *input_dev;
0028 };
0029
0030 static void
0031 pcf50633_input_irq(int irq, void *data)
0032 {
0033 struct pcf50633_input *input;
0034 int onkey_released;
0035
0036 input = data;
0037
0038
0039 onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
0040 & PCF50633_OOCSTAT_ONKEY;
0041
0042 if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
0043 input_report_key(input->input_dev, KEY_POWER, 1);
0044 else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
0045 input_report_key(input->input_dev, KEY_POWER, 0);
0046
0047 input_sync(input->input_dev);
0048 }
0049
0050 static int pcf50633_input_probe(struct platform_device *pdev)
0051 {
0052 struct pcf50633_input *input;
0053 struct input_dev *input_dev;
0054 int ret;
0055
0056
0057 input = kzalloc(sizeof(*input), GFP_KERNEL);
0058 if (!input)
0059 return -ENOMEM;
0060
0061 input_dev = input_allocate_device();
0062 if (!input_dev) {
0063 kfree(input);
0064 return -ENOMEM;
0065 }
0066
0067 platform_set_drvdata(pdev, input);
0068 input->pcf = dev_to_pcf50633(pdev->dev.parent);
0069 input->input_dev = input_dev;
0070
0071 input_dev->name = "PCF50633 PMU events";
0072 input_dev->id.bustype = BUS_I2C;
0073 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
0074 set_bit(KEY_POWER, input_dev->keybit);
0075
0076 ret = input_register_device(input_dev);
0077 if (ret) {
0078 input_free_device(input_dev);
0079 kfree(input);
0080 return ret;
0081 }
0082 pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,
0083 pcf50633_input_irq, input);
0084 pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,
0085 pcf50633_input_irq, input);
0086
0087 return 0;
0088 }
0089
0090 static int pcf50633_input_remove(struct platform_device *pdev)
0091 {
0092 struct pcf50633_input *input = platform_get_drvdata(pdev);
0093
0094 pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
0095 pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
0096
0097 input_unregister_device(input->input_dev);
0098 kfree(input);
0099
0100 return 0;
0101 }
0102
0103 static struct platform_driver pcf50633_input_driver = {
0104 .driver = {
0105 .name = "pcf50633-input",
0106 },
0107 .probe = pcf50633_input_probe,
0108 .remove = pcf50633_input_remove,
0109 };
0110 module_platform_driver(pcf50633_input_driver);
0111
0112 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
0113 MODULE_DESCRIPTION("PCF50633 input driver");
0114 MODULE_LICENSE("GPL");
0115 MODULE_ALIAS("platform:pcf50633-input");