1 // SPDX-License-Identifier: GPL-2.0
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
8 * Copyright (C) 2017,2018 Microchip Technology,
9 * Author: Eugen Hristev <eugen.hristev@microchip.com>
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/mod_devicetable.h>
17 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/property.h>
21 #define DRIVER_NAME "resistive-adc-touch"
22 #define GRTS_DEFAULT_PRESSURE_MIN 50000
23 #define GRTS_DEFAULT_PRESSURE_MAX 65535
24 #define GRTS_MAX_POS_MASK GENMASK(11, 0)
25 #define GRTS_MAX_CHANNELS 4
33 GRTS_CH_MAX
= GRTS_CH_Z2
+ 1
37 * struct grts_state - generic resistive touch screen information struct
38 * @x_plate_ohms: resistance of the X plate
39 * @pressure_min: number representing the minimum for the pressure
40 * @pressure: are we getting pressure info or not
41 * @iio_chans: list of channels acquired
42 * @iio_cb: iio_callback buffer for the data
43 * @input: the input device structure that we register
44 * @prop: touchscreen properties struct
45 * @ch_map: map of channels that are defined for the touchscreen
51 struct iio_channel
*iio_chans
;
52 struct iio_cb_buffer
*iio_cb
;
53 struct input_dev
*input
;
54 struct touchscreen_properties prop
;
55 u8 ch_map
[GRTS_CH_MAX
];
58 static int grts_cb(const void *data
, void *private)
60 const u16
*touch_info
= data
;
61 struct grts_state
*st
= private;
62 unsigned int x
, y
, press
= 0;
64 x
= touch_info
[st
->ch_map
[GRTS_CH_X
]];
65 y
= touch_info
[st
->ch_map
[GRTS_CH_Y
]];
67 if (st
->ch_map
[GRTS_CH_PRESSURE
] < GRTS_MAX_CHANNELS
) {
68 press
= touch_info
[st
->ch_map
[GRTS_CH_PRESSURE
]];
69 } else if (st
->ch_map
[GRTS_CH_Z1
] < GRTS_MAX_CHANNELS
) {
70 unsigned int z1
= touch_info
[st
->ch_map
[GRTS_CH_Z1
]];
71 unsigned int z2
= touch_info
[st
->ch_map
[GRTS_CH_Z2
]];
74 if (likely(x
&& z1
)) {
77 Rt
*= st
->x_plate_ohms
;
78 Rt
= DIV_ROUND_CLOSEST(Rt
, 16);
81 Rt
= DIV_ROUND_CLOSEST(Rt
, 256);
83 * On increased pressure the resistance (Rt) is
84 * decreasing so, convert values to make it looks as
87 if (Rt
< GRTS_DEFAULT_PRESSURE_MAX
)
88 press
= GRTS_DEFAULT_PRESSURE_MAX
- Rt
;
92 if ((!x
&& !y
) || (st
->pressure
&& (press
< st
->pressure_min
))) {
93 /* report end of touch */
94 input_report_key(st
->input
, BTN_TOUCH
, 0);
95 input_sync(st
->input
);
99 /* report proper touch to subsystem*/
100 touchscreen_report_pos(st
->input
, &st
->prop
, x
, y
, false);
102 input_report_abs(st
->input
, ABS_PRESSURE
, press
);
103 input_report_key(st
->input
, BTN_TOUCH
, 1);
104 input_sync(st
->input
);
109 static int grts_open(struct input_dev
*dev
)
112 struct grts_state
*st
= input_get_drvdata(dev
);
114 error
= iio_channel_start_all_cb(st
->iio_cb
);
116 dev_err(dev
->dev
.parent
, "failed to start callback buffer.\n");
122 static void grts_close(struct input_dev
*dev
)
124 struct grts_state
*st
= input_get_drvdata(dev
);
126 iio_channel_stop_all_cb(st
->iio_cb
);
129 static void grts_disable(void *data
)
131 iio_channel_release_all_cb(data
);
134 static int grts_map_channel(struct grts_state
*st
, struct device
*dev
,
135 enum grts_ch_type type
, const char *name
,
140 idx
= device_property_match_string(dev
, "io-channel-names", name
);
144 idx
= GRTS_MAX_CHANNELS
;
145 } else if (idx
>= GRTS_MAX_CHANNELS
) {
149 st
->ch_map
[type
] = idx
;
153 static int grts_get_properties(struct grts_state
*st
, struct device
*dev
)
157 error
= grts_map_channel(st
, dev
, GRTS_CH_X
, "x", false);
161 error
= grts_map_channel(st
, dev
, GRTS_CH_Y
, "y", false);
165 /* pressure is optional */
166 error
= grts_map_channel(st
, dev
, GRTS_CH_PRESSURE
, "pressure", true);
170 if (st
->ch_map
[GRTS_CH_PRESSURE
] < GRTS_MAX_CHANNELS
) {
175 /* if no pressure is defined, try optional z1 + z2 */
176 error
= grts_map_channel(st
, dev
, GRTS_CH_Z1
, "z1", true);
180 if (st
->ch_map
[GRTS_CH_Z1
] >= GRTS_MAX_CHANNELS
)
183 /* if z1 is provided z2 is not optional */
184 error
= grts_map_channel(st
, dev
, GRTS_CH_Z2
, "z2", true);
188 error
= device_property_read_u32(dev
,
189 "touchscreen-x-plate-ohms",
192 dev_err(dev
, "can't get touchscreen-x-plate-ohms property\n");
200 static int grts_probe(struct platform_device
*pdev
)
202 struct grts_state
*st
;
203 struct input_dev
*input
;
204 struct device
*dev
= &pdev
->dev
;
207 st
= devm_kzalloc(dev
, sizeof(struct grts_state
), GFP_KERNEL
);
211 /* get the channels from IIO device */
212 st
->iio_chans
= devm_iio_channel_get_all(dev
);
213 if (IS_ERR(st
->iio_chans
))
214 return dev_err_probe(dev
, PTR_ERR(st
->iio_chans
), "can't get iio channels\n");
216 if (!device_property_present(dev
, "io-channel-names"))
219 error
= grts_get_properties(st
, dev
);
221 dev_err(dev
, "Failed to parse properties\n");
226 error
= device_property_read_u32(dev
,
227 "touchscreen-min-pressure",
230 dev_dbg(dev
, "can't get touchscreen-min-pressure property.\n");
231 st
->pressure_min
= GRTS_DEFAULT_PRESSURE_MIN
;
235 input
= devm_input_allocate_device(dev
);
237 dev_err(dev
, "failed to allocate input device.\n");
241 input
->name
= DRIVER_NAME
;
242 input
->id
.bustype
= BUS_HOST
;
243 input
->open
= grts_open
;
244 input
->close
= grts_close
;
246 input_set_abs_params(input
, ABS_X
, 0, GRTS_MAX_POS_MASK
- 1, 0, 0);
247 input_set_abs_params(input
, ABS_Y
, 0, GRTS_MAX_POS_MASK
- 1, 0, 0);
249 input_set_abs_params(input
, ABS_PRESSURE
, st
->pressure_min
,
250 GRTS_DEFAULT_PRESSURE_MAX
, 0, 0);
252 input_set_capability(input
, EV_KEY
, BTN_TOUCH
);
254 /* parse optional device tree properties */
255 touchscreen_parse_properties(input
, false, &st
->prop
);
258 input_set_drvdata(input
, st
);
260 error
= input_register_device(input
);
262 dev_err(dev
, "failed to register input device.");
266 st
->iio_cb
= iio_channel_get_all_cb(dev
, grts_cb
, st
);
267 if (IS_ERR(st
->iio_cb
)) {
268 dev_err(dev
, "failed to allocate callback buffer.\n");
269 return PTR_ERR(st
->iio_cb
);
272 error
= devm_add_action_or_reset(dev
, grts_disable
, st
->iio_cb
);
274 dev_err(dev
, "failed to add disable action.\n");
281 static const struct of_device_id grts_of_match
[] = {
283 .compatible
= "resistive-adc-touch",
289 MODULE_DEVICE_TABLE(of
, grts_of_match
);
291 static struct platform_driver grts_driver
= {
295 .of_match_table
= grts_of_match
,
299 module_platform_driver(grts_driver
);
301 MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
302 MODULE_DESCRIPTION("Generic ADC Resistive Touch Driver");
303 MODULE_LICENSE("GPL v2");