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