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