From: Marge Yang <marge.yang@xxxxxxxxxxxxx> RMI4 F21 supports the forcepad click feature. Signed-off-by: Marge Yang <marge.yang@xxxxxxxxxxxxx> --- drivers/input/rmi4/Kconfig | 8 +++ drivers/input/rmi4/Makefile | 1 + drivers/input/rmi4/rmi_bus.c | 3 ++ drivers/input/rmi4/rmi_driver.h | 5 +- drivers/input/rmi4/rmi_f21.c | 110 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 drivers/input/rmi4/rmi_f21.c diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig index c0163b9..37e2ba4 100644 --- a/drivers/input/rmi4/Kconfig +++ b/drivers/input/rmi4/Kconfig @@ -108,6 +108,14 @@ config RMI4_F3A Function 3A provides GPIO support for RMI4 devices. This includes support for buttons on TouchPads and ClickPads. +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_F54 bool "RMI4 Function 54 (Analog diagnostics)" depends on VIDEO_DEV=y || (RMI4_CORE=m && VIDEO_DEV=m) diff --git a/drivers/input/rmi4/Makefile b/drivers/input/rmi4/Makefile index 02f14c8..ec4f085 100644 --- a/drivers/input/rmi4/Makefile +++ b/drivers/input/rmi4/Makefile @@ -11,6 +11,7 @@ rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.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 +rmi_core-$(CONFIG_RMI4_F21) += rmi_f21.o rmi_core-$(CONFIG_RMI4_F54) += rmi_f54.o rmi_core-$(CONFIG_RMI4_F55) += rmi_f55.o diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c index 50a0134..d42df5f 100644 --- a/drivers/input/rmi4/rmi_bus.c +++ b/drivers/input/rmi4/rmi_bus.c @@ -369,6 +369,9 @@ static struct rmi_function_handler *fn_handlers[] = { #ifdef CONFIG_RMI4_F3A &rmi_f3a_handler, #endif +#ifdef CONFIG_RMI4_F21 + &rmi_f21_handler, +#endif #ifdef CONFIG_RMI4_F54 &rmi_f54_handler, #endif diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h index 1c6c608..57f2583 100644 --- a/drivers/input/rmi4/rmi_driver.h +++ b/drivers/input/rmi4/rmi_driver.h @@ -114,7 +114,9 @@ static inline int rmi_f03_overwrite_button(struct rmi_function *fn, } static inline void rmi_f03_commit_buttons(struct rmi_function *fn) {} #endif - +#ifdef CONFIG_RMI4_F21 +int rmi_f21_report_pressure(struct rmi_function *fn, int i); +#endif #ifdef CONFIG_RMI4_F34 int rmi_f34_create_sysfs(struct rmi_device *rmi_dev); void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev); @@ -136,6 +138,7 @@ extern struct rmi_function_handler rmi_f12_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; +extern struct rmi_function_handler rmi_f21_handler; extern struct rmi_function_handler rmi_f54_handler; extern struct rmi_function_handler rmi_f55_handler; #endif diff --git a/drivers/input/rmi4/rmi_f21.c b/drivers/input/rmi4/rmi_f21.c new file mode 100644 index 0000000..5657bf4 --- /dev/null +++ b/drivers/input/rmi4/rmi_f21.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2012-2020 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_OFFSET 8 +#define RMI_f21_FORCE_CLICK 0x01 +#define RMI_f21_DATA_REGS_MAX_SIZE 1 +#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; +}; + +static irqreturn_t rmi_f21_attention(int irq, void *ctx) +{ + struct rmi_function *fn = ctx; + struct f21_data *f21 = dev_get_drvdata(&fn->dev); + int error; + + error = rmi_read_block(fn->rmi_dev, + fn->fd.data_base_addr+RMI_F21_FORCE_CLICK_OFFSET, + f21->data_regs, 1); + if (error) { + dev_err(&fn->dev, + "%s: Failed to read f21 data registers: %d\n", + __func__, error); + return IRQ_RETVAL(error); + } + + if (!!(f21->data_regs[0] & RMI_f21_FORCE_CLICK)) + input_report_key(f21->input, f21->key_code, true); + else + input_report_key(f21->input, f21->key_code, false); + return IRQ_HANDLED; +} + +static int rmi_f21_config(struct rmi_function *fn) +{ + struct f21_data *f21 = dev_get_drvdata(&fn->dev); + struct rmi_driver *drv = fn->rmi_dev->driver; + + if (!f21) + return 0; + + 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; + unsigned int button = BTN_LEFT; + + f21->key_code = button; + 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); + 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.7.4