Input: sh_keysc - remove dependency on SUPERH
[deliverable/linux.git] / drivers / input / mouse / cyapa_gen5.c
CommitLineData
6972a859
DD
1/*
2 * Cypress APA trackpad with I2C interface
3 *
4 * Author: Dudley Du <dudl@cypress.com>
5 *
94897619 6 * Copyright (C) 2014-2015 Cypress Semiconductor, Inc.
6972a859
DD
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file COPYING in the main directory of this archive for
10 * more details.
11 */
12
13#include <linux/delay.h>
14#include <linux/i2c.h>
15#include <linux/input.h>
16#include <linux/input/mt.h>
17#include <linux/mutex.h>
18#include <linux/completion.h>
19#include <linux/slab.h>
17a28055 20#include <asm/unaligned.h>
5812d306 21#include <linux/crc-itu-t.h>
757cae5a 22#include <linux/pm_runtime.h>
6972a859
DD
23#include "cyapa.h"
24
25
94897619 26/* Macro of TSG firmware image */
6972a859
DD
27#define CYAPA_TSG_FLASH_MAP_BLOCK_SIZE 0x80
28#define CYAPA_TSG_IMG_FW_HDR_SIZE 13
29#define CYAPA_TSG_FW_ROW_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE)
30#define CYAPA_TSG_IMG_START_ROW_NUM 0x002e
31#define CYAPA_TSG_IMG_END_ROW_NUM 0x01fe
32#define CYAPA_TSG_IMG_APP_INTEGRITY_ROW_NUM 0x01ff
33#define CYAPA_TSG_IMG_MAX_RECORDS (CYAPA_TSG_IMG_END_ROW_NUM - \
34 CYAPA_TSG_IMG_START_ROW_NUM + 1 + 1)
35#define CYAPA_TSG_IMG_READ_SIZE (CYAPA_TSG_FLASH_MAP_BLOCK_SIZE / 2)
36#define CYAPA_TSG_START_OF_APPLICATION 0x1700
37#define CYAPA_TSG_APP_INTEGRITY_SIZE 60
38#define CYAPA_TSG_FLASH_MAP_METADATA_SIZE 60
39#define CYAPA_TSG_BL_KEY_SIZE 8
40
41#define CYAPA_TSG_MAX_CMD_SIZE 256
42
94897619
DD
43/* Macro of PIP interface */
44#define PIP_BL_INITIATE_RESP_LEN 11
45#define PIP_BL_FAIL_EXIT_RESP_LEN 11
46#define PIP_BL_FAIL_EXIT_STATUS_CODE 0x0c
47#define PIP_BL_VERIFY_INTEGRITY_RESP_LEN 12
48#define PIP_BL_INTEGRITY_CHEKC_PASS 0x00
49#define PIP_BL_BLOCK_WRITE_RESP_LEN 11
50
51#define PIP_TOUCH_REPORT_ID 0x01
52#define PIP_BTN_REPORT_ID 0x03
53#define PIP_WAKEUP_EVENT_REPORT_ID 0x04
54#define PIP_PUSH_BTN_REPORT_ID 0x06
55#define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 /* Special for old Gen5 TP. */
945525ee
DD
56#define PIP_PROXIMITY_REPORT_ID 0x07
57
58#define PIP_PROXIMITY_REPORT_SIZE 6
59#define PIP_PROXIMITY_DISTANCE_OFFSET 0x05
60#define PIP_PROXIMITY_DISTANCE_MASK 0x01
94897619
DD
61
62#define PIP_TOUCH_REPORT_HEAD_SIZE 7
63#define PIP_TOUCH_REPORT_MAX_SIZE 127
64#define PIP_BTN_REPORT_HEAD_SIZE 6
65#define PIP_BTN_REPORT_MAX_SIZE 14
66#define PIP_WAKEUP_EVENT_SIZE 4
67
68#define PIP_NUMBER_OF_TOUCH_OFFSET 5
69#define PIP_NUMBER_OF_TOUCH_MASK 0x1f
70#define PIP_BUTTONS_OFFSET 5
71#define PIP_BUTTONS_MASK 0x0f
72#define PIP_GET_EVENT_ID(reg) (((reg) >> 5) & 0x03)
73#define PIP_GET_TOUCH_ID(reg) ((reg) & 0x1f)
74#define PIP_TOUCH_TYPE_FINGER 0x00
75#define PIP_TOUCH_TYPE_PROXIMITY 0x01
76#define PIP_TOUCH_TYPE_HOVER 0x02
77#define PIP_GET_TOUCH_TYPE(reg) ((reg) & 0x07)
6972a859 78
94897619
DD
79#define RECORD_EVENT_NONE 0
80#define RECORD_EVENT_TOUCHDOWN 1
81#define RECORD_EVENT_DISPLACE 2
82#define RECORD_EVENT_LIFTOFF 3
6972a859 83
94897619
DD
84#define PIP_SENSING_MODE_MUTUAL_CAP_FINE 0x00
85#define PIP_SENSING_MODE_SELF_CAP 0x02
86
945525ee
DD
87#define PIP_SET_PROXIMITY 0x49
88
94897619
DD
89/* Macro of Gen5 */
90#define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100
91#define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe
6972a859
DD
92
93#define GEN5_POWER_STATE_ACTIVE 0x01
94#define GEN5_POWER_STATE_LOOK_FOR_TOUCH 0x02
95#define GEN5_POWER_STATE_READY 0x03
96#define GEN5_POWER_STATE_IDLE 0x04
97#define GEN5_POWER_STATE_BTN_ONLY 0x05
98#define GEN5_POWER_STATE_OFF 0x06
99
6972a859
DD
100#define GEN5_POWER_READY_MAX_INTRVL_TIME 50 /* Unit: ms */
101#define GEN5_POWER_IDLE_MAX_INTRVL_TIME 250 /* Unit: ms */
102
94897619
DD
103#define GEN5_CMD_GET_PARAMETER 0x05
104#define GEN5_CMD_SET_PARAMETER 0x06
105#define GEN5_PARAMETER_ACT_INTERVL_ID 0x4d
106#define GEN5_PARAMETER_ACT_INTERVL_SIZE 1
107#define GEN5_PARAMETER_ACT_LFT_INTERVL_ID 0x4f
108#define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE 2
109#define GEN5_PARAMETER_LP_INTRVL_ID 0x4c
110#define GEN5_PARAMETER_LP_INTRVL_SIZE 2
111
112#define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08
6972a859
DD
113
114#define GEN5_BL_REPORT_DESCRIPTOR_SIZE 0x1d
115#define GEN5_BL_REPORT_DESCRIPTOR_ID 0xfe
116#define GEN5_APP_REPORT_DESCRIPTOR_SIZE 0xee
117#define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE 0xfa
118#define GEN5_APP_REPORT_DESCRIPTOR_ID 0xf6
119
6972a859
DD
120#define GEN5_RETRIEVE_MUTUAL_PWC_DATA 0x00
121#define GEN5_RETRIEVE_SELF_CAP_PWC_DATA 0x01
122
123#define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07
124
125#define GEN5_CMD_EXECUTE_PANEL_SCAN 0x2a
126#define GEN5_CMD_RETRIEVE_PANEL_SCAN 0x2b
127#define GEN5_PANEL_SCAN_MUTUAL_RAW_DATA 0x00
128#define GEN5_PANEL_SCAN_MUTUAL_BASELINE 0x01
129#define GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT 0x02
130#define GEN5_PANEL_SCAN_SELF_RAW_DATA 0x03
131#define GEN5_PANEL_SCAN_SELF_BASELINE 0x04
132#define GEN5_PANEL_SCAN_SELF_DIFFCOUNT 0x05
133
94897619 134/* The offset only valid for retrieve PWC and panel scan commands */
6972a859
DD
135#define GEN5_RESP_DATA_STRUCTURE_OFFSET 10
136#define GEN5_PWC_DATA_ELEMENT_SIZE_MASK 0x07
137
6972a859 138
94897619 139struct cyapa_pip_touch_record {
6972a859
DD
140 /*
141 * Bit 7 - 3: reserved
142 * Bit 2 - 0: touch type;
143 * 0 : standard finger;
c2c06c41
DD
144 * 1 : proximity (Start supported in Gen5 TP).
145 * 2 : finger hover (defined, but not used yet.)
146 * 3 - 15 : reserved.
6972a859
DD
147 */
148 u8 touch_type;
149
150 /*
151 * Bit 7: indicates touch liftoff status.
152 * 0 : touch is currently on the panel.
153 * 1 : touch record indicates a liftoff.
154 * Bit 6 - 5: indicates an event associated with this touch instance
155 * 0 : no event
156 * 1 : touchdown
157 * 2 : significant displacement (> active distance)
158 * 3 : liftoff (record reports last known coordinates)
159 * Bit 4 - 0: An arbitrary ID tag associated with a finger
160 * to allow tracking a touch as it moves around the panel.
161 */
162 u8 touch_tip_event_id;
163
164 /* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */
165 u8 x_lo;
166
167 /* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */
168 u8 x_hi;
169
170 /* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */
171 u8 y_lo;
172
173 /* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */
174 u8 y_hi;
175
94897619
DD
176 /*
177 * The meaning of this value is different when touch_type is different.
178 * For standard finger type:
179 * Touch intensity in counts, pressure value.
c2c06c41
DD
180 * For proximity type (Start supported in Gen5 TP):
181 * The distance, in surface units, between the contact and
182 * the surface.
94897619 183 **/
6972a859
DD
184 u8 z;
185
186 /*
187 * The length of the major axis of the ellipse of contact between
188 * the finger and the panel (ABS_MT_TOUCH_MAJOR).
189 */
190 u8 major_axis_len;
191
192 /*
193 * The length of the minor axis of the ellipse of contact between
194 * the finger and the panel (ABS_MT_TOUCH_MINOR).
195 */
196 u8 minor_axis_len;
197
198 /*
199 * The length of the major axis of the approaching tool.
200 * (ABS_MT_WIDTH_MAJOR)
201 */
202 u8 major_tool_len;
203
204 /*
205 * The length of the minor axis of the approaching tool.
206 * (ABS_MT_WIDTH_MINOR)
207 */
208 u8 minor_tool_len;
209
210 /*
211 * The angle between the panel vertical axis and
212 * the major axis of the contact ellipse. This value is an 8-bit
213 * signed integer. The range is -127 to +127 (corresponding to
214 * -90 degree and +90 degree respectively).
215 * The positive direction is clockwise from the vertical axis.
216 * If the ellipse of contact degenerates into a circle,
217 * orientation is reported as 0.
218 */
219 u8 orientation;
220} __packed;
221
94897619
DD
222struct cyapa_pip_report_data {
223 u8 report_head[PIP_TOUCH_REPORT_HEAD_SIZE];
224 struct cyapa_pip_touch_record touch_records[10];
6972a859
DD
225} __packed;
226
5812d306
DD
227struct cyapa_tsg_bin_image_head {
228 u8 head_size; /* Unit: bytes, including itself. */
229 u8 ttda_driver_major_version; /* Reserved as 0. */
230 u8 ttda_driver_minor_version; /* Reserved as 0. */
231 u8 fw_major_version;
232 u8 fw_minor_version;
233 u8 fw_revision_control_number[8];
c2c06c41
DD
234 u8 silicon_id_hi;
235 u8 silicon_id_lo;
236 u8 chip_revision;
237 u8 family_id;
238 u8 bl_ver_maj;
239 u8 bl_ver_min;
5812d306
DD
240} __packed;
241
242struct cyapa_tsg_bin_image_data_record {
243 u8 flash_array_id;
244 __be16 row_number;
245 /* The number of bytes of flash data contained in this record. */
246 __be16 record_len;
247 /* The flash program data. */
248 u8 record_data[CYAPA_TSG_FW_ROW_SIZE];
249} __packed;
250
251struct cyapa_tsg_bin_image {
252 struct cyapa_tsg_bin_image_head image_head;
253 struct cyapa_tsg_bin_image_data_record records[0];
254} __packed;
255
94897619 256struct pip_bl_packet_start {
5812d306
DD
257 u8 sop; /* Start of packet, must be 01h */
258 u8 cmd_code;
259 __le16 data_length; /* Size of data parameter start from data[0] */
260} __packed;
261
94897619 262struct pip_bl_packet_end {
5812d306
DD
263 __le16 crc;
264 u8 eop; /* End of packet, must be 17h */
265} __packed;
266
94897619 267struct pip_bl_cmd_head {
5812d306
DD
268 __le16 addr; /* Output report register address, must be 0004h */
269 /* Size of packet not including output report register address */
270 __le16 length;
271 u8 report_id; /* Bootloader output report id, must be 40h */
272 u8 rsvd; /* Reserved, must be 0 */
94897619 273 struct pip_bl_packet_start packet_start;
5812d306
DD
274 u8 data[0]; /* Command data variable based on commands */
275} __packed;
276
277/* Initiate bootload command data structure. */
94897619 278struct pip_bl_initiate_cmd_data {
5812d306
DD
279 /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */
280 u8 key[CYAPA_TSG_BL_KEY_SIZE];
281 u8 metadata_raw_parameter[CYAPA_TSG_FLASH_MAP_METADATA_SIZE];
282 __le16 metadata_crc;
283} __packed;
284
94897619 285struct tsg_bl_metadata_row_params {
5812d306 286 __le16 size;
2be7256f 287 __le16 maximum_size;
5812d306
DD
288 __le32 app_start;
289 __le16 app_len;
290 __le16 app_crc;
291 __le32 app_entry;
292 __le32 upgrade_start;
293 __le16 upgrade_len;
294 __le16 entry_row_crc;
295 u8 padding[36]; /* Padding data must be 0 */
296 __le16 metadata_crc; /* CRC starts at offset of 60 */
297} __packed;
298
299/* Bootload program and verify row command data structure */
94897619 300struct tsg_bl_flash_row_head {
5812d306
DD
301 u8 flash_array_id;
302 __le16 flash_row_id;
303 u8 flash_data[0];
304} __packed;
305
94897619 306struct pip_app_cmd_head {
6972a859
DD
307 __le16 addr; /* Output report register address, must be 0004h */
308 /* Size of packet not including output report register address */
309 __le16 length;
310 u8 report_id; /* Application output report id, must be 2Fh */
311 u8 rsvd; /* Reserved, must be 0 */
312 /*
313 * Bit 7: reserved, must be 0.
314 * Bit 6-0: command code.
315 */
316 u8 cmd_code;
317 u8 parameter_data[0]; /* Parameter data variable based on cmd_code */
318} __packed;
319
7debcbb1 320/* Application get/set parameter command data structure */
6972a859
DD
321struct gen5_app_set_parameter_data {
322 u8 parameter_id;
323 u8 parameter_size;
324 __le32 value;
325} __packed;
326
327struct gen5_app_get_parameter_data {
328 u8 parameter_id;
329} __packed;
330
6499d390
DD
331struct gen5_retrieve_panel_scan_data {
332 __le16 read_offset;
333 __le16 read_elements;
334 u8 data_id;
335} __packed;
336
94897619
DD
337u8 pip_read_sys_info[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 };
338u8 pip_bl_read_app_info[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00,
339 0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17
340 };
5812d306 341
94897619 342static u8 cyapa_pip_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03,
5812d306
DD
343 0xff, 0xfe, 0xfd, 0x5a };
344
94897619 345int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa)
6972a859 346{
94897619 347 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859 348
94897619
DD
349 init_completion(&pip->cmd_ready);
350 atomic_set(&pip->cmd_issued, 0);
351 mutex_init(&pip->cmd_lock);
6972a859 352
94897619
DD
353 pip->resp_sort_func = NULL;
354 pip->in_progress_cmd = PIP_INVALID_CMD;
355 pip->resp_data = NULL;
356 pip->resp_len = NULL;
6972a859
DD
357
358 cyapa->dev_pwr_mode = UNINIT_PWR_MODE;
359 cyapa->dev_sleep_time = UNINIT_SLEEP_TIME;
360
361 return 0;
362}
363
364/* Return negative errno, or else the number of bytes read. */
94897619 365ssize_t cyapa_i2c_pip_read(struct cyapa *cyapa, u8 *buf, size_t size)
6972a859
DD
366{
367 int ret;
368
369 if (size == 0)
370 return 0;
371
372 if (!buf || size > CYAPA_REG_MAP_SIZE)
373 return -EINVAL;
374
375 ret = i2c_master_recv(cyapa->client, buf, size);
376
377 if (ret != size)
378 return (ret < 0) ? ret : -EIO;
6972a859
DD
379 return size;
380}
381
382/**
383 * Return a negative errno code else zero on success.
384 */
94897619 385ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size)
6972a859
DD
386{
387 int ret;
388
389 if (!buf || !size)
390 return -EINVAL;
391
392 ret = i2c_master_send(cyapa->client, buf, size);
393
394 if (ret != size)
395 return (ret < 0) ? ret : -EIO;
396
397 return 0;
398}
399
400/**
401 * This function is aimed to dump all not read data in Gen5 trackpad
402 * before send any command, otherwise, the interrupt line will be blocked.
403 */
94897619 404int cyapa_empty_pip_output_data(struct cyapa *cyapa,
6972a859
DD
405 u8 *buf, int *len, cb_sort func)
406{
94897619 407 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
408 int length;
409 int report_count;
410 int empty_count;
411 int buf_len;
412 int error;
413
414 buf_len = 0;
415 if (len) {
416 buf_len = (*len < CYAPA_REG_MAP_SIZE) ?
417 *len : CYAPA_REG_MAP_SIZE;
418 *len = 0;
419 }
420
421 report_count = 8; /* max 7 pending data before command response data */
422 empty_count = 0;
423 do {
424 /*
425 * Depending on testing in cyapa driver, there are max 5 "02 00"
426 * packets between two valid buffered data report in firmware.
427 * So in order to dump all buffered data out and
428 * make interrupt line release for reassert again,
429 * we must set the empty_count check value bigger than 5 to
430 * make it work. Otherwise, in some situation,
431 * the interrupt line may unable to reactive again,
432 * which will cause trackpad device unable to
433 * report data any more.
434 * for example, it may happen in EFT and ESD testing.
435 */
436 if (empty_count > 5)
437 return 0;
438
94897619
DD
439 error = cyapa_i2c_pip_read(cyapa, pip->empty_buf,
440 PIP_RESP_LENGTH_SIZE);
6972a859
DD
441 if (error < 0)
442 return error;
443
94897619
DD
444 length = get_unaligned_le16(pip->empty_buf);
445 if (length == PIP_RESP_LENGTH_SIZE) {
6972a859
DD
446 empty_count++;
447 continue;
448 } else if (length > CYAPA_REG_MAP_SIZE) {
449 /* Should not happen */
450 return -EINVAL;
451 } else if (length == 0) {
452 /* Application or bootloader launch data polled out. */
94897619 453 length = PIP_RESP_LENGTH_SIZE;
6972a859 454 if (buf && buf_len && func &&
94897619 455 func(cyapa, pip->empty_buf, length)) {
6972a859 456 length = min(buf_len, length);
94897619 457 memcpy(buf, pip->empty_buf, length);
6972a859
DD
458 *len = length;
459 /* Response found, success. */
460 return 0;
461 }
462 continue;
463 }
464
94897619 465 error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length);
6972a859
DD
466 if (error < 0)
467 return error;
468
469 report_count--;
470 empty_count = 0;
94897619
DD
471 length = get_unaligned_le16(pip->empty_buf);
472 if (length <= PIP_RESP_LENGTH_SIZE) {
6972a859
DD
473 empty_count++;
474 } else if (buf && buf_len && func &&
94897619 475 func(cyapa, pip->empty_buf, length)) {
6972a859 476 length = min(buf_len, length);
94897619 477 memcpy(buf, pip->empty_buf, length);
6972a859
DD
478 *len = length;
479 /* Response found, success. */
480 return 0;
481 }
482
483 error = -EINVAL;
484 } while (report_count);
485
486 return error;
487}
488
489static int cyapa_do_i2c_pip_cmd_irq_sync(
490 struct cyapa *cyapa,
491 u8 *cmd, size_t cmd_len,
492 unsigned long timeout)
493{
94897619 494 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
495 int error;
496
497 /* Wait for interrupt to set ready completion */
94897619 498 init_completion(&pip->cmd_ready);
6972a859 499
94897619 500 atomic_inc(&pip->cmd_issued);
6972a859
DD
501 error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
502 if (error) {
94897619 503 atomic_dec(&pip->cmd_issued);
6972a859
DD
504 return (error < 0) ? error : -EIO;
505 }
506
507 /* Wait for interrupt to indicate command is completed. */
94897619 508 timeout = wait_for_completion_timeout(&pip->cmd_ready,
6972a859
DD
509 msecs_to_jiffies(timeout));
510 if (timeout == 0) {
94897619 511 atomic_dec(&pip->cmd_issued);
6972a859
DD
512 return -ETIMEDOUT;
513 }
514
515 return 0;
516}
517
518static int cyapa_do_i2c_pip_cmd_polling(
519 struct cyapa *cyapa,
520 u8 *cmd, size_t cmd_len,
521 u8 *resp_data, int *resp_len,
522 unsigned long timeout,
523 cb_sort func)
524{
94897619 525 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
526 int tries;
527 int length;
528 int error;
529
94897619 530 atomic_inc(&pip->cmd_issued);
6972a859
DD
531 error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len);
532 if (error) {
94897619 533 atomic_dec(&pip->cmd_issued);
6972a859
DD
534 return error < 0 ? error : -EIO;
535 }
536
537 length = resp_len ? *resp_len : 0;
538 if (resp_data && resp_len && length != 0 && func) {
539 tries = timeout / 5;
540 do {
541 usleep_range(3000, 5000);
542 *resp_len = length;
543 error = cyapa_empty_pip_output_data(cyapa,
544 resp_data, resp_len, func);
545 if (error || *resp_len == 0)
546 continue;
547 else
548 break;
549 } while (--tries > 0);
550 if ((error || *resp_len == 0) || tries <= 0)
551 error = error ? error : -ETIMEDOUT;
552 }
553
94897619 554 atomic_dec(&pip->cmd_issued);
6972a859
DD
555 return error;
556}
557
94897619 558int cyapa_i2c_pip_cmd_irq_sync(
6972a859
DD
559 struct cyapa *cyapa,
560 u8 *cmd, int cmd_len,
561 u8 *resp_data, int *resp_len,
562 unsigned long timeout,
563 cb_sort func,
564 bool irq_mode)
565{
94897619 566 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
567 int error;
568
569 if (!cmd || !cmd_len)
570 return -EINVAL;
571
572 /* Commands must be serialized. */
94897619 573 error = mutex_lock_interruptible(&pip->cmd_lock);
6972a859
DD
574 if (error)
575 return error;
576
94897619
DD
577 pip->resp_sort_func = func;
578 pip->resp_data = resp_data;
579 pip->resp_len = resp_len;
6972a859 580
94897619
DD
581 if (cmd_len >= PIP_MIN_APP_CMD_LENGTH &&
582 cmd[4] == PIP_APP_CMD_REPORT_ID) {
6972a859 583 /* Application command */
94897619
DD
584 pip->in_progress_cmd = cmd[6] & 0x7f;
585 } else if (cmd_len >= PIP_MIN_BL_CMD_LENGTH &&
586 cmd[4] == PIP_BL_CMD_REPORT_ID) {
6972a859 587 /* Bootloader command */
94897619 588 pip->in_progress_cmd = cmd[7];
6972a859
DD
589 }
590
591 /* Send command data, wait and read output response data's length. */
592 if (irq_mode) {
94897619 593 pip->is_irq_mode = true;
6972a859
DD
594 error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
595 timeout);
596 if (error == -ETIMEDOUT && resp_data &&
597 resp_len && *resp_len != 0 && func) {
598 /*
599 * For some old version, there was no interrupt for
600 * the command response data, so need to poll here
601 * to try to get the response data.
602 */
603 error = cyapa_empty_pip_output_data(cyapa,
604 resp_data, resp_len, func);
605 if (error || *resp_len == 0)
606 error = error ? error : -ETIMEDOUT;
607 }
608 } else {
94897619 609 pip->is_irq_mode = false;
6972a859
DD
610 error = cyapa_do_i2c_pip_cmd_polling(cyapa, cmd, cmd_len,
611 resp_data, resp_len, timeout, func);
612 }
613
94897619
DD
614 pip->resp_sort_func = NULL;
615 pip->resp_data = NULL;
616 pip->resp_len = NULL;
617 pip->in_progress_cmd = PIP_INVALID_CMD;
6972a859 618
94897619 619 mutex_unlock(&pip->cmd_lock);
6972a859
DD
620 return error;
621}
622
94897619 623bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa,
6972a859
DD
624 u8 *data, int len)
625{
94897619 626 if (!data || len < PIP_MIN_BL_RESP_LENGTH)
6972a859
DD
627 return false;
628
629 /* Bootloader input report id 30h */
94897619
DD
630 if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_BL_RESP_REPORT_ID &&
631 data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY &&
632 data[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY)
6972a859
DD
633 return true;
634
635 return false;
636}
637
94897619 638bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa,
6972a859
DD
639 u8 *data, int len)
640{
94897619 641 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
642 int resp_len;
643
94897619 644 if (!data || len < PIP_MIN_APP_RESP_LENGTH)
6972a859
DD
645 return false;
646
94897619
DD
647 if (data[PIP_RESP_REPORT_ID_OFFSET] == PIP_APP_RESP_REPORT_ID &&
648 data[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY) {
649 resp_len = get_unaligned_le16(&data[PIP_RESP_LENGTH_OFFSET]);
650 if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == 0x00 &&
651 resp_len == PIP_UNSUPPORTED_CMD_RESP_LENGTH &&
652 data[5] == pip->in_progress_cmd) {
6972a859
DD
653 /* Unsupported command code */
654 return false;
94897619
DD
655 } else if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) ==
656 pip->in_progress_cmd) {
6972a859
DD
657 /* Correct command response received */
658 return true;
659 }
660 }
661
662 return false;
663}
664
94897619 665static bool cyapa_sort_pip_application_launch_data(struct cyapa *cyapa,
5812d306
DD
666 u8 *buf, int len)
667{
94897619 668 if (buf == NULL || len < PIP_RESP_LENGTH_SIZE)
5812d306
DD
669 return false;
670
671 /*
672 * After reset or power on, trackpad device always sets to 0x00 0x00
673 * to indicate a reset or power on event.
674 */
675 if (buf[0] == 0 && buf[1] == 0)
676 return true;
677
678 return false;
679}
680
94897619 681static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa *cyapa,
6972a859
DD
682 u8 *buf, int len)
683{
684 int resp_len;
685 int max_output_len;
686
687 /* Check hid descriptor. */
94897619 688 if (len != PIP_HID_DESCRIPTOR_SIZE)
6972a859
DD
689 return false;
690
94897619 691 resp_len = get_unaligned_le16(&buf[PIP_RESP_LENGTH_OFFSET]);
6972a859 692 max_output_len = get_unaligned_le16(&buf[16]);
94897619
DD
693 if (resp_len == PIP_HID_DESCRIPTOR_SIZE) {
694 if (buf[PIP_RESP_REPORT_ID_OFFSET] == PIP_HID_BL_REPORT_ID &&
6972a859
DD
695 max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
696 /* BL mode HID Descriptor */
697 return true;
94897619
DD
698 } else if ((buf[PIP_RESP_REPORT_ID_OFFSET] ==
699 PIP_HID_APP_REPORT_ID) &&
6972a859
DD
700 max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
701 /* APP mode HID Descriptor */
702 return true;
703 }
704 }
705
706 return false;
707}
708
94897619 709static bool cyapa_sort_pip_deep_sleep_data(struct cyapa *cyapa,
6972a859
DD
710 u8 *buf, int len)
711{
94897619
DD
712 if (len == PIP_DEEP_SLEEP_RESP_LENGTH &&
713 buf[PIP_RESP_REPORT_ID_OFFSET] ==
714 PIP_APP_DEEP_SLEEP_REPORT_ID &&
715 (buf[4] & PIP_DEEP_SLEEP_OPCODE_MASK) ==
716 PIP_DEEP_SLEEP_OPCODE)
6972a859
DD
717 return true;
718 return false;
719}
720
721static int gen5_idle_state_parse(struct cyapa *cyapa)
722{
94897619 723 u8 resp_data[PIP_HID_DESCRIPTOR_SIZE];
6972a859
DD
724 int max_output_len;
725 int length;
726 u8 cmd[2];
727 int ret;
728 int error;
729
730 /*
731 * Dump all buffered data firstly for the situation
732 * when the trackpad is just power on the cyapa go here.
733 */
734 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
735
736 memset(resp_data, 0, sizeof(resp_data));
737 ret = cyapa_i2c_pip_read(cyapa, resp_data, 3);
738 if (ret != 3)
739 return ret < 0 ? ret : -EIO;
740
94897619
DD
741 length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]);
742 if (length == PIP_RESP_LENGTH_SIZE) {
743 /* Normal state of Gen5 with no data to response */
6972a859
DD
744 cyapa->gen = CYAPA_GEN5;
745
746 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
747
748 /* Read description from trackpad device */
749 cmd[0] = 0x01;
750 cmd[1] = 0x00;
94897619 751 length = PIP_HID_DESCRIPTOR_SIZE;
6972a859 752 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
94897619 753 cmd, PIP_RESP_LENGTH_SIZE,
6972a859
DD
754 resp_data, &length,
755 300,
94897619 756 cyapa_sort_gen5_hid_descriptor_data,
6972a859
DD
757 false);
758 if (error)
759 return error;
760
761 length = get_unaligned_le16(
94897619 762 &resp_data[PIP_RESP_LENGTH_OFFSET]);
6972a859 763 max_output_len = get_unaligned_le16(&resp_data[16]);
94897619
DD
764 if ((length == PIP_HID_DESCRIPTOR_SIZE ||
765 length == PIP_RESP_LENGTH_SIZE) &&
766 (resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
767 PIP_HID_BL_REPORT_ID) &&
6972a859
DD
768 max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
769 /* BL mode HID Description read */
770 cyapa->state = CYAPA_STATE_GEN5_BL;
94897619
DD
771 } else if ((length == PIP_HID_DESCRIPTOR_SIZE ||
772 length == PIP_RESP_LENGTH_SIZE) &&
773 (resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
774 PIP_HID_APP_REPORT_ID) &&
6972a859
DD
775 max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
776 /* APP mode HID Description read */
777 cyapa->state = CYAPA_STATE_GEN5_APP;
778 } else {
779 /* Should not happen!!! */
780 cyapa->state = CYAPA_STATE_NO_DEVICE;
781 }
782 }
783
784 return 0;
785}
786
787static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data)
788{
789 int length;
790 u8 resp_data[32];
791 int max_output_len;
792 int ret;
793
794 /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
7debcbb1 795 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
6972a859
DD
796 *
797 * Must read HID Description content through out,
798 * otherwise Gen5 trackpad cannot response next command
799 * or report any touch or button data.
800 */
801 ret = cyapa_i2c_pip_read(cyapa, resp_data,
94897619
DD
802 PIP_HID_DESCRIPTOR_SIZE);
803 if (ret != PIP_HID_DESCRIPTOR_SIZE)
6972a859 804 return ret < 0 ? ret : -EIO;
94897619 805 length = get_unaligned_le16(&resp_data[PIP_RESP_LENGTH_OFFSET]);
6972a859 806 max_output_len = get_unaligned_le16(&resp_data[16]);
94897619
DD
807 if (length == PIP_RESP_LENGTH_SIZE) {
808 if (reg_data[PIP_RESP_REPORT_ID_OFFSET] ==
809 PIP_HID_BL_REPORT_ID) {
6972a859
DD
810 /*
811 * BL mode HID Description has been previously
812 * read out.
813 */
814 cyapa->gen = CYAPA_GEN5;
815 cyapa->state = CYAPA_STATE_GEN5_BL;
816 } else {
817 /*
818 * APP mode HID Description has been previously
819 * read out.
820 */
821 cyapa->gen = CYAPA_GEN5;
822 cyapa->state = CYAPA_STATE_GEN5_APP;
823 }
94897619
DD
824 } else if (length == PIP_HID_DESCRIPTOR_SIZE &&
825 resp_data[2] == PIP_HID_BL_REPORT_ID &&
6972a859
DD
826 max_output_len == GEN5_BL_MAX_OUTPUT_LENGTH) {
827 /* BL mode HID Description read. */
828 cyapa->gen = CYAPA_GEN5;
829 cyapa->state = CYAPA_STATE_GEN5_BL;
94897619
DD
830 } else if (length == PIP_HID_DESCRIPTOR_SIZE &&
831 (resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
832 PIP_HID_APP_REPORT_ID) &&
6972a859
DD
833 max_output_len == GEN5_APP_MAX_OUTPUT_LENGTH) {
834 /* APP mode HID Description read. */
835 cyapa->gen = CYAPA_GEN5;
836 cyapa->state = CYAPA_STATE_GEN5_APP;
837 } else {
838 /* Should not happen!!! */
839 cyapa->state = CYAPA_STATE_NO_DEVICE;
840 }
841
842 return 0;
843}
844
845static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data)
846{
847 int length;
848
94897619
DD
849 length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
850 switch (reg_data[PIP_RESP_REPORT_ID_OFFSET]) {
851 case PIP_TOUCH_REPORT_ID:
852 if (length < PIP_TOUCH_REPORT_HEAD_SIZE ||
853 length > PIP_TOUCH_REPORT_MAX_SIZE)
6972a859
DD
854 return -EINVAL;
855 break;
94897619 856 case PIP_BTN_REPORT_ID:
6972a859 857 case GEN5_OLD_PUSH_BTN_REPORT_ID:
94897619
DD
858 case PIP_PUSH_BTN_REPORT_ID:
859 if (length < PIP_BTN_REPORT_HEAD_SIZE ||
860 length > PIP_BTN_REPORT_MAX_SIZE)
6972a859
DD
861 return -EINVAL;
862 break;
94897619
DD
863 case PIP_WAKEUP_EVENT_REPORT_ID:
864 if (length != PIP_WAKEUP_EVENT_SIZE)
6972a859
DD
865 return -EINVAL;
866 break;
867 default:
868 return -EINVAL;
869 }
870
871 cyapa->gen = CYAPA_GEN5;
872 cyapa->state = CYAPA_STATE_GEN5_APP;
873 return 0;
874}
875
876static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data)
877{
94897619 878 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
879 int length;
880 int ret;
881
882 /*
883 * Must read report data through out,
884 * otherwise Gen5 trackpad cannot response next command
885 * or report any touch or button data.
886 */
94897619
DD
887 length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
888 ret = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length);
6972a859
DD
889 if (ret != length)
890 return ret < 0 ? ret : -EIO;
891
94897619 892 if (length == PIP_RESP_LENGTH_SIZE) {
6972a859 893 /* Previous command has read the data through out. */
94897619
DD
894 if (reg_data[PIP_RESP_REPORT_ID_OFFSET] ==
895 PIP_BL_RESP_REPORT_ID) {
6972a859
DD
896 /* Gen5 BL command response data detected */
897 cyapa->gen = CYAPA_GEN5;
898 cyapa->state = CYAPA_STATE_GEN5_BL;
899 } else {
900 /* Gen5 APP command response data detected */
901 cyapa->gen = CYAPA_GEN5;
902 cyapa->state = CYAPA_STATE_GEN5_APP;
903 }
94897619
DD
904 } else if ((pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] ==
905 PIP_BL_RESP_REPORT_ID) &&
906 (pip->empty_buf[PIP_RESP_RSVD_OFFSET] ==
907 PIP_RESP_RSVD_KEY) &&
908 (pip->empty_buf[PIP_RESP_BL_SOP_OFFSET] ==
909 PIP_SOP_KEY) &&
910 (pip->empty_buf[length - 1] ==
911 PIP_EOP_KEY)) {
6972a859
DD
912 /* Gen5 BL command response data detected */
913 cyapa->gen = CYAPA_GEN5;
914 cyapa->state = CYAPA_STATE_GEN5_BL;
94897619
DD
915 } else if (pip->empty_buf[PIP_RESP_REPORT_ID_OFFSET] ==
916 PIP_APP_RESP_REPORT_ID &&
917 pip->empty_buf[PIP_RESP_RSVD_OFFSET] ==
918 PIP_RESP_RSVD_KEY) {
6972a859
DD
919 /* Gen5 APP command response data detected */
920 cyapa->gen = CYAPA_GEN5;
921 cyapa->state = CYAPA_STATE_GEN5_APP;
922 } else {
923 /* Should not happen!!! */
924 cyapa->state = CYAPA_STATE_NO_DEVICE;
925 }
926
927 return 0;
928}
929
930static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len)
931{
932 int length;
933
934 if (!reg_data || len < 3)
935 return -EINVAL;
936
937 cyapa->state = CYAPA_STATE_NO_DEVICE;
938
939 /* Parse based on Gen5 characteristic registers and bits */
94897619
DD
940 length = get_unaligned_le16(&reg_data[PIP_RESP_LENGTH_OFFSET]);
941 if (length == 0 || length == PIP_RESP_LENGTH_SIZE) {
6972a859 942 gen5_idle_state_parse(cyapa);
94897619
DD
943 } else if (length == PIP_HID_DESCRIPTOR_SIZE &&
944 (reg_data[2] == PIP_HID_BL_REPORT_ID ||
945 reg_data[2] == PIP_HID_APP_REPORT_ID)) {
6972a859
DD
946 gen5_hid_description_header_parse(cyapa, reg_data);
947 } else if ((length == GEN5_APP_REPORT_DESCRIPTOR_SIZE ||
948 length == GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE) &&
949 reg_data[2] == GEN5_APP_REPORT_DESCRIPTOR_ID) {
950 /* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
951 cyapa->gen = CYAPA_GEN5;
952 cyapa->state = CYAPA_STATE_GEN5_APP;
953 } else if (length == GEN5_BL_REPORT_DESCRIPTOR_SIZE &&
954 reg_data[2] == GEN5_BL_REPORT_DESCRIPTOR_ID) {
94897619 955 /* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */
6972a859
DD
956 cyapa->gen = CYAPA_GEN5;
957 cyapa->state = CYAPA_STATE_GEN5_BL;
94897619
DD
958 } else if (reg_data[2] == PIP_TOUCH_REPORT_ID ||
959 reg_data[2] == PIP_BTN_REPORT_ID ||
6972a859 960 reg_data[2] == GEN5_OLD_PUSH_BTN_REPORT_ID ||
94897619
DD
961 reg_data[2] == PIP_PUSH_BTN_REPORT_ID ||
962 reg_data[2] == PIP_WAKEUP_EVENT_REPORT_ID) {
6972a859 963 gen5_report_data_header_parse(cyapa, reg_data);
94897619
DD
964 } else if (reg_data[2] == PIP_BL_RESP_REPORT_ID ||
965 reg_data[2] == PIP_APP_RESP_REPORT_ID) {
6972a859
DD
966 gen5_cmd_resp_header_parse(cyapa, reg_data);
967 }
968
969 if (cyapa->gen == CYAPA_GEN5) {
970 /*
971 * Must read the content (e.g.: report description and so on)
972 * from trackpad device throughout. Otherwise,
973 * Gen5 trackpad cannot response to next command or
974 * report any touch or button data later.
975 */
976 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
977
978 if (cyapa->state == CYAPA_STATE_GEN5_APP ||
979 cyapa->state == CYAPA_STATE_GEN5_BL)
980 return 0;
981 }
982
983 return -EAGAIN;
984}
985
94897619
DD
986static struct cyapa_tsg_bin_image_data_record *
987cyapa_get_image_record_data_num(const struct firmware *fw,
988 int *record_num)
989{
990 int head_size;
991
992 head_size = fw->data[0] + 1;
993 *record_num = (fw->size - head_size) /
994 sizeof(struct cyapa_tsg_bin_image_data_record);
995 return (struct cyapa_tsg_bin_image_data_record *)&fw->data[head_size];
996}
997
998int cyapa_pip_bl_initiate(struct cyapa *cyapa, const struct firmware *fw)
5812d306 999{
94897619
DD
1000 struct cyapa_tsg_bin_image_data_record *image_records;
1001 struct pip_bl_cmd_head *bl_cmd_head;
1002 struct pip_bl_packet_start *bl_packet_start;
1003 struct pip_bl_initiate_cmd_data *cmd_data;
1004 struct pip_bl_packet_end *bl_packet_end;
5812d306
DD
1005 u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
1006 int cmd_len;
1007 u16 cmd_data_len;
1008 u16 cmd_crc = 0;
1009 u16 meta_data_crc = 0;
1010 u8 resp_data[11];
1011 int resp_len;
1012 int records_num;
1013 u8 *data;
1014 int error;
1015
1016 /* Try to dump all buffered report data before any send command. */
1017 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1018
1019 memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
94897619 1020 bl_cmd_head = (struct pip_bl_cmd_head *)cmd;
5812d306 1021 cmd_data_len = CYAPA_TSG_BL_KEY_SIZE + CYAPA_TSG_FLASH_MAP_BLOCK_SIZE;
94897619
DD
1022 cmd_len = sizeof(struct pip_bl_cmd_head) + cmd_data_len +
1023 sizeof(struct pip_bl_packet_end);
5812d306 1024
94897619 1025 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr);
5812d306 1026 put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length);
94897619 1027 bl_cmd_head->report_id = PIP_BL_CMD_REPORT_ID;
5812d306
DD
1028
1029 bl_packet_start = &bl_cmd_head->packet_start;
94897619
DD
1030 bl_packet_start->sop = PIP_SOP_KEY;
1031 bl_packet_start->cmd_code = PIP_BL_CMD_INITIATE_BL;
5812d306
DD
1032 /* 8 key bytes and 128 bytes block size */
1033 put_unaligned_le16(cmd_data_len, &bl_packet_start->data_length);
1034
94897619
DD
1035 cmd_data = (struct pip_bl_initiate_cmd_data *)bl_cmd_head->data;
1036 memcpy(cmd_data->key, cyapa_pip_bl_cmd_key, CYAPA_TSG_BL_KEY_SIZE);
1037
1038 image_records = cyapa_get_image_record_data_num(fw, &records_num);
5812d306 1039
5812d306 1040 /* APP_INTEGRITY row is always the last row block */
94897619 1041 data = image_records[records_num - 1].record_data;
5812d306
DD
1042 memcpy(cmd_data->metadata_raw_parameter, data,
1043 CYAPA_TSG_FLASH_MAP_METADATA_SIZE);
1044
1045 meta_data_crc = crc_itu_t(0xffff, cmd_data->metadata_raw_parameter,
1046 CYAPA_TSG_FLASH_MAP_METADATA_SIZE);
1047 put_unaligned_le16(meta_data_crc, &cmd_data->metadata_crc);
1048
94897619 1049 bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data +
5812d306
DD
1050 cmd_data_len);
1051 cmd_crc = crc_itu_t(0xffff, (u8 *)bl_packet_start,
94897619 1052 sizeof(struct pip_bl_packet_start) + cmd_data_len);
5812d306 1053 put_unaligned_le16(cmd_crc, &bl_packet_end->crc);
94897619 1054 bl_packet_end->eop = PIP_EOP_KEY;
5812d306
DD
1055
1056 resp_len = sizeof(resp_data);
1057 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1058 cmd, cmd_len,
1059 resp_data, &resp_len, 12000,
94897619
DD
1060 cyapa_sort_tsg_pip_bl_resp_data, true);
1061 if (error || resp_len != PIP_BL_INITIATE_RESP_LEN ||
1062 resp_data[2] != PIP_BL_RESP_REPORT_ID ||
1063 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
5812d306
DD
1064 return error ? error : -EAGAIN;
1065
1066 return 0;
1067}
1068
94897619 1069static bool cyapa_sort_pip_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len)
6972a859 1070{
94897619 1071 if (buf == NULL || len < PIP_RESP_LENGTH_SIZE)
6972a859
DD
1072 return false;
1073
1074 if (buf[0] == 0 && buf[1] == 0)
1075 return true;
1076
1077 /* Exit bootloader failed for some reason. */
94897619
DD
1078 if (len == PIP_BL_FAIL_EXIT_RESP_LEN &&
1079 buf[PIP_RESP_REPORT_ID_OFFSET] ==
1080 PIP_BL_RESP_REPORT_ID &&
1081 buf[PIP_RESP_RSVD_OFFSET] == PIP_RESP_RSVD_KEY &&
1082 buf[PIP_RESP_BL_SOP_OFFSET] == PIP_SOP_KEY &&
1083 buf[10] == PIP_EOP_KEY)
6972a859
DD
1084 return true;
1085
1086 return false;
1087}
1088
94897619 1089int cyapa_pip_bl_exit(struct cyapa *cyapa)
6972a859
DD
1090{
1091
1092 u8 bl_gen5_bl_exit[] = { 0x04, 0x00,
1093 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00,
1094 0x20, 0xc7, 0x17
1095 };
1096 u8 resp_data[11];
1097 int resp_len;
1098 int error;
1099
1100 resp_len = sizeof(resp_data);
1101 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1102 bl_gen5_bl_exit, sizeof(bl_gen5_bl_exit),
1103 resp_data, &resp_len,
94897619 1104 5000, cyapa_sort_pip_bl_exit_data, false);
6972a859
DD
1105 if (error)
1106 return error;
1107
94897619
DD
1108 if (resp_len == PIP_BL_FAIL_EXIT_RESP_LEN ||
1109 resp_data[PIP_RESP_REPORT_ID_OFFSET] ==
1110 PIP_BL_RESP_REPORT_ID)
6972a859
DD
1111 return -EAGAIN;
1112
1113 if (resp_data[0] == 0x00 && resp_data[1] == 0x00)
1114 return 0;
1115
1116 return -ENODEV;
1117}
1118
94897619 1119int cyapa_pip_bl_enter(struct cyapa *cyapa)
5812d306
DD
1120{
1121 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 };
1122 u8 resp_data[2];
1123 int resp_len;
1124 int error;
1125
1126 error = cyapa_poll_state(cyapa, 500);
1127 if (error < 0)
1128 return error;
5812d306 1129
94897619
DD
1130 /* Already in bootloader mode, Skipping exit. */
1131 if (cyapa_is_pip_bl_mode(cyapa))
5812d306 1132 return 0;
94897619
DD
1133 else if (!cyapa_is_pip_app_mode(cyapa))
1134 return -EINVAL;
5812d306
DD
1135
1136 /* Try to dump all buffered report data before any send command. */
1137 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1138
1139 /*
1140 * Send bootloader enter command to trackpad device,
1141 * after enter bootloader, the response data is two bytes of 0x00 0x00.
1142 */
1143 resp_len = sizeof(resp_data);
1144 memset(resp_data, 0, resp_len);
1145 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1146 cmd, sizeof(cmd),
1147 resp_data, &resp_len,
94897619 1148 5000, cyapa_sort_pip_application_launch_data,
5812d306
DD
1149 true);
1150 if (error || resp_data[0] != 0x00 || resp_data[1] != 0x00)
1151 return error < 0 ? error : -EAGAIN;
1152
1153 cyapa->operational = false;
94897619
DD
1154 if (cyapa->gen == CYAPA_GEN5)
1155 cyapa->state = CYAPA_STATE_GEN5_BL;
c2c06c41
DD
1156 else if (cyapa->gen == CYAPA_GEN6)
1157 cyapa->state = CYAPA_STATE_GEN6_BL;
1158 return 0;
1159}
1160
1161static int cyapa_pip_fw_head_check(struct cyapa *cyapa,
1162 struct cyapa_tsg_bin_image_head *image_head)
1163{
1164 if (image_head->head_size != 0x0C && image_head->head_size != 0x12)
1165 return -EINVAL;
1166
1167 switch (cyapa->gen) {
1168 case CYAPA_GEN6:
1169 if (image_head->family_id != 0x9B ||
1170 image_head->silicon_id_hi != 0x0B)
1171 return -EINVAL;
1172 break;
1173 case CYAPA_GEN5:
1174 /* Gen5 without proximity support. */
1175 if (cyapa->platform_ver < 2) {
1176 if (image_head->head_size == 0x0C)
1177 break;
1178 return -EINVAL;
1179 }
1180
1181 if (image_head->family_id != 0x91 ||
1182 image_head->silicon_id_hi != 0x02)
1183 return -EINVAL;
1184 break;
1185 default:
1186 return -EINVAL;
1187 }
1188
5812d306
DD
1189 return 0;
1190}
1191
94897619 1192int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw)
5812d306
DD
1193{
1194 struct device *dev = &cyapa->client->dev;
94897619 1195 struct cyapa_tsg_bin_image_data_record *image_records;
2be7256f 1196 const struct cyapa_tsg_bin_image_data_record *app_integrity;
94897619
DD
1197 const struct tsg_bl_metadata_row_params *metadata;
1198 int flash_records_count;
2be7256f
DT
1199 u32 fw_app_start, fw_upgrade_start;
1200 u16 fw_app_len, fw_upgrade_len;
1201 u16 app_crc;
1202 u16 app_integrity_crc;
5812d306
DD
1203 int i;
1204
c2c06c41
DD
1205 /* Verify the firmware image not miss-used for Gen5 and Gen6. */
1206 if (cyapa_pip_fw_head_check(cyapa,
1207 (struct cyapa_tsg_bin_image_head *)fw->data)) {
1208 dev_err(dev, "%s: firmware image not match TP device.\n",
1209 __func__);
1210 return -EINVAL;
1211 }
1212
94897619
DD
1213 image_records =
1214 cyapa_get_image_record_data_num(fw, &flash_records_count);
5812d306 1215
2be7256f
DT
1216 /*
1217 * APP_INTEGRITY row is always the last row block,
1218 * and the row id must be 0x01ff.
1219 */
94897619 1220 app_integrity = &image_records[flash_records_count - 1];
2be7256f
DT
1221
1222 if (app_integrity->flash_array_id != 0x00 ||
1223 get_unaligned_be16(&app_integrity->row_number) != 0x01ff) {
5812d306
DD
1224 dev_err(dev, "%s: invalid app_integrity data.\n", __func__);
1225 return -EINVAL;
1226 }
2be7256f
DT
1227
1228 metadata = (const void *)app_integrity->record_data;
5812d306
DD
1229
1230 /* Verify app_integrity crc */
2be7256f
DT
1231 app_integrity_crc = crc_itu_t(0xffff, app_integrity->record_data,
1232 CYAPA_TSG_APP_INTEGRITY_SIZE);
1233 if (app_integrity_crc != get_unaligned_le16(&metadata->metadata_crc)) {
5812d306
DD
1234 dev_err(dev, "%s: invalid app_integrity crc.\n", __func__);
1235 return -EINVAL;
1236 }
1237
2be7256f
DT
1238 fw_app_start = get_unaligned_le32(&metadata->app_start);
1239 fw_app_len = get_unaligned_le16(&metadata->app_len);
1240 fw_upgrade_start = get_unaligned_le32(&metadata->upgrade_start);
1241 fw_upgrade_len = get_unaligned_le16(&metadata->upgrade_len);
1242
1243 if (fw_app_start % CYAPA_TSG_FW_ROW_SIZE ||
1244 fw_app_len % CYAPA_TSG_FW_ROW_SIZE ||
1245 fw_upgrade_start % CYAPA_TSG_FW_ROW_SIZE ||
1246 fw_upgrade_len % CYAPA_TSG_FW_ROW_SIZE) {
1247 dev_err(dev, "%s: invalid image alignment.\n", __func__);
1248 return -EINVAL;
1249 }
1250
94897619 1251 /* Verify application image CRC. */
2be7256f
DT
1252 app_crc = 0xffffU;
1253 for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) {
94897619
DD
1254 const u8 *data = image_records[i].record_data;
1255
5812d306
DD
1256 app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE);
1257 }
1258
2be7256f 1259 if (app_crc != get_unaligned_le16(&metadata->app_crc)) {
5812d306
DD
1260 dev_err(dev, "%s: invalid firmware app crc check.\n", __func__);
1261 return -EINVAL;
1262 }
1263
1264 return 0;
1265}
1266
94897619 1267static int cyapa_pip_write_fw_block(struct cyapa *cyapa,
5812d306
DD
1268 struct cyapa_tsg_bin_image_data_record *flash_record)
1269{
94897619
DD
1270 struct pip_bl_cmd_head *bl_cmd_head;
1271 struct pip_bl_packet_start *bl_packet_start;
1272 struct tsg_bl_flash_row_head *flash_row_head;
1273 struct pip_bl_packet_end *bl_packet_end;
5812d306
DD
1274 u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
1275 u16 cmd_len;
1276 u8 flash_array_id;
1277 u16 flash_row_id;
1278 u16 record_len;
1279 u8 *record_data;
1280 u16 data_len;
1281 u16 crc;
1282 u8 resp_data[11];
1283 int resp_len;
1284 int error;
1285
1286 flash_array_id = flash_record->flash_array_id;
1287 flash_row_id = get_unaligned_be16(&flash_record->row_number);
1288 record_len = get_unaligned_be16(&flash_record->record_len);
1289 record_data = flash_record->record_data;
1290
1291 memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
94897619 1292 bl_cmd_head = (struct pip_bl_cmd_head *)cmd;
5812d306 1293 bl_packet_start = &bl_cmd_head->packet_start;
94897619
DD
1294 cmd_len = sizeof(struct pip_bl_cmd_head) +
1295 sizeof(struct tsg_bl_flash_row_head) +
5812d306 1296 CYAPA_TSG_FLASH_MAP_BLOCK_SIZE +
94897619 1297 sizeof(struct pip_bl_packet_end);
5812d306 1298
94897619 1299 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &bl_cmd_head->addr);
5812d306
DD
1300 /* Don't include 2 bytes register address */
1301 put_unaligned_le16(cmd_len - 2, &bl_cmd_head->length);
94897619
DD
1302 bl_cmd_head->report_id = PIP_BL_CMD_REPORT_ID;
1303 bl_packet_start->sop = PIP_SOP_KEY;
1304 bl_packet_start->cmd_code = PIP_BL_CMD_PROGRAM_VERIFY_ROW;
5812d306
DD
1305
1306 /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */
94897619 1307 data_len = sizeof(struct tsg_bl_flash_row_head) + record_len;
5812d306
DD
1308 put_unaligned_le16(data_len, &bl_packet_start->data_length);
1309
94897619 1310 flash_row_head = (struct tsg_bl_flash_row_head *)bl_cmd_head->data;
5812d306
DD
1311 flash_row_head->flash_array_id = flash_array_id;
1312 put_unaligned_le16(flash_row_id, &flash_row_head->flash_row_id);
1313 memcpy(flash_row_head->flash_data, record_data, record_len);
1314
94897619 1315 bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data +
5812d306
DD
1316 data_len);
1317 crc = crc_itu_t(0xffff, (u8 *)bl_packet_start,
94897619 1318 sizeof(struct pip_bl_packet_start) + data_len);
5812d306 1319 put_unaligned_le16(crc, &bl_packet_end->crc);
94897619 1320 bl_packet_end->eop = PIP_EOP_KEY;
5812d306
DD
1321
1322 resp_len = sizeof(resp_data);
1323 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
1324 resp_data, &resp_len,
94897619
DD
1325 500, cyapa_sort_tsg_pip_bl_resp_data, true);
1326 if (error || resp_len != PIP_BL_BLOCK_WRITE_RESP_LEN ||
1327 resp_data[2] != PIP_BL_RESP_REPORT_ID ||
1328 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
5812d306
DD
1329 return error < 0 ? error : -EAGAIN;
1330
1331 return 0;
1332}
1333
94897619 1334int cyapa_pip_do_fw_update(struct cyapa *cyapa,
5812d306
DD
1335 const struct firmware *fw)
1336{
1337 struct device *dev = &cyapa->client->dev;
94897619 1338 struct cyapa_tsg_bin_image_data_record *image_records;
5812d306
DD
1339 int flash_records_count;
1340 int i;
1341 int error;
1342
1343 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1344
94897619
DD
1345 image_records =
1346 cyapa_get_image_record_data_num(fw, &flash_records_count);
1347
5812d306
DD
1348 /*
1349 * The last flash row 0x01ff has been written through bl_initiate
1350 * command, so DO NOT write flash 0x01ff to trackpad device.
1351 */
1352 for (i = 0; i < (flash_records_count - 1); i++) {
94897619 1353 error = cyapa_pip_write_fw_block(cyapa, &image_records[i]);
5812d306
DD
1354 if (error) {
1355 dev_err(dev, "%s: Gen5 FW update aborted: %d\n",
1356 __func__, error);
1357 return error;
1358 }
1359 }
1360
1361 return 0;
1362}
1363
6972a859
DD
1364static int cyapa_gen5_change_power_state(struct cyapa *cyapa, u8 power_state)
1365{
1366 u8 cmd[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 };
1367 u8 resp_data[6];
1368 int resp_len;
1369 int error;
1370
1371 cmd[7] = power_state;
1372 resp_len = sizeof(resp_data);
1373 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
1374 resp_data, &resp_len,
94897619 1375 500, cyapa_sort_tsg_pip_app_resp_data, false);
6972a859 1376 if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x08) ||
94897619 1377 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
6972a859
DD
1378 return error < 0 ? error : -EINVAL;
1379
1380 return 0;
1381}
1382
1383static int cyapa_gen5_set_interval_time(struct cyapa *cyapa,
1384 u8 parameter_id, u16 interval_time)
1385{
94897619 1386 struct pip_app_cmd_head *app_cmd_head;
6972a859
DD
1387 struct gen5_app_set_parameter_data *parameter_data;
1388 u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
1389 int cmd_len;
1390 u8 resp_data[7];
1391 int resp_len;
1392 u8 parameter_size;
1393 int error;
1394
1395 memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
94897619 1396 app_cmd_head = (struct pip_app_cmd_head *)cmd;
6972a859
DD
1397 parameter_data = (struct gen5_app_set_parameter_data *)
1398 app_cmd_head->parameter_data;
94897619 1399 cmd_len = sizeof(struct pip_app_cmd_head) +
6972a859
DD
1400 sizeof(struct gen5_app_set_parameter_data);
1401
1402 switch (parameter_id) {
1403 case GEN5_PARAMETER_ACT_INTERVL_ID:
1404 parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE;
1405 break;
1406 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID:
1407 parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE;
1408 break;
1409 case GEN5_PARAMETER_LP_INTRVL_ID:
1410 parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE;
1411 break;
1412 default:
1413 return -EINVAL;
1414 }
1415
94897619 1416 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
6972a859
DD
1417 /*
1418 * Don't include unused parameter value bytes and
1419 * 2 bytes register address.
1420 */
1421 put_unaligned_le16(cmd_len - (4 - parameter_size) - 2,
1422 &app_cmd_head->length);
94897619 1423 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6972a859
DD
1424 app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER;
1425 parameter_data->parameter_id = parameter_id;
1426 parameter_data->parameter_size = parameter_size;
1427 put_unaligned_le32((u32)interval_time, &parameter_data->value);
1428 resp_len = sizeof(resp_data);
1429 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
1430 resp_data, &resp_len,
94897619 1431 500, cyapa_sort_tsg_pip_app_resp_data, false);
6972a859
DD
1432 if (error || resp_data[5] != parameter_id ||
1433 resp_data[6] != parameter_size ||
1434 !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER))
1435 return error < 0 ? error : -EINVAL;
1436
1437 return 0;
1438}
1439
1440static int cyapa_gen5_get_interval_time(struct cyapa *cyapa,
1441 u8 parameter_id, u16 *interval_time)
1442{
94897619 1443 struct pip_app_cmd_head *app_cmd_head;
6972a859
DD
1444 struct gen5_app_get_parameter_data *parameter_data;
1445 u8 cmd[CYAPA_TSG_MAX_CMD_SIZE];
1446 int cmd_len;
1447 u8 resp_data[11];
1448 int resp_len;
1449 u8 parameter_size;
1450 u16 mask, i;
1451 int error;
1452
1453 memset(cmd, 0, CYAPA_TSG_MAX_CMD_SIZE);
94897619 1454 app_cmd_head = (struct pip_app_cmd_head *)cmd;
6972a859
DD
1455 parameter_data = (struct gen5_app_get_parameter_data *)
1456 app_cmd_head->parameter_data;
94897619 1457 cmd_len = sizeof(struct pip_app_cmd_head) +
6972a859
DD
1458 sizeof(struct gen5_app_get_parameter_data);
1459
1460 *interval_time = 0;
1461 switch (parameter_id) {
1462 case GEN5_PARAMETER_ACT_INTERVL_ID:
1463 parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE;
1464 break;
1465 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID:
1466 parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE;
1467 break;
1468 case GEN5_PARAMETER_LP_INTRVL_ID:
1469 parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE;
1470 break;
1471 default:
1472 return -EINVAL;
1473 }
1474
94897619 1475 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
6972a859
DD
1476 /* Don't include 2 bytes register address */
1477 put_unaligned_le16(cmd_len - 2, &app_cmd_head->length);
94897619 1478 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6972a859
DD
1479 app_cmd_head->cmd_code = GEN5_CMD_GET_PARAMETER;
1480 parameter_data->parameter_id = parameter_id;
1481
1482 resp_len = sizeof(resp_data);
1483 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len,
1484 resp_data, &resp_len,
94897619 1485 500, cyapa_sort_tsg_pip_app_resp_data, false);
6972a859
DD
1486 if (error || resp_data[5] != parameter_id || resp_data[6] == 0 ||
1487 !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_GET_PARAMETER))
1488 return error < 0 ? error : -EINVAL;
1489
1490 mask = 0;
1491 for (i = 0; i < parameter_size; i++)
1492 mask |= (0xff << (i * 8));
1493 *interval_time = get_unaligned_le16(&resp_data[7]) & mask;
1494
1495 return 0;
1496}
1497
1498static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa)
1499{
94897619 1500 struct pip_app_cmd_head *app_cmd_head;
6972a859
DD
1501 u8 cmd[10];
1502 u8 resp_data[7];
1503 int resp_len;
1504 int error;
1505
1506 memset(cmd, 0, sizeof(cmd));
94897619 1507 app_cmd_head = (struct pip_app_cmd_head *)cmd;
6972a859 1508
94897619 1509 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
6972a859 1510 put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
94897619 1511 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6972a859
DD
1512 app_cmd_head->cmd_code = GEN5_CMD_SET_PARAMETER;
1513 app_cmd_head->parameter_data[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT;
1514 app_cmd_head->parameter_data[1] = 0x01;
1515 app_cmd_head->parameter_data[2] = 0x01;
1516 resp_len = sizeof(resp_data);
1517 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
1518 resp_data, &resp_len,
94897619 1519 500, cyapa_sort_tsg_pip_app_resp_data, false);
6972a859
DD
1520 if (error || resp_data[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT ||
1521 !VALID_CMD_RESP_HEADER(resp_data, GEN5_CMD_SET_PARAMETER) ||
1522 resp_data[6] != 0x01)
1523 return error < 0 ? error : -EINVAL;
1524
1525 return 0;
1526}
1527
945525ee
DD
1528int cyapa_pip_set_proximity(struct cyapa *cyapa, bool enable)
1529{
1530 u8 cmd[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY,
1531 (u8)!!enable
1532 };
1533 u8 resp_data[6];
1534 int resp_len;
1535 int error;
1536
1537 resp_len = sizeof(resp_data);
1538 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
1539 resp_data, &resp_len,
1540 500, cyapa_sort_tsg_pip_app_resp_data, false);
1541 if (error || !VALID_CMD_RESP_HEADER(resp_data, PIP_SET_PROXIMITY) ||
1542 !PIP_CMD_COMPLETE_SUCCESS(resp_data)) {
1543 error = (error == -ETIMEDOUT) ? -EOPNOTSUPP : error;
1544 return error < 0 ? error : -EINVAL;
1545 }
1546
1547 return 0;
1548}
1549
94897619 1550int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state)
6972a859
DD
1551{
1552 u8 cmd[] = { 0x05, 0x00, 0x00, 0x08};
1553 u8 resp_data[5];
1554 int resp_len;
1555 int error;
1556
94897619 1557 cmd[2] = state & PIP_DEEP_SLEEP_STATE_MASK;
6972a859
DD
1558 resp_len = sizeof(resp_data);
1559 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, cmd, sizeof(cmd),
1560 resp_data, &resp_len,
94897619
DD
1561 500, cyapa_sort_pip_deep_sleep_data, false);
1562 if (error || ((resp_data[3] & PIP_DEEP_SLEEP_STATE_MASK) != state))
6972a859
DD
1563 return -EINVAL;
1564
1565 return 0;
1566}
1567
1568static int cyapa_gen5_set_power_mode(struct cyapa *cyapa,
757cae5a 1569 u8 power_mode, u16 sleep_time, bool is_suspend)
6972a859
DD
1570{
1571 struct device *dev = &cyapa->client->dev;
1572 u8 power_state;
1573 int error;
1574
1575 if (cyapa->state != CYAPA_STATE_GEN5_APP)
1576 return 0;
1577
94897619 1578 if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) {
6972a859
DD
1579 /*
1580 * Assume TP in deep sleep mode when driver is loaded,
1581 * avoid driver unload and reload command IO issue caused by TP
1582 * has been set into deep sleep mode when unloading.
1583 */
94897619 1584 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF);
6972a859
DD
1585 }
1586
94897619
DD
1587 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa) &&
1588 PIP_DEV_GET_PWR_STATE(cyapa) != PWR_MODE_OFF)
6972a859
DD
1589 if (cyapa_gen5_get_interval_time(cyapa,
1590 GEN5_PARAMETER_LP_INTRVL_ID,
1591 &cyapa->dev_sleep_time) != 0)
94897619 1592 PIP_DEV_SET_SLEEP_TIME(cyapa, UNINIT_SLEEP_TIME);
6972a859 1593
94897619 1594 if (PIP_DEV_GET_PWR_STATE(cyapa) == power_mode) {
6972a859
DD
1595 if (power_mode == PWR_MODE_OFF ||
1596 power_mode == PWR_MODE_FULL_ACTIVE ||
1597 power_mode == PWR_MODE_BTN_ONLY ||
94897619 1598 PIP_DEV_GET_SLEEP_TIME(cyapa) == sleep_time) {
6972a859
DD
1599 /* Has in correct power mode state, early return. */
1600 return 0;
1601 }
1602 }
1603
1604 if (power_mode == PWR_MODE_OFF) {
94897619 1605 error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_OFF);
6972a859
DD
1606 if (error) {
1607 dev_err(dev, "enter deep sleep fail: %d\n", error);
1608 return error;
1609 }
1610
94897619 1611 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF);
6972a859
DD
1612 return 0;
1613 }
1614
1615 /*
1616 * When trackpad in power off mode, it cannot change to other power
1617 * state directly, must be wake up from sleep firstly, then
1618 * continue to do next power sate change.
1619 */
94897619
DD
1620 if (PIP_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) {
1621 error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_ON);
6972a859
DD
1622 if (error) {
1623 dev_err(dev, "deep sleep wake fail: %d\n", error);
1624 return error;
1625 }
1626 }
1627
1628 if (power_mode == PWR_MODE_FULL_ACTIVE) {
1629 error = cyapa_gen5_change_power_state(cyapa,
1630 GEN5_POWER_STATE_ACTIVE);
1631 if (error) {
1632 dev_err(dev, "change to active fail: %d\n", error);
1633 return error;
1634 }
1635
94897619 1636 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_FULL_ACTIVE);
6972a859
DD
1637 } else if (power_mode == PWR_MODE_BTN_ONLY) {
1638 error = cyapa_gen5_change_power_state(cyapa,
1639 GEN5_POWER_STATE_BTN_ONLY);
1640 if (error) {
1641 dev_err(dev, "fail to button only mode: %d\n", error);
1642 return error;
1643 }
1644
94897619 1645 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY);
6972a859
DD
1646 } else {
1647 /*
1648 * Continue to change power mode even failed to set
1649 * interval time, it won't affect the power mode change.
1650 * except the sleep interval time is not correct.
1651 */
94897619
DD
1652 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa) ||
1653 sleep_time != PIP_DEV_GET_SLEEP_TIME(cyapa))
6972a859
DD
1654 if (cyapa_gen5_set_interval_time(cyapa,
1655 GEN5_PARAMETER_LP_INTRVL_ID,
1656 sleep_time) == 0)
94897619 1657 PIP_DEV_SET_SLEEP_TIME(cyapa, sleep_time);
6972a859
DD
1658
1659 if (sleep_time <= GEN5_POWER_READY_MAX_INTRVL_TIME)
1660 power_state = GEN5_POWER_STATE_READY;
1661 else
1662 power_state = GEN5_POWER_STATE_IDLE;
1663 error = cyapa_gen5_change_power_state(cyapa, power_state);
1664 if (error) {
1665 dev_err(dev, "set power state to 0x%02x failed: %d\n",
1666 power_state, error);
1667 return error;
1668 }
1669
1670 /*
1671 * Disable pip report for a little time, firmware will
1672 * re-enable it automatically. It's used to fix the issue
1673 * that trackpad unable to report signal to wake system up
1674 * in the special situation that system is in suspending, and
1675 * at the same time, user touch trackpad to wake system up.
7debcbb1
SV
1676 * This function can avoid the data to be buffered when system
1677 * is suspending which may cause interrupt line unable to be
6972a859
DD
1678 * asserted again.
1679 */
757cae5a
DD
1680 if (is_suspend)
1681 cyapa_gen5_disable_pip_report(cyapa);
6972a859 1682
94897619 1683 PIP_DEV_SET_PWR_STATE(cyapa,
6972a859
DD
1684 cyapa_sleep_time_to_pwr_cmd(sleep_time));
1685 }
1686
1687 return 0;
1688}
1689
94897619 1690int cyapa_pip_resume_scanning(struct cyapa *cyapa)
6499d390
DD
1691{
1692 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
1693 u8 resp_data[6];
1694 int resp_len;
1695 int error;
1696
1697 /* Try to dump all buffered data before doing command. */
1698 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1699
1700 resp_len = sizeof(resp_data);
1701 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1702 cmd, sizeof(cmd),
1703 resp_data, &resp_len,
94897619 1704 500, cyapa_sort_tsg_pip_app_resp_data, true);
6499d390
DD
1705 if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x04))
1706 return -EINVAL;
1707
1708 /* Try to dump all buffered data when resuming scanning. */
1709 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1710
1711 return 0;
1712}
1713
94897619 1714int cyapa_pip_suspend_scanning(struct cyapa *cyapa)
6499d390
DD
1715{
1716 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
1717 u8 resp_data[6];
1718 int resp_len;
1719 int error;
1720
1721 /* Try to dump all buffered data before doing command. */
1722 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1723
1724 resp_len = sizeof(resp_data);
1725 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1726 cmd, sizeof(cmd),
1727 resp_data, &resp_len,
94897619 1728 500, cyapa_sort_tsg_pip_app_resp_data, true);
6499d390
DD
1729 if (error || !VALID_CMD_RESP_HEADER(resp_data, 0x03))
1730 return -EINVAL;
1731
1732 /* Try to dump all buffered data when suspending scanning. */
1733 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1734
1735 return 0;
1736}
1737
94897619 1738static int cyapa_pip_calibrate_pwcs(struct cyapa *cyapa,
daceed1e
DD
1739 u8 calibrate_sensing_mode_type)
1740{
94897619 1741 struct pip_app_cmd_head *app_cmd_head;
daceed1e
DD
1742 u8 cmd[8];
1743 u8 resp_data[6];
1744 int resp_len;
1745 int error;
1746
1747 /* Try to dump all buffered data before doing command. */
1748 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
1749
1750 memset(cmd, 0, sizeof(cmd));
94897619
DD
1751 app_cmd_head = (struct pip_app_cmd_head *)cmd;
1752 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
daceed1e 1753 put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
94897619
DD
1754 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
1755 app_cmd_head->cmd_code = PIP_CMD_CALIBRATE;
daceed1e
DD
1756 app_cmd_head->parameter_data[0] = calibrate_sensing_mode_type;
1757 resp_len = sizeof(resp_data);
1758 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1759 cmd, sizeof(cmd),
1760 resp_data, &resp_len,
94897619
DD
1761 5000, cyapa_sort_tsg_pip_app_resp_data, true);
1762 if (error || !VALID_CMD_RESP_HEADER(resp_data, PIP_CMD_CALIBRATE) ||
1763 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
daceed1e
DD
1764 return error < 0 ? error : -EAGAIN;
1765
1766 return 0;
1767}
1768
94897619 1769ssize_t cyapa_pip_do_calibrate(struct device *dev,
daceed1e
DD
1770 struct device_attribute *attr,
1771 const char *buf, size_t count)
1772{
1773 struct cyapa *cyapa = dev_get_drvdata(dev);
1774 int error, calibrate_error;
1775
1776 /* 1. Suspend Scanning*/
94897619 1777 error = cyapa_pip_suspend_scanning(cyapa);
daceed1e
DD
1778 if (error)
1779 return error;
1780
1781 /* 2. Do mutual capacitance fine calibrate. */
94897619
DD
1782 calibrate_error = cyapa_pip_calibrate_pwcs(cyapa,
1783 PIP_SENSING_MODE_MUTUAL_CAP_FINE);
daceed1e
DD
1784 if (calibrate_error)
1785 goto resume_scanning;
1786
1787 /* 3. Do self capacitance calibrate. */
94897619
DD
1788 calibrate_error = cyapa_pip_calibrate_pwcs(cyapa,
1789 PIP_SENSING_MODE_SELF_CAP);
daceed1e
DD
1790 if (calibrate_error)
1791 goto resume_scanning;
1792
1793resume_scanning:
1794 /* 4. Resume Scanning*/
94897619 1795 error = cyapa_pip_resume_scanning(cyapa);
daceed1e
DD
1796 if (error || calibrate_error)
1797 return error ? error : calibrate_error;
1798
1799 return count;
1800}
1801
6499d390
DD
1802static s32 twos_complement_to_s32(s32 value, int num_bits)
1803{
1804 if (value >> (num_bits - 1))
1805 value |= -1 << num_bits;
1806 return value;
1807}
1808
1809static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len)
1810{
1811 int data_size;
1812 bool big_endian;
1813 bool unsigned_type;
1814 s32 value;
1815
1816 data_size = (data_format & 0x07);
1817 big_endian = ((data_format & 0x10) == 0x00);
1818 unsigned_type = ((data_format & 0x20) == 0x00);
1819
1820 if (buf_len < data_size)
1821 return 0;
1822
1823 switch (data_size) {
1824 case 1:
1825 value = buf[0];
1826 break;
1827 case 2:
1828 if (big_endian)
1829 value = get_unaligned_be16(buf);
1830 else
1831 value = get_unaligned_le16(buf);
1832 break;
1833 case 4:
1834 if (big_endian)
1835 value = get_unaligned_be32(buf);
1836 else
1837 value = get_unaligned_le32(buf);
1838 break;
1839 default:
1840 /* Should not happen, just as default case here. */
1841 value = 0;
1842 break;
1843 }
1844
1845 if (!unsigned_type)
1846 value = twos_complement_to_s32(value, data_size * 8);
1847
1848 return value;
1849}
1850
1851static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa,
1852 int *electrodes_rx, int *electrodes_tx)
1853{
1854 if (cyapa->electrodes_rx != 0) {
1855 *electrodes_rx = cyapa->electrodes_rx;
1856 *electrodes_tx = (cyapa->electrodes_x == *electrodes_rx) ?
1857 cyapa->electrodes_y : cyapa->electrodes_x;
1858 } else {
1859 *electrodes_tx = min(cyapa->electrodes_x, cyapa->electrodes_y);
1860 *electrodes_rx = max(cyapa->electrodes_x, cyapa->electrodes_y);
1861 }
1862}
1863
1864/*
1865 * Read all the global mutual or self idac data or mutual or self local PWC
1866 * data based on the @idac_data_type.
1867 * If the input value of @data_size is 0, then means read global mutual or
1868 * self idac data. For read global mutual idac data, @idac_max, @idac_min and
1869 * @idac_ave are in order used to return the max value of global mutual idac
1870 * data, the min value of global mutual idac and the average value of the
1871 * global mutual idac data. For read global self idac data, @idac_max is used
1872 * to return the global self cap idac data in Rx direction, @idac_min is used
1873 * to return the global self cap idac data in Tx direction. @idac_ave is not
1874 * used.
1875 * If the input value of @data_size is not 0, than means read the mutual or
1876 * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
1877 * return the max, min and average value of the mutual or self local PWC data.
94897619 1878 * Note, in order to read mutual local PWC data, must read invoke this function
6499d390
DD
1879 * to read the mutual global idac data firstly to set the correct Rx number
1880 * value, otherwise, the read mutual idac and PWC data may not correct.
1881 */
1882static int cyapa_gen5_read_idac_data(struct cyapa *cyapa,
1883 u8 cmd_code, u8 idac_data_type, int *data_size,
1884 int *idac_max, int *idac_min, int *idac_ave)
1885{
94897619 1886 struct pip_app_cmd_head *cmd_head;
6499d390
DD
1887 u8 cmd[12];
1888 u8 resp_data[256];
1889 int resp_len;
1890 int read_len;
1891 int value;
1892 u16 offset;
1893 int read_elements;
1894 bool read_global_idac;
1895 int sum, count, max_element_cnt;
1896 int tmp_max, tmp_min, tmp_ave, tmp_sum, tmp_count;
1897 int electrodes_rx, electrodes_tx;
1898 int i;
1899 int error;
1900
94897619 1901 if (cmd_code != PIP_RETRIEVE_DATA_STRUCTURE ||
6499d390
DD
1902 (idac_data_type != GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
1903 idac_data_type != GEN5_RETRIEVE_SELF_CAP_PWC_DATA) ||
1904 !data_size || !idac_max || !idac_min || !idac_ave)
1905 return -EINVAL;
1906
1907 *idac_max = INT_MIN;
1908 *idac_min = INT_MAX;
1909 sum = count = tmp_count = 0;
1910 electrodes_rx = electrodes_tx = 0;
1911 if (*data_size == 0) {
1912 /*
1913 * Read global idac values firstly.
1914 * Currently, no idac data exceed 4 bytes.
1915 */
1916 read_global_idac = true;
1917 offset = 0;
1918 *data_size = 4;
1919 tmp_max = INT_MIN;
1920 tmp_min = INT_MAX;
1921 tmp_ave = tmp_sum = tmp_count = 0;
1922
1923 if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
1924 if (cyapa->aligned_electrodes_rx == 0) {
1925 cyapa_gen5_guess_electrodes(cyapa,
1926 &electrodes_rx, &electrodes_tx);
1927 cyapa->aligned_electrodes_rx =
1928 (electrodes_rx + 3) & ~3u;
1929 }
1930 max_element_cnt =
1931 (cyapa->aligned_electrodes_rx + 7) & ~7u;
1932 } else {
1933 max_element_cnt = 2;
1934 }
1935 } else {
1936 read_global_idac = false;
1937 if (*data_size > 4)
1938 *data_size = 4;
1939 /* Calculate the start offset in bytes of local PWC data. */
1940 if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
1941 offset = cyapa->aligned_electrodes_rx * (*data_size);
1942 if (cyapa->electrodes_rx == cyapa->electrodes_x)
1943 electrodes_tx = cyapa->electrodes_y;
1944 else
1945 electrodes_tx = cyapa->electrodes_x;
1946 max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) &
1947 ~7u) * electrodes_tx;
2523caab 1948 } else {
6499d390
DD
1949 offset = 2;
1950 max_element_cnt = cyapa->electrodes_x +
1951 cyapa->electrodes_y;
1952 max_element_cnt = (max_element_cnt + 3) & ~3u;
1953 }
1954 }
1955
1956 memset(cmd, 0, sizeof(cmd));
94897619
DD
1957 cmd_head = (struct pip_app_cmd_head *)cmd;
1958 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd_head->addr);
6499d390 1959 put_unaligned_le16(sizeof(cmd) - 2, &cmd_head->length);
94897619 1960 cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6499d390
DD
1961 cmd_head->cmd_code = cmd_code;
1962 do {
1963 read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) /
1964 (*data_size);
1965 read_elements = min(read_elements, max_element_cnt - count);
1966 read_len = read_elements * (*data_size);
1967
1968 put_unaligned_le16(offset, &cmd_head->parameter_data[0]);
1969 put_unaligned_le16(read_len, &cmd_head->parameter_data[2]);
1970 cmd_head->parameter_data[4] = idac_data_type;
1971 resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
1972 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
1973 cmd, sizeof(cmd),
1974 resp_data, &resp_len,
94897619 1975 500, cyapa_sort_tsg_pip_app_resp_data,
6499d390
DD
1976 true);
1977 if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
1978 !VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
94897619 1979 !PIP_CMD_COMPLETE_SUCCESS(resp_data) ||
6499d390
DD
1980 resp_data[6] != idac_data_type)
1981 return (error < 0) ? error : -EAGAIN;
1982 read_len = get_unaligned_le16(&resp_data[7]);
1983 if (read_len == 0)
1984 break;
1985
1986 *data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
1987 if (read_len < *data_size)
1988 return -EINVAL;
1989
1990 if (read_global_idac &&
1991 idac_data_type == GEN5_RETRIEVE_SELF_CAP_PWC_DATA) {
1992 /* Rx's self global idac data. */
1993 *idac_max = cyapa_parse_structure_data(
1994 resp_data[9],
1995 &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET],
1996 *data_size);
1997 /* Tx's self global idac data. */
1998 *idac_min = cyapa_parse_structure_data(
1999 resp_data[9],
2000 &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET +
2001 *data_size],
2002 *data_size);
2003 break;
2004 }
2005
2006 /* Read mutual global idac or local mutual/self PWC data. */
2007 offset += read_len;
2008 for (i = 10; i < (read_len + GEN5_RESP_DATA_STRUCTURE_OFFSET);
2009 i += *data_size) {
2010 value = cyapa_parse_structure_data(resp_data[9],
2011 &resp_data[i], *data_size);
2012 *idac_min = min(value, *idac_min);
2013 *idac_max = max(value, *idac_max);
2014
2015 if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA &&
2016 tmp_count < cyapa->aligned_electrodes_rx &&
2017 read_global_idac) {
2018 /*
94897619 2019 * The value gap between global and local mutual
6499d390
DD
2020 * idac data must bigger than 50%.
2021 * Normally, global value bigger than 50,
2022 * local values less than 10.
2023 */
2024 if (!tmp_ave || value > tmp_ave / 2) {
2025 tmp_min = min(value, tmp_min);
2026 tmp_max = max(value, tmp_max);
2027 tmp_sum += value;
2028 tmp_count++;
2029
2030 tmp_ave = tmp_sum / tmp_count;
2031 }
2032 }
2033
2034 sum += value;
2035 count++;
2036
2037 if (count >= max_element_cnt)
2038 goto out;
2039 }
2040 } while (true);
2041
2042out:
2043 *idac_ave = count ? (sum / count) : 0;
2044
2045 if (read_global_idac &&
2046 idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) {
2047 if (tmp_count == 0)
2048 return 0;
2049
2050 if (tmp_count == cyapa->aligned_electrodes_rx) {
2051 cyapa->electrodes_rx = cyapa->electrodes_rx ?
2052 cyapa->electrodes_rx : electrodes_rx;
2053 } else if (tmp_count == electrodes_rx) {
2054 cyapa->electrodes_rx = cyapa->electrodes_rx ?
2055 cyapa->electrodes_rx : electrodes_rx;
2056 cyapa->aligned_electrodes_rx = electrodes_rx;
2057 } else {
2058 cyapa->electrodes_rx = cyapa->electrodes_rx ?
2059 cyapa->electrodes_rx : electrodes_tx;
2060 cyapa->aligned_electrodes_rx = tmp_count;
2061 }
2062
2063 *idac_min = tmp_min;
2064 *idac_max = tmp_max;
2065 *idac_ave = tmp_ave;
2066 }
2067
2068 return 0;
2069}
2070
2071static int cyapa_gen5_read_mutual_idac_data(struct cyapa *cyapa,
2072 int *gidac_mutual_max, int *gidac_mutual_min, int *gidac_mutual_ave,
2073 int *lidac_mutual_max, int *lidac_mutual_min, int *lidac_mutual_ave)
2074{
2075 int data_size;
2076 int error;
2077
2078 *gidac_mutual_max = *gidac_mutual_min = *gidac_mutual_ave = 0;
2079 *lidac_mutual_max = *lidac_mutual_min = *lidac_mutual_ave = 0;
2080
2081 data_size = 0;
2082 error = cyapa_gen5_read_idac_data(cyapa,
94897619 2083 PIP_RETRIEVE_DATA_STRUCTURE,
6499d390
DD
2084 GEN5_RETRIEVE_MUTUAL_PWC_DATA,
2085 &data_size,
2086 gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave);
2087 if (error)
2088 return error;
2089
2090 error = cyapa_gen5_read_idac_data(cyapa,
94897619 2091 PIP_RETRIEVE_DATA_STRUCTURE,
6499d390
DD
2092 GEN5_RETRIEVE_MUTUAL_PWC_DATA,
2093 &data_size,
2094 lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave);
2095 return error;
2096}
2097
2098static int cyapa_gen5_read_self_idac_data(struct cyapa *cyapa,
2099 int *gidac_self_rx, int *gidac_self_tx,
2100 int *lidac_self_max, int *lidac_self_min, int *lidac_self_ave)
2101{
2102 int data_size;
2103 int error;
2104
2105 *gidac_self_rx = *gidac_self_tx = 0;
2106 *lidac_self_max = *lidac_self_min = *lidac_self_ave = 0;
2107
2108 data_size = 0;
2109 error = cyapa_gen5_read_idac_data(cyapa,
94897619 2110 PIP_RETRIEVE_DATA_STRUCTURE,
6499d390
DD
2111 GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
2112 &data_size,
2113 lidac_self_max, lidac_self_min, lidac_self_ave);
2114 if (error)
2115 return error;
2116 *gidac_self_rx = *lidac_self_max;
2117 *gidac_self_tx = *lidac_self_min;
2118
2119 error = cyapa_gen5_read_idac_data(cyapa,
94897619 2120 PIP_RETRIEVE_DATA_STRUCTURE,
6499d390
DD
2121 GEN5_RETRIEVE_SELF_CAP_PWC_DATA,
2122 &data_size,
2123 lidac_self_max, lidac_self_min, lidac_self_ave);
2124 return error;
2125}
2126
2127static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa)
2128{
94897619 2129 struct pip_app_cmd_head *app_cmd_head;
6499d390
DD
2130 u8 cmd[7];
2131 u8 resp_data[6];
2132 int resp_len;
2133 int error;
2134
2135 memset(cmd, 0, sizeof(cmd));
94897619
DD
2136 app_cmd_head = (struct pip_app_cmd_head *)cmd;
2137 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
6499d390 2138 put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
94897619 2139 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6499d390
DD
2140 app_cmd_head->cmd_code = GEN5_CMD_EXECUTE_PANEL_SCAN;
2141 resp_len = sizeof(resp_data);
2142 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
2143 cmd, sizeof(cmd),
2144 resp_data, &resp_len,
94897619 2145 500, cyapa_sort_tsg_pip_app_resp_data, true);
6499d390
DD
2146 if (error || resp_len != sizeof(resp_data) ||
2147 !VALID_CMD_RESP_HEADER(resp_data,
2148 GEN5_CMD_EXECUTE_PANEL_SCAN) ||
94897619 2149 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
6499d390
DD
2150 return error ? error : -EAGAIN;
2151
2152 return 0;
2153}
2154
2155static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa *cyapa,
2156 u8 cmd_code, u8 raw_data_type, int raw_data_max_num,
2157 int *raw_data_max, int *raw_data_min, int *raw_data_ave,
2158 u8 *buffer)
2159{
94897619 2160 struct pip_app_cmd_head *app_cmd_head;
6499d390
DD
2161 struct gen5_retrieve_panel_scan_data *panel_sacn_data;
2162 u8 cmd[12];
2163 u8 resp_data[256]; /* Max bytes can transfer one time. */
2164 int resp_len;
2165 int read_elements;
2166 int read_len;
2167 u16 offset;
2168 s32 value;
2169 int sum, count;
2170 int data_size;
2171 s32 *intp;
2172 int i;
2173 int error;
2174
2175 if (cmd_code != GEN5_CMD_RETRIEVE_PANEL_SCAN ||
2176 (raw_data_type > GEN5_PANEL_SCAN_SELF_DIFFCOUNT) ||
2177 !raw_data_max || !raw_data_min || !raw_data_ave)
2178 return -EINVAL;
2179
2180 intp = (s32 *)buffer;
2181 *raw_data_max = INT_MIN;
2182 *raw_data_min = INT_MAX;
2183 sum = count = 0;
2184 offset = 0;
2185 /* Assume max element size is 4 currently. */
2186 read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 4;
2187 read_len = read_elements * 4;
94897619
DD
2188 app_cmd_head = (struct pip_app_cmd_head *)cmd;
2189 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr);
6499d390 2190 put_unaligned_le16(sizeof(cmd) - 2, &app_cmd_head->length);
94897619 2191 app_cmd_head->report_id = PIP_APP_CMD_REPORT_ID;
6499d390
DD
2192 app_cmd_head->cmd_code = cmd_code;
2193 panel_sacn_data = (struct gen5_retrieve_panel_scan_data *)
2194 app_cmd_head->parameter_data;
2195 do {
2196 put_unaligned_le16(offset, &panel_sacn_data->read_offset);
2197 put_unaligned_le16(read_elements,
2198 &panel_sacn_data->read_elements);
2199 panel_sacn_data->data_id = raw_data_type;
2200
2201 resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len;
2202 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
2203 cmd, sizeof(cmd),
2204 resp_data, &resp_len,
94897619 2205 500, cyapa_sort_tsg_pip_app_resp_data, true);
6499d390
DD
2206 if (error || resp_len < GEN5_RESP_DATA_STRUCTURE_OFFSET ||
2207 !VALID_CMD_RESP_HEADER(resp_data, cmd_code) ||
94897619 2208 !PIP_CMD_COMPLETE_SUCCESS(resp_data) ||
6499d390
DD
2209 resp_data[6] != raw_data_type)
2210 return error ? error : -EAGAIN;
2211
2212 read_elements = get_unaligned_le16(&resp_data[7]);
2213 if (read_elements == 0)
2214 break;
2215
2216 data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK);
2217 offset += read_elements;
2218 if (read_elements) {
2219 for (i = GEN5_RESP_DATA_STRUCTURE_OFFSET;
2220 i < (read_elements * data_size +
2221 GEN5_RESP_DATA_STRUCTURE_OFFSET);
2222 i += data_size) {
2223 value = cyapa_parse_structure_data(resp_data[9],
2224 &resp_data[i], data_size);
2225 *raw_data_min = min(value, *raw_data_min);
2226 *raw_data_max = max(value, *raw_data_max);
2227
2228 if (intp)
2229 put_unaligned_le32(value, &intp[count]);
2230
2231 sum += value;
2232 count++;
2233
2234 }
2235 }
2236
2237 if (count >= raw_data_max_num)
2238 break;
2239
2240 read_elements = (sizeof(resp_data) -
2241 GEN5_RESP_DATA_STRUCTURE_OFFSET) / data_size;
2242 read_len = read_elements * data_size;
2243 } while (true);
2244
2245 *raw_data_ave = count ? (sum / count) : 0;
2246
2247 return 0;
2248}
2249
2250static ssize_t cyapa_gen5_show_baseline(struct device *dev,
2251 struct device_attribute *attr, char *buf)
2252{
2253 struct cyapa *cyapa = dev_get_drvdata(dev);
2254 int gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave;
2255 int lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave;
2256 int gidac_self_rx, gidac_self_tx;
2257 int lidac_self_max, lidac_self_min, lidac_self_ave;
2258 int raw_cap_mutual_max, raw_cap_mutual_min, raw_cap_mutual_ave;
2259 int raw_cap_self_max, raw_cap_self_min, raw_cap_self_ave;
2260 int mutual_diffdata_max, mutual_diffdata_min, mutual_diffdata_ave;
2261 int self_diffdata_max, self_diffdata_min, self_diffdata_ave;
2262 int mutual_baseline_max, mutual_baseline_min, mutual_baseline_ave;
2263 int self_baseline_max, self_baseline_min, self_baseline_ave;
2264 int error, resume_error;
2265 int size;
2266
94897619 2267 if (!cyapa_is_pip_app_mode(cyapa))
6499d390
DD
2268 return -EBUSY;
2269
2270 /* 1. Suspend Scanning*/
94897619 2271 error = cyapa_pip_suspend_scanning(cyapa);
6499d390
DD
2272 if (error)
2273 return error;
2274
2275 /* 2. Read global and local mutual IDAC data. */
2276 gidac_self_rx = gidac_self_tx = 0;
2277 error = cyapa_gen5_read_mutual_idac_data(cyapa,
2278 &gidac_mutual_max, &gidac_mutual_min,
2279 &gidac_mutual_ave, &lidac_mutual_max,
2280 &lidac_mutual_min, &lidac_mutual_ave);
2281 if (error)
2282 goto resume_scanning;
2283
2284 /* 3. Read global and local self IDAC data. */
2285 error = cyapa_gen5_read_self_idac_data(cyapa,
2286 &gidac_self_rx, &gidac_self_tx,
2287 &lidac_self_max, &lidac_self_min,
2288 &lidac_self_ave);
2289 if (error)
2290 goto resume_scanning;
2291
94897619 2292 /* 4. Execute panel scan. It must be executed before read data. */
6499d390
DD
2293 error = cyapa_gen5_execute_panel_scan(cyapa);
2294 if (error)
2295 goto resume_scanning;
2296
2297 /* 5. Retrieve panel scan, mutual cap raw data. */
2298 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2299 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2300 GEN5_PANEL_SCAN_MUTUAL_RAW_DATA,
2301 cyapa->electrodes_x * cyapa->electrodes_y,
2302 &raw_cap_mutual_max, &raw_cap_mutual_min,
2303 &raw_cap_mutual_ave,
2304 NULL);
2305 if (error)
2306 goto resume_scanning;
2307
2308 /* 6. Retrieve panel scan, self cap raw data. */
2309 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2310 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2311 GEN5_PANEL_SCAN_SELF_RAW_DATA,
2312 cyapa->electrodes_x + cyapa->electrodes_y,
2313 &raw_cap_self_max, &raw_cap_self_min,
2314 &raw_cap_self_ave,
2315 NULL);
2316 if (error)
2317 goto resume_scanning;
2318
2319 /* 7. Retrieve panel scan, mutual cap diffcount raw data. */
2320 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2321 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2322 GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT,
2323 cyapa->electrodes_x * cyapa->electrodes_y,
2324 &mutual_diffdata_max, &mutual_diffdata_min,
2325 &mutual_diffdata_ave,
2326 NULL);
2327 if (error)
2328 goto resume_scanning;
2329
2330 /* 8. Retrieve panel scan, self cap diffcount raw data. */
2331 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2332 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2333 GEN5_PANEL_SCAN_SELF_DIFFCOUNT,
2334 cyapa->electrodes_x + cyapa->electrodes_y,
2335 &self_diffdata_max, &self_diffdata_min,
2336 &self_diffdata_ave,
2337 NULL);
2338 if (error)
2339 goto resume_scanning;
2340
2341 /* 9. Retrieve panel scan, mutual cap baseline raw data. */
2342 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2343 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2344 GEN5_PANEL_SCAN_MUTUAL_BASELINE,
2345 cyapa->electrodes_x * cyapa->electrodes_y,
2346 &mutual_baseline_max, &mutual_baseline_min,
2347 &mutual_baseline_ave,
2348 NULL);
2349 if (error)
2350 goto resume_scanning;
2351
2352 /* 10. Retrieve panel scan, self cap baseline raw data. */
2353 error = cyapa_gen5_read_panel_scan_raw_data(cyapa,
2354 GEN5_CMD_RETRIEVE_PANEL_SCAN,
2355 GEN5_PANEL_SCAN_SELF_BASELINE,
2356 cyapa->electrodes_x + cyapa->electrodes_y,
2357 &self_baseline_max, &self_baseline_min,
2358 &self_baseline_ave,
2359 NULL);
2360 if (error)
2361 goto resume_scanning;
2362
2363resume_scanning:
2364 /* 11. Resume Scanning*/
94897619 2365 resume_error = cyapa_pip_resume_scanning(cyapa);
6499d390
DD
2366 if (resume_error || error)
2367 return resume_error ? resume_error : error;
2368
2369 /* 12. Output data strings */
2370 size = scnprintf(buf, PAGE_SIZE, "%d %d %d %d %d %d %d %d %d %d %d ",
2371 gidac_mutual_min, gidac_mutual_max, gidac_mutual_ave,
2372 lidac_mutual_min, lidac_mutual_max, lidac_mutual_ave,
2373 gidac_self_rx, gidac_self_tx,
2374 lidac_self_min, lidac_self_max, lidac_self_ave);
2375 size += scnprintf(buf + size, PAGE_SIZE - size,
2376 "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
2377 raw_cap_mutual_min, raw_cap_mutual_max, raw_cap_mutual_ave,
2378 raw_cap_self_min, raw_cap_self_max, raw_cap_self_ave,
2379 mutual_diffdata_min, mutual_diffdata_max, mutual_diffdata_ave,
2380 self_diffdata_min, self_diffdata_max, self_diffdata_ave,
2381 mutual_baseline_min, mutual_baseline_max, mutual_baseline_ave,
2382 self_baseline_min, self_baseline_max, self_baseline_ave);
2383 return size;
2384}
2385
94897619 2386bool cyapa_pip_sort_system_info_data(struct cyapa *cyapa,
6972a859
DD
2387 u8 *buf, int len)
2388{
2389 /* Check the report id and command code */
2390 if (VALID_CMD_RESP_HEADER(buf, 0x02))
2391 return true;
2392
2393 return false;
2394}
2395
2396static int cyapa_gen5_bl_query_data(struct cyapa *cyapa)
2397{
94897619 2398 u8 resp_data[PIP_BL_APP_INFO_RESP_LENGTH];
6972a859
DD
2399 int resp_len;
2400 int error;
2401
94897619 2402 resp_len = sizeof(resp_data);
6972a859 2403 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
94897619 2404 pip_bl_read_app_info, PIP_BL_READ_APP_INFO_CMD_LENGTH,
6972a859 2405 resp_data, &resp_len,
94897619
DD
2406 500, cyapa_sort_tsg_pip_bl_resp_data, false);
2407 if (error || resp_len < PIP_BL_APP_INFO_RESP_LENGTH ||
2408 !PIP_CMD_COMPLETE_SUCCESS(resp_data))
6972a859
DD
2409 return error ? error : -EIO;
2410
2411 memcpy(&cyapa->product_id[0], &resp_data[8], 5);
2412 cyapa->product_id[5] = '-';
2413 memcpy(&cyapa->product_id[6], &resp_data[13], 6);
2414 cyapa->product_id[12] = '-';
2415 memcpy(&cyapa->product_id[13], &resp_data[19], 2);
2416 cyapa->product_id[15] = '\0';
2417
2418 cyapa->fw_maj_ver = resp_data[22];
2419 cyapa->fw_min_ver = resp_data[23];
2420
c2c06c41
DD
2421 cyapa->platform_ver = (resp_data[26] >> PIP_BL_PLATFORM_VER_SHIFT) &
2422 PIP_BL_PLATFORM_VER_MASK;
2423
6972a859
DD
2424 return 0;
2425}
2426
2427static int cyapa_gen5_get_query_data(struct cyapa *cyapa)
2428{
94897619 2429 u8 resp_data[PIP_READ_SYS_INFO_RESP_LENGTH];
6972a859
DD
2430 int resp_len;
2431 u16 product_family;
2432 int error;
2433
2434 resp_len = sizeof(resp_data);
2435 error = cyapa_i2c_pip_cmd_irq_sync(cyapa,
94897619 2436 pip_read_sys_info, PIP_READ_SYS_INFO_CMD_LENGTH,
6972a859 2437 resp_data, &resp_len,
94897619 2438 2000, cyapa_pip_sort_system_info_data, false);
6972a859
DD
2439 if (error || resp_len < sizeof(resp_data))
2440 return error ? error : -EIO;
2441
2442 product_family = get_unaligned_le16(&resp_data[7]);
94897619
DD
2443 if ((product_family & PIP_PRODUCT_FAMILY_MASK) !=
2444 PIP_PRODUCT_FAMILY_TRACKPAD)
6972a859
DD
2445 return -EINVAL;
2446
c2c06c41
DD
2447 cyapa->platform_ver = (resp_data[49] >> PIP_BL_PLATFORM_VER_SHIFT) &
2448 PIP_BL_PLATFORM_VER_MASK;
2449 if (cyapa->gen == CYAPA_GEN5 && cyapa->platform_ver < 2) {
2450 /* Gen5 firmware that does not support proximity. */
2451 cyapa->fw_maj_ver = resp_data[15];
2452 cyapa->fw_min_ver = resp_data[16];
2453 } else {
2454 cyapa->fw_maj_ver = resp_data[9];
2455 cyapa->fw_min_ver = resp_data[10];
2456 }
6972a859
DD
2457
2458 cyapa->electrodes_x = resp_data[52];
2459 cyapa->electrodes_y = resp_data[53];
2460
2461 cyapa->physical_size_x = get_unaligned_le16(&resp_data[54]) / 100;
2462 cyapa->physical_size_y = get_unaligned_le16(&resp_data[56]) / 100;
2463
2464 cyapa->max_abs_x = get_unaligned_le16(&resp_data[58]);
2465 cyapa->max_abs_y = get_unaligned_le16(&resp_data[60]);
2466
2467 cyapa->max_z = get_unaligned_le16(&resp_data[62]);
2468
2469 cyapa->x_origin = resp_data[64] & 0x01;
2470 cyapa->y_origin = resp_data[65] & 0x01;
2471
2472 cyapa->btn_capability = (resp_data[70] << 3) & CAPABILITY_BTN_MASK;
2473
2474 memcpy(&cyapa->product_id[0], &resp_data[33], 5);
2475 cyapa->product_id[5] = '-';
2476 memcpy(&cyapa->product_id[6], &resp_data[38], 6);
2477 cyapa->product_id[12] = '-';
2478 memcpy(&cyapa->product_id[13], &resp_data[44], 2);
2479 cyapa->product_id[15] = '\0';
2480
2481 if (!cyapa->electrodes_x || !cyapa->electrodes_y ||
2482 !cyapa->physical_size_x || !cyapa->physical_size_y ||
2483 !cyapa->max_abs_x || !cyapa->max_abs_y || !cyapa->max_z)
2484 return -EINVAL;
2485
2486 return 0;
2487}
2488
2489static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
2490{
2491 struct device *dev = &cyapa->client->dev;
2492 int error;
2493
2494 if (cyapa->gen != CYAPA_GEN5)
2495 return -ENODEV;
2496
2497 switch (cyapa->state) {
2498 case CYAPA_STATE_GEN5_BL:
94897619 2499 error = cyapa_pip_bl_exit(cyapa);
6972a859 2500 if (error) {
94897619 2501 /* Try to update trackpad product information. */
6972a859
DD
2502 cyapa_gen5_bl_query_data(cyapa);
2503 goto out;
2504 }
2505
2506 cyapa->state = CYAPA_STATE_GEN5_APP;
2507
2508 case CYAPA_STATE_GEN5_APP:
2509 /*
2510 * If trackpad device in deep sleep mode,
2511 * the app command will fail.
2512 * So always try to reset trackpad device to full active when
94897619 2513 * the device state is required.
6972a859
DD
2514 */
2515 error = cyapa_gen5_set_power_mode(cyapa,
757cae5a 2516 PWR_MODE_FULL_ACTIVE, 0, false);
6972a859
DD
2517 if (error)
2518 dev_warn(dev, "%s: failed to set power active mode.\n",
2519 __func__);
2520
945525ee 2521 /* By default, the trackpad proximity function is enabled. */
0642ffd6
DD
2522 if (cyapa->platform_ver >= 2) {
2523 error = cyapa_pip_set_proximity(cyapa, true);
2524 if (error)
2525 dev_warn(dev,
2526 "%s: failed to enable proximity.\n",
2527 __func__);
2528 }
945525ee 2529
6972a859
DD
2530 /* Get trackpad product information. */
2531 error = cyapa_gen5_get_query_data(cyapa);
2532 if (error)
2533 goto out;
2534 /* Only support product ID starting with CYTRA */
2535 if (memcmp(cyapa->product_id, product_id,
2536 strlen(product_id)) != 0) {
2537 dev_err(dev, "%s: unknown product ID (%s)\n",
2538 __func__, cyapa->product_id);
2539 error = -EINVAL;
2540 }
2541 break;
2542 default:
2543 error = -EINVAL;
2544 }
2545
2546out:
2547 return error;
2548}
2549
2550/*
2551 * Return false, do not continue process
2552 * Return true, continue process.
2553 */
94897619 2554bool cyapa_pip_irq_cmd_handler(struct cyapa *cyapa)
6972a859 2555{
94897619 2556 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip;
6972a859
DD
2557 int length;
2558
94897619 2559 if (atomic_read(&pip->cmd_issued)) {
6972a859 2560 /* Polling command response data. */
94897619 2561 if (pip->is_irq_mode == false)
6972a859
DD
2562 return false;
2563
2564 /*
2565 * Read out all none command response data.
2566 * these output data may caused by user put finger on
2567 * trackpad when host waiting the command response.
2568 */
94897619
DD
2569 cyapa_i2c_pip_read(cyapa, pip->irq_cmd_buf,
2570 PIP_RESP_LENGTH_SIZE);
2571 length = get_unaligned_le16(pip->irq_cmd_buf);
2572 length = (length <= PIP_RESP_LENGTH_SIZE) ?
2573 PIP_RESP_LENGTH_SIZE : length;
2574 if (length > PIP_RESP_LENGTH_SIZE)
6972a859 2575 cyapa_i2c_pip_read(cyapa,
94897619
DD
2576 pip->irq_cmd_buf, length);
2577 if (!(pip->resp_sort_func &&
2578 pip->resp_sort_func(cyapa,
2579 pip->irq_cmd_buf, length))) {
6972a859 2580 /*
94897619
DD
2581 * Cover the Gen5 V1 firmware issue.
2582 * The issue is no interrupt would be asserted from
2583 * trackpad device to host for the command response
2584 * ready event. Because when there was a finger touch
2585 * on trackpad device, and the firmware output queue
2586 * won't be empty (always with touch report data), so
2587 * the interrupt signal won't be asserted again until
2588 * the output queue was previous emptied.
2589 * This issue would happen in the scenario that
2590 * user always has his/her fingers touched on the
2591 * trackpad device during system booting/rebooting.
6972a859 2592 */
a535a9f1 2593 length = 0;
94897619
DD
2594 if (pip->resp_len)
2595 length = *pip->resp_len;
6972a859 2596 cyapa_empty_pip_output_data(cyapa,
94897619 2597 pip->resp_data,
6972a859 2598 &length,
94897619
DD
2599 pip->resp_sort_func);
2600 if (pip->resp_len && length != 0) {
2601 *pip->resp_len = length;
2602 atomic_dec(&pip->cmd_issued);
2603 complete(&pip->cmd_ready);
6972a859
DD
2604 }
2605 return false;
2606 }
2607
94897619
DD
2608 if (pip->resp_data && pip->resp_len) {
2609 *pip->resp_len = (*pip->resp_len < length) ?
2610 *pip->resp_len : length;
2611 memcpy(pip->resp_data, pip->irq_cmd_buf,
2612 *pip->resp_len);
6972a859 2613 }
94897619
DD
2614 atomic_dec(&pip->cmd_issued);
2615 complete(&pip->cmd_ready);
6972a859
DD
2616 return false;
2617 }
2618
2619 return true;
2620}
2621
94897619
DD
2622static void cyapa_pip_report_buttons(struct cyapa *cyapa,
2623 const struct cyapa_pip_report_data *report_data)
6972a859
DD
2624{
2625 struct input_dev *input = cyapa->input;
94897619 2626 u8 buttons = report_data->report_head[PIP_BUTTONS_OFFSET];
6972a859
DD
2627
2628 buttons = (buttons << CAPABILITY_BTN_SHIFT) & CAPABILITY_BTN_MASK;
2629
2630 if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) {
2631 input_report_key(input, BTN_LEFT,
2632 !!(buttons & CAPABILITY_LEFT_BTN_MASK));
2633 }
2634 if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) {
2635 input_report_key(input, BTN_MIDDLE,
2636 !!(buttons & CAPABILITY_MIDDLE_BTN_MASK));
2637 }
2638 if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) {
2639 input_report_key(input, BTN_RIGHT,
2640 !!(buttons & CAPABILITY_RIGHT_BTN_MASK));
2641 }
2642
2643 input_sync(input);
2644}
2645
945525ee
DD
2646static void cyapa_pip_report_proximity(struct cyapa *cyapa,
2647 const struct cyapa_pip_report_data *report_data)
2648{
2649 struct input_dev *input = cyapa->input;
2650 u8 distance = report_data->report_head[PIP_PROXIMITY_DISTANCE_OFFSET] &
2651 PIP_PROXIMITY_DISTANCE_MASK;
2652
2653 input_report_abs(input, ABS_DISTANCE, distance);
2654 input_sync(input);
2655}
2656
94897619
DD
2657static void cyapa_pip_report_slot_data(struct cyapa *cyapa,
2658 const struct cyapa_pip_touch_record *touch)
6972a859
DD
2659{
2660 struct input_dev *input = cyapa->input;
94897619
DD
2661 u8 event_id = PIP_GET_EVENT_ID(touch->touch_tip_event_id);
2662 int slot = PIP_GET_TOUCH_ID(touch->touch_tip_event_id);
6972a859
DD
2663 int x, y;
2664
2665 if (event_id == RECORD_EVENT_LIFTOFF)
2666 return;
2667
2668 input_mt_slot(input, slot);
2669 input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
2670 x = (touch->x_hi << 8) | touch->x_lo;
2671 if (cyapa->x_origin)
2672 x = cyapa->max_abs_x - x;
6972a859
DD
2673 y = (touch->y_hi << 8) | touch->y_lo;
2674 if (cyapa->y_origin)
2675 y = cyapa->max_abs_y - y;
94897619 2676 input_report_abs(input, ABS_MT_POSITION_X, x);
6972a859 2677 input_report_abs(input, ABS_MT_POSITION_Y, y);
945525ee 2678 input_report_abs(input, ABS_DISTANCE, 0);
6972a859
DD
2679 input_report_abs(input, ABS_MT_PRESSURE,
2680 touch->z);
2681 input_report_abs(input, ABS_MT_TOUCH_MAJOR,
2682 touch->major_axis_len);
2683 input_report_abs(input, ABS_MT_TOUCH_MINOR,
2684 touch->minor_axis_len);
2685
2686 input_report_abs(input, ABS_MT_WIDTH_MAJOR,
2687 touch->major_tool_len);
2688 input_report_abs(input, ABS_MT_WIDTH_MINOR,
2689 touch->minor_tool_len);
2690
2691 input_report_abs(input, ABS_MT_ORIENTATION,
2692 touch->orientation);
2693}
2694
94897619
DD
2695static void cyapa_pip_report_touches(struct cyapa *cyapa,
2696 const struct cyapa_pip_report_data *report_data)
6972a859
DD
2697{
2698 struct input_dev *input = cyapa->input;
2699 unsigned int touch_num;
2700 int i;
2701
94897619
DD
2702 touch_num = report_data->report_head[PIP_NUMBER_OF_TOUCH_OFFSET] &
2703 PIP_NUMBER_OF_TOUCH_MASK;
6972a859
DD
2704
2705 for (i = 0; i < touch_num; i++)
94897619 2706 cyapa_pip_report_slot_data(cyapa,
6972a859
DD
2707 &report_data->touch_records[i]);
2708
2709 input_mt_sync_frame(input);
2710 input_sync(input);
2711}
2712
94897619 2713int cyapa_pip_irq_handler(struct cyapa *cyapa)
6972a859
DD
2714{
2715 struct device *dev = &cyapa->client->dev;
94897619 2716 struct cyapa_pip_report_data report_data;
6972a859 2717 unsigned int report_len;
94897619
DD
2718 u8 report_id;
2719 int ret;
6972a859 2720
94897619 2721 if (!cyapa_is_pip_app_mode(cyapa)) {
6972a859
DD
2722 dev_err(dev, "invalid device state, gen=%d, state=0x%02x\n",
2723 cyapa->gen, cyapa->state);
2724 return -EINVAL;
2725 }
2726
2727 ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data,
94897619
DD
2728 PIP_RESP_LENGTH_SIZE);
2729 if (ret != PIP_RESP_LENGTH_SIZE) {
6972a859
DD
2730 dev_err(dev, "failed to read length bytes, (%d)\n", ret);
2731 return -EINVAL;
2732 }
2733
2734 report_len = get_unaligned_le16(
94897619
DD
2735 &report_data.report_head[PIP_RESP_LENGTH_OFFSET]);
2736 if (report_len < PIP_RESP_LENGTH_SIZE) {
2737 /* Invalid length or internal reset happened. */
6972a859
DD
2738 dev_err(dev, "invalid report_len=%d. bytes: %02x %02x\n",
2739 report_len, report_data.report_head[0],
2740 report_data.report_head[1]);
2741 return -EINVAL;
2742 }
2743
2744 /* Idle, no data for report. */
94897619 2745 if (report_len == PIP_RESP_LENGTH_SIZE)
6972a859
DD
2746 return 0;
2747
2748 ret = cyapa_i2c_pip_read(cyapa, (u8 *)&report_data, report_len);
2749 if (ret != report_len) {
2750 dev_err(dev, "failed to read %d bytes report data, (%d)\n",
2751 report_len, ret);
2752 return -EINVAL;
2753 }
2754
94897619
DD
2755 report_id = report_data.report_head[PIP_RESP_REPORT_ID_OFFSET];
2756 if (report_id == PIP_WAKEUP_EVENT_REPORT_ID &&
2757 report_len == PIP_WAKEUP_EVENT_SIZE) {
6972a859
DD
2758 /*
2759 * Device wake event from deep sleep mode for touch.
2760 * This interrupt event is used to wake system up.
757cae5a
DD
2761 *
2762 * Note:
2763 * It will introduce about 20~40 ms additional delay
2764 * time in receiving for first valid touch report data.
2765 * The time is used to execute device runtime resume
2766 * process.
6972a859 2767 */
757cae5a
DD
2768 pm_runtime_get_sync(dev);
2769 pm_runtime_mark_last_busy(dev);
2770 pm_runtime_put_sync_autosuspend(dev);
6972a859 2771 return 0;
94897619
DD
2772 } else if (report_id != PIP_TOUCH_REPORT_ID &&
2773 report_id != PIP_BTN_REPORT_ID &&
6972a859 2774 report_id != GEN5_OLD_PUSH_BTN_REPORT_ID &&
945525ee
DD
2775 report_id != PIP_PUSH_BTN_REPORT_ID &&
2776 report_id != PIP_PROXIMITY_REPORT_ID) {
6972a859
DD
2777 /* Running in BL mode or unknown response data read. */
2778 dev_err(dev, "invalid report_id=0x%02x\n", report_id);
2779 return -EINVAL;
2780 }
2781
94897619
DD
2782 if (report_id == PIP_TOUCH_REPORT_ID &&
2783 (report_len < PIP_TOUCH_REPORT_HEAD_SIZE ||
2784 report_len > PIP_TOUCH_REPORT_MAX_SIZE)) {
6972a859
DD
2785 /* Invalid report data length for finger packet. */
2786 dev_err(dev, "invalid touch packet length=%d\n", report_len);
2787 return 0;
2788 }
2789
94897619 2790 if ((report_id == PIP_BTN_REPORT_ID ||
6972a859 2791 report_id == GEN5_OLD_PUSH_BTN_REPORT_ID ||
94897619
DD
2792 report_id == PIP_PUSH_BTN_REPORT_ID) &&
2793 (report_len < PIP_BTN_REPORT_HEAD_SIZE ||
2794 report_len > PIP_BTN_REPORT_MAX_SIZE)) {
6972a859
DD
2795 /* Invalid report data length of button packet. */
2796 dev_err(dev, "invalid button packet length=%d\n", report_len);
2797 return 0;
2798 }
2799
945525ee
DD
2800 if (report_id == PIP_PROXIMITY_REPORT_ID &&
2801 report_len != PIP_PROXIMITY_REPORT_SIZE) {
2802 /* Invalid report data length of proximity packet. */
2803 dev_err(dev, "invalid proximity data, length=%d\n", report_len);
2804 return 0;
2805 }
2806
94897619
DD
2807 if (report_id == PIP_TOUCH_REPORT_ID)
2808 cyapa_pip_report_touches(cyapa, &report_data);
945525ee
DD
2809 else if (report_id == PIP_PROXIMITY_REPORT_ID)
2810 cyapa_pip_report_proximity(cyapa, &report_data);
6972a859 2811 else
94897619 2812 cyapa_pip_report_buttons(cyapa, &report_data);
6972a859
DD
2813
2814 return 0;
2815}
2816
94897619
DD
2817int cyapa_pip_bl_activate(struct cyapa *cyapa) { return 0; }
2818int cyapa_pip_bl_deactivate(struct cyapa *cyapa) { return 0; }
2819
5812d306 2820
6972a859 2821const struct cyapa_dev_ops cyapa_gen5_ops = {
94897619
DD
2822 .check_fw = cyapa_pip_check_fw,
2823 .bl_enter = cyapa_pip_bl_enter,
2824 .bl_initiate = cyapa_pip_bl_initiate,
2825 .update_fw = cyapa_pip_do_fw_update,
2826 .bl_activate = cyapa_pip_bl_activate,
2827 .bl_deactivate = cyapa_pip_bl_deactivate,
5812d306 2828
6499d390 2829 .show_baseline = cyapa_gen5_show_baseline,
94897619 2830 .calibrate_store = cyapa_pip_do_calibrate,
6499d390 2831
94897619 2832 .initialize = cyapa_pip_cmd_state_initialize,
6972a859
DD
2833
2834 .state_parse = cyapa_gen5_state_parse,
2835 .operational_check = cyapa_gen5_do_operational_check,
2836
94897619
DD
2837 .irq_handler = cyapa_pip_irq_handler,
2838 .irq_cmd_handler = cyapa_pip_irq_cmd_handler,
6972a859
DD
2839 .sort_empty_output_data = cyapa_empty_pip_output_data,
2840 .set_power_mode = cyapa_gen5_set_power_mode,
945525ee
DD
2841
2842 .set_proximity = cyapa_pip_set_proximity,
6972a859 2843};
This page took 0.1623 seconds and 5 git commands to generate.