aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Duggan <aduggan@synaptics.com>2016-03-10 18:56:58 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-03-10 19:04:23 -0500
commit562b42d3ee305472e1b2ea31574c59925e95fd7e (patch)
tree1555790b31bb76bc3b3347f4cccb8ef74053a664
parentb43d2c1e9353814ce1716fff03d9223f40fa73b5 (diff)
Input: synaptics-rmi4 - add support for F30
RMI4 F30 supports input from clickpad buttons and controls LEDs located on the touchpad PCB. This patch adds support of the clickpad buttons and defers supporting LEDs for the future. Signed-off-by: Andrew Duggan <aduggan@synaptics.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Tested-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/rmi4/Kconfig9
-rw-r--r--drivers/input/rmi4/Makefile1
-rw-r--r--drivers/input/rmi4/rmi_bus.c3
-rw-r--r--drivers/input/rmi4/rmi_driver.h1
-rw-r--r--drivers/input/rmi4/rmi_f30.c407
-rw-r--r--include/linux/rmi.h16
6 files changed, 437 insertions, 0 deletions
diff --git a/drivers/input/rmi4/Kconfig b/drivers/input/rmi4/Kconfig
index aabb8542a55d..284faec30a7a 100644
--- a/drivers/input/rmi4/Kconfig
+++ b/drivers/input/rmi4/Kconfig
@@ -43,3 +43,12 @@ config RMI4_F12
43 Function 12 provides 2D multifinger pointing for touchscreens and 43 Function 12 provides 2D multifinger pointing for touchscreens and
44 touchpads. For sensors that support relative pointing, F12 also 44 touchpads. For sensors that support relative pointing, F12 also
45 provides mouse input. 45 provides mouse input.
46
47config RMI4_F30
48 bool "RMI4 Function 30 (GPIO LED)"
49 depends on RMI4_CORE
50 help
51 Say Y here if you want to add support for RMI4 function 30.
52
53 Function 30 provides GPIO and LED support for RMI4 devices. This
54 includes support for buttons on TouchPads and ClickPads.
diff --git a/drivers/input/rmi4/Makefile b/drivers/input/rmi4/Makefile
index d01e703304c3..ad7156d8252c 100644
--- a/drivers/input/rmi4/Makefile
+++ b/drivers/input/rmi4/Makefile
@@ -6,6 +6,7 @@ rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
6# Function drivers 6# Function drivers
7rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o 7rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
8rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o 8rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
9rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
9 10
10# Transports 11# Transports
11obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o 12obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index a3d766118b61..b368b0515c5a 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -312,6 +312,9 @@ static struct rmi_function_handler *fn_handlers[] = {
312#ifdef CONFIG_RMI4_F12 312#ifdef CONFIG_RMI4_F12
313 &rmi_f12_handler, 313 &rmi_f12_handler,
314#endif 314#endif
315#ifdef CONFIG_RMI4_F30
316 &rmi_f30_handler,
317#endif
315}; 318};
316 319
317static void __rmi_unregister_function_handlers(int start_idx) 320static void __rmi_unregister_function_handlers(int start_idx)
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index ed9127daf5a2..6e140fa3cce1 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -101,4 +101,5 @@ char *rmi_f01_get_product_ID(struct rmi_function *fn);
101extern struct rmi_function_handler rmi_f01_handler; 101extern struct rmi_function_handler rmi_f01_handler;
102extern struct rmi_function_handler rmi_f11_handler; 102extern struct rmi_function_handler rmi_f11_handler;
103extern struct rmi_function_handler rmi_f12_handler; 103extern struct rmi_function_handler rmi_f12_handler;
104extern struct rmi_function_handler rmi_f30_handler;
104#endif 105#endif
diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c
new file mode 100644
index 000000000000..760aff1bc420
--- /dev/null
+++ b/drivers/input/rmi4/rmi_f30.c
@@ -0,0 +1,407 @@
1/*
2 * Copyright (c) 2012-2016 Synaptics Incorporated
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published by
6 * the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/rmi.h>
11#include <linux/input.h>
12#include <linux/slab.h>
13#include "rmi_driver.h"
14
15#define RMI_F30_QUERY_SIZE 2
16
17/* Defs for Query 0 */
18#define RMI_F30_EXTENDED_PATTERNS 0x01
19#define RMI_F30_HAS_MAPPABLE_BUTTONS (1 << 1)
20#define RMI_F30_HAS_LED (1 << 2)
21#define RMI_F30_HAS_GPIO (1 << 3)
22#define RMI_F30_HAS_HAPTIC (1 << 4)
23#define RMI_F30_HAS_GPIO_DRV_CTL (1 << 5)
24#define RMI_F30_HAS_MECH_MOUSE_BTNS (1 << 6)
25
26/* Defs for Query 1 */
27#define RMI_F30_GPIO_LED_COUNT 0x1F
28
29/* Defs for Control Registers */
30#define RMI_F30_CTRL_1_GPIO_DEBOUNCE 0x01
31#define RMI_F30_CTRL_1_HALT (1 << 4)
32#define RMI_F30_CTRL_1_HALTED (1 << 5)
33#define RMI_F30_CTRL_10_NUM_MECH_MOUSE_BTNS 0x03
34
35struct rmi_f30_ctrl_data {
36 int address;
37 int length;
38 u8 *regs;
39};
40
41#define RMI_F30_CTRL_MAX_REGS 32
42#define RMI_F30_CTRL_MAX_BYTES ((RMI_F30_CTRL_MAX_REGS + 7) >> 3)
43#define RMI_F30_CTRL_MAX_REG_BLOCKS 11
44
45#define RMI_F30_CTRL_REGS_MAX_SIZE (RMI_F30_CTRL_MAX_BYTES \
46 + 1 \
47 + RMI_F30_CTRL_MAX_BYTES \
48 + RMI_F30_CTRL_MAX_BYTES \
49 + RMI_F30_CTRL_MAX_BYTES \
50 + 6 \
51 + RMI_F30_CTRL_MAX_REGS \
52 + RMI_F30_CTRL_MAX_REGS \
53 + RMI_F30_CTRL_MAX_BYTES \
54 + 1 \
55 + 1)
56
57struct f30_data {
58 /* Query Data */
59 bool has_extended_pattern;
60 bool has_mappable_buttons;
61 bool has_led;
62 bool has_gpio;
63 bool has_haptic;
64 bool has_gpio_driver_control;
65 bool has_mech_mouse_btns;
66 u8 gpioled_count;
67
68 u8 register_count;
69
70 /* Control Register Data */
71 struct rmi_f30_ctrl_data ctrl[RMI_F30_CTRL_MAX_REG_BLOCKS];
72 u8 ctrl_regs[RMI_F30_CTRL_REGS_MAX_SIZE];
73 u32 ctrl_regs_size;
74
75 u8 data_regs[RMI_F30_CTRL_MAX_BYTES];
76 u16 *gpioled_key_map;
77
78 struct input_dev *input;
79};
80
81static int rmi_f30_read_control_parameters(struct rmi_function *fn,
82 struct f30_data *f30)
83{
84 struct rmi_device *rmi_dev = fn->rmi_dev;
85 int error = 0;
86
87 error = rmi_read_block(rmi_dev, fn->fd.control_base_addr,
88 f30->ctrl_regs, f30->ctrl_regs_size);
89 if (error) {
90 dev_err(&rmi_dev->dev, "%s : Could not read control registers at 0x%x error (%d)\n",
91 __func__, fn->fd.control_base_addr, error);
92 return error;
93 }
94
95 return 0;
96}
97
98static int rmi_f30_attention(struct rmi_function *fn, unsigned long *irq_bits)
99{
100 struct f30_data *f30 = dev_get_drvdata(&fn->dev);
101 struct rmi_device *rmi_dev = fn->rmi_dev;
102 int retval;
103 int gpiled = 0;
104 int value = 0;
105 int i;
106 int reg_num;
107
108 if (!f30->input)
109 return 0;
110
111 /* Read the gpi led data. */
112 if (rmi_dev->xport->attn_data) {
113 memcpy(f30->data_regs, rmi_dev->xport->attn_data,
114 f30->register_count);
115 rmi_dev->xport->attn_data += f30->register_count;
116 rmi_dev->xport->attn_size -= f30->register_count;
117 } else {
118 retval = rmi_read_block(rmi_dev, fn->fd.data_base_addr,
119 f30->data_regs, f30->register_count);
120
121 if (retval) {
122 dev_err(&fn->dev, "%s: Failed to read F30 data registers.\n",
123 __func__);
124 return retval;
125 }
126 }
127
128 for (reg_num = 0; reg_num < f30->register_count; ++reg_num) {
129 for (i = 0; gpiled < f30->gpioled_count && i < 8; ++i,
130 ++gpiled) {
131 if (f30->gpioled_key_map[gpiled] != 0) {
132 /* buttons have pull up resistors */
133 value = (((f30->data_regs[reg_num] >> i) & 0x01)
134 == 0);
135
136 rmi_dbg(RMI_DEBUG_FN, &fn->dev,
137 "%s: call input report key (0x%04x) value (0x%02x)",
138 __func__,
139 f30->gpioled_key_map[gpiled], value);
140 input_report_key(f30->input,
141 f30->gpioled_key_map[gpiled],
142 value);
143 }
144
145 }
146 }
147
148 return 0;
149}
150
151static int rmi_f30_register_device(struct rmi_function *fn)
152{
153 int i;
154 struct rmi_device *rmi_dev = fn->rmi_dev;
155 struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
156 struct f30_data *f30 = dev_get_drvdata(&fn->dev);
157 struct input_dev *input_dev;
158 int button_count = 0;
159
160 input_dev = drv_data->input;
161 if (!input_dev) {
162 dev_info(&fn->dev, "F30: no input device found, ignoring.\n");
163 return -EINVAL;
164 }
165
166 f30->input = input_dev;
167
168 set_bit(EV_KEY, input_dev->evbit);
169
170 input_dev->keycode = f30->gpioled_key_map;
171 input_dev->keycodesize = sizeof(u16);
172 input_dev->keycodemax = f30->gpioled_count;
173
174 for (i = 0; i < f30->gpioled_count; i++) {
175 if (f30->gpioled_key_map[i] != 0) {
176 input_set_capability(input_dev, EV_KEY,
177 f30->gpioled_key_map[i]);
178 button_count++;
179 }
180 }
181
182 if (button_count == 1)
183 __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
184 return 0;
185}
186
187static int rmi_f30_config(struct rmi_function *fn)
188{
189 struct f30_data *f30 = dev_get_drvdata(&fn->dev);
190 struct rmi_driver *drv = fn->rmi_dev->driver;
191 const struct rmi_device_platform_data *pdata =
192 rmi_get_platform_data(fn->rmi_dev);
193 int error;
194
195 if (pdata->f30_data && pdata->f30_data->disable) {
196 drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
197 } else {
198 /* Write Control Register values back to device */
199 error = rmi_write_block(fn->rmi_dev, fn->fd.control_base_addr,
200 f30->ctrl_regs, f30->ctrl_regs_size);
201 if (error) {
202 dev_err(&fn->rmi_dev->dev,
203 "%s : Could not write control registers at 0x%x error (%d)\n",
204 __func__, fn->fd.control_base_addr, error);
205 return error;
206 }
207
208 drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
209 }
210 return 0;
211}
212
213static inline void rmi_f30_set_ctrl_data(struct rmi_f30_ctrl_data *ctrl,
214 int *ctrl_addr, int len, u8 **reg)
215{
216 ctrl->address = *ctrl_addr;
217 ctrl->length = len;
218 ctrl->regs = *reg;
219 *ctrl_addr += len;
220 *reg += len;
221}
222
223static inline bool rmi_f30_is_valid_button(int button,
224 struct rmi_f30_ctrl_data *ctrl)
225{
226 int byte_position = button >> 3;
227 int bit_position = button & 0x07;
228
229 /*
230 * ctrl2 -> dir == 0 -> input mode
231 * ctrl3 -> data == 1 -> actual button
232 */
233 return !(ctrl[2].regs[byte_position] & BIT(bit_position)) &&
234 (ctrl[3].regs[byte_position] & BIT(bit_position));
235}
236
237static inline int rmi_f30_initialize(struct rmi_function *fn)
238{
239 struct f30_data *f30;
240 struct rmi_device *rmi_dev = fn->rmi_dev;
241 const struct rmi_device_platform_data *pdata;
242 int retval = 0;
243 int control_address;
244 int i;
245 int button;
246 u8 buf[RMI_F30_QUERY_SIZE];
247 u8 *ctrl_reg;
248 u8 *map_memory;
249
250 f30 = devm_kzalloc(&fn->dev, sizeof(struct f30_data),
251 GFP_KERNEL);
252 if (!f30)
253 return -ENOMEM;
254
255 dev_set_drvdata(&fn->dev, f30);
256
257 retval = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, buf,
258 RMI_F30_QUERY_SIZE);
259
260 if (retval) {
261 dev_err(&fn->dev, "Failed to read query register.\n");
262 return retval;
263 }
264
265 f30->has_extended_pattern = buf[0] & RMI_F30_EXTENDED_PATTERNS;
266 f30->has_mappable_buttons = buf[0] & RMI_F30_HAS_MAPPABLE_BUTTONS;
267 f30->has_led = buf[0] & RMI_F30_HAS_LED;
268 f30->has_gpio = buf[0] & RMI_F30_HAS_GPIO;
269 f30->has_haptic = buf[0] & RMI_F30_HAS_HAPTIC;
270 f30->has_gpio_driver_control = buf[0] & RMI_F30_HAS_GPIO_DRV_CTL;
271 f30->has_mech_mouse_btns = buf[0] & RMI_F30_HAS_MECH_MOUSE_BTNS;
272 f30->gpioled_count = buf[1] & RMI_F30_GPIO_LED_COUNT;
273
274 f30->register_count = (f30->gpioled_count + 7) >> 3;
275
276 control_address = fn->fd.control_base_addr;
277 ctrl_reg = f30->ctrl_regs;
278
279 if (f30->has_gpio && f30->has_led)
280 rmi_f30_set_ctrl_data(&f30->ctrl[0], &control_address,
281 f30->register_count, &ctrl_reg);
282
283 rmi_f30_set_ctrl_data(&f30->ctrl[1], &control_address, sizeof(u8),
284 &ctrl_reg);
285
286 if (f30->has_gpio) {
287 rmi_f30_set_ctrl_data(&f30->ctrl[2], &control_address,
288 f30->register_count, &ctrl_reg);
289
290 rmi_f30_set_ctrl_data(&f30->ctrl[3], &control_address,
291 f30->register_count, &ctrl_reg);
292 }
293
294 if (f30->has_led) {
295 int ctrl5_len;
296
297 rmi_f30_set_ctrl_data(&f30->ctrl[4], &control_address,
298 f30->register_count, &ctrl_reg);
299
300 if (f30->has_extended_pattern)
301 ctrl5_len = 6;
302 else
303 ctrl5_len = 2;
304
305 rmi_f30_set_ctrl_data(&f30->ctrl[5], &control_address,
306 ctrl5_len, &ctrl_reg);
307 }
308
309 if (f30->has_led || f30->has_gpio_driver_control) {
310 /* control 6 uses a byte per gpio/led */
311 rmi_f30_set_ctrl_data(&f30->ctrl[6], &control_address,
312 f30->gpioled_count, &ctrl_reg);
313 }
314
315 if (f30->has_mappable_buttons) {
316 /* control 7 uses a byte per gpio/led */
317 rmi_f30_set_ctrl_data(&f30->ctrl[7], &control_address,
318 f30->gpioled_count, &ctrl_reg);
319 }
320
321 if (f30->has_haptic) {
322 rmi_f30_set_ctrl_data(&f30->ctrl[8], &control_address,
323 f30->register_count, &ctrl_reg);
324
325 rmi_f30_set_ctrl_data(&f30->ctrl[9], &control_address,
326 sizeof(u8), &ctrl_reg);
327 }
328
329 if (f30->has_mech_mouse_btns)
330 rmi_f30_set_ctrl_data(&f30->ctrl[10], &control_address,
331 sizeof(u8), &ctrl_reg);
332
333 f30->ctrl_regs_size = ctrl_reg - f30->ctrl_regs
334 ?: RMI_F30_CTRL_REGS_MAX_SIZE;
335
336 retval = rmi_f30_read_control_parameters(fn, f30);
337 if (retval < 0) {
338 dev_err(&fn->dev,
339 "Failed to initialize F19 control params.\n");
340 return retval;
341 }
342
343 map_memory = devm_kzalloc(&fn->dev,
344 (f30->gpioled_count * (sizeof(u16))),
345 GFP_KERNEL);
346 if (!map_memory) {
347 dev_err(&fn->dev, "Failed to allocate gpioled map memory.\n");
348 return -ENOMEM;
349 }
350
351 f30->gpioled_key_map = (u16 *)map_memory;
352
353 pdata = rmi_get_platform_data(rmi_dev);
354 if (pdata && f30->has_gpio) {
355 button = BTN_LEFT;
356 for (i = 0; i < f30->gpioled_count; i++) {
357 if (rmi_f30_is_valid_button(i, f30->ctrl)) {
358 f30->gpioled_key_map[i] = button++;
359
360 /*
361 * buttonpad might be given by
362 * f30->has_mech_mouse_btns, but I am
363 * not sure, so use only the pdata info
364 */
365 if (pdata->f30_data &&
366 pdata->f30_data->buttonpad)
367 break;
368 }
369 }
370 }
371
372 return 0;
373}
374
375static int rmi_f30_probe(struct rmi_function *fn)
376{
377 int rc;
378 const struct rmi_device_platform_data *pdata =
379 rmi_get_platform_data(fn->rmi_dev);
380
381 if (pdata->f30_data && pdata->f30_data->disable)
382 return 0;
383
384 rc = rmi_f30_initialize(fn);
385 if (rc < 0)
386 goto error_exit;
387
388 rc = rmi_f30_register_device(fn);
389 if (rc < 0)
390 goto error_exit;
391
392 return 0;
393
394error_exit:
395 return rc;
396
397}
398
399struct rmi_function_handler rmi_f30_handler = {
400 .driver = {
401 .name = "rmi4_f30",
402 },
403 .func = 0x30,
404 .probe = rmi_f30_probe,
405 .config = rmi_f30_config,
406 .attention = rmi_f30_attention,
407};
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
index b527064bac47..ac89d1e731dc 100644
--- a/include/linux/rmi.h
+++ b/include/linux/rmi.h
@@ -102,6 +102,21 @@ struct rmi_2d_sensor_platform_data {
102}; 102};
103 103
104/** 104/**
105 * struct rmi_f30_data - overrides defaults for a single F30 GPIOs/LED chip.
106 * @buttonpad - the touchpad is a buttonpad, so enable only the first actual
107 * button that is found.
108 * @trackstick_buttons - Set when the function 30 is handling the physical
109 * buttons of the trackstick (as a PD/2 passthrough device.
110 * @disable - the touchpad incorrectly reports F30 and it should be ignored.
111 * This is a special case which is due to misconfigured firmware.
112 */
113struct rmi_f30_data {
114 bool buttonpad;
115 bool trackstick_buttons;
116 bool disable;
117};
118
119/**
105 * struct rmi_f01_power - override default power management settings. 120 * struct rmi_f01_power - override default power management settings.
106 * 121 *
107 */ 122 */
@@ -147,6 +162,7 @@ struct rmi_device_platform_data {
147 /* function handler pdata */ 162 /* function handler pdata */
148 struct rmi_2d_sensor_platform_data *sensor_pdata; 163 struct rmi_2d_sensor_platform_data *sensor_pdata;
149 struct rmi_f01_power_management power_management; 164 struct rmi_f01_power_management power_management;
165 struct rmi_f30_data *f30_data;
150}; 166};
151 167
152/** 168/**