4 * (c) 2009 Daniel Mack <daniel@caiaq.de>
5 * Copyright (C) 2011 Johan Hovold <jhovold@gmail.com>
7 * state machine code inspired by code from Tim Ruetz
9 * A generic driver for rotary encoders connected to GPIO lines.
10 * See file:Documentation/input/rotary-encoder.txt for more information
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/interrupt.h>
20 #include <linux/input.h>
21 #include <linux/device.h>
22 #include <linux/platform_device.h>
23 #include <linux/gpio/consumer.h>
24 #include <linux/slab.h>
27 #include <linux/property.h>
29 #define DRV_NAME "rotary-encoder"
31 struct rotary_encoder {
32 struct input_dev *input;
34 struct mutex access_mutex;
43 struct gpio_desc *gpio_a;
44 struct gpio_desc *gpio_b;
50 unsigned char dir; /* 0 - clockwise, 1 - CCW */
55 static int rotary_encoder_get_state(struct rotary_encoder *encoder)
57 int a = !!gpiod_get_value_cansleep(encoder->gpio_a);
58 int b = !!gpiod_get_value_cansleep(encoder->gpio_b);
60 return ((a << 1) | b);
63 static void rotary_encoder_report_event(struct rotary_encoder *encoder)
65 if (encoder->relative_axis) {
66 input_report_rel(encoder->input,
67 encoder->axis, encoder->dir ? -1 : 1);
69 unsigned int pos = encoder->pos;
72 /* turning counter-clockwise */
73 if (encoder->rollover)
74 pos += encoder->steps;
78 /* turning clockwise */
79 if (encoder->rollover || pos < encoder->steps)
83 if (encoder->rollover)
84 pos %= encoder->steps;
87 input_report_abs(encoder->input, encoder->axis, encoder->pos);
90 input_sync(encoder->input);
93 static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
95 struct rotary_encoder *encoder = dev_id;
98 mutex_lock(&encoder->access_mutex);
100 state = rotary_encoder_get_state(encoder);
104 if (encoder->armed) {
105 rotary_encoder_report_event(encoder);
106 encoder->armed = false;
113 encoder->dir = state - 1;
117 encoder->armed = true;
121 mutex_unlock(&encoder->access_mutex);
126 static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
128 struct rotary_encoder *encoder = dev_id;
131 mutex_lock(&encoder->access_mutex);
133 state = rotary_encoder_get_state(encoder);
138 if (state != encoder->last_stable) {
139 rotary_encoder_report_event(encoder);
140 encoder->last_stable = state;
146 encoder->dir = (encoder->last_stable + state) & 0x01;
150 mutex_unlock(&encoder->access_mutex);
155 static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
157 struct rotary_encoder *encoder = dev_id;
161 mutex_lock(&encoder->access_mutex);
163 state = rotary_encoder_get_state(encoder);
166 * We encode the previous and the current state using a byte.
167 * The previous state in the MSB nibble, the current state in the LSB
168 * nibble. Then use a table to decide the direction of the turn.
170 sum = (encoder->last_stable << 4) + state;
176 encoder->dir = 0; /* clockwise */
183 encoder->dir = 1; /* counter-clockwise */
188 * Ignore all other values. This covers the case when the
189 * state didn't change (a spurious interrupt) and the
190 * cases where the state changed by two steps, making it
191 * impossible to tell the direction.
193 * In either case, don't report any event and save the
199 rotary_encoder_report_event(encoder);
202 encoder->last_stable = state;
203 mutex_unlock(&encoder->access_mutex);
208 static int rotary_encoder_probe(struct platform_device *pdev)
210 struct device *dev = &pdev->dev;
211 struct rotary_encoder *encoder;
212 struct input_dev *input;
213 irq_handler_t handler;
214 u32 steps_per_period;
217 encoder = devm_kzalloc(dev, sizeof(struct rotary_encoder), GFP_KERNEL);
221 mutex_init(&encoder->access_mutex);
223 device_property_read_u32(dev, "rotary-encoder,steps", &encoder->steps);
225 err = device_property_read_u32(dev, "rotary-encoder,steps-per-period",
229 * The 'half-period' property has been deprecated, you must
230 * use 'steps-per-period' and set an appropriate value, but
231 * we still need to parse it to maintain compatibility. If
232 * neither property is present we fall back to the one step
233 * per period behavior.
235 steps_per_period = device_property_read_bool(dev,
236 "rotary-encoder,half-period") ? 2 : 1;
240 device_property_read_bool(dev, "rotary-encoder,rollover");
242 device_property_read_u32(dev, "linux,axis", &encoder->axis);
243 encoder->relative_axis =
244 device_property_read_bool(dev, "rotary-encoder,relative-axis");
246 encoder->gpio_a = devm_gpiod_get_index(dev, NULL, 0, GPIOD_IN);
247 if (IS_ERR(encoder->gpio_a)) {
248 err = PTR_ERR(encoder->gpio_a);
249 dev_err(dev, "unable to get GPIO at index 0: %d\n", err);
253 encoder->irq_a = gpiod_to_irq(encoder->gpio_a);
255 encoder->gpio_b = devm_gpiod_get_index(dev, NULL, 1, GPIOD_IN);
256 if (IS_ERR(encoder->gpio_b)) {
257 err = PTR_ERR(encoder->gpio_b);
258 dev_err(dev, "unable to get GPIO at index 1: %d\n", err);
262 encoder->irq_b = gpiod_to_irq(encoder->gpio_b);
264 input = devm_input_allocate_device(dev);
268 encoder->input = input;
270 input->name = pdev->name;
271 input->id.bustype = BUS_HOST;
272 input->dev.parent = dev;
274 if (encoder->relative_axis)
275 input_set_capability(input, EV_REL, encoder->axis);
277 input_set_abs_params(input,
278 encoder->axis, 0, encoder->steps, 0, 1);
280 switch (steps_per_period) {
282 handler = &rotary_encoder_quarter_period_irq;
283 encoder->last_stable = rotary_encoder_get_state(encoder);
286 handler = &rotary_encoder_half_period_irq;
287 encoder->last_stable = rotary_encoder_get_state(encoder);
290 handler = &rotary_encoder_irq;
293 dev_err(dev, "'%d' is not a valid steps-per-period value\n",
298 err = devm_request_threaded_irq(dev, encoder->irq_a, NULL, handler,
299 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
303 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
307 err = devm_request_threaded_irq(dev, encoder->irq_b, NULL, handler,
308 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
312 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
316 err = input_register_device(input);
318 dev_err(dev, "failed to register input device\n");
322 device_init_wakeup(dev,
323 device_property_read_bool(dev, "wakeup-source"));
325 platform_set_drvdata(pdev, encoder);
330 static int __maybe_unused rotary_encoder_suspend(struct device *dev)
332 struct rotary_encoder *encoder = dev_get_drvdata(dev);
334 if (device_may_wakeup(dev)) {
335 enable_irq_wake(encoder->irq_a);
336 enable_irq_wake(encoder->irq_b);
342 static int __maybe_unused rotary_encoder_resume(struct device *dev)
344 struct rotary_encoder *encoder = dev_get_drvdata(dev);
346 if (device_may_wakeup(dev)) {
347 disable_irq_wake(encoder->irq_a);
348 disable_irq_wake(encoder->irq_b);
354 static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops,
355 rotary_encoder_suspend, rotary_encoder_resume);
358 static const struct of_device_id rotary_encoder_of_match[] = {
359 { .compatible = "rotary-encoder", },
362 MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
365 static struct platform_driver rotary_encoder_driver = {
366 .probe = rotary_encoder_probe,
369 .pm = &rotary_encoder_pm_ops,
370 .of_match_table = of_match_ptr(rotary_encoder_of_match),
373 module_platform_driver(rotary_encoder_driver);
375 MODULE_ALIAS("platform:" DRV_NAME);
376 MODULE_DESCRIPTION("GPIO rotary encoder driver");
377 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
378 MODULE_LICENSE("GPL v2");