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->flip_x) 36 obj->x = sensor->max_x - obj->x; 37 38 if (axis_align->flip_y) 39 obj->y = sensor->max_y - obj->y; 40 41 if (axis_align->swap_axes) 42 swap(obj->x, 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->flip_x) 124 x = min(RMI_2D_REL_POS_MAX, -x); 125 126 if (axis_align->flip_y) 127 y = min(RMI_2D_REL_POS_MAX, -y); 128 129 if (axis_align->swap_axes) 130 swap(x, 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 max_x, max_y; 145 int input_flags = 0; 146 147 if (sensor->report_abs) { 148 sensor->min_x = sensor->axis_align.clip_x_low; 149 if (sensor->axis_align.clip_x_high) 150 sensor->max_x = min(sensor->max_x, 151 sensor->axis_align.clip_x_high); 152 153 sensor->min_y = sensor->axis_align.clip_y_low; 154 if (sensor->axis_align.clip_y_high) 155 sensor->max_y = min(sensor->max_y, 156 sensor->axis_align.clip_y_high); 157 158 set_bit(EV_ABS, input->evbit); 159 160 max_x = sensor->max_x; 161 max_y = sensor->max_y; 162 if (sensor->axis_align.swap_axes) 163 swap(max_x, max_y); 164 input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_x, 0, 0); 165 input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_y, 0, 0); 166 167 if (sensor->x_mm && sensor->y_mm) { 168 res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm; 169 res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm; 170 if (sensor->axis_align.swap_axes) 171 swap(res_x, res_y); 172 173 input_abs_set_res(input, ABS_X, res_x); 174 input_abs_set_res(input, ABS_Y, res_y); 175 176 input_abs_set_res(input, ABS_MT_POSITION_X, res_x); 177 input_abs_set_res(input, ABS_MT_POSITION_Y, res_y); 178 179 if (!sensor->dmax) 180 sensor->dmax = DMAX * res_x; 181 } 182 183 input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0); 184 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); 185 input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); 186 input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); 187 input_set_abs_params(input, ABS_MT_TOOL_TYPE, 188 0, MT_TOOL_MAX, 0, 0); 189 190 if (sensor->sensor_type == rmi_sensor_touchpad) 191 input_flags = INPUT_MT_POINTER; 192 else 193 input_flags = INPUT_MT_DIRECT; 194 195 if (sensor->kernel_tracking) 196 input_flags |= INPUT_MT_TRACK; 197 198 input_mt_init_slots(input, sensor->nbr_fingers, input_flags); 199 } 200 201 if (sensor->report_rel) { 202 set_bit(EV_REL, input->evbit); 203 set_bit(REL_X, input->relbit); 204 set_bit(REL_Y, input->relbit); 205 } 206 207 if (sensor->topbuttonpad) 208 set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit); 209 } 210 EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params); 211 212 int rmi_2d_sensor_configure_input(struct rmi_function *fn, 213 struct rmi_2d_sensor *sensor) 214 { 215 struct rmi_device *rmi_dev = fn->rmi_dev; 216 struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); 217 218 if (!drv_data->input) 219 return -ENODEV; 220 221 sensor->input = drv_data->input; 222 rmi_2d_sensor_set_input_params(sensor); 223 224 return 0; 225 } 226 EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input); 227 228 #ifdef CONFIG_OF 229 int rmi_2d_sensor_of_probe(struct device *dev, 230 struct rmi_2d_sensor_platform_data *pdata) 231 { 232 int retval; 233 u32 val; 234 235 pdata->axis_align.swap_axes = of_property_read_bool(dev->of_node, 236 "touchscreen-swapped-x-y"); 237 238 pdata->axis_align.flip_x = of_property_read_bool(dev->of_node, 239 "touchscreen-inverted-x"); 240 241 pdata->axis_align.flip_y = of_property_read_bool(dev->of_node, 242 "touchscreen-inverted-y"); 243 244 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-low", 1); 245 if (retval) 246 return retval; 247 248 pdata->axis_align.clip_x_low = val; 249 250 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-low", 1); 251 if (retval) 252 return retval; 253 254 pdata->axis_align.clip_y_low = val; 255 256 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-x-high", 1); 257 if (retval) 258 return retval; 259 260 pdata->axis_align.clip_x_high = val; 261 262 retval = rmi_of_property_read_u32(dev, &val, "syna,clip-y-high", 1); 263 if (retval) 264 return retval; 265 266 pdata->axis_align.clip_y_high = val; 267 268 retval = rmi_of_property_read_u32(dev, &val, "syna,offset-x", 1); 269 if (retval) 270 return retval; 271 272 pdata->axis_align.offset_x = val; 273 274 retval = rmi_of_property_read_u32(dev, &val, "syna,offset-y", 1); 275 if (retval) 276 return retval; 277 278 pdata->axis_align.offset_y = val; 279 280 retval = rmi_of_property_read_u32(dev, &val, "syna,delta-x-threshold", 281 1); 282 if (retval) 283 return retval; 284 285 pdata->axis_align.delta_x_threshold = val; 286 287 retval = rmi_of_property_read_u32(dev, &val, "syna,delta-y-threshold", 288 1); 289 if (retval) 290 return retval; 291 292 pdata->axis_align.delta_y_threshold = val; 293 294 retval = rmi_of_property_read_u32(dev, (u32 *)&pdata->sensor_type, 295 "syna,sensor-type", 1); 296 if (retval) 297 return retval; 298 299 retval = rmi_of_property_read_u32(dev, &val, "touchscreen-x-mm", 1); 300 if (retval) 301 return retval; 302 303 pdata->x_mm = val; 304 305 retval = rmi_of_property_read_u32(dev, &val, "touchscreen-y-mm", 1); 306 if (retval) 307 return retval; 308 309 pdata->y_mm = val; 310 311 retval = rmi_of_property_read_u32(dev, &val, 312 "syna,disable-report-mask", 1); 313 if (retval) 314 return retval; 315 316 pdata->disable_report_mask = val; 317 318 retval = rmi_of_property_read_u32(dev, &val, "syna,rezero-wait-ms", 319 1); 320 if (retval) 321 return retval; 322 323 pdata->rezero_wait = val; 324 325 return 0; 326 } 327 #else 328 inline int rmi_2d_sensor_of_probe(struct device *dev, 329 struct rmi_2d_sensor_platform_data *pdata) 330 { 331 return -ENODEV; 332 } 333 #endif 334 EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe); 335