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