Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Generic DT helper functions for touchscreen devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (c) 2014 Sebastian Reichel <sre@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/input/touchscreen.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) static bool touchscreen_get_prop_u32(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 				     const char *property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 				     unsigned int default_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 				     unsigned int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 	int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	error = device_property_read_u32(dev, property, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 		*value = default_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	*value = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static void touchscreen_set_params(struct input_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 				   unsigned long axis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 				   int min, int max, int fuzz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct input_absinfo *absinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	if (!test_bit(axis, dev->absbit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 		dev_warn(&dev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 			 "DT specifies parameters but the axis %lu is not set up\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			 axis);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	absinfo = &dev->absinfo[axis];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	absinfo->minimum = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	absinfo->maximum = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	absinfo->fuzz = fuzz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * touchscreen_parse_properties - parse common touchscreen DT properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * @input: input device that should be parsed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * @multitouch: specifies whether parsed properties should be applied to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  *	single-touch or multi-touch axes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * @prop: pointer to a struct touchscreen_properties into which to store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  *	axis swap and invert info for use with touchscreen_report_x_y();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *	or %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * This function parses common DT properties for touchscreens and setups the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * input device accordingly. The function keeps previously set up default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * values if no value is specified via DT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				  struct touchscreen_properties *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	struct device *dev = input->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct input_absinfo *absinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	unsigned int axis, axis_x, axis_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	unsigned int minimum, maximum, fuzz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	bool data_present;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	input_alloc_absinfo(input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	if (!input->absinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	axis_x = multitouch ? ABS_MT_POSITION_X : ABS_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	axis_y = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 						input_abs_get_min(input, axis_x),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 						&minimum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 						 input_abs_get_max(input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 								   axis_x) + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 						 &maximum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 						 input_abs_get_fuzz(input, axis_x),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 						 &fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (data_present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		touchscreen_set_params(input, axis_x, minimum, maximum - 1, fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 						input_abs_get_min(input, axis_y),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 						&minimum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-y",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 						 input_abs_get_max(input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 								   axis_y) + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 						 &maximum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 						 input_abs_get_fuzz(input, axis_y),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 						 &fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (data_present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		touchscreen_set_params(input, axis_y, minimum, maximum - 1, fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	data_present = touchscreen_get_prop_u32(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 						"touchscreen-max-pressure",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 						input_abs_get_max(input, axis),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 						&maximum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	data_present |= touchscreen_get_prop_u32(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 						 "touchscreen-fuzz-pressure",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 						 input_abs_get_fuzz(input, axis),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 						 &fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (data_present)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		touchscreen_set_params(input, axis, 0, maximum, fuzz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	prop->max_x = input_abs_get_max(input, axis_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	prop->max_y = input_abs_get_max(input, axis_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	prop->invert_x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		device_property_read_bool(dev, "touchscreen-inverted-x");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (prop->invert_x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		absinfo = &input->absinfo[axis_x];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		absinfo->maximum -= absinfo->minimum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		absinfo->minimum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	prop->invert_y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		device_property_read_bool(dev, "touchscreen-inverted-y");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	if (prop->invert_y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		absinfo = &input->absinfo[axis_y];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		absinfo->maximum -= absinfo->minimum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		absinfo->minimum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	prop->swap_x_y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		device_property_read_bool(dev, "touchscreen-swapped-x-y");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (prop->swap_x_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		swap(input->absinfo[axis_x], input->absinfo[axis_y]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) EXPORT_SYMBOL(touchscreen_parse_properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			      unsigned int *x, unsigned int *y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	if (prop->invert_x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		*x = prop->max_x - *x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (prop->invert_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		*y = prop->max_y - *y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (prop->swap_x_y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		swap(*x, *y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)  * touchscreen_set_mt_pos - Set input_mt_pos coordinates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)  * @pos: input_mt_pos to set coordinates of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)  * @prop: pointer to a struct touchscreen_properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)  * @x: X coordinate to store in pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)  * @y: Y coordinate to store in pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  * Adjust the passed in x and y values applying any axis inversion and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * swapping requested in the passed in touchscreen_properties and store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * the result in a struct input_mt_pos.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) void touchscreen_set_mt_pos(struct input_mt_pos *pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 			    const struct touchscreen_properties *prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			    unsigned int x, unsigned int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	touchscreen_apply_prop_to_x_y(prop, &x, &y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	pos->x = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	pos->y = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) EXPORT_SYMBOL(touchscreen_set_mt_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * touchscreen_report_pos - Report touchscreen coordinates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * @input: input_device to report coordinates for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * @prop: pointer to a struct touchscreen_properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @x: X coordinate to report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  * @y: Y coordinate to report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * @multitouch: Report coordinates on single-touch or multi-touch axes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * Adjust the passed in x and y values applying any axis inversion and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * swapping requested in the passed in touchscreen_properties and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  * report the resulting coordinates on the input_dev's x and y axis.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) void touchscreen_report_pos(struct input_dev *input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			    const struct touchscreen_properties *prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			    unsigned int x, unsigned int y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			    bool multitouch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	touchscreen_apply_prop_to_x_y(prop, &x, &y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) EXPORT_SYMBOL(touchscreen_report_pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) MODULE_DESCRIPTION("Device-tree helpers functions for touchscreen devices");