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