2 * Copyright (c) 2011-2016 Synaptics Incorporated
3 * Copyright (c) 2011 Unixphere
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.
10 #include <linux/kernel.h>
11 #include <linux/device.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"
19 #define RMI_2D_REL_POS_MIN -128
20 #define RMI_2D_REL_POS_MAX 127
22 /* maximum ABS_MT_POSITION displacement (in mm) */
25 void rmi_2d_sensor_abs_process(struct rmi_2d_sensor
*sensor
,
26 struct rmi_2d_sensor_abs_object
*obj
,
29 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
31 /* we keep the previous values if the finger is released */
32 if (obj
->type
== RMI_2D_OBJECT_NONE
)
35 if (axis_align
->swap_axes
)
38 if (axis_align
->flip_x
)
39 obj
->x
= sensor
->max_x
- obj
->x
;
41 if (axis_align
->flip_y
)
42 obj
->y
= sensor
->max_y
- obj
->y
;
45 * Here checking if X offset or y offset are specified is
46 * redundant. We just add the offsets or clip the values.
48 * Note: offsets need to be applied before clipping occurs,
49 * or we could get funny values that are outside of
50 * clipping boundaries.
52 obj
->x
+= axis_align
->offset_x
;
53 obj
->y
+= axis_align
->offset_y
;
55 obj
->x
= max(axis_align
->clip_x_low
, obj
->x
);
56 obj
->y
= max(axis_align
->clip_y_low
, obj
->y
);
58 if (axis_align
->clip_x_high
)
59 obj
->x
= min(sensor
->max_x
, obj
->x
);
61 if (axis_align
->clip_y_high
)
62 obj
->y
= min(sensor
->max_y
, obj
->y
);
64 sensor
->tracking_pos
[slot
].x
= obj
->x
;
65 sensor
->tracking_pos
[slot
].y
= obj
->y
;
67 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_process
);
69 void rmi_2d_sensor_abs_report(struct rmi_2d_sensor
*sensor
,
70 struct rmi_2d_sensor_abs_object
*obj
,
73 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
74 struct input_dev
*input
= sensor
->input
;
75 int wide
, major
, minor
;
77 if (sensor
->kernel_tracking
)
78 input_mt_slot(input
, sensor
->tracking_slots
[slot
]);
80 input_mt_slot(input
, slot
);
82 input_mt_report_slot_state(input
, obj
->mt_tool
,
83 obj
->type
!= RMI_2D_OBJECT_NONE
);
85 if (obj
->type
!= RMI_2D_OBJECT_NONE
) {
86 obj
->x
= sensor
->tracking_pos
[slot
].x
;
87 obj
->y
= sensor
->tracking_pos
[slot
].y
;
89 if (axis_align
->swap_axes
)
90 swap(obj
->wx
, obj
->wy
);
92 wide
= (obj
->wx
> obj
->wy
);
93 major
= max(obj
->wx
, obj
->wy
);
94 minor
= min(obj
->wx
, obj
->wy
);
96 if (obj
->type
== RMI_2D_OBJECT_STYLUS
) {
97 major
= max(1, major
);
98 minor
= max(1, minor
);
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
);
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
,
114 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_report
);
116 void rmi_2d_sensor_rel_report(struct rmi_2d_sensor
*sensor
, int x
, int y
)
118 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
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
));
123 if (axis_align
->swap_axes
)
126 if (axis_align
->flip_x
)
127 x
= min(RMI_2D_REL_POS_MAX
, -x
);
129 if (axis_align
->flip_y
)
130 y
= min(RMI_2D_REL_POS_MAX
, -y
);
133 input_report_rel(sensor
->input
, REL_X
, x
);
134 input_report_rel(sensor
->input
, REL_Y
, y
);
137 EXPORT_SYMBOL_GPL(rmi_2d_sensor_rel_report
);
139 static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor
*sensor
)
141 struct input_dev
*input
= sensor
->input
;
146 if (sensor
->report_abs
) {
147 if (sensor
->axis_align
.swap_axes
)
148 swap(sensor
->max_x
, sensor
->max_y
);
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
);
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
);
160 set_bit(EV_ABS
, input
->evbit
);
161 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, sensor
->max_x
,
163 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, sensor
->max_y
,
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
;
170 input_abs_set_res(input
, ABS_X
, res_x
);
171 input_abs_set_res(input
, ABS_Y
, res_y
);
173 input_abs_set_res(input
, ABS_MT_POSITION_X
, res_x
);
174 input_abs_set_res(input
, ABS_MT_POSITION_Y
, res_y
);
177 sensor
->dmax
= DMAX
* res_x
;
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);
185 if (sensor
->sensor_type
== rmi_sensor_touchpad
)
186 input_flags
= INPUT_MT_POINTER
;
188 input_flags
= INPUT_MT_DIRECT
;
190 if (sensor
->kernel_tracking
)
191 input_flags
|= INPUT_MT_TRACK
;
193 input_mt_init_slots(input
, sensor
->nbr_fingers
, input_flags
);
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
);
202 if (sensor
->topbuttonpad
)
203 set_bit(INPUT_PROP_TOPBUTTONPAD
, input
->propbit
);
205 EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params
);
207 int rmi_2d_sensor_configure_input(struct rmi_function
*fn
,
208 struct rmi_2d_sensor
*sensor
)
210 struct rmi_device
*rmi_dev
= fn
->rmi_dev
;
211 struct rmi_driver_data
*drv_data
= dev_get_drvdata(&rmi_dev
->dev
);
213 if (!drv_data
->input
)
216 sensor
->input
= drv_data
->input
;
217 rmi_2d_sensor_set_input_params(sensor
);
221 EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input
);
224 int rmi_2d_sensor_of_probe(struct device
*dev
,
225 struct rmi_2d_sensor_platform_data
*pdata
)
230 pdata
->axis_align
.swap_axes
= of_property_read_bool(dev
->of_node
,
231 "touchscreen-swapped-x-y");
233 pdata
->axis_align
.flip_x
= of_property_read_bool(dev
->of_node
,
234 "touchscreen-inverted-x");
236 pdata
->axis_align
.flip_y
= of_property_read_bool(dev
->of_node
,
237 "touchscreen-inverted-y");
239 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-low", 1);
243 pdata
->axis_align
.clip_x_low
= val
;
245 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-low", 1);
249 pdata
->axis_align
.clip_y_low
= val
;
251 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-high", 1);
255 pdata
->axis_align
.clip_x_high
= val
;
257 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-high", 1);
261 pdata
->axis_align
.clip_y_high
= val
;
263 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-x", 1);
267 pdata
->axis_align
.offset_x
= val
;
269 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-y", 1);
273 pdata
->axis_align
.offset_y
= val
;
275 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-x-threshold",
280 pdata
->axis_align
.delta_x_threshold
= val
;
282 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-y-threshold",
287 pdata
->axis_align
.delta_y_threshold
= val
;
289 retval
= rmi_of_property_read_u32(dev
, (u32
*)&pdata
->sensor_type
,
290 "syna,sensor-type", 1);
294 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-x-mm", 1);
300 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-y-mm", 1);
306 retval
= rmi_of_property_read_u32(dev
, &val
,
307 "syna,disable-report-mask", 1);
311 pdata
->disable_report_mask
= val
;
313 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,rezero-wait-ms",
318 pdata
->rezero_wait
= val
;
323 inline int rmi_2d_sensor_of_probe(struct device
*dev
,
324 struct rmi_2d_sensor_platform_data
*pdata
)
329 EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe
);