aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/misc
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2011-05-11 19:35:30 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-05-12 11:28:47 -0400
commite70bdd41bd0ead91b4a43e9d656ac1569d7c8779 (patch)
tree9518f22417dde4f2b2d2ed3a25af8bc8f4e3814c /drivers/input/misc
parent521a8f5cb79d1017d00d26143227159674e3b79d (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.c42
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
43static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) 46static 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
118static 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
115static int __devinit rotary_encoder_probe(struct platform_device *pdev) 143static 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
265MODULE_ALIAS("platform:" DRV_NAME); 301MODULE_ALIAS("platform:" DRV_NAME);
266MODULE_DESCRIPTION("GPIO rotary encoder driver"); 302MODULE_DESCRIPTION("GPIO rotary encoder driver");
267MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 303MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
268MODULE_LICENSE("GPL v2"); 304MODULE_LICENSE("GPL v2");