1 /* 2 * Copyright (c) 2011-2016 Synaptics Incorporated 3 * Copyright (c) 2011 Unixphere 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 as published by 7 * the Free Software Foundation. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/device.h> 12 #include <linux/of.h> 13 #include <linux/input.h> 14 #include <linux/input/mt.h> 15 #include <linux/rmi.h> 16 #include "rmi_driver.h" 17 #include "rmi_2d_sensor.h" 18 19 #define RMI_2D_REL_POS_MIN -128 20 #define RMI_2D_REL_POS_MAX 127 21 22 /* maximum ABS_MT_POSITION displacement (in mm) */ 23 #define DMAX 10 24 25 void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor, 26 struct rmi_2d_sensor_abs_object *obj, 27 int slot) 28 { 29 struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; 30 31 /* we keep the previous values if the finger is released */ 32 if (obj->type == RMI_2D_OBJECT_NONE) 33 return; 34 35 if (axis_align->swap_axes) 36 swap(obj->x, obj->y); 37 38 if (axis_align->flip_x) 39 obj->x = sensor->max_x - obj->x; 40 41 if (axis_align->flip_y) 42 obj->y = sensor->max_y - obj->y; 43 44 /* 45 * Here checking if X offset or y offset are specified is 46 * redundant. We just add the offsets or clip the values. 47 * 48 * Note: offsets need to be applied before clipping occurs, 49 * or we could get funny values that are outside of 50 * clipping boundaries. 51 */ 52 obj->x += axis_align->offset_x; 53 obj->y += axis_align->offset_y; 54 55 obj->x = max(axis_align->clip_x_low, obj->x); 56 obj->y = max(axis_align->clip_y_low, obj->y); 57 58 if (axis_align->clip_x_high) 59 obj->x = min(sensor->max_x, obj->x); 60 61 if (axis_align->clip_y_high) 62 obj->y = min(sensor->max_y, obj->y); 63 64 sensor->tracking_pos[slot].x = obj->x; 65 sensor->tracking_pos[slot].y = obj->y; 66 } 67 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_process); 68 69 void rmi_2d_sensor_abs_report(struct rmi_2d_sensor *sensor, 70 struct rmi_2d_sensor_abs_object *obj, 71 int slot) 72 { 73 struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; 74 struct input_dev *input = sensor->input; 75 int wide, major, minor; 76 77 if (sensor->kernel_tracking) 78 input_mt_slot(input, sensor->tracking_slots[slot]); 79 else 80 input_mt_slot(input, slot); 81 82 input_mt_report_slot_state(input, obj->mt_tool, 83 obj->type != RMI_2D_OBJECT_NONE); 84 85 if (obj->type != RMI_2D_OBJECT_NONE) { 86 obj->x = sensor->tracking_pos[slot].x; 87 obj->y = sensor->tracking_pos[slot].y; 88 89 if (axis_align->swap_axes) 90 swap(obj->wx, obj->wy); 91 92 wide = (obj->wx > obj->wy); 93 major = max(obj->wx, obj->wy); 94 minor = min(obj->wx, obj->wy); 95 96 if (obj->type == RMI_2D_OBJECT_STYLUS) { 97 major = max(1, major); 98 minor = max(1, minor); 99 } 100 101 input_event(sensor->input, EV_ABS, ABS_MT_POSITION_X, obj->x); 102 input_event(sensor->input, EV_ABS, ABS_MT_POSITION_Y, obj->y); 103 input_event(sensor->input, EV_ABS, ABS_MT_ORIENTATION, wide); 104 input_event(sensor->input, EV_ABS, ABS_MT_PRESSURE, obj->z); 105 input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); 106 input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); 107 108 rmi_dbg(RMI_DEBUG_2D_SENSOR, &sensor->input->dev, 109 "%s: obj[%d]: type: 0x%02x X: %d Y: %d Z: %d WX: %d WY: %d\n", 110 __func__, slot, obj->type, obj->x, obj->y, obj->z, 111 obj->wx, obj->wy); 112 } 113 } 114 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_report); 115 116 void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y) 117 { 118 struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; 119 120 x = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)x)); 121 y = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)y)); 122 123 if (axis_align->swap_axes) 124 swap(x, y); 125 126 if (axis_align->flip_x) 127 x = min(RMI_2D_REL_POS_MAX, -x); 128 129 if (axis_align->flip_y) 130 y = min(RMI_2D_REL_POS_MAX, -y); 131 132 if (x || y) { 133 input_report_rel(sensor->input, REL_X, x); 134 input_report_rel(sensor->input, REL_Y, y); 135 } 136 } 137 EXPORT_SYMBOL_GPL(rmi_2d_sensor_rel_report); 138 139 static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) 140 { 141 struct input_dev *input = sensor->input; 142 int res_x; 143 int res_y; 144 int input_flags = 0; 145 146 if (sensor->report_abs) { 147 if (sensor->axis_align.swap_axes) 148 swap(sensor->max_x, sensor->max_y); 149 150 sensor->min_x = sensor->axis_align.clip_x_low; 151 if (sensor->axis_align.clip_x_high) 152 sensor->max_x = min(sensor->max_x, 153 sensor->axis_align.clip_x_high); 154 155 sensor->min_y = sensor->axis_align.clip_y_low; 156 if (sensor->axis_align.clip_y_high) 157 sensor->max_y = min(sensor->max_y, 158 sensor->axis_align.clip_y_high); 159 160 set_bit(EV_ABS, input->evbit); 161 input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensor->max_x, 162 0, 0); 163 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensor->max_y, 164 0, 0); 165 166 if (sensor->x_mm && sensor->y_mm) { 167 res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm; 168 res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm; 169 170 input_abs_set_res(input, ABS_X, res_x); 171 input_abs_set_res(input, ABS_Y, res_y); 172 173 input_abs_set_res(input, ABS_MT_POSITION_X, res_x); 174 input_abs_set_res(input, ABS_MT_POSITION_Y, res_y); 175 176 if (!sensor->dmax) 177 sensor->dmax = DMAX * res_x; 178 } 179 180 input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0); 181 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); 182 input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); 183 input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); 184 185 if (sensor->sensor_type == rmi_sensor_touchpad) 186 input_flags = INPUT_MT_POINTER; 187 else 188 input_flags = INPUT_MT_DIRECT; 189 190 if (sensor->kernel_tracking) 191 input_flags |= INPUT_MT_TRACK; 192 193 input_mt_init_slots(input, sensor->nbr_fingers, input_flags); 194 } 195 196 if (sensor->report_rel) { 197 set_bit(EV_REL, input->evbit); 198 set_bit(REL_X, input->relbit); 199 set_bit(REL_Y, input->relbit); 200 } 201 202 if (sensor->topbuttonpad) 203 set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit); 204 } 205 EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params); 206 207 int rmi_2d_sensor_configure_input(struct rmi_function *fn, 208 struct rmi_2d_sensor *sensor) 209 { 210 struct rmi_device *rmi_dev = fn->rmi_dev; 211 struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); 212 213 if (!drv_data->input) 214 return -ENODEV; 215 216 sensor->input = drv_data->input; 217 rmi_2d_sensor_set_input_params(sensor); 218 219 return 0; 220 } 221 EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input); 222 223 #ifdef CONFIG_OF 224 int rmi_2d_sensor_of_probe(struct device *dev, 225 struct rmi_2d_sensor_platform_data *pdata) 226 { 227 int retval; 228 u32 val; 229 230 pdata->axis_align.swap_axes = of_property_read_bool(dev->of_node, 231 "touchscreen-swapped-x-y"); 232 233 pdata->axis_align.flip_x = of_property_read_bool(dev->of_node, 234 "touchscreen-inverted-x"); 235 236 pdata->axis_align.flip_y = of_property_read_bool(dev->of_node, 237 "touchscreen-inverted-y"); 238 239 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-low", 1); 240 if (retval) 241 return retval; 242 243 pdata->axis_align.clip_x_low = val; 244 245 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-low", 1); 246 if (retval) 247 return retval; 248 249 pdata->axis_align.clip_y_low = val; 250 251 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-high", 1); 252 if (retval) 253 return retval; 254 255 pdata->axis_align.clip_x_high = val; 256 257 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-high", 1); 258 if (retval) 259 return retval; 260 261 pdata->axis_align.clip_y_high = val; 262 263 retval = rmi_of_property_read_u32(dev, &val, "syna,offset-x", 1); 264 if (retval) 265 return retval; 266 267 pdata->axis_align.offset_x = val; 268 269 retval = rmi_of_property_read_u32(dev, &val, "syna,offset-y", 1); 270 if (retval) 271 return retval; 272 273 pdata->axis_align.offset_y = val; 274 275 retval = rmi_of_property_read_u32(dev, &val, "syna,delta-x-threshold", 276 1); 277 if (retval) 278 return retval; 279 280 pdata->axis_align.delta_x_threshold = val; 281 282 retval = rmi_of_property_read_u32(dev, &val, "syna,delta-y-threshold", 283 1); 284 if (retval) 285 return retval; 286 287 pdata->axis_align.delta_y_threshold = val; 288 289 retval = rmi_of_property_read_u32(dev, (u32 *)&pdata->sensor_type, 290 "syna,sensor-type", 1); 291 if (retval) 292 return retval; 293 294 retval = rmi_of_property_read_u32(dev, &val, "touchscreen-x-mm", 1); 295 if (retval) 296 return retval; 297 298 pdata->x_mm = val; 299 300 retval = rmi_of_property_read_u32(dev, &val, "touchscreen-y-mm", 1); 301 if (retval) 302 return retval; 303 304 pdata->y_mm = val; 305 306 retval = rmi_of_property_read_u32(dev, &val, 307 "syna,disable-report-mask", 1); 308 if (retval) 309 return retval; 310 311 pdata->disable_report_mask = val; 312 313 retval = rmi_of_property_read_u32(dev, &val, "syna,rezero-wait-ms", 314 1); 315 if (retval) 316 return retval; 317 318 pdata->rezero_wait = val; 319 320 return 0; 321 } 322 #else 323 inline int rmi_2d_sensor_of_probe(struct device *dev, 324 struct rmi_2d_sensor_platform_data *pdata) 325 { 326 return -ENODEV; 327 } 328 #endif 329 EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe); 330