* [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad.
@ 2025-07-16 3:36 Marge Yang
2025-07-23 16:30 ` Dmitry Torokhov
0 siblings, 1 reply; 3+ messages in thread
From: Marge Yang @ 2025-07-16 3:36 UTC (permalink / raw)
To: dmitry.torokhov, linux-input, linux-kernel, marge.yang
Cc: david.chiu, derek.cheng, sam.tsai, vincent.huang, Marge Yang
From: Marge Yang <Marge.Yang@tw.synaptics.com>
Forcepad devices will use F21, for click simulation
due to lack of a metal button, so we add F21 support
to make forcepad support click function.
Signed-off-by: Marge Yang <Marge.Yang@tw.synaptics.com>
---
drivers/input/rmi4/Kconfig | 8 ++
drivers/input/rmi4/Makefile | 1 +
drivers/input/rmi4/rmi_bus.c | 3 +
drivers/input/rmi4/rmi_driver.h | 1 +
drivers/input/rmi4/rmi_f21.c | 162 ++++++++++++++++++++++++++++++++
5 files changed, 175 insertions(+)
create mode 100644 drivers/input/rmi4/rmi_f21.c
diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
index c0163b983ce6..086013be6a64 100644
--- a/drivers/input/rmi4/Kconfig
+++ b/drivers/input/rmi4/Kconfig
@@ -82,6 +82,14 @@ config RMI4_F12
touchpads. For sensors that support relative pointing, F12 also
provides mouse input.
+config RMI4_F21
+ bool "RMI4 Function 21 (PRESSURE)"
+ help
+ Say Y here if you want to add support for RMI4 function 21.
+
+ Function 21 provides buttons/pressure for RMI4 devices. This includes
+ support for buttons/pressure on PressurePad.
+
config RMI4_F30
bool "RMI4 Function 30 (GPIO LED)"
help
diff --git a/drivers/input/rmi4/Makefile b/drivers/input/rmi4/Makefile
index 02f14c846861..484b97eca025 100644
--- a/drivers/input/rmi4/Makefile
+++ b/drivers/input/rmi4/Makefile
@@ -8,6 +8,7 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
+rmi_core-$(CONFIG_RMI4_F21) += rmi_f21.o
rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
rmi_core-$(CONFIG_RMI4_F3A) += rmi_f3a.o
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 3aee04837205..47fe7a88c92b 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -360,6 +360,9 @@ static struct rmi_function_handler *fn_handlers[] = {
#ifdef CONFIG_RMI4_F12
&rmi_f12_handler,
#endif
+#ifdef CONFIG_RMI4_F21
+ &rmi_f21_handler,
+#endif
#ifdef CONFIG_RMI4_F30
&rmi_f30_handler,
#endif
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 3bfe9013043e..21e1c7663561 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -133,6 +133,7 @@ extern struct rmi_function_handler rmi_f01_handler;
extern struct rmi_function_handler rmi_f03_handler;
extern struct rmi_function_handler rmi_f11_handler;
extern struct rmi_function_handler rmi_f12_handler;
+extern struct rmi_function_handler rmi_f21_handler;
extern struct rmi_function_handler rmi_f30_handler;
extern struct rmi_function_handler rmi_f34_handler;
extern struct rmi_function_handler rmi_f3a_handler;
diff --git a/drivers/input/rmi4/rmi_f21.c b/drivers/input/rmi4/rmi_f21.c
new file mode 100644
index 000000000000..510278ee7704
--- /dev/null
+++ b/drivers/input/rmi4/rmi_f21.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2012-2025 Synaptics Incorporated
+ */
+
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+
+#define RMI_f21_FORCE_CLICK BIT(0)
+#define RMI_f21_DATA_REGS_MAX_SIZE 255
+#define RMI_f21_FORCEPAD_BUTTON_COUNT 1
+
+struct f21_data {
+ /* Query Data */
+ u8 data_regs[RMI_f21_DATA_REGS_MAX_SIZE];
+ struct input_dev *input;
+ u16 key_code;
+
+ unsigned int attn_data_size;
+ unsigned int attn_data_index_for_button;
+ unsigned int sensor_count;
+ unsigned int max_number_Of_finger;
+ unsigned int data_reg_size;
+ unsigned int data_reg_index_for_button;
+ unsigned int query15_offset;
+};
+
+static irqreturn_t rmi_f21_attention(int irq, void *ctx)
+{
+ struct rmi_function *fn = ctx;
+ struct f21_data *f21 = dev_get_drvdata(&fn->dev);
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
+ int error;
+ bool pressed = false;
+
+ if (drvdata->attn_data.data) {
+ if (drvdata->attn_data.size < f21->attn_data_size) {
+ dev_warn(&fn->dev, "f21 interrupted, but data is missing\n");
+ return IRQ_HANDLED;
+ }
+ pressed = (((u8 *)drvdata->attn_data.data)[f21->attn_data_index_for_button] &
+ RMI_f21_FORCE_CLICK);
+ drvdata->attn_data.data += f21->attn_data_size;
+ drvdata->attn_data.size -= f21->attn_data_size;
+ } else {
+ error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
+ f21->data_regs, f21->data_reg_size);
+ if (error) {
+ dev_err(&fn->dev, "%s: Failed to read f21 data registers: %d\n",
+ __func__, error);
+ return IRQ_RETVAL(error);
+ }
+ pressed = (f21->data_regs[f21->data_reg_index_for_button] &
+ RMI_f21_FORCE_CLICK);
+ }
+
+ input_report_key(f21->input, f21->key_code, pressed);
+
+ return IRQ_HANDLED;
+}
+
+static int rmi_f21_config(struct rmi_function *fn)
+{
+ struct rmi_driver *drv = fn->rmi_dev->driver;
+
+ drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
+
+ return 0;
+}
+
+static int rmi_f21_initialize(struct rmi_function *fn, struct f21_data *f21)
+{
+ struct input_dev *input = f21->input;
+
+ f21->key_code = BTN_LEFT;
+ input_set_capability(input, EV_KEY, f21->key_code);
+ input->keycode = &f21->key_code;
+ input->keycodesize = sizeof(f21->key_code);
+ input->keycodemax = RMI_f21_FORCEPAD_BUTTON_COUNT;
+
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
+ return 0;
+}
+
+static int rmi_f21_probe(struct rmi_function *fn)
+{
+ struct rmi_device *rmi_dev = fn->rmi_dev;
+ struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
+ struct f21_data *f21;
+ int error;
+
+ if (!drv_data->input) {
+ dev_info(&fn->dev, "f21: no input device found, ignoring\n");
+ return -ENXIO;
+ }
+
+ f21 = devm_kzalloc(&fn->dev, sizeof(*f21), GFP_KERNEL);
+ if (!f21)
+ return -ENOMEM;
+
+ f21->input = drv_data->input;
+
+ error = rmi_f21_initialize(fn, f21);
+ if (error)
+ return error;
+
+ dev_set_drvdata(&fn->dev, f21);
+
+ f21->sensor_count = fn->fd.query_base_addr & (BIT(0) | BIT(1) | BIT(2) | BIT(3));
+
+ if (fn->fd.query_base_addr & BIT(5)) {
+ if (fn->fd.query_base_addr & BIT(6))
+ f21->query15_offset = 2;
+ else
+ f21->query15_offset = 1;
+
+ rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + f21->query15_offset,
+ f21->data_regs, 1);
+ f21->max_number_Of_finger = f21->data_regs[0] & 0x0F;
+ } else {
+ dev_info(&fn->dev, "f21_query15 doesn't support.\n");
+ f21->query15_offset = 0;
+ f21->max_number_Of_finger = 5;
+ }
+
+ if (fn->fd.query_base_addr & BIT(6)) {
+ dev_info(&fn->dev, "Support new F21 feature.\n");
+ /*Each finger uses one byte, and the button state uses one byte.*/
+ f21->attn_data_size = f21->max_number_Of_finger + 1;
+ f21->attn_data_index_for_button = f21->attn_data_size - 1;
+ /*
+ * Each sensor uses two bytes, the button state uses one byte,
+ * and each finger uses two bytes.
+ */
+ f21->data_reg_size = f21->sensor_count * 2 + 1 +
+ f21->max_number_Of_finger * 2;
+ f21->data_reg_index_for_button = f21->sensor_count * 2;
+ } else {
+ dev_info(&fn->dev, "Support old F21 feature.\n");
+ /*Each finger uses two bytes, and the button state uses one byte.*/
+ f21->attn_data_size = f21->sensor_count * 2 + 1;
+ f21->attn_data_index_for_button = f21->attn_data_size - 1;
+ /*Each finger uses two bytes, and the button state uses one byte.*/
+ f21->data_reg_size = f21->sensor_count * 2 + 1;
+ f21->data_reg_index_for_button = f21->data_reg_size - 1;
+ }
+ return 0;
+}
+
+struct rmi_function_handler rmi_f21_handler = {
+ .driver = {
+ .name = "rmi4_f21",
+ },
+ .func = 0x21,
+ .probe = rmi_f21_probe,
+ .config = rmi_f21_config,
+ .attention = rmi_f21_attention,
+};
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad.
2025-07-16 3:36 [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad Marge Yang
@ 2025-07-23 16:30 ` Dmitry Torokhov
2025-07-24 3:38 ` Marge Yang
0 siblings, 1 reply; 3+ messages in thread
From: Dmitry Torokhov @ 2025-07-23 16:30 UTC (permalink / raw)
To: Marge Yang
Cc: linux-input, linux-kernel, david.chiu, derek.cheng, sam.tsai,
vincent.huang
Hi Marge,
On Wed, Jul 16, 2025 at 03:36:48AM +0000, Marge Yang wrote:
> + f21->sensor_count = fn->fd.query_base_addr & (BIT(0) | BIT(1) | BIT(2) | BIT(3));
We could either use GENMASK or just 0x0f. BIT() is for individual bits.
> +
> + if (fn->fd.query_base_addr & BIT(5)) {
> + if (fn->fd.query_base_addr & BIT(6))
> + f21->query15_offset = 2;
> + else
> + f21->query15_offset = 1;
> +
> + rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + f21->query15_offset,
> + f21->data_regs, 1);
> + f21->max_number_Of_finger = f21->data_regs[0] & 0x0F;
> + } else {
> + dev_info(&fn->dev, "f21_query15 doesn't support.\n");
> + f21->query15_offset = 0;
> + f21->max_number_Of_finger = 5;
> + }
> +
> + if (fn->fd.query_base_addr & BIT(6)) {
Just double-checking - should it be BIT(5) give that reading of number of fingers
is gated by BIT(5) in the block above.
> + dev_info(&fn->dev, "Support new F21 feature.\n");
> + /*Each finger uses one byte, and the button state uses one byte.*/
> + f21->attn_data_size = f21->max_number_Of_finger + 1;
> + f21->attn_data_index_for_button = f21->attn_data_size - 1;
> + /*
> + * Each sensor uses two bytes, the button state uses one byte,
> + * and each finger uses two bytes.
> + */
> + f21->data_reg_size = f21->sensor_count * 2 + 1 +
> + f21->max_number_Of_finger * 2;
> + f21->data_reg_index_for_button = f21->sensor_count * 2;
> + } else {
> + dev_info(&fn->dev, "Support old F21 feature.\n");
> + /*Each finger uses two bytes, and the button state uses one byte.*/
> + f21->attn_data_size = f21->sensor_count * 2 + 1;
> + f21->attn_data_index_for_button = f21->attn_data_size - 1;
> + /*Each finger uses two bytes, and the button state uses one byte.*/
> + f21->data_reg_size = f21->sensor_count * 2 + 1;
> + f21->data_reg_index_for_button = f21->data_reg_size - 1;
The block is duplicated?
No need to resubmit the patch, please just provide the answer to the
above questions.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad.
2025-07-23 16:30 ` Dmitry Torokhov
@ 2025-07-24 3:38 ` Marge Yang
0 siblings, 0 replies; 3+ messages in thread
From: Marge Yang @ 2025-07-24 3:38 UTC (permalink / raw)
To: Dmitry Torokhov, Marge Yang
Cc: linux-input, linux-kernel, David Chiu, Derek Cheng, Sam Tsai,
Vincent Huang
Hi Dmitry,
Update the status.
Thanks
Marge Yang
-----Original Message-----
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Sent: Thursday, July 24, 2025 12:30 AM
To: Marge Yang <Marge.Yang@tw.synaptics.com>
Cc: linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; David Chiu <David.Chiu@tw.synaptics.com>; Derek Cheng <derek.cheng@tw.synaptics.com>; Sam Tsai <Sam.Tsai@synaptics.com>; Vincent Huang <Vincent.huang@tw.synaptics.com>
Subject: Re: [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad.
CAUTION: Email originated externally, do not click links or open attachments unless you recognize the sender and know the content is safe.
Hi Marge,
On Wed, Jul 16, 2025 at 03:36:48AM +0000, Marge Yang wrote:
> + f21->sensor_count = fn->fd.query_base_addr & (BIT(0) | BIT(1) |
> + BIT(2) | BIT(3));
We could either use GENMASK or just 0x0f. BIT() is for individual bits.
[Marge 0724]
Thank you for the reminder. We will use this design going forward.
> +
> + if (fn->fd.query_base_addr & BIT(5)) {
> + if (fn->fd.query_base_addr & BIT(6))
> + f21->query15_offset = 2;
> + else
> + f21->query15_offset = 1;
> +
> + rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + f21->query15_offset,
> + f21->data_regs, 1);
> + f21->max_number_Of_finger = f21->data_regs[0] & 0x0F;
> + } else {
> + dev_info(&fn->dev, "f21_query15 doesn't support.\n");
> + f21->query15_offset = 0;
> + f21->max_number_Of_finger = 5;
> + }
> +
> + if (fn->fd.query_base_addr & BIT(6)) {
Just double-checking - should it be BIT(5) give that reading of number of fingers is gated by BIT(5) in the block above.
[Marge 0724]
Using BIT (6) is more appropriate.
BIT6: Indicates whether the force-calibration version is supported.
The old firmware does not support this feature.
The new firmware can use this BIT to determine whether it's the new or old version.
BIT5: Indicates whether reading the maximum number of finger-pressure levels is supported.
> + dev_info(&fn->dev, "Support new F21 feature.\n");
> + /*Each finger uses one byte, and the button state uses one byte.*/
> + f21->attn_data_size = f21->max_number_Of_finger + 1;
> + f21->attn_data_index_for_button = f21->attn_data_size - 1;
> + /*
> + * Each sensor uses two bytes, the button state uses one byte,
> + * and each finger uses two bytes.
> + */
> + f21->data_reg_size = f21->sensor_count * 2 + 1 +
> + f21->max_number_Of_finger * 2;
> + f21->data_reg_index_for_button = f21->sensor_count * 2;
> + } else {
> + dev_info(&fn->dev, "Support old F21 feature.\n");
> + /*Each finger uses two bytes, and the button state uses one byte.*/
> + f21->attn_data_size = f21->sensor_count * 2 + 1;
> + f21->attn_data_index_for_button = f21->attn_data_size - 1;
> + /*Each finger uses two bytes, and the button state uses one byte.*/
> + f21->data_reg_size = f21->sensor_count * 2 + 1;
> + f21->data_reg_index_for_button = f21->data_reg_size - 1;
The block is duplicated?
[Marge 0724]
Comparing the new and old firmware versions:
Based on BIT6, we can distinguish between the new and old firmware versions.
The definition of the attention data size differs.
The size of the F21 data block and the definition of its button index also differ.
Therefore, by definition, this block is not duplicated.
No need to resubmit the patch, please just provide the answer to the above questions.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-24 3:38 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-07-16 3:36 [PATCH V2] Input: synaptics-rmi4- Add a new feature for Forcepad Marge Yang
2025-07-23 16:30 ` Dmitry Torokhov
2025-07-24 3:38 ` Marge Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®