Skip to content

Commit a9c95d1

Browse files
myangsynapticsdtor
authored andcommitted
Input: synaptics-rmi4 - add support for Forcepads (F21)
Forcepad devices do not have physical buttons underneath the surface and use F21 to report "clicks" based on touch pressure. Signed-off-by: Marge Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent bc25e6b commit a9c95d1

File tree

5 files changed

+192
-0
lines changed

5 files changed

+192
-0
lines changed

drivers/input/rmi4/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ config RMI4_F12
8282
touchpads. For sensors that support relative pointing, F12 also
8383
provides mouse input.
8484

85+
config RMI4_F21
86+
bool "RMI4 Function 21 (PRESSURE)"
87+
help
88+
Say Y here if you want to add support for RMI4 function 21.
89+
90+
Function 21 provides buttons/pressure handling for RMI4 devices.
91+
This includes support for buttons/pressure on PressurePad.
92+
8593
config RMI4_F30
8694
bool "RMI4 Function 30 (GPIO LED)"
8795
help

drivers/input/rmi4/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
88
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
99
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
1010
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
11+
rmi_core-$(CONFIG_RMI4_F21) += rmi_f21.o
1112
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
1213
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
1314
rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o

drivers/input/rmi4/rmi_bus.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ static struct rmi_function_handler *fn_handlers[] = {
360360
#ifdef CONFIG_RMI4_F12
361361
&rmi_f12_handler,
362362
#endif
363+
#ifdef CONFIG_RMI4_F21
364+
&rmi_f21_handler,
365+
#endif
363366
#ifdef CONFIG_RMI4_F30
364367
&rmi_f30_handler,
365368
#endif

drivers/input/rmi4/rmi_driver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ extern struct rmi_function_handler rmi_f01_handler;
133133
extern struct rmi_function_handler rmi_f03_handler;
134134
extern struct rmi_function_handler rmi_f11_handler;
135135
extern struct rmi_function_handler rmi_f12_handler;
136+
extern struct rmi_function_handler rmi_f21_handler;
136137
extern struct rmi_function_handler rmi_f30_handler;
137138
extern struct rmi_function_handler rmi_f34_handler;
138139
extern struct rmi_function_handler rmi_f3a_handler;

drivers/input/rmi4/rmi_f21.c

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2012-2025 Synaptics Incorporated
4+
*/
5+
6+
#include <linux/bits.h>
7+
#include <linux/dev_printk.h>
8+
#include <linux/kernel.h>
9+
#include <linux/rmi.h>
10+
#include <linux/input.h>
11+
#include <linux/slab.h>
12+
#include "rmi_driver.h"
13+
14+
#define RMI_F21_SENSOR_COUNT_MASK GENMASK(3, 0)
15+
#define RMI_F21_FINGER_COUNT_PRESENT BIT(5)
16+
#define RMI_F21_NEW_REPORT_FORMAT BIT(6)
17+
18+
#define RMI_F21_FINGER_COUNT_MASK GENMASK(3, 0)
19+
20+
#define RMI_F21_MAX_SENSORS 16
21+
#define RMI_F21_MAX_FINGERS 16
22+
#define RMI_F21_DATA_REGS_MAX_SIZE (RMI_F21_MAX_SENSORS * 2 + \
23+
RMI_F21_MAX_FINGERS * 2 + 1)
24+
25+
#define RMI_F21_FORCE_CLICK_BIT BIT(0)
26+
27+
#define RMI_F21_FORCEPAD_BUTTON_COUNT 1
28+
29+
struct f21_data {
30+
struct input_dev *input;
31+
u16 key_code;
32+
33+
unsigned int attn_data_size;
34+
unsigned int attn_data_button_offset;
35+
36+
unsigned int data_reg_size;
37+
unsigned int data_reg_button_offset;
38+
u8 data_regs[RMI_F21_DATA_REGS_MAX_SIZE];
39+
};
40+
41+
static irqreturn_t rmi_f21_attention(int irq, void *ctx)
42+
{
43+
struct rmi_function *fn = ctx;
44+
struct f21_data *f21 = dev_get_drvdata(&fn->dev);
45+
struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
46+
u8 *pdata;
47+
int error;
48+
bool pressed;
49+
50+
if (drvdata->attn_data.data) {
51+
if (drvdata->attn_data.size < f21->attn_data_size) {
52+
dev_warn(&fn->dev, "f21 interrupt, but data is missing\n");
53+
return IRQ_HANDLED;
54+
}
55+
56+
pdata = drvdata->attn_data.data + f21->attn_data_button_offset;
57+
58+
drvdata->attn_data.data += f21->attn_data_size;
59+
drvdata->attn_data.size -= f21->attn_data_size;
60+
} else {
61+
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
62+
f21->data_regs, f21->data_reg_size);
63+
if (error) {
64+
dev_err(&fn->dev, "failed to read f21 data registers: %d\n",
65+
error);
66+
return IRQ_RETVAL(error);
67+
}
68+
69+
pdata = f21->data_regs + f21->data_reg_button_offset;
70+
}
71+
72+
pressed = *pdata & RMI_F21_FORCE_CLICK_BIT;
73+
input_report_key(f21->input, f21->key_code, pressed);
74+
75+
return IRQ_HANDLED;
76+
}
77+
78+
static int rmi_f21_config(struct rmi_function *fn)
79+
{
80+
struct rmi_driver *drv = fn->rmi_dev->driver;
81+
82+
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
83+
84+
return 0;
85+
}
86+
87+
static int rmi_f21_initialize(struct rmi_function *fn, struct f21_data *f21)
88+
{
89+
struct input_dev *input = f21->input;
90+
91+
f21->key_code = BTN_LEFT;
92+
93+
input->keycode = &f21->key_code;
94+
input->keycodesize = sizeof(f21->key_code);
95+
input->keycodemax = RMI_F21_FORCEPAD_BUTTON_COUNT;
96+
97+
input_set_capability(input, EV_KEY, f21->key_code);
98+
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
99+
100+
return 0;
101+
}
102+
103+
static int rmi_f21_probe(struct rmi_function *fn)
104+
{
105+
struct rmi_device *rmi_dev = fn->rmi_dev;
106+
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
107+
struct f21_data *f21;
108+
unsigned int sensor_count;
109+
unsigned int max_fingers;
110+
unsigned int query15_offset;
111+
u8 query15_data;
112+
int error;
113+
114+
if (!drv_data->input) {
115+
dev_info(&fn->dev, "f21: no input device found, ignoring\n");
116+
return -ENXIO;
117+
}
118+
119+
f21 = devm_kzalloc(&fn->dev, sizeof(*f21), GFP_KERNEL);
120+
if (!f21)
121+
return -ENOMEM;
122+
123+
f21->input = drv_data->input;
124+
125+
error = rmi_f21_initialize(fn, f21);
126+
if (error)
127+
return error;
128+
129+
dev_set_drvdata(&fn->dev, f21);
130+
131+
sensor_count = fn->fd.query_base_addr & RMI_F21_SENSOR_COUNT_MASK;
132+
if (fn->fd.query_base_addr & RMI_F21_FINGER_COUNT_PRESENT) {
133+
query15_offset = fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT ? 2 : 1;
134+
error = rmi_read_block(fn->rmi_dev,
135+
fn->fd.query_base_addr + query15_offset,
136+
&query15_data, sizeof(query15_data));
137+
if (error)
138+
return dev_err_probe(&fn->dev, error,
139+
"failed to read 'query15' data");
140+
141+
max_fingers = query15_data & RMI_F21_FINGER_COUNT_MASK;
142+
} else {
143+
max_fingers = 5;
144+
}
145+
146+
if (fn->fd.query_base_addr & RMI_F21_NEW_REPORT_FORMAT) {
147+
/* Each finger uses one byte, and the button state uses one byte.*/
148+
f21->attn_data_size = max_fingers + 1;
149+
f21->attn_data_button_offset = f21->attn_data_size - 1;
150+
/*
151+
* Each sensor uses two bytes, the button state uses one byte,
152+
* and each finger uses two bytes.
153+
*/
154+
f21->data_reg_size = sensor_count * 2 + 1 + max_fingers * 2;
155+
f21->data_reg_button_offset = sensor_count * 2;
156+
} else {
157+
/*
158+
* Regardless of the transport each finger uses two bytes,
159+
* and the button state uses one byte.
160+
*/
161+
f21->attn_data_size = sensor_count * 2 + 1;
162+
f21->attn_data_button_offset = sensor_count * 2;
163+
164+
f21->data_reg_size = f21->attn_data_size;
165+
f21->data_reg_button_offset = f21->attn_data_button_offset;
166+
}
167+
168+
return 0;
169+
}
170+
171+
struct rmi_function_handler rmi_f21_handler = {
172+
.driver = {
173+
.name = "rmi4_f21",
174+
},
175+
.func = 0x21,
176+
.probe = rmi_f21_probe,
177+
.config = rmi_f21_config,
178+
.attention = rmi_f21_attention,
179+
};

0 commit comments

Comments
 (0)