resistive-adc-touch.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * ADC generic resistive touchscreen (GRTS)
  4. * This is a generic input driver that connects to an ADC
  5. * given the channels in device tree, and reports events to the input
  6. * subsystem.
  7. *
  8. * Copyright (C) 2017,2018 Microchip Technology,
  9. * Author: Eugen Hristev <eugen.hristev@microchip.com>
  10. *
  11. */
  12. #include <linux/input.h>
  13. #include <linux/input/touchscreen.h>
  14. #include <linux/iio/consumer.h>
  15. #include <linux/iio/iio.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/of_device.h>
  19. #include <linux/platform_device.h>
  20. #define DRIVER_NAME "resistive-adc-touch"
  21. #define GRTS_DEFAULT_PRESSURE_MIN 50000
  22. #define GRTS_MAX_POS_MASK GENMASK(11, 0)
  23. /**
  24. * grts_state - generic resistive touch screen information struct
  25. * @pressure_min: number representing the minimum for the pressure
  26. * @pressure: are we getting pressure info or not
  27. * @iio_chans: list of channels acquired
  28. * @iio_cb: iio_callback buffer for the data
  29. * @input: the input device structure that we register
  30. * @prop: touchscreen properties struct
  31. */
  32. struct grts_state {
  33. u32 pressure_min;
  34. bool pressure;
  35. struct iio_channel *iio_chans;
  36. struct iio_cb_buffer *iio_cb;
  37. struct input_dev *input;
  38. struct touchscreen_properties prop;
  39. };
  40. static int grts_cb(const void *data, void *private)
  41. {
  42. const u16 *touch_info = data;
  43. struct grts_state *st = private;
  44. unsigned int x, y, press = 0x0;
  45. /* channel data coming in buffer in the order below */
  46. x = touch_info[0];
  47. y = touch_info[1];
  48. if (st->pressure)
  49. press = touch_info[2];
  50. if ((!x && !y) || (st->pressure && (press < st->pressure_min))) {
  51. /* report end of touch */
  52. input_report_key(st->input, BTN_TOUCH, 0);
  53. input_sync(st->input);
  54. return 0;
  55. }
  56. /* report proper touch to subsystem*/
  57. touchscreen_report_pos(st->input, &st->prop, x, y, false);
  58. if (st->pressure)
  59. input_report_abs(st->input, ABS_PRESSURE, press);
  60. input_report_key(st->input, BTN_TOUCH, 1);
  61. input_sync(st->input);
  62. return 0;
  63. }
  64. static int grts_open(struct input_dev *dev)
  65. {
  66. int error;
  67. struct grts_state *st = input_get_drvdata(dev);
  68. error = iio_channel_start_all_cb(st->iio_cb);
  69. if (error) {
  70. dev_err(dev->dev.parent, "failed to start callback buffer.\n");
  71. return error;
  72. }
  73. return 0;
  74. }
  75. static void grts_close(struct input_dev *dev)
  76. {
  77. struct grts_state *st = input_get_drvdata(dev);
  78. iio_channel_stop_all_cb(st->iio_cb);
  79. }
  80. static void grts_disable(void *data)
  81. {
  82. iio_channel_release_all_cb(data);
  83. }
  84. static int grts_probe(struct platform_device *pdev)
  85. {
  86. struct grts_state *st;
  87. struct input_dev *input;
  88. struct device *dev = &pdev->dev;
  89. struct iio_channel *chan;
  90. int error;
  91. st = devm_kzalloc(dev, sizeof(struct grts_state), GFP_KERNEL);
  92. if (!st)
  93. return -ENOMEM;
  94. /* get the channels from IIO device */
  95. st->iio_chans = devm_iio_channel_get_all(dev);
  96. if (IS_ERR(st->iio_chans)) {
  97. error = PTR_ERR(st->iio_chans);
  98. if (error != -EPROBE_DEFER)
  99. dev_err(dev, "can't get iio channels.\n");
  100. return error;
  101. }
  102. chan = &st->iio_chans[0];
  103. st->pressure = false;
  104. while (chan && chan->indio_dev) {
  105. if (!strcmp(chan->channel->datasheet_name, "pressure"))
  106. st->pressure = true;
  107. chan++;
  108. }
  109. if (st->pressure) {
  110. error = device_property_read_u32(dev,
  111. "touchscreen-min-pressure",
  112. &st->pressure_min);
  113. if (error) {
  114. dev_dbg(dev, "can't get touchscreen-min-pressure property.\n");
  115. st->pressure_min = GRTS_DEFAULT_PRESSURE_MIN;
  116. }
  117. }
  118. input = devm_input_allocate_device(dev);
  119. if (!input) {
  120. dev_err(dev, "failed to allocate input device.\n");
  121. return -ENOMEM;
  122. }
  123. input->name = DRIVER_NAME;
  124. input->id.bustype = BUS_HOST;
  125. input->open = grts_open;
  126. input->close = grts_close;
  127. input_set_abs_params(input, ABS_X, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
  128. input_set_abs_params(input, ABS_Y, 0, GRTS_MAX_POS_MASK - 1, 0, 0);
  129. if (st->pressure)
  130. input_set_abs_params(input, ABS_PRESSURE, st->pressure_min,
  131. 0xffff, 0, 0);
  132. input_set_capability(input, EV_KEY, BTN_TOUCH);
  133. /* parse optional device tree properties */
  134. touchscreen_parse_properties(input, false, &st->prop);
  135. st->input = input;
  136. input_set_drvdata(input, st);
  137. error = input_register_device(input);
  138. if (error) {
  139. dev_err(dev, "failed to register input device.");
  140. return error;
  141. }
  142. st->iio_cb = iio_channel_get_all_cb(dev, grts_cb, st);
  143. if (IS_ERR(st->iio_cb)) {
  144. dev_err(dev, "failed to allocate callback buffer.\n");
  145. return PTR_ERR(st->iio_cb);
  146. }
  147. error = devm_add_action_or_reset(dev, grts_disable, st->iio_cb);
  148. if (error) {
  149. dev_err(dev, "failed to add disable action.\n");
  150. return error;
  151. }
  152. return 0;
  153. }
  154. static const struct of_device_id grts_of_match[] = {
  155. {
  156. .compatible = "resistive-adc-touch",
  157. }, {
  158. /* sentinel */
  159. },
  160. };
  161. MODULE_DEVICE_TABLE(of, grts_of_match);
  162. static struct platform_driver grts_driver = {
  163. .probe = grts_probe,
  164. .driver = {
  165. .name = DRIVER_NAME,
  166. .of_match_table = of_match_ptr(grts_of_match),
  167. },
  168. };
  169. module_platform_driver(grts_driver);
  170. MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
  171. MODULE_DESCRIPTION("Generic ADC Resistive Touch Driver");
  172. MODULE_LICENSE("GPL v2");