File Index
Files and directories
Sign in
FILE

rmi_f21.c

File preview with syntax highlighting.

linux-6.19.14/drivers/input/rmi4/rmi_f21.c C
  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
 29struct 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
 41static 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
 78static 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
 87static 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
103static 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
171struct 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};
~/ Read-only file preview.