Branch data Line data Source code
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 : : 14 : : static 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 : 0 : if (error) { 24 : : *value = default_value; 25 : : return false; 26 : : } 27 : : 28 : 0 : *value = val; 29 : : return true; 30 : : } 31 : : 32 : 0 : static 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 : 0 : if (!test_bit(axis, dev->absbit)) { 39 : 0 : dev_warn(&dev->dev, 40 : : "DT specifies parameters but the axis %lu is not set up\n", 41 : : axis); 42 : 0 : return; 43 : : } 44 : : 45 : 0 : absinfo = &dev->absinfo[axis]; 46 : 0 : absinfo->minimum = min; 47 : 0 : absinfo->maximum = max; 48 : 0 : 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 : : */ 64 : 0 : void touchscreen_parse_properties(struct input_dev *input, bool multitouch, 65 : : struct touchscreen_properties *prop) 66 : : { 67 : 0 : 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 : 0 : input_alloc_absinfo(input); 74 : 0 : if (!input->absinfo) 75 : : return; 76 : : 77 : 0 : axis = multitouch ? ABS_MT_POSITION_X : ABS_X; 78 : 0 : data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x", 79 : : input_abs_get_min(input, axis), 80 : 0 : &minimum) | 81 : 0 : touchscreen_get_prop_u32(dev, "touchscreen-size-x", 82 : : input_abs_get_max(input, 83 : 0 : axis) + 1, 84 : 0 : &maximum) | 85 : 0 : touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x", 86 : : input_abs_get_fuzz(input, axis), 87 : : &fuzz); 88 : 0 : if (data_present) 89 : 0 : touchscreen_set_params(input, axis, minimum, maximum - 1, fuzz); 90 : : 91 : 0 : axis = multitouch ? ABS_MT_POSITION_Y : ABS_Y; 92 : 0 : data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y", 93 : : input_abs_get_min(input, axis), 94 : 0 : &minimum) | 95 : 0 : touchscreen_get_prop_u32(dev, "touchscreen-size-y", 96 : : input_abs_get_max(input, 97 : 0 : axis) + 1, 98 : 0 : &maximum) | 99 : 0 : touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y", 100 : : input_abs_get_fuzz(input, axis), 101 : : &fuzz); 102 : 0 : if (data_present) 103 : 0 : touchscreen_set_params(input, axis, minimum, maximum - 1, fuzz); 104 : : 105 : 0 : axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE; 106 : 0 : data_present = touchscreen_get_prop_u32(dev, 107 : : "touchscreen-max-pressure", 108 : : input_abs_get_max(input, axis), 109 : 0 : &maximum) | 110 : 0 : touchscreen_get_prop_u32(dev, 111 : : "touchscreen-fuzz-pressure", 112 : : input_abs_get_fuzz(input, axis), 113 : : &fuzz); 114 : 0 : if (data_present) 115 : 0 : touchscreen_set_params(input, axis, 0, maximum, fuzz); 116 : : 117 : 0 : if (!prop) 118 : : return; 119 : : 120 : 0 : axis = multitouch ? ABS_MT_POSITION_X : ABS_X; 121 : : 122 : 0 : prop->max_x = input_abs_get_max(input, axis); 123 : 0 : prop->max_y = input_abs_get_max(input, axis + 1); 124 : : 125 : 0 : prop->invert_x = 126 : : device_property_read_bool(dev, "touchscreen-inverted-x"); 127 : 0 : if (prop->invert_x) { 128 : 0 : absinfo = &input->absinfo[axis]; 129 : 0 : absinfo->maximum -= absinfo->minimum; 130 : 0 : absinfo->minimum = 0; 131 : : } 132 : : 133 : 0 : prop->invert_y = 134 : : device_property_read_bool(dev, "touchscreen-inverted-y"); 135 : 0 : if (prop->invert_y) { 136 : 0 : absinfo = &input->absinfo[axis + 1]; 137 : 0 : absinfo->maximum -= absinfo->minimum; 138 : 0 : absinfo->minimum = 0; 139 : : } 140 : : 141 : 0 : prop->swap_x_y = 142 : : device_property_read_bool(dev, "touchscreen-swapped-x-y"); 143 : 0 : if (prop->swap_x_y) 144 : 0 : swap(input->absinfo[axis], input->absinfo[axis + 1]); 145 : : } 146 : : EXPORT_SYMBOL(touchscreen_parse_properties); 147 : : 148 : : static void 149 : : touchscreen_apply_prop_to_x_y(const struct touchscreen_properties *prop, 150 : : unsigned int *x, unsigned int *y) 151 : : { 152 : 0 : if (prop->invert_x) 153 : 0 : *x = prop->max_x - *x; 154 : : 155 : 0 : if (prop->invert_y) 156 : 0 : *y = prop->max_y - *y; 157 : : 158 : 0 : 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 : : */ 173 : 0 : void 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 : 0 : pos->x = x; 179 : 0 : pos->y = y; 180 : 0 : } 181 : : EXPORT_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 : : */ 195 : 0 : void 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 : 0 : input_report_abs(input, multitouch ? ABS_MT_POSITION_X : ABS_X, x); 202 : 0 : input_report_abs(input, multitouch ? ABS_MT_POSITION_Y : ABS_Y, y); 203 : 0 : } 204 : : EXPORT_SYMBOL(touchscreen_report_pos); 205 : : 206 : : MODULE_LICENSE("GPL v2"); 207 : : MODULE_DESCRIPTION("Device-tree helpers functions for touchscreen devices");