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
->flip_x
)
36 obj
->x
= sensor
->max_x
- obj
->x
;
38 if (axis_align
->flip_y
)
39 obj
->y
= sensor
->max_y
- obj
->y
;
41 if (axis_align
->swap_axes
)
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
->flip_x
)
124 x
= min(RMI_2D_REL_POS_MAX
, -x
);
126 if (axis_align
->flip_y
)
127 y
= min(RMI_2D_REL_POS_MAX
, -y
);
129 if (axis_align
->swap_axes
)
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
;
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
);
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
);
158 set_bit(EV_ABS
, input
->evbit
);
160 max_x
= sensor
->max_x
;
161 max_y
= sensor
->max_y
;
162 if (sensor
->axis_align
.swap_axes
)
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);
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
)
173 input_abs_set_res(input
, ABS_X
, res_x
);
174 input_abs_set_res(input
, ABS_Y
, res_y
);
176 input_abs_set_res(input
, ABS_MT_POSITION_X
, res_x
);
177 input_abs_set_res(input
, ABS_MT_POSITION_Y
, res_y
);
180 sensor
->dmax
= DMAX
* res_x
;
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);
190 if (sensor
->sensor_type
== rmi_sensor_touchpad
)
191 input_flags
= INPUT_MT_POINTER
;
193 input_flags
= INPUT_MT_DIRECT
;
195 if (sensor
->kernel_tracking
)
196 input_flags
|= INPUT_MT_TRACK
;
198 input_mt_init_slots(input
, sensor
->nbr_fingers
, input_flags
);
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
);
207 if (sensor
->topbuttonpad
)
208 set_bit(INPUT_PROP_TOPBUTTONPAD
, input
->propbit
);
210 EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params
);
212 int rmi_2d_sensor_configure_input(struct rmi_function
*fn
,
213 struct rmi_2d_sensor
*sensor
)
215 struct rmi_device
*rmi_dev
= fn
->rmi_dev
;
216 struct rmi_driver_data
*drv_data
= dev_get_drvdata(&rmi_dev
->dev
);
218 if (!drv_data
->input
)
221 sensor
->input
= drv_data
->input
;
222 rmi_2d_sensor_set_input_params(sensor
);
226 EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input
);
229 int rmi_2d_sensor_of_probe(struct device
*dev
,
230 struct rmi_2d_sensor_platform_data
*pdata
)
235 pdata
->axis_align
.swap_axes
= of_property_read_bool(dev
->of_node
,
236 "touchscreen-swapped-x-y");
238 pdata
->axis_align
.flip_x
= of_property_read_bool(dev
->of_node
,
239 "touchscreen-inverted-x");
241 pdata
->axis_align
.flip_y
= of_property_read_bool(dev
->of_node
,
242 "touchscreen-inverted-y");
244 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-low", 1);
248 pdata
->axis_align
.clip_x_low
= val
;
250 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-low", 1);
254 pdata
->axis_align
.clip_y_low
= val
;
256 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-high", 1);
260 pdata
->axis_align
.clip_x_high
= val
;
262 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-high", 1);
266 pdata
->axis_align
.clip_y_high
= val
;
268 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-x", 1);
272 pdata
->axis_align
.offset_x
= val
;
274 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-y", 1);
278 pdata
->axis_align
.offset_y
= val
;
280 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-x-threshold",
285 pdata
->axis_align
.delta_x_threshold
= val
;
287 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-y-threshold",
292 pdata
->axis_align
.delta_y_threshold
= val
;
294 retval
= rmi_of_property_read_u32(dev
, (u32
*)&pdata
->sensor_type
,
295 "syna,sensor-type", 1);
299 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-x-mm", 1);
305 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-y-mm", 1);
311 retval
= rmi_of_property_read_u32(dev
, &val
,
312 "syna,disable-report-mask", 1);
316 pdata
->disable_report_mask
= val
;
318 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,rezero-wait-ms",
323 pdata
->rezero_wait
= val
;
328 inline int rmi_2d_sensor_of_probe(struct device
*dev
,
329 struct rmi_2d_sensor_platform_data
*pdata
)
334 EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe
);