1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2011-2016 Synaptics Incorporated
4 * Copyright (c) 2011 Unixphere
7 #include <linux/kernel.h>
8 #include <linux/device.h>
10 #include <linux/input.h>
11 #include <linux/input/mt.h>
12 #include <linux/rmi.h>
13 #include "rmi_driver.h"
14 #include "rmi_2d_sensor.h"
16 #define RMI_2D_REL_POS_MIN -128
17 #define RMI_2D_REL_POS_MAX 127
19 /* maximum ABS_MT_POSITION displacement (in mm) */
22 void rmi_2d_sensor_abs_process(struct rmi_2d_sensor
*sensor
,
23 struct rmi_2d_sensor_abs_object
*obj
,
26 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
28 /* we keep the previous values if the finger is released */
29 if (obj
->type
== RMI_2D_OBJECT_NONE
)
32 if (axis_align
->flip_x
)
33 obj
->x
= sensor
->max_x
- obj
->x
;
35 if (axis_align
->flip_y
)
36 obj
->y
= sensor
->max_y
- obj
->y
;
38 if (axis_align
->swap_axes
)
42 * Here checking if X offset or y offset are specified is
43 * redundant. We just add the offsets or clip the values.
45 * Note: offsets need to be applied before clipping occurs,
46 * or we could get funny values that are outside of
47 * clipping boundaries.
49 obj
->x
+= axis_align
->offset_x
;
50 obj
->y
+= axis_align
->offset_y
;
52 obj
->x
= max(axis_align
->clip_x_low
, obj
->x
);
53 obj
->y
= max(axis_align
->clip_y_low
, obj
->y
);
55 if (axis_align
->clip_x_high
)
56 obj
->x
= min(sensor
->max_x
, obj
->x
);
58 if (axis_align
->clip_y_high
)
59 obj
->y
= min(sensor
->max_y
, obj
->y
);
61 sensor
->tracking_pos
[slot
].x
= obj
->x
;
62 sensor
->tracking_pos
[slot
].y
= obj
->y
;
64 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_process
);
66 void rmi_2d_sensor_abs_report(struct rmi_2d_sensor
*sensor
,
67 struct rmi_2d_sensor_abs_object
*obj
,
70 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
71 struct input_dev
*input
= sensor
->input
;
72 int wide
, major
, minor
;
74 if (sensor
->kernel_tracking
)
75 input_mt_slot(input
, sensor
->tracking_slots
[slot
]);
77 input_mt_slot(input
, slot
);
79 input_mt_report_slot_state(input
, obj
->mt_tool
,
80 obj
->type
!= RMI_2D_OBJECT_NONE
);
82 if (obj
->type
!= RMI_2D_OBJECT_NONE
) {
83 obj
->x
= sensor
->tracking_pos
[slot
].x
;
84 obj
->y
= sensor
->tracking_pos
[slot
].y
;
86 if (axis_align
->swap_axes
)
87 swap(obj
->wx
, obj
->wy
);
89 wide
= (obj
->wx
> obj
->wy
);
90 major
= max(obj
->wx
, obj
->wy
);
91 minor
= min(obj
->wx
, obj
->wy
);
93 if (obj
->type
== RMI_2D_OBJECT_STYLUS
) {
94 major
= max(1, major
);
95 minor
= max(1, minor
);
98 input_event(sensor
->input
, EV_ABS
, ABS_MT_POSITION_X
, obj
->x
);
99 input_event(sensor
->input
, EV_ABS
, ABS_MT_POSITION_Y
, obj
->y
);
100 input_event(sensor
->input
, EV_ABS
, ABS_MT_ORIENTATION
, wide
);
101 input_event(sensor
->input
, EV_ABS
, ABS_MT_PRESSURE
, obj
->z
);
102 input_event(sensor
->input
, EV_ABS
, ABS_MT_TOUCH_MAJOR
, major
);
103 input_event(sensor
->input
, EV_ABS
, ABS_MT_TOUCH_MINOR
, minor
);
105 rmi_dbg(RMI_DEBUG_2D_SENSOR
, &sensor
->input
->dev
,
106 "%s: obj[%d]: type: 0x%02x X: %d Y: %d Z: %d WX: %d WY: %d\n",
107 __func__
, slot
, obj
->type
, obj
->x
, obj
->y
, obj
->z
,
111 EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_report
);
113 void rmi_2d_sensor_rel_report(struct rmi_2d_sensor
*sensor
, int x
, int y
)
115 struct rmi_2d_axis_alignment
*axis_align
= &sensor
->axis_align
;
117 x
= min(RMI_2D_REL_POS_MAX
, max(RMI_2D_REL_POS_MIN
, (int)x
));
118 y
= min(RMI_2D_REL_POS_MAX
, max(RMI_2D_REL_POS_MIN
, (int)y
));
120 if (axis_align
->flip_x
)
121 x
= min(RMI_2D_REL_POS_MAX
, -x
);
123 if (axis_align
->flip_y
)
124 y
= min(RMI_2D_REL_POS_MAX
, -y
);
126 if (axis_align
->swap_axes
)
130 input_report_rel(sensor
->input
, REL_X
, x
);
131 input_report_rel(sensor
->input
, REL_Y
, y
);
134 EXPORT_SYMBOL_GPL(rmi_2d_sensor_rel_report
);
136 static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor
*sensor
)
138 struct input_dev
*input
= sensor
->input
;
144 if (sensor
->report_abs
) {
145 sensor
->min_x
= sensor
->axis_align
.clip_x_low
;
146 if (sensor
->axis_align
.clip_x_high
)
147 sensor
->max_x
= min(sensor
->max_x
,
148 sensor
->axis_align
.clip_x_high
);
150 sensor
->min_y
= sensor
->axis_align
.clip_y_low
;
151 if (sensor
->axis_align
.clip_y_high
)
152 sensor
->max_y
= min(sensor
->max_y
,
153 sensor
->axis_align
.clip_y_high
);
155 set_bit(EV_ABS
, input
->evbit
);
157 max_x
= sensor
->max_x
;
158 max_y
= sensor
->max_y
;
159 if (sensor
->axis_align
.swap_axes
)
161 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, max_x
, 0, 0);
162 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, max_y
, 0, 0);
164 if (sensor
->x_mm
&& sensor
->y_mm
) {
165 res_x
= (sensor
->max_x
- sensor
->min_x
) / sensor
->x_mm
;
166 res_y
= (sensor
->max_y
- sensor
->min_y
) / sensor
->y_mm
;
167 if (sensor
->axis_align
.swap_axes
)
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);
184 input_set_abs_params(input
, ABS_MT_TOOL_TYPE
,
185 0, MT_TOOL_MAX
, 0, 0);
187 if (sensor
->sensor_type
== rmi_sensor_touchpad
)
188 input_flags
= INPUT_MT_POINTER
;
190 input_flags
= INPUT_MT_DIRECT
;
192 if (sensor
->kernel_tracking
)
193 input_flags
|= INPUT_MT_TRACK
;
195 input_mt_init_slots(input
, sensor
->nbr_fingers
, input_flags
);
198 if (sensor
->report_rel
) {
199 set_bit(EV_REL
, input
->evbit
);
200 set_bit(REL_X
, input
->relbit
);
201 set_bit(REL_Y
, input
->relbit
);
204 if (sensor
->topbuttonpad
)
205 set_bit(INPUT_PROP_TOPBUTTONPAD
, input
->propbit
);
208 int rmi_2d_sensor_configure_input(struct rmi_function
*fn
,
209 struct rmi_2d_sensor
*sensor
)
211 struct rmi_device
*rmi_dev
= fn
->rmi_dev
;
212 struct rmi_driver_data
*drv_data
= dev_get_drvdata(&rmi_dev
->dev
);
214 if (!drv_data
->input
)
217 sensor
->input
= drv_data
->input
;
218 rmi_2d_sensor_set_input_params(sensor
);
222 EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input
);
225 int rmi_2d_sensor_of_probe(struct device
*dev
,
226 struct rmi_2d_sensor_platform_data
*pdata
)
231 pdata
->axis_align
.swap_axes
= of_property_read_bool(dev
->of_node
,
232 "touchscreen-swapped-x-y");
234 pdata
->axis_align
.flip_x
= of_property_read_bool(dev
->of_node
,
235 "touchscreen-inverted-x");
237 pdata
->axis_align
.flip_y
= of_property_read_bool(dev
->of_node
,
238 "touchscreen-inverted-y");
240 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-low", 1);
244 pdata
->axis_align
.clip_x_low
= val
;
246 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-low", 1);
250 pdata
->axis_align
.clip_y_low
= val
;
252 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-x-high", 1);
256 pdata
->axis_align
.clip_x_high
= val
;
258 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,clip-y-high", 1);
262 pdata
->axis_align
.clip_y_high
= val
;
264 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-x", 1);
268 pdata
->axis_align
.offset_x
= val
;
270 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,offset-y", 1);
274 pdata
->axis_align
.offset_y
= val
;
276 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-x-threshold",
281 pdata
->axis_align
.delta_x_threshold
= val
;
283 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,delta-y-threshold",
288 pdata
->axis_align
.delta_y_threshold
= val
;
290 retval
= rmi_of_property_read_u32(dev
, (u32
*)&pdata
->sensor_type
,
291 "syna,sensor-type", 1);
295 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-x-mm", 1);
301 retval
= rmi_of_property_read_u32(dev
, &val
, "touchscreen-y-mm", 1);
307 retval
= rmi_of_property_read_u32(dev
, &val
,
308 "syna,disable-report-mask", 1);
312 pdata
->disable_report_mask
= val
;
314 retval
= rmi_of_property_read_u32(dev
, &val
, "syna,rezero-wait-ms",
319 pdata
->rezero_wait
= val
;
324 inline int rmi_2d_sensor_of_probe(struct device
*dev
,
325 struct rmi_2d_sensor_platform_data
*pdata
)
330 EXPORT_SYMBOL_GPL(rmi_2d_sensor_of_probe
);