Skip to content

Commit ff8f837

Browse files
aduggan-synadtor
authored andcommitted
Input: synaptics-rmi4 - add support for 2D sensors and F11
RMI4 currently defines two functions for reporting data for 2D sensors (F11 and F12). This patch adds the common functionality which is shared by devices with 2D reporting along with implementing functionality for F11. Signed-off-by: Andrew Duggan <[email protected]> Signed-off-by: Christopher Heiny <[email protected]> Tested-by: Benjamin Tissoires <[email protected]> Tested-by: Linus Walleij <[email protected]> Tested-by: Bjorn Andersson <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent d8a8b3e commit ff8f837

File tree

8 files changed

+1724
-1
lines changed

8 files changed

+1724
-1
lines changed

drivers/input/rmi4/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,18 @@ config RMI4_I2C
1717
bus.
1818

1919
If unsure, say Y.
20+
21+
config RMI4_2D_SENSOR
22+
bool
23+
depends on RMI4_CORE
24+
25+
config RMI4_F11
26+
bool "RMI4 Function 11 (2D pointing)"
27+
select RMI4_2D_SENSOR
28+
depends on RMI4_CORE
29+
help
30+
Say Y here if you want to add support for RMI4 function 11.
31+
32+
Function 11 provides 2D multifinger pointing for touchscreens and
33+
touchpads. For sensors that support relative pointing, F11 also
34+
provides mouse input.

drivers/input/rmi4/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
obj-$(CONFIG_RMI4_CORE) += rmi_core.o
22
rmi_core-y := rmi_bus.o rmi_driver.o rmi_f01.o
33

4+
rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
5+
6+
# Function drivers
7+
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
8+
49
# Transports
510
obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o

drivers/input/rmi4/rmi_2d_sensor.c

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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+
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);
154+
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);
159+
160+
set_bit(EV_ABS, input->evbit);
161+
input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensor->max_x,
162+
0, 0);
163+
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensor->max_y,
164+
0, 0);
165+
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;
169+
170+
input_abs_set_res(input, ABS_X, res_x);
171+
input_abs_set_res(input, ABS_Y, res_y);
172+
173+
input_abs_set_res(input, ABS_MT_POSITION_X, res_x);
174+
input_abs_set_res(input, ABS_MT_POSITION_Y, res_y);
175+
176+
if (!sensor->dmax)
177+
sensor->dmax = DMAX * res_x;
178+
}
179+
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+
185+
if (sensor->sensor_type == rmi_sensor_touchpad)
186+
input_flags = INPUT_MT_POINTER;
187+
else
188+
input_flags = INPUT_MT_DIRECT;
189+
190+
if (sensor->kernel_tracking)
191+
input_flags |= INPUT_MT_TRACK;
192+
193+
input_mt_init_slots(input, sensor->nbr_fingers, input_flags);
194+
}
195+
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);
200+
}
201+
202+
if (sensor->topbuttonpad)
203+
set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit);
204+
}
205+
EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params);
206+
207+
int rmi_2d_sensor_configure_input(struct rmi_function *fn,
208+
struct rmi_2d_sensor *sensor)
209+
{
210+
struct rmi_device *rmi_dev = fn->rmi_dev;
211+
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
212+
213+
if (!drv_data->input)
214+
return -ENODEV;
215+
216+
sensor->input = drv_data->input;
217+
rmi_2d_sensor_set_input_params(sensor);
218+
219+
return 0;
220+
}
221+
EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input);

drivers/input/rmi4/rmi_2d_sensor.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
#ifndef _RMI_2D_SENSOR_H
11+
#define _RMI_2D_SENSOR_H
12+
13+
enum rmi_2d_sensor_object_type {
14+
RMI_2D_OBJECT_NONE,
15+
RMI_2D_OBJECT_FINGER,
16+
RMI_2D_OBJECT_STYLUS,
17+
RMI_2D_OBJECT_PALM,
18+
RMI_2D_OBJECT_UNCLASSIFIED,
19+
};
20+
21+
struct rmi_2d_sensor_abs_object {
22+
enum rmi_2d_sensor_object_type type;
23+
int mt_tool;
24+
u16 x;
25+
u16 y;
26+
u8 z;
27+
u8 wx;
28+
u8 wy;
29+
};
30+
31+
/**
32+
* @axis_align - controls parameters that are useful in system prototyping
33+
* and bring up.
34+
* @max_x - The maximum X coordinate that will be reported by this sensor.
35+
* @max_y - The maximum Y coordinate that will be reported by this sensor.
36+
* @nbr_fingers - How many fingers can this sensor report?
37+
* @data_pkt - buffer for data reported by this sensor.
38+
* @pkt_size - number of bytes in that buffer.
39+
* @attn_size - Size of the HID attention report (only contains abs data).
40+
* position when two fingers are on the device. When this is true, we
41+
* assume we have one of those sensors and report events appropriately.
42+
* @sensor_type - indicates whether we're touchscreen or touchpad.
43+
* @input - input device for absolute pointing stream
44+
* @input_phys - buffer for the absolute phys name for this sensor.
45+
*/
46+
struct rmi_2d_sensor {
47+
struct rmi_2d_axis_alignment axis_align;
48+
struct input_mt_pos *tracking_pos;
49+
int *tracking_slots;
50+
bool kernel_tracking;
51+
struct rmi_2d_sensor_abs_object *objs;
52+
int dmax;
53+
u16 min_x;
54+
u16 max_x;
55+
u16 min_y;
56+
u16 max_y;
57+
u8 nbr_fingers;
58+
u8 *data_pkt;
59+
int pkt_size;
60+
int attn_size;
61+
bool topbuttonpad;
62+
enum rmi_sensor_type sensor_type;
63+
struct input_dev *input;
64+
struct rmi_function *fn;
65+
char input_phys[32];
66+
u8 report_abs;
67+
u8 report_rel;
68+
u8 x_mm;
69+
u8 y_mm;
70+
};
71+
72+
void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor,
73+
struct rmi_2d_sensor_abs_object *obj,
74+
int slot);
75+
76+
void rmi_2d_sensor_abs_report(struct rmi_2d_sensor *sensor,
77+
struct rmi_2d_sensor_abs_object *obj,
78+
int slot);
79+
80+
void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y);
81+
82+
int rmi_2d_sensor_configure_input(struct rmi_function *fn,
83+
struct rmi_2d_sensor *sensor);
84+
#endif /* _RMI_2D_SENSOR_H */

drivers/input/rmi4/rmi_bus.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ struct bus_type rmi_bus_type = {
306306

307307
static struct rmi_function_handler *fn_handlers[] = {
308308
&rmi_f01_handler,
309+
#ifdef CONFIG_RMI4_F11
310+
&rmi_f11_handler,
311+
#endif
309312
};
310313

311314
static void __rmi_unregister_function_handlers(int start_idx)

drivers/input/rmi4/rmi_driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,5 +99,5 @@ void rmi_unregister_physical_driver(void);
9999
char *rmi_f01_get_product_ID(struct rmi_function *fn);
100100

101101
extern struct rmi_function_handler rmi_f01_handler;
102-
102+
extern struct rmi_function_handler rmi_f11_handler;
103103
#endif

0 commit comments

Comments
 (0)