diff options
author | Jani Nikula <ext-jani.1.nikula@nokia.com> | 2009-06-29 01:38:44 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-29 02:58:17 -0400 |
commit | ca865a77b5949f5c403e0f13de5a5a9cd499a11e (patch) | |
tree | 567ebe13fe9800a4a7d6584af4ba012e9472bb91 /drivers/input/keyboard/gpio_keys.c | |
parent | 00b8ac409cad653137f087e3ff69c020174cbc15 (diff) |
Input: gpio-keys - revert 'change timer to workqueue'
This reverts commit 0b346838c5862bfe911432956a106d602535d030.
This commit breaks GPIO debouncing by replacing the original mod_timer
with schedule_delayed_work in the interrupt handler. The latter does not
kick the timer further on GPIO line changes as it should to perform
debouncing.
Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2157cd7de00c..9767213b6c8f 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -22,14 +22,13 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
24 | #include <linux/gpio_keys.h> | 24 | #include <linux/gpio_keys.h> |
25 | #include <linux/workqueue.h> | ||
26 | 25 | ||
27 | #include <asm/gpio.h> | 26 | #include <asm/gpio.h> |
28 | 27 | ||
29 | struct gpio_button_data { | 28 | struct gpio_button_data { |
30 | struct gpio_keys_button *button; | 29 | struct gpio_keys_button *button; |
31 | struct input_dev *input; | 30 | struct input_dev *input; |
32 | struct delayed_work work; | 31 | struct timer_list timer; |
33 | }; | 32 | }; |
34 | 33 | ||
35 | struct gpio_keys_drvdata { | 34 | struct gpio_keys_drvdata { |
@@ -37,10 +36,8 @@ struct gpio_keys_drvdata { | |||
37 | struct gpio_button_data data[0]; | 36 | struct gpio_button_data data[0]; |
38 | }; | 37 | }; |
39 | 38 | ||
40 | static void gpio_keys_report_event(struct work_struct *work) | 39 | static void gpio_keys_report_event(struct gpio_button_data *bdata) |
41 | { | 40 | { |
42 | struct gpio_button_data *bdata = | ||
43 | container_of(work, struct gpio_button_data, work.work); | ||
44 | struct gpio_keys_button *button = bdata->button; | 41 | struct gpio_keys_button *button = bdata->button; |
45 | struct input_dev *input = bdata->input; | 42 | struct input_dev *input = bdata->input; |
46 | unsigned int type = button->type ?: EV_KEY; | 43 | unsigned int type = button->type ?: EV_KEY; |
@@ -50,17 +47,25 @@ static void gpio_keys_report_event(struct work_struct *work) | |||
50 | input_sync(input); | 47 | input_sync(input); |
51 | } | 48 | } |
52 | 49 | ||
50 | static 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); | ||
55 | } | ||
56 | |||
53 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | 57 | static irqreturn_t gpio_keys_isr(int irq, void *dev_id) |
54 | { | 58 | { |
55 | struct gpio_button_data *bdata = dev_id; | 59 | struct gpio_button_data *bdata = dev_id; |
56 | struct gpio_keys_button *button = bdata->button; | 60 | struct gpio_keys_button *button = bdata->button; |
57 | unsigned long delay; | ||
58 | 61 | ||
59 | BUG_ON(irq != gpio_to_irq(button->gpio)); | 62 | BUG_ON(irq != gpio_to_irq(button->gpio)); |
60 | 63 | ||
61 | delay = button->debounce_interval ? | 64 | if (button->debounce_interval) |
62 | msecs_to_jiffies(button->debounce_interval) : 0; | 65 | mod_timer(&bdata->timer, |
63 | schedule_delayed_work(&bdata->work, delay); | 66 | jiffies + msecs_to_jiffies(button->debounce_interval)); |
67 | else | ||
68 | gpio_keys_report_event(bdata); | ||
64 | 69 | ||
65 | return IRQ_HANDLED; | 70 | return IRQ_HANDLED; |
66 | } | 71 | } |
@@ -107,7 +112,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
107 | 112 | ||
108 | bdata->input = input; | 113 | bdata->input = input; |
109 | bdata->button = button; | 114 | bdata->button = button; |
110 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); | 115 | setup_timer(&bdata->timer, |
116 | gpio_check_button, (unsigned long)bdata); | ||
111 | 117 | ||
112 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); | 118 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); |
113 | if (error < 0) { | 119 | if (error < 0) { |
@@ -166,7 +172,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
166 | fail2: | 172 | fail2: |
167 | while (--i >= 0) { | 173 | while (--i >= 0) { |
168 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 174 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
169 | cancel_delayed_work_sync(&ddata->data[i].work); | 175 | if (pdata->buttons[i].debounce_interval) |
176 | del_timer_sync(&ddata->data[i].timer); | ||
170 | gpio_free(pdata->buttons[i].gpio); | 177 | gpio_free(pdata->buttons[i].gpio); |
171 | } | 178 | } |
172 | 179 | ||
@@ -190,7 +197,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
190 | for (i = 0; i < pdata->nbuttons; i++) { | 197 | for (i = 0; i < pdata->nbuttons; i++) { |
191 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 198 | int irq = gpio_to_irq(pdata->buttons[i].gpio); |
192 | free_irq(irq, &ddata->data[i]); | 199 | free_irq(irq, &ddata->data[i]); |
193 | cancel_delayed_work_sync(&ddata->data[i].work); | 200 | if (pdata->buttons[i].debounce_interval) |
201 | del_timer_sync(&ddata->data[i].timer); | ||
194 | gpio_free(pdata->buttons[i].gpio); | 202 | gpio_free(pdata->buttons[i].gpio); |
195 | } | 203 | } |
196 | 204 | ||