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