diff options
author | Johan Hovold <jhovold@gmail.com> | 2011-05-11 19:35:30 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-05-12 11:28:47 -0400 |
commit | e70bdd41bd0ead91b4a43e9d656ac1569d7c8779 (patch) | |
tree | 9518f22417dde4f2b2d2ed3a25af8bc8f4e3814c /drivers/input/misc | |
parent | 521a8f5cb79d1017d00d26143227159674e3b79d (diff) |
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>
Diffstat (limited to 'drivers/input/misc')
-rw-r--r-- | drivers/input/misc/rotary_encoder.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 077b80bdca69..2c8b84dd9dac 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * rotary_encoder.c | 2 | * rotary_encoder.c |
3 | * | 3 | * |
4 | * (c) 2009 Daniel Mack <daniel@caiaq.de> | 4 | * (c) 2009 Daniel Mack <daniel@caiaq.de> |
5 | * Copyright (C) 2011 Johan Hovold <jhovold@gmail.com> | ||
5 | * | 6 | * |
6 | * state machine code inspired by code from Tim Ruetz | 7 | * state machine code inspired by code from Tim Ruetz |
7 | * | 8 | * |
@@ -38,6 +39,8 @@ struct rotary_encoder { | |||
38 | 39 | ||
39 | bool armed; | 40 | bool armed; |
40 | unsigned char dir; /* 0 - clockwise, 1 - CCW */ | 41 | unsigned char dir; /* 0 - clockwise, 1 - CCW */ |
42 | |||
43 | char last_stable; | ||
41 | }; | 44 | }; |
42 | 45 | ||
43 | static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) | 46 | static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) |
@@ -112,11 +115,37 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) | |||
112 | return IRQ_HANDLED; | 115 | return IRQ_HANDLED; |
113 | } | 116 | } |
114 | 117 | ||
118 | static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) | ||
119 | { | ||
120 | struct rotary_encoder *encoder = dev_id; | ||
121 | int state; | ||
122 | |||
123 | state = rotary_encoder_get_state(encoder->pdata); | ||
124 | |||
125 | switch (state) { | ||
126 | case 0x00: | ||
127 | case 0x03: | ||
128 | if (state != encoder->last_stable) { | ||
129 | rotary_encoder_report_event(encoder); | ||
130 | encoder->last_stable = state; | ||
131 | } | ||
132 | break; | ||
133 | |||
134 | case 0x01: | ||
135 | case 0x02: | ||
136 | encoder->dir = (encoder->last_stable + state) & 0x01; | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | return IRQ_HANDLED; | ||
141 | } | ||
142 | |||
115 | static int __devinit rotary_encoder_probe(struct platform_device *pdev) | 143 | static int __devinit rotary_encoder_probe(struct platform_device *pdev) |
116 | { | 144 | { |
117 | struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; | 145 | struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; |
118 | struct rotary_encoder *encoder; | 146 | struct rotary_encoder *encoder; |
119 | struct input_dev *input; | 147 | struct input_dev *input; |
148 | irq_handler_t handler; | ||
120 | int err; | 149 | int err; |
121 | 150 | ||
122 | if (!pdata) { | 151 | if (!pdata) { |
@@ -187,7 +216,14 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
187 | } | 216 | } |
188 | 217 | ||
189 | /* request the IRQs */ | 218 | /* request the IRQs */ |
190 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, | 219 | if (pdata->half_period) { |
220 | handler = &rotary_encoder_half_period_irq; | ||
221 | encoder->last_stable = rotary_encoder_get_state(pdata); | ||
222 | } else { | ||
223 | handler = &rotary_encoder_irq; | ||
224 | } | ||
225 | |||
226 | err = request_irq(encoder->irq_a, handler, | ||
191 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 227 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
192 | DRV_NAME, encoder); | 228 | DRV_NAME, encoder); |
193 | if (err) { | 229 | if (err) { |
@@ -196,7 +232,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
196 | goto exit_free_gpio_b; | 232 | goto exit_free_gpio_b; |
197 | } | 233 | } |
198 | 234 | ||
199 | err = request_irq(encoder->irq_b, &rotary_encoder_irq, | 235 | err = request_irq(encoder->irq_b, handler, |
200 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 236 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
201 | DRV_NAME, encoder); | 237 | DRV_NAME, encoder); |
202 | if (err) { | 238 | if (err) { |
@@ -264,5 +300,5 @@ module_exit(rotary_encoder_exit); | |||
264 | 300 | ||
265 | MODULE_ALIAS("platform:" DRV_NAME); | 301 | MODULE_ALIAS("platform:" DRV_NAME); |
266 | MODULE_DESCRIPTION("GPIO rotary encoder driver"); | 302 | MODULE_DESCRIPTION("GPIO rotary encoder driver"); |
267 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 303 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold"); |
268 | MODULE_LICENSE("GPL v2"); | 304 | MODULE_LICENSE("GPL v2"); |