Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2012-2020 Synaptics Incorporated
  4 */
  5
  6#include <linux/kernel.h>
  7#include <linux/rmi.h>
  8#include <linux/input.h>
  9#include <linux/slab.h>
 10#include "rmi_driver.h"
 11
 12#define RMI_F3A_MAX_GPIO_COUNT		128
 13#define RMI_F3A_MAX_REG_SIZE		DIV_ROUND_UP(RMI_F3A_MAX_GPIO_COUNT, 8)
 14
 15/* Defs for Query 0 */
 16#define RMI_F3A_GPIO_COUNT		0x7F
 17
 18#define RMI_F3A_DATA_REGS_MAX_SIZE	RMI_F3A_MAX_REG_SIZE
 19
 20#define TRACKSTICK_RANGE_START		3
 21#define TRACKSTICK_RANGE_END		6
 22
 23struct f3a_data {
 24	/* Query Data */
 25	u8 gpio_count;
 26
 27	u8 register_count;
 28
 29	u8 data_regs[RMI_F3A_DATA_REGS_MAX_SIZE];
 30	u16 *gpio_key_map;
 31
 32	struct input_dev *input;
 33
 34	struct rmi_function *f03;
 35	bool trackstick_buttons;
 36};
 37
 38static void rmi_f3a_report_button(struct rmi_function *fn,
 39				  struct f3a_data *f3a, unsigned int button)
 40{
 41	u16 key_code = f3a->gpio_key_map[button];
 42	bool key_down = !(f3a->data_regs[0] & BIT(button));
 43
 44	if (f3a->trackstick_buttons &&
 45		button >= TRACKSTICK_RANGE_START &&
 46		button <= TRACKSTICK_RANGE_END) {
 47		rmi_f03_overwrite_button(f3a->f03, key_code, key_down);
 48	} else {
 49		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
 50			"%s: call input report key (0x%04x) value (0x%02x)",
 51			__func__, key_code, key_down);
 52		input_report_key(f3a->input, key_code, key_down);
 53	}
 54}
 55
 56static irqreturn_t rmi_f3a_attention(int irq, void *ctx)
 57{
 58	struct rmi_function *fn = ctx;
 59	struct f3a_data *f3a = dev_get_drvdata(&fn->dev);
 60	struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
 61	int error;
 62	int i;
 63
 64	if (drvdata->attn_data.data) {
 65		if (drvdata->attn_data.size < f3a->register_count) {
 66			dev_warn(&fn->dev,
 67				 "F3A interrupted, but data is missing\n");
 68			return IRQ_HANDLED;
 69		}
 70		memcpy(f3a->data_regs, drvdata->attn_data.data,
 71			f3a->register_count);
 72		drvdata->attn_data.data += f3a->register_count;
 73		drvdata->attn_data.size -= f3a->register_count;
 74	} else {
 75		error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr,
 76					f3a->data_regs, f3a->register_count);
 77		if (error) {
 78			dev_err(&fn->dev,
 79				"%s: Failed to read F3a data registers: %d\n",
 80				__func__, error);
 81			return IRQ_RETVAL(error);
 82		}
 83	}
 84
 85	for (i = 0; i < f3a->gpio_count; i++)
 86		if (f3a->gpio_key_map[i] != KEY_RESERVED)
 87			rmi_f3a_report_button(fn, f3a, i);
 88	if (f3a->trackstick_buttons)
 89		rmi_f03_commit_buttons(f3a->f03);
 90
 91	return IRQ_HANDLED;
 92}
 93
 94static int rmi_f3a_config(struct rmi_function *fn)
 95{
 96	struct f3a_data *f3a = dev_get_drvdata(&fn->dev);
 97	struct rmi_driver *drv = fn->rmi_dev->driver;
 98	const struct rmi_device_platform_data *pdata =
 99			rmi_get_platform_data(fn->rmi_dev);
100
101	if (!f3a)
102		return 0;
103
104	if (pdata->gpio_data.trackstick_buttons) {
105		/* Try [re-]establish link to F03. */
106		f3a->f03 = rmi_find_function(fn->rmi_dev, 0x03);
107		f3a->trackstick_buttons = f3a->f03 != NULL;
108	}
109
110	drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
111
112	return 0;
113}
114
115static bool rmi_f3a_is_valid_button(int button, struct f3a_data *f3a,
116					u8 *query1_regs, u8 *ctrl1_regs)
117{
118	/* gpio exist && direction input */
119	return (query1_regs[0] & BIT(button)) && !(ctrl1_regs[0] & BIT(button));
120}
121
122static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a,
123				u8 *query1_regs, u8 *ctrl1_regs)
124{
125	const struct rmi_device_platform_data *pdata =
126			rmi_get_platform_data(fn->rmi_dev);
127	struct input_dev *input = f3a->input;
128	unsigned int button = BTN_LEFT;
129	unsigned int trackstick_button = BTN_LEFT;
130	bool button_mapped = false;
131	int i;
132	int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END);
133
134	f3a->gpio_key_map = devm_kcalloc(&fn->dev,
135						button_count,
136						sizeof(f3a->gpio_key_map[0]),
137						GFP_KERNEL);
138	if (!f3a->gpio_key_map) {
139		dev_err(&fn->dev, "Failed to allocate gpio map memory.\n");
140		return -ENOMEM;
141	}
142
143	for (i = 0; i < button_count; i++) {
144		if (!rmi_f3a_is_valid_button(i, f3a, query1_regs, ctrl1_regs))
145			continue;
146
147		if (pdata->gpio_data.trackstick_buttons &&
148			i >= TRACKSTICK_RANGE_START &&
149			i < TRACKSTICK_RANGE_END) {
150			f3a->gpio_key_map[i] = trackstick_button++;
151		} else if (!pdata->gpio_data.buttonpad || !button_mapped) {
152			f3a->gpio_key_map[i] = button;
153			input_set_capability(input, EV_KEY, button++);
154			button_mapped = true;
155		}
156	}
157	input->keycode = f3a->gpio_key_map;
158	input->keycodesize = sizeof(f3a->gpio_key_map[0]);
159	input->keycodemax = f3a->gpio_count;
160
161	if (pdata->gpio_data.buttonpad || (button - BTN_LEFT == 1))
162		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
163
164	return 0;
165}
166
167static int rmi_f3a_initialize(struct rmi_function *fn, struct f3a_data *f3a)
168{
169	u8 query1[RMI_F3A_MAX_REG_SIZE];
170	u8 ctrl1[RMI_F3A_MAX_REG_SIZE];
171	u8 buf;
172	int error;
173
174	error = rmi_read(fn->rmi_dev, fn->fd.query_base_addr, &buf);
175	if (error < 0) {
176		dev_err(&fn->dev, "Failed to read general info register: %d\n",
177			error);
178		return -ENODEV;
179	}
180
181	f3a->gpio_count = buf & RMI_F3A_GPIO_COUNT;
182	f3a->register_count = DIV_ROUND_UP(f3a->gpio_count, 8);
183
184	/* Query1 -> gpio exist */
185	error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + 1,
186				query1, f3a->register_count);
187	if (error) {
188		dev_err(&fn->dev, "Failed to read query1 register\n");
189		return error;
190	}
191
192	/* Ctrl1 -> gpio direction */
193	error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr + 1,
194				ctrl1, f3a->register_count);
195	if (error) {
196		dev_err(&fn->dev, "Failed to read control1 register\n");
197		return error;
198	}
199
200	error = rmi_f3a_map_gpios(fn, f3a, query1, ctrl1);
201	if (error)
202		return error;
203
204	return 0;
205}
206
207static int rmi_f3a_probe(struct rmi_function *fn)
208{
209	struct rmi_device *rmi_dev = fn->rmi_dev;
210	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
211	struct f3a_data *f3a;
212	int error;
213
214	if (!drv_data->input) {
215		dev_info(&fn->dev, "F3A: no input device found, ignoring\n");
216		return -ENXIO;
217	}
218
219	f3a = devm_kzalloc(&fn->dev, sizeof(*f3a), GFP_KERNEL);
220	if (!f3a)
221		return -ENOMEM;
222
223	f3a->input = drv_data->input;
224
225	error = rmi_f3a_initialize(fn, f3a);
226	if (error)
227		return error;
228
229	dev_set_drvdata(&fn->dev, f3a);
230	return 0;
231}
232
233struct rmi_function_handler rmi_f3a_handler = {
234	.driver = {
235		.name = "rmi4_f3a",
236	},
237	.func = 0x3a,
238	.probe = rmi_f3a_probe,
239	.config = rmi_f3a_config,
240	.attention = rmi_f3a_attention,
241};