Skip to content

Commit 4619b6b

Browse files
André Apitzschdtor
authored andcommitted
Input: synaptics-rmi4 - add support for F1A
RMI4 F1A implements capacitive keys. Add support for touch keys found in some Synaptics touch controller configurations. Signed-off-by: André Apitzsch <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 0da8959 commit 4619b6b

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

drivers/input/rmi4/Kconfig

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

85+
config RMI4_F1A
86+
bool "RMI4 Function 1A (0D pointing)"
87+
help
88+
Say Y here if you want to add support for RMI4 function 1A.
89+
90+
Function 1A provides capacitive keys support for RMI4 devices.
91+
8592
config RMI4_F21
8693
bool "RMI4 Function 21 (PRESSURE)"
8794
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_F1A) += rmi_f1a.o
1112
rmi_core-$(CONFIG_RMI4_F21) += rmi_f21.o
1213
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
1314
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.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_F1A
364+
&rmi_f1a_handler,
365+
#endif
363366
#ifdef CONFIG_RMI4_F21
364367
&rmi_f21_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_f1a_handler;
136137
extern struct rmi_function_handler rmi_f21_handler;
137138
extern struct rmi_function_handler rmi_f30_handler;
138139
extern struct rmi_function_handler rmi_f34_handler;

drivers/input/rmi4/rmi_f1a.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2025 André Apitzsch <[email protected]>
4+
*/
5+
6+
#include <linux/input.h>
7+
#include <linux/property.h>
8+
#include "rmi_driver.h"
9+
10+
struct f1a_data {
11+
struct input_dev *input;
12+
13+
u32 *keymap;
14+
unsigned int num_keys;
15+
};
16+
17+
static int rmi_f1a_parse_device_properties(struct rmi_function *fn, struct f1a_data *f1a)
18+
{
19+
static const char buttons_property[] = "linux,keycodes";
20+
struct device *dev = &fn->dev;
21+
u32 *buttonmap;
22+
int n_keys;
23+
int error;
24+
25+
if (!device_property_present(dev, buttons_property))
26+
return 0;
27+
28+
n_keys = device_property_count_u32(dev, buttons_property);
29+
if (n_keys <= 0) {
30+
error = n_keys < 0 ? n_keys : -EINVAL;
31+
dev_err(dev, "Invalid/malformed '%s' property: %d\n",
32+
buttons_property, error);
33+
return error;
34+
}
35+
36+
buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
37+
GFP_KERNEL);
38+
if (!buttonmap)
39+
return -ENOMEM;
40+
41+
error = device_property_read_u32_array(dev, buttons_property,
42+
buttonmap, n_keys);
43+
if (error) {
44+
dev_err(dev, "Failed to parse '%s' property: %d\n",
45+
buttons_property, error);
46+
return error;
47+
}
48+
49+
f1a->keymap = buttonmap;
50+
f1a->num_keys = n_keys;
51+
52+
return 0;
53+
}
54+
55+
static irqreturn_t rmi_f1a_attention(int irq, void *ctx)
56+
{
57+
struct rmi_function *fn = ctx;
58+
struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
59+
char button_bitmask;
60+
int key;
61+
int error;
62+
63+
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
64+
&button_bitmask, sizeof(button_bitmask));
65+
if (error) {
66+
dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
67+
error);
68+
return IRQ_RETVAL(error);
69+
}
70+
71+
for (key = 0; key < f1a->num_keys; key++)
72+
input_report_key(f1a->input, f1a->keymap[key],
73+
button_bitmask & BIT(key));
74+
75+
return IRQ_HANDLED;
76+
}
77+
78+
static int rmi_f1a_config(struct rmi_function *fn)
79+
{
80+
struct f1a_data *f1a = dev_get_drvdata(&fn->dev);
81+
struct rmi_driver *drv = fn->rmi_dev->driver;
82+
83+
if (f1a->num_keys)
84+
drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
85+
86+
return 0;
87+
}
88+
89+
static int rmi_f1a_initialize(struct rmi_function *fn, struct f1a_data *f1a)
90+
{
91+
int error;
92+
int i;
93+
94+
error = rmi_f1a_parse_device_properties(fn, f1a);
95+
if (error)
96+
return error;
97+
98+
for (i = 0; i < f1a->num_keys; i++)
99+
input_set_capability(f1a->input, EV_KEY, f1a->keymap[i]);
100+
101+
f1a->input->keycode = f1a->keymap;
102+
f1a->input->keycodemax = f1a->num_keys;
103+
f1a->input->keycodesize = sizeof(f1a->keymap[0]);
104+
105+
return 0;
106+
}
107+
108+
static int rmi_f1a_probe(struct rmi_function *fn)
109+
{
110+
struct rmi_device *rmi_dev = fn->rmi_dev;
111+
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
112+
struct f1a_data *f1a;
113+
int error;
114+
115+
if (!drv_data->input) {
116+
dev_info(&fn->dev, "F1A: no input device found, ignoring\n");
117+
return -ENXIO;
118+
}
119+
120+
f1a = devm_kzalloc(&fn->dev, sizeof(*f1a), GFP_KERNEL);
121+
if (!f1a)
122+
return -ENOMEM;
123+
124+
f1a->input = drv_data->input;
125+
126+
error = rmi_f1a_initialize(fn, f1a);
127+
if (error)
128+
return error;
129+
130+
dev_set_drvdata(&fn->dev, f1a);
131+
132+
return 0;
133+
}
134+
135+
struct rmi_function_handler rmi_f1a_handler = {
136+
.driver = {
137+
.name = "rmi4_f1a",
138+
},
139+
.func = 0x1a,
140+
.probe = rmi_f1a_probe,
141+
.config = rmi_f1a_config,
142+
.attention = rmi_f1a_attention,
143+
};

0 commit comments

Comments
 (0)