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