blob: 8c5360c25266a17c2e917bf658dc3256e10e2026 [file] [log] [blame]
Andrew Dugganb43d2c12016-03-10 15:55:29 -08001/*
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#include <linux/input.h>
9#include <linux/input/mt.h>
10#include <linux/rmi.h>
11#include "rmi_driver.h"
12#include "rmi_2d_sensor.h"
13
14enum rmi_f12_object_type {
15 RMI_F12_OBJECT_NONE = 0x00,
16 RMI_F12_OBJECT_FINGER = 0x01,
17 RMI_F12_OBJECT_STYLUS = 0x02,
18 RMI_F12_OBJECT_PALM = 0x03,
19 RMI_F12_OBJECT_UNCLASSIFIED = 0x04,
20 RMI_F12_OBJECT_GLOVED_FINGER = 0x06,
21 RMI_F12_OBJECT_NARROW_OBJECT = 0x07,
22 RMI_F12_OBJECT_HAND_EDGE = 0x08,
23 RMI_F12_OBJECT_COVER = 0x0A,
24 RMI_F12_OBJECT_STYLUS_2 = 0x0B,
25 RMI_F12_OBJECT_ERASER = 0x0C,
26 RMI_F12_OBJECT_SMALL_OBJECT = 0x0D,
27};
28
Andrew Duggan6d0dbea2016-11-08 16:46:20 -080029#define F12_DATA1_BYTES_PER_OBJ 8
30
Andrew Dugganb43d2c12016-03-10 15:55:29 -080031struct f12_data {
Andrew Dugganb43d2c12016-03-10 15:55:29 -080032 struct rmi_2d_sensor sensor;
33 struct rmi_2d_sensor_platform_data sensor_pdata;
Andrew Duggan24f63b12016-11-08 16:47:58 -080034 bool has_dribble;
Andrew Dugganb43d2c12016-03-10 15:55:29 -080035
36 u16 data_addr;
37
38 struct rmi_register_descriptor query_reg_desc;
39 struct rmi_register_descriptor control_reg_desc;
40 struct rmi_register_descriptor data_reg_desc;
41
42 /* F12 Data1 describes sensed objects */
43 const struct rmi_register_desc_item *data1;
44 u16 data1_offset;
45
46 /* F12 Data5 describes finger ACM */
47 const struct rmi_register_desc_item *data5;
48 u16 data5_offset;
49
50 /* F12 Data5 describes Pen */
51 const struct rmi_register_desc_item *data6;
52 u16 data6_offset;
53
54
55 /* F12 Data9 reports relative data */
56 const struct rmi_register_desc_item *data9;
57 u16 data9_offset;
58
59 const struct rmi_register_desc_item *data15;
60 u16 data15_offset;
61};
62
63static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
64{
65 const struct rmi_register_desc_item *item;
66 struct rmi_2d_sensor *sensor = &f12->sensor;
67 struct rmi_function *fn = sensor->fn;
68 struct rmi_device *rmi_dev = fn->rmi_dev;
69 int ret;
70 int offset;
Andrew Duggane4add7b2016-07-19 17:53:59 -070071 u8 buf[15];
Andrew Dugganb43d2c12016-03-10 15:55:29 -080072 int pitch_x = 0;
73 int pitch_y = 0;
74 int clip_x_low = 0;
75 int clip_x_high = 0;
76 int clip_y_low = 0;
77 int clip_y_high = 0;
78 int rx_receivers = 0;
79 int tx_receivers = 0;
80 int sensor_flags = 0;
81
82 item = rmi_get_register_desc_item(&f12->control_reg_desc, 8);
83 if (!item) {
84 dev_err(&fn->dev,
85 "F12 does not have the sensor tuning control register\n");
86 return -ENODEV;
87 }
88
89 offset = rmi_register_desc_calc_reg_offset(&f12->control_reg_desc, 8);
90
Andrew Duggane4add7b2016-07-19 17:53:59 -070091 if (item->reg_size > sizeof(buf)) {
92 dev_err(&fn->dev,
93 "F12 control8 should be no bigger than %zd bytes, not: %ld\n",
94 sizeof(buf), item->reg_size);
Andrew Dugganb43d2c12016-03-10 15:55:29 -080095 return -ENODEV;
96 }
97
98 ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset, buf,
99 item->reg_size);
100 if (ret)
101 return ret;
102
103 offset = 0;
104 if (rmi_register_desc_has_subpacket(item, 0)) {
105 sensor->max_x = (buf[offset + 1] << 8) | buf[offset];
106 sensor->max_y = (buf[offset + 3] << 8) | buf[offset + 2];
107 offset += 4;
108 }
109
110 rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: max_x: %d max_y: %d\n", __func__,
111 sensor->max_x, sensor->max_y);
112
113 if (rmi_register_desc_has_subpacket(item, 1)) {
114 pitch_x = (buf[offset + 1] << 8) | buf[offset];
115 pitch_y = (buf[offset + 3] << 8) | buf[offset + 2];
116 offset += 4;
117 }
118
119 if (rmi_register_desc_has_subpacket(item, 2)) {
120 sensor->axis_align.clip_x_low = buf[offset];
121 sensor->axis_align.clip_x_high = sensor->max_x
122 - buf[offset + 1];
123 sensor->axis_align.clip_y_low = buf[offset + 2];
124 sensor->axis_align.clip_y_high = sensor->max_y
125 - buf[offset + 3];
126 offset += 4;
127 }
128
129 rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x low: %d x high: %d y low: %d y high: %d\n",
130 __func__, clip_x_low, clip_x_high, clip_y_low, clip_y_high);
131
132 if (rmi_register_desc_has_subpacket(item, 3)) {
133 rx_receivers = buf[offset];
134 tx_receivers = buf[offset + 1];
135 offset += 2;
136 }
137
138 if (rmi_register_desc_has_subpacket(item, 4)) {
139 sensor_flags = buf[offset];
140 offset += 1;
141 }
142
143 sensor->x_mm = (pitch_x * rx_receivers) >> 12;
144 sensor->y_mm = (pitch_y * tx_receivers) >> 12;
145
146 rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x_mm: %d y_mm: %d\n", __func__,
147 sensor->x_mm, sensor->y_mm);
148
149 return 0;
150}
151
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800152static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800153{
154 int i;
155 struct rmi_2d_sensor *sensor = &f12->sensor;
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800156 int objects = f12->data1->num_subpackets;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800157
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800158 if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
159 objects = size / F12_DATA1_BYTES_PER_OBJ;
160
161 for (i = 0; i < objects; i++) {
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800162 struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
163
164 obj->type = RMI_2D_OBJECT_NONE;
165 obj->mt_tool = MT_TOOL_FINGER;
166
167 switch (data1[0]) {
168 case RMI_F12_OBJECT_FINGER:
169 obj->type = RMI_2D_OBJECT_FINGER;
170 break;
171 case RMI_F12_OBJECT_STYLUS:
172 obj->type = RMI_2D_OBJECT_STYLUS;
173 obj->mt_tool = MT_TOOL_PEN;
174 break;
175 case RMI_F12_OBJECT_PALM:
176 obj->type = RMI_2D_OBJECT_PALM;
177 obj->mt_tool = MT_TOOL_PALM;
178 break;
179 case RMI_F12_OBJECT_UNCLASSIFIED:
180 obj->type = RMI_2D_OBJECT_UNCLASSIFIED;
181 break;
182 }
183
184 obj->x = (data1[2] << 8) | data1[1];
185 obj->y = (data1[4] << 8) | data1[3];
186 obj->z = data1[5];
187 obj->wx = data1[6];
188 obj->wy = data1[7];
189
190 rmi_2d_sensor_abs_process(sensor, obj, i);
191
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800192 data1 += F12_DATA1_BYTES_PER_OBJ;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800193 }
194
195 if (sensor->kernel_tracking)
196 input_mt_assign_slots(sensor->input,
197 sensor->tracking_slots,
198 sensor->tracking_pos,
199 sensor->nbr_fingers,
200 sensor->dmax);
201
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800202 for (i = 0; i < objects; i++)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800203 rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
204}
205
206static int rmi_f12_attention(struct rmi_function *fn,
207 unsigned long *irq_nr_regs)
208{
209 int retval;
210 struct rmi_device *rmi_dev = fn->rmi_dev;
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800211 struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800212 struct f12_data *f12 = dev_get_drvdata(&fn->dev);
213 struct rmi_2d_sensor *sensor = &f12->sensor;
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800214 int valid_bytes = sensor->pkt_size;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800215
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800216 if (drvdata->attn_data.data) {
217 if (sensor->attn_size > drvdata->attn_data.size)
218 valid_bytes = drvdata->attn_data.size;
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800219 else
220 valid_bytes = sensor->attn_size;
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800221 memcpy(sensor->data_pkt, drvdata->attn_data.data,
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800222 valid_bytes);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800223 drvdata->attn_data.data += sensor->attn_size;
224 drvdata->attn_data.size -= sensor->attn_size;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800225 } else {
226 retval = rmi_read_block(rmi_dev, f12->data_addr,
227 sensor->data_pkt, sensor->pkt_size);
228 if (retval < 0) {
229 dev_err(&fn->dev, "Failed to read object data. Code: %d.\n",
230 retval);
231 return retval;
232 }
233 }
234
235 if (f12->data1)
236 rmi_f12_process_objects(f12,
Andrew Duggan6d0dbea2016-11-08 16:46:20 -0800237 &sensor->data_pkt[f12->data1_offset], valid_bytes);
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800238
239 input_mt_sync_frame(sensor->input);
240
241 return 0;
242}
243
Andrew Duggan24f63b12016-11-08 16:47:58 -0800244static int rmi_f12_write_control_regs(struct rmi_function *fn)
245{
246 int ret;
247 const struct rmi_register_desc_item *item;
248 struct rmi_device *rmi_dev = fn->rmi_dev;
249 struct f12_data *f12 = dev_get_drvdata(&fn->dev);
250 int control_size;
251 char buf[3];
252 u16 control_offset = 0;
253 u8 subpacket_offset = 0;
254
255 if (f12->has_dribble
256 && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
257 item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
258 if (item) {
259 control_offset = rmi_register_desc_calc_reg_offset(
260 &f12->control_reg_desc, 20);
261
262 /*
263 * The byte containing the EnableDribble bit will be
264 * in either byte 0 or byte 2 of control 20. Depending
265 * on the existence of subpacket 0. If control 20 is
266 * larger then 3 bytes, just read the first 3.
267 */
268 control_size = min(item->reg_size, 3UL);
269
270 ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
271 + control_offset, buf, control_size);
272 if (ret)
273 return ret;
274
275 if (rmi_register_desc_has_subpacket(item, 0))
276 subpacket_offset += 1;
277
278 switch (f12->sensor.dribble) {
279 case RMI_REG_STATE_OFF:
280 buf[subpacket_offset] &= ~BIT(2);
281 break;
282 case RMI_REG_STATE_ON:
283 buf[subpacket_offset] |= BIT(2);
284 break;
285 case RMI_REG_STATE_DEFAULT:
286 default:
287 break;
288 }
289
290 ret = rmi_write_block(rmi_dev,
291 fn->fd.control_base_addr + control_offset,
292 buf, control_size);
293 if (ret)
294 return ret;
295 }
296 }
297
298 return 0;
299
300}
301
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800302static int rmi_f12_config(struct rmi_function *fn)
303{
304 struct rmi_driver *drv = fn->rmi_dev->driver;
Andrew Duggan24f63b12016-11-08 16:47:58 -0800305 int ret;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800306
307 drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
308
Andrew Duggan24f63b12016-11-08 16:47:58 -0800309 ret = rmi_f12_write_control_regs(fn);
310 if (ret)
311 dev_warn(&fn->dev,
312 "Failed to write F12 control registers: %d\n", ret);
313
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800314 return 0;
315}
316
317static int rmi_f12_probe(struct rmi_function *fn)
318{
319 struct f12_data *f12;
320 int ret;
321 struct rmi_device *rmi_dev = fn->rmi_dev;
322 char buf;
323 u16 query_addr = fn->fd.query_base_addr;
324 const struct rmi_register_desc_item *item;
325 struct rmi_2d_sensor *sensor;
326 struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800327 struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800328 u16 data_offset = 0;
329
330 rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
331
332 ret = rmi_read(fn->rmi_dev, query_addr, &buf);
333 if (ret < 0) {
334 dev_err(&fn->dev, "Failed to read general info register: %d\n",
335 ret);
336 return -ENODEV;
337 }
338 ++query_addr;
339
Andrew Duggan24f63b12016-11-08 16:47:58 -0800340 if (!(buf & BIT(0))) {
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800341 dev_err(&fn->dev,
342 "Behavior of F12 without register descriptors is undefined.\n");
343 return -ENODEV;
344 }
345
346 f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data), GFP_KERNEL);
347 if (!f12)
348 return -ENOMEM;
349
Andrew Duggan24f63b12016-11-08 16:47:58 -0800350 f12->has_dribble = !!(buf & BIT(3));
351
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800352 if (fn->dev.of_node) {
353 ret = rmi_2d_sensor_of_probe(&fn->dev, &f12->sensor_pdata);
354 if (ret)
355 return ret;
Benjamin Tissoires0a135b82016-11-30 17:01:50 -0800356 } else {
357 f12->sensor_pdata = pdata->sensor_pdata;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800358 }
359
360 ret = rmi_read_register_desc(rmi_dev, query_addr,
361 &f12->query_reg_desc);
362 if (ret) {
363 dev_err(&fn->dev,
364 "Failed to read the Query Register Descriptor: %d\n",
365 ret);
366 return ret;
367 }
368 query_addr += 3;
369
370 ret = rmi_read_register_desc(rmi_dev, query_addr,
371 &f12->control_reg_desc);
372 if (ret) {
373 dev_err(&fn->dev,
374 "Failed to read the Control Register Descriptor: %d\n",
375 ret);
376 return ret;
377 }
378 query_addr += 3;
379
380 ret = rmi_read_register_desc(rmi_dev, query_addr,
381 &f12->data_reg_desc);
382 if (ret) {
383 dev_err(&fn->dev,
384 "Failed to read the Data Register Descriptor: %d\n",
385 ret);
386 return ret;
387 }
388 query_addr += 3;
389
390 sensor = &f12->sensor;
391 sensor->fn = fn;
392 f12->data_addr = fn->fd.data_base_addr;
393 sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
394
395 sensor->axis_align =
396 f12->sensor_pdata.axis_align;
397
398 sensor->x_mm = f12->sensor_pdata.x_mm;
399 sensor->y_mm = f12->sensor_pdata.y_mm;
Andrew Duggan24f63b12016-11-08 16:47:58 -0800400 sensor->dribble = f12->sensor_pdata.dribble;
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800401
402 if (sensor->sensor_type == rmi_sensor_default)
403 sensor->sensor_type =
404 f12->sensor_pdata.sensor_type;
405
406 rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
407 sensor->pkt_size);
408 sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
409 if (!sensor->data_pkt)
410 return -ENOMEM;
411
412 dev_set_drvdata(&fn->dev, f12);
413
414 ret = rmi_f12_read_sensor_tuning(f12);
415 if (ret)
416 return ret;
417
418 /*
419 * Figure out what data is contained in the data registers. HID devices
420 * may have registers defined, but their data is not reported in the
421 * HID attention report. Registers which are not reported in the HID
422 * attention report check to see if the device is receiving data from
423 * HID attention reports.
424 */
425 item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800426 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800427 data_offset += item->reg_size;
428
429 item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
430 if (item) {
431 f12->data1 = item;
432 f12->data1_offset = data_offset;
433 data_offset += item->reg_size;
434 sensor->nbr_fingers = item->num_subpackets;
435 sensor->report_abs = 1;
436 sensor->attn_size += item->reg_size;
437 }
438
439 item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800440 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800441 data_offset += item->reg_size;
442
443 item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800444 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800445 data_offset += item->reg_size;
446
447 item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800448 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800449 data_offset += item->reg_size;
450
451 item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
452 if (item) {
453 f12->data5 = item;
454 f12->data5_offset = data_offset;
455 data_offset += item->reg_size;
456 sensor->attn_size += item->reg_size;
457 }
458
459 item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800460 if (item && !drvdata->attn_data.data) {
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800461 f12->data6 = item;
462 f12->data6_offset = data_offset;
463 data_offset += item->reg_size;
464 }
465
466 item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800467 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800468 data_offset += item->reg_size;
469
470 item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800471 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800472 data_offset += item->reg_size;
473
474 item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800475 if (item && !drvdata->attn_data.data) {
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800476 f12->data9 = item;
477 f12->data9_offset = data_offset;
478 data_offset += item->reg_size;
479 if (!sensor->report_abs)
480 sensor->report_rel = 1;
481 }
482
483 item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800484 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800485 data_offset += item->reg_size;
486
487 item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800488 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800489 data_offset += item->reg_size;
490
491 item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800492 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800493 data_offset += item->reg_size;
494
495 item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800496 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800497 data_offset += item->reg_size;
498
499 item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800500 if (item && !drvdata->attn_data.data)
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800501 data_offset += item->reg_size;
502
503 item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
Benjamin Tissoiresae9979c2016-12-02 17:49:10 -0800504 if (item && !drvdata->attn_data.data) {
Andrew Dugganb43d2c12016-03-10 15:55:29 -0800505 f12->data15 = item;
506 f12->data15_offset = data_offset;
507 data_offset += item->reg_size;
508 }
509
510 /* allocate the in-kernel tracking buffers */
511 sensor->tracking_pos = devm_kzalloc(&fn->dev,
512 sizeof(struct input_mt_pos) * sensor->nbr_fingers,
513 GFP_KERNEL);
514 sensor->tracking_slots = devm_kzalloc(&fn->dev,
515 sizeof(int) * sensor->nbr_fingers, GFP_KERNEL);
516 sensor->objs = devm_kzalloc(&fn->dev,
517 sizeof(struct rmi_2d_sensor_abs_object)
518 * sensor->nbr_fingers, GFP_KERNEL);
519 if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
520 return -ENOMEM;
521
522 ret = rmi_2d_sensor_configure_input(fn, sensor);
523 if (ret)
524 return ret;
525
526 return 0;
527}
528
529struct rmi_function_handler rmi_f12_handler = {
530 .driver = {
531 .name = "rmi4_f12",
532 },
533 .func = 0x12,
534 .probe = rmi_f12_probe,
535 .config = rmi_f12_config,
536 .attention = rmi_f12_attention,
537};