Input: rotary-encoder - add support for half-period encoders
Add support for encoders that have two detents per input signal period.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Acked-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 077b80b..2c8b84d 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -2,6 +2,7 @@
* rotary_encoder.c
*
* (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2011 Johan Hovold <jhovold@gmail.com>
*
* state machine code inspired by code from Tim Ruetz
*
@@ -38,6 +39,8 @@
bool armed;
unsigned char dir; /* 0 - clockwise, 1 - CCW */
+
+ char last_stable;
};
static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata)
@@ -112,11 +115,37 @@
return IRQ_HANDLED;
}
+static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
+{
+ struct rotary_encoder *encoder = dev_id;
+ int state;
+
+ state = rotary_encoder_get_state(encoder->pdata);
+
+ switch (state) {
+ case 0x00:
+ case 0x03:
+ if (state != encoder->last_stable) {
+ rotary_encoder_report_event(encoder);
+ encoder->last_stable = state;
+ }
+ break;
+
+ case 0x01:
+ case 0x02:
+ encoder->dir = (encoder->last_stable + state) & 0x01;
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int __devinit rotary_encoder_probe(struct platform_device *pdev)
{
struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data;
struct rotary_encoder *encoder;
struct input_dev *input;
+ irq_handler_t handler;
int err;
if (!pdata) {
@@ -187,7 +216,14 @@
}
/* request the IRQs */
- err = request_irq(encoder->irq_a, &rotary_encoder_irq,
+ if (pdata->half_period) {
+ handler = &rotary_encoder_half_period_irq;
+ encoder->last_stable = rotary_encoder_get_state(pdata);
+ } else {
+ handler = &rotary_encoder_irq;
+ }
+
+ err = request_irq(encoder->irq_a, handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
DRV_NAME, encoder);
if (err) {
@@ -196,7 +232,7 @@
goto exit_free_gpio_b;
}
- err = request_irq(encoder->irq_b, &rotary_encoder_irq,
+ err = request_irq(encoder->irq_b, handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
DRV_NAME, encoder);
if (err) {
@@ -264,5 +300,5 @@
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_DESCRIPTION("GPIO rotary encoder driver");
-MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
MODULE_LICENSE("GPL v2");