@@ -45,7 +45,18 @@ static void gpio_keys_report_event(struct work_struct *work)
struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
- int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
+ int state = gpio_get_value(button->gpio) ? 1 : 0;
+
+ /* If the hardware can't do both edges, set the appropriate
+ * interrupt control */
+ if (button->not_both_edges) {
+ if (state)
+ set_irq_type(gpio_to_irq(button->gpio), IRQ_TYPE_EDGE_FALLING);
+ else
+ set_irq_type(gpio_to_irq(button->gpio), IRQ_TYPE_EDGE_RISING);
+ }
+
+ state ^= button->active_low;
input_event(input, type, button->code, !!state);
input_sync(input);
@@ -79,7 +90,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata;
struct input_dev *input;
- int i, error;
+ int i, error, trigger;
int wakeup = 0;
ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
@@ -146,9 +157,17 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
goto fail2;
}
+ if (button->not_both_edges) {
+ if (gpio_get_value(button->gpio))
+ trigger = IRQF_TRIGGER_FALLING;
+ else
+ trigger = IRQF_TRIGGER_RISING;
+ } else {
+ trigger = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
+ }
+
error = request_irq(irq, gpio_keys_isr,
- IRQF_SHARED |
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ IRQF_SHARED | trigger,
button->desc ? button->desc : "gpio_keys",
bdata);
if (error) {
@@ -10,6 +10,7 @@ struct gpio_keys_button {
int type; /* input event type (EV_KEY, EV_SW) */
int wakeup; /* configure the button as a wake-up source */
int debounce_interval; /* debounce ticks interval in msecs */
+ int not_both_edges; /* some hardware can't do interrupts on both edges */
};
struct gpio_keys_platform_data {