rotary_encoder.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * rotary_encoder.c
  3. *
  4. * (c) 2009 Daniel Mack <daniel@caiaq.de>
  5. * Copyright (C) 2011 Johan Hovold <jhovold@gmail.com>
  6. *
  7. * state machine code inspired by code from Tim Ruetz
  8. *
  9. * A generic driver for rotary encoders connected to GPIO lines.
  10. * See file:Documentation/input/rotary-encoder.txt for more information
  11. *
  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.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/init.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.h>
  24. #include <linux/rotary_encoder.h>
  25. #include <linux/slab.h>
  26. #include <linux/of_platform.h>
  27. #include <linux/of_gpio.h>
  28. #define DRV_NAME "rotary-encoder"
  29. struct rotary_encoder {
  30. struct input_dev *input;
  31. const struct rotary_encoder_platform_data *pdata;
  32. unsigned int axis;
  33. unsigned int pos;
  34. unsigned int irq_a;
  35. unsigned int irq_b;
  36. bool armed;
  37. unsigned char dir; /* 0 - clockwise, 1 - CCW */
  38. char last_stable;
  39. };
  40. static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
  41. {
  42. int a = !!gpio_get_value(pdata->gpio_a);
  43. int b = !!gpio_get_value(pdata->gpio_b);
  44. a ^= pdata->inverted_a;
  45. b ^= pdata->inverted_b;
  46. return ((a << 1) | b);
  47. }
  48. static void rotary_encoder_report_event(struct rotary_encoder *encoder)
  49. {
  50. const struct rotary_encoder_platform_data *pdata = encoder->pdata;
  51. if (pdata->relative_axis) {
  52. input_report_rel(encoder->input,
  53. pdata->axis, encoder->dir ? -1 : 1);
  54. } else {
  55. unsigned int pos = encoder->pos;
  56. if (encoder->dir) {
  57. /* turning counter-clockwise */
  58. if (pdata->rollover)
  59. pos += pdata->steps;
  60. if (pos)
  61. pos--;
  62. } else {
  63. /* turning clockwise */
  64. if (pdata->rollover || pos < pdata->steps)
  65. pos++;
  66. }
  67. if (pdata->rollover)
  68. pos %= pdata->steps;
  69. encoder->pos = pos;
  70. input_report_abs(encoder->input, pdata->axis, encoder->pos);
  71. }
  72. input_sync(encoder->input);
  73. }
  74. static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
  75. {
  76. struct rotary_encoder *encoder = dev_id;
  77. int state;
  78. state = rotary_encoder_get_state(encoder->pdata);
  79. switch (state) {
  80. case 0x0:
  81. if (encoder->armed) {
  82. rotary_encoder_report_event(encoder);
  83. encoder->armed = false;
  84. }
  85. break;
  86. case 0x1:
  87. case 0x2:
  88. if (encoder->armed)
  89. encoder->dir = state - 1;
  90. break;
  91. case 0x3:
  92. encoder->armed = true;
  93. break;
  94. }
  95. return IRQ_HANDLED;
  96. }
  97. static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
  98. {
  99. struct rotary_encoder *encoder = dev_id;
  100. int state;
  101. state = rotary_encoder_get_state(encoder->pdata);
  102. switch (state) {
  103. case 0x00:
  104. case 0x03:
  105. if (state != encoder->last_stable) {
  106. rotary_encoder_report_event(encoder);
  107. encoder->last_stable = state;
  108. }
  109. break;
  110. case 0x01:
  111. case 0x02:
  112. encoder->dir = (encoder->last_stable + state) & 0x01;
  113. break;
  114. }
  115. return IRQ_HANDLED;
  116. }
  117. #ifdef CONFIG_OF
  118. static struct of_device_id rotary_encoder_of_match[] = {
  119. { .compatible = "rotary-encoder", },
  120. { },
  121. };
  122. MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
  123. static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev)
  124. {
  125. const struct of_device_id *of_id =
  126. of_match_device(rotary_encoder_of_match, dev);
  127. struct device_node *np = dev->of_node;
  128. struct rotary_encoder_platform_data *pdata;
  129. enum of_gpio_flags flags;
  130. if (!of_id || !np)
  131. return NULL;
  132. pdata = kzalloc(sizeof(struct rotary_encoder_platform_data),
  133. GFP_KERNEL);
  134. if (!pdata)
  135. return ERR_PTR(-ENOMEM);
  136. of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps);
  137. of_property_read_u32(np, "linux,axis", &pdata->axis);
  138. pdata->gpio_a = of_get_gpio_flags(np, 0, &flags);
  139. pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW;
  140. pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
  141. pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
  142. pdata->relative_axis = !!of_get_property(np,
  143. "rotary-encoder,relative-axis", NULL);
  144. pdata->rollover = !!of_get_property(np,
  145. "rotary-encoder,rollover", NULL);
  146. pdata->half_period = !!of_get_property(np,
  147. "rotary-encoder,half-period", NULL);
  148. return pdata;
  149. }
  150. #else
  151. static inline struct rotary_encoder_platform_data *
  152. rotary_encoder_parse_dt(struct device *dev)
  153. {
  154. return NULL;
  155. }
  156. #endif
  157. static int rotary_encoder_probe(struct platform_device *pdev)
  158. {
  159. struct device *dev = &pdev->dev;
  160. const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
  161. struct rotary_encoder *encoder;
  162. struct input_dev *input;
  163. irq_handler_t handler;
  164. int err;
  165. if (!pdata) {
  166. pdata = rotary_encoder_parse_dt(dev);
  167. if (IS_ERR(pdata))
  168. return PTR_ERR(pdata);
  169. if (!pdata) {
  170. dev_err(dev, "missing platform data\n");
  171. return -EINVAL;
  172. }
  173. }
  174. encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL);
  175. input = input_allocate_device();
  176. if (!encoder || !input) {
  177. err = -ENOMEM;
  178. goto exit_free_mem;
  179. }
  180. encoder->input = input;
  181. encoder->pdata = pdata;
  182. input->name = pdev->name;
  183. input->id.bustype = BUS_HOST;
  184. input->dev.parent = dev;
  185. if (pdata->relative_axis) {
  186. input->evbit[0] = BIT_MASK(EV_REL);
  187. input->relbit[0] = BIT_MASK(pdata->axis);
  188. } else {
  189. input->evbit[0] = BIT_MASK(EV_ABS);
  190. input_set_abs_params(encoder->input,
  191. pdata->axis, 0, pdata->steps, 0, 1);
  192. }
  193. /* request the GPIOs */
  194. err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev));
  195. if (err) {
  196. dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a);
  197. goto exit_free_mem;
  198. }
  199. err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev));
  200. if (err) {
  201. dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b);
  202. goto exit_free_gpio_a;
  203. }
  204. encoder->irq_a = gpio_to_irq(pdata->gpio_a);
  205. encoder->irq_b = gpio_to_irq(pdata->gpio_b);
  206. /* request the IRQs */
  207. if (pdata->half_period) {
  208. handler = &rotary_encoder_half_period_irq;
  209. encoder->last_stable = rotary_encoder_get_state(pdata);
  210. } else {
  211. handler = &rotary_encoder_irq;
  212. }
  213. err = request_irq(encoder->irq_a, handler,
  214. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  215. DRV_NAME, encoder);
  216. if (err) {
  217. dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
  218. goto exit_free_gpio_b;
  219. }
  220. err = request_irq(encoder->irq_b, handler,
  221. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  222. DRV_NAME, encoder);
  223. if (err) {
  224. dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
  225. goto exit_free_irq_a;
  226. }
  227. err = input_register_device(input);
  228. if (err) {
  229. dev_err(dev, "failed to register input device\n");
  230. goto exit_free_irq_b;
  231. }
  232. platform_set_drvdata(pdev, encoder);
  233. return 0;
  234. exit_free_irq_b:
  235. free_irq(encoder->irq_b, encoder);
  236. exit_free_irq_a:
  237. free_irq(encoder->irq_a, encoder);
  238. exit_free_gpio_b:
  239. gpio_free(pdata->gpio_b);
  240. exit_free_gpio_a:
  241. gpio_free(pdata->gpio_a);
  242. exit_free_mem:
  243. input_free_device(input);
  244. kfree(encoder);
  245. if (!dev_get_platdata(&pdev->dev))
  246. kfree(pdata);
  247. return err;
  248. }
  249. static int rotary_encoder_remove(struct platform_device *pdev)
  250. {
  251. struct rotary_encoder *encoder = platform_get_drvdata(pdev);
  252. const struct rotary_encoder_platform_data *pdata = encoder->pdata;
  253. free_irq(encoder->irq_a, encoder);
  254. free_irq(encoder->irq_b, encoder);
  255. gpio_free(pdata->gpio_a);
  256. gpio_free(pdata->gpio_b);
  257. input_unregister_device(encoder->input);
  258. kfree(encoder);
  259. if (!dev_get_platdata(&pdev->dev))
  260. kfree(pdata);
  261. platform_set_drvdata(pdev, NULL);
  262. return 0;
  263. }
  264. static struct platform_driver rotary_encoder_driver = {
  265. .probe = rotary_encoder_probe,
  266. .remove = rotary_encoder_remove,
  267. .driver = {
  268. .name = DRV_NAME,
  269. .owner = THIS_MODULE,
  270. .of_match_table = of_match_ptr(rotary_encoder_of_match),
  271. }
  272. };
  273. module_platform_driver(rotary_encoder_driver);
  274. MODULE_ALIAS("platform:" DRV_NAME);
  275. MODULE_DESCRIPTION("GPIO rotary encoder driver");
  276. MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>, Johan Hovold");
  277. MODULE_LICENSE("GPL v2");