aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/keyboard/gpio_keys.c89
-rw-r--r--include/linux/gpio_keys.h1
2 files changed, 70 insertions, 20 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index bbd00c3fe98c..be58730e636a 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -26,23 +26,54 @@
26 26
27#include <asm/gpio.h> 27#include <asm/gpio.h>
28 28
29struct gpio_button_data {
30 struct gpio_keys_button *button;
31 struct input_dev *input;
32 struct timer_list timer;
33};
34
35struct gpio_keys_drvdata {
36 struct input_dev *input;
37 struct gpio_button_data data[0];
38};
39
40static void gpio_keys_report_event(struct gpio_keys_button *button,
41 struct input_dev *input)
42{
43 unsigned int type = button->type ?: EV_KEY;
44 int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
45
46 input_event(input, type, button->code, !!state);
47 input_sync(input);
48}
49
50static void gpio_check_button(unsigned long _data)
51{
52 struct gpio_button_data *data = (struct gpio_button_data *)_data;
53
54 gpio_keys_report_event(data->button, data->input);
55}
56
29static irqreturn_t gpio_keys_isr(int irq, void *dev_id) 57static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
30{ 58{
31 int i;
32 struct platform_device *pdev = dev_id; 59 struct platform_device *pdev = dev_id;
33 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 60 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
34 struct input_dev *input = platform_get_drvdata(pdev); 61 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
62 int i;
35 63
36 for (i = 0; i < pdata->nbuttons; i++) { 64 for (i = 0; i < pdata->nbuttons; i++) {
37 struct gpio_keys_button *button = &pdata->buttons[i]; 65 struct gpio_keys_button *button = &pdata->buttons[i];
38 int gpio = button->gpio;
39 66
40 if (irq == gpio_to_irq(gpio)) { 67 if (irq == gpio_to_irq(button->gpio)) {
41 unsigned int type = button->type ?: EV_KEY; 68 struct gpio_button_data *bdata = &ddata->data[i];
42 int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low; 69
70 if (button->debounce_interval)
71 mod_timer(&bdata->timer,
72 jiffies +
73 msecs_to_jiffies(button->debounce_interval));
74 else
75 gpio_keys_report_event(button, bdata->input);
43 76
44 input_event(input, type, button->code, !!state);
45 input_sync(input);
46 return IRQ_HANDLED; 77 return IRQ_HANDLED;
47 } 78 }
48 } 79 }
@@ -53,17 +84,21 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
53static int __devinit gpio_keys_probe(struct platform_device *pdev) 84static int __devinit gpio_keys_probe(struct platform_device *pdev)
54{ 85{
55 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 86 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
87 struct gpio_keys_drvdata *ddata;
56 struct input_dev *input; 88 struct input_dev *input;
57 int i, error; 89 int i, error;
58 int wakeup = 0; 90 int wakeup = 0;
59 91
92 ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
93 pdata->nbuttons * sizeof(struct gpio_button_data),
94 GFP_KERNEL);
60 input = input_allocate_device(); 95 input = input_allocate_device();
61 if (!input) 96 if (!ddata || !input) {
62 return -ENOMEM; 97 error = -ENOMEM;
63 98 goto fail1;
64 platform_set_drvdata(pdev, input); 99 }
65 100
66 input->evbit[0] = BIT_MASK(EV_KEY); 101 platform_set_drvdata(pdev, ddata);
67 102
68 input->name = pdev->name; 103 input->name = pdev->name;
69 input->phys = "gpio-keys/input0"; 104 input->phys = "gpio-keys/input0";
@@ -74,16 +109,23 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
74 input->id.product = 0x0001; 109 input->id.product = 0x0001;
75 input->id.version = 0x0100; 110 input->id.version = 0x0100;
76 111
112 ddata->input = input;
113
77 for (i = 0; i < pdata->nbuttons; i++) { 114 for (i = 0; i < pdata->nbuttons; i++) {
78 struct gpio_keys_button *button = &pdata->buttons[i]; 115 struct gpio_keys_button *button = &pdata->buttons[i];
116 struct gpio_button_data *bdata = &ddata->data[i];
79 int irq; 117 int irq;
80 unsigned int type = button->type ?: EV_KEY; 118 unsigned int type = button->type ?: EV_KEY;
81 119
120 bdata->input = input;
121 setup_timer(&bdata->timer,
122 gpio_check_button, (unsigned long)bdata);
123
82 error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); 124 error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
83 if (error < 0) { 125 if (error < 0) {
84 pr_err("gpio-keys: failed to request GPIO %d," 126 pr_err("gpio-keys: failed to request GPIO %d,"
85 " error %d\n", button->gpio, error); 127 " error %d\n", button->gpio, error);
86 goto fail; 128 goto fail2;
87 } 129 }
88 130
89 error = gpio_direction_input(button->gpio); 131 error = gpio_direction_input(button->gpio);
@@ -92,7 +134,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
92 " direction for GPIO %d, error %d\n", 134 " direction for GPIO %d, error %d\n",
93 button->gpio, error); 135 button->gpio, error);
94 gpio_free(button->gpio); 136 gpio_free(button->gpio);
95 goto fail; 137 goto fail2;
96 } 138 }
97 139
98 irq = gpio_to_irq(button->gpio); 140 irq = gpio_to_irq(button->gpio);
@@ -102,7 +144,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
102 " for GPIO %d, error %d\n", 144 " for GPIO %d, error %d\n",
103 button->gpio, error); 145 button->gpio, error);
104 gpio_free(button->gpio); 146 gpio_free(button->gpio);
105 goto fail; 147 goto fail2;
106 } 148 }
107 149
108 error = request_irq(irq, gpio_keys_isr, 150 error = request_irq(irq, gpio_keys_isr,
@@ -114,7 +156,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
114 pr_err("gpio-keys: Unable to claim irq %d; error %d\n", 156 pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
115 irq, error); 157 irq, error);
116 gpio_free(button->gpio); 158 gpio_free(button->gpio);
117 goto fail; 159 goto fail2;
118 } 160 }
119 161
120 if (button->wakeup) 162 if (button->wakeup)
@@ -127,21 +169,25 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
127 if (error) { 169 if (error) {
128 pr_err("gpio-keys: Unable to register input device, " 170 pr_err("gpio-keys: Unable to register input device, "
129 "error: %d\n", error); 171 "error: %d\n", error);
130 goto fail; 172 goto fail2;
131 } 173 }
132 174
133 device_init_wakeup(&pdev->dev, wakeup); 175 device_init_wakeup(&pdev->dev, wakeup);
134 176
135 return 0; 177 return 0;
136 178
137 fail: 179 fail2:
138 while (--i >= 0) { 180 while (--i >= 0) {
139 free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev); 181 free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
182 if (pdata->buttons[i].debounce_interval)
183 del_timer_sync(&ddata->data[i].timer);
140 gpio_free(pdata->buttons[i].gpio); 184 gpio_free(pdata->buttons[i].gpio);
141 } 185 }
142 186
143 platform_set_drvdata(pdev, NULL); 187 platform_set_drvdata(pdev, NULL);
188 fail1:
144 input_free_device(input); 189 input_free_device(input);
190 kfree(ddata);
145 191
146 return error; 192 return error;
147} 193}
@@ -149,7 +195,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
149static int __devexit gpio_keys_remove(struct platform_device *pdev) 195static int __devexit gpio_keys_remove(struct platform_device *pdev)
150{ 196{
151 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 197 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
152 struct input_dev *input = platform_get_drvdata(pdev); 198 struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
199 struct input_dev *input = ddata->input;
153 int i; 200 int i;
154 201
155 device_init_wakeup(&pdev->dev, 0); 202 device_init_wakeup(&pdev->dev, 0);
@@ -157,6 +204,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
157 for (i = 0; i < pdata->nbuttons; i++) { 204 for (i = 0; i < pdata->nbuttons; i++) {
158 int irq = gpio_to_irq(pdata->buttons[i].gpio); 205 int irq = gpio_to_irq(pdata->buttons[i].gpio);
159 free_irq(irq, pdev); 206 free_irq(irq, pdev);
207 if (pdata->buttons[i].debounce_interval)
208 del_timer_sync(&ddata->data[i].timer);
160 gpio_free(pdata->buttons[i].gpio); 209 gpio_free(pdata->buttons[i].gpio);
161 } 210 }
162 211
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index c6d3a9de5634..ec6ecd74781d 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -9,6 +9,7 @@ struct gpio_keys_button {
9 char *desc; 9 char *desc;
10 int type; /* input event type (EV_KEY, EV_SW) */ 10 int type; /* input event type (EV_KEY, EV_SW) */
11 int wakeup; /* configure the button as a wake-up source */ 11 int wakeup; /* configure the button as a wake-up source */
12 int debounce_interval; /* debounce ticks interval in msecs */
12}; 13};
13 14
14struct gpio_keys_platform_data { 15struct gpio_keys_platform_data {