2 * Cypress APA trackpad with I2C interface
4 * Author: Dudley Du <dudl@cypress.com>
6 * Copyright (C) 2014-2015 Cypress Semiconductor, Inc.
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
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>
26 /* Macro of TSG firmware image */
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
41 #define CYAPA_TSG_MAX_CMD_SIZE 256
43 /* Macro of PIP interface */
44 #define PIP_BL_INITIATE_RESP_LEN 11
45 #define PIP_BL_FAIL_EXIT_RESP_LEN 11
46 #define PIP_BL_FAIL_EXIT_STATUS_CODE 0x0c
47 #define PIP_BL_VERIFY_INTEGRITY_RESP_LEN 12
48 #define PIP_BL_INTEGRITY_CHEKC_PASS 0x00
49 #define PIP_BL_BLOCK_WRITE_RESP_LEN 11
51 #define PIP_TOUCH_REPORT_ID 0x01
52 #define PIP_BTN_REPORT_ID 0x03
53 #define PIP_WAKEUP_EVENT_REPORT_ID 0x04
54 #define PIP_PUSH_BTN_REPORT_ID 0x06
55 #define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 /* Special for old Gen5 TP. */
56 #define PIP_PROXIMITY_REPORT_ID 0x07
58 #define PIP_PROXIMITY_REPORT_SIZE 6
59 #define PIP_PROXIMITY_DISTANCE_OFFSET 0x05
60 #define PIP_PROXIMITY_DISTANCE_MASK 0x01
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
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)
79 #define RECORD_EVENT_NONE 0
80 #define RECORD_EVENT_TOUCHDOWN 1
81 #define RECORD_EVENT_DISPLACE 2
82 #define RECORD_EVENT_LIFTOFF 3
84 #define PIP_SENSING_MODE_MUTUAL_CAP_FINE 0x00
85 #define PIP_SENSING_MODE_SELF_CAP 0x02
87 #define PIP_SET_PROXIMITY 0x49
90 #define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100
91 #define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe
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
100 #define GEN5_POWER_READY_MAX_INTRVL_TIME 50 /* Unit: ms */
101 #define GEN5_POWER_IDLE_MAX_INTRVL_TIME 250 /* Unit: ms */
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
112 #define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08
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
120 #define GEN5_RETRIEVE_MUTUAL_PWC_DATA 0x00
121 #define GEN5_RETRIEVE_SELF_CAP_PWC_DATA 0x01
123 #define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07
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
134 /* The offset only valid for retrieve PWC and panel scan commands */
135 #define GEN5_RESP_DATA_STRUCTURE_OFFSET 10
136 #define GEN5_PWC_DATA_ELEMENT_SIZE_MASK 0x07
139 struct cyapa_pip_touch_record
{
141 * Bit 7 - 3: reserved
142 * Bit 2 - 0: touch type;
143 * 0 : standard finger;
144 * 1 : proximity (Start supported in Gen5 TP).
145 * 2 : finger hover (defined, but not used yet.)
151 * Bit 7: indicates touch liftoff status.
152 * 0 : touch is currently on the panel.
153 * 1 : touch record indicates a liftoff.
154 * Bit 6 - 5: indicates an event associated with this touch instance
157 * 2 : significant displacement (> active distance)
158 * 3 : liftoff (record reports last known coordinates)
159 * Bit 4 - 0: An arbitrary ID tag associated with a finger
160 * to allow tracking a touch as it moves around the panel.
162 u8 touch_tip_event_id
;
164 /* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */
167 /* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */
170 /* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */
173 /* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */
177 * The meaning of this value is different when touch_type is different.
178 * For standard finger type:
179 * Touch intensity in counts, pressure value.
180 * For proximity type (Start supported in Gen5 TP):
181 * The distance, in surface units, between the contact and
187 * The length of the major axis of the ellipse of contact between
188 * the finger and the panel (ABS_MT_TOUCH_MAJOR).
193 * The length of the minor axis of the ellipse of contact between
194 * the finger and the panel (ABS_MT_TOUCH_MINOR).
199 * The length of the major axis of the approaching tool.
200 * (ABS_MT_WIDTH_MAJOR)
205 * The length of the minor axis of the approaching tool.
206 * (ABS_MT_WIDTH_MINOR)
211 * The angle between the panel vertical axis and
212 * the major axis of the contact ellipse. This value is an 8-bit
213 * signed integer. The range is -127 to +127 (corresponding to
214 * -90 degree and +90 degree respectively).
215 * The positive direction is clockwise from the vertical axis.
216 * If the ellipse of contact degenerates into a circle,
217 * orientation is reported as 0.
222 struct cyapa_pip_report_data
{
223 u8 report_head
[PIP_TOUCH_REPORT_HEAD_SIZE
];
224 struct cyapa_pip_touch_record touch_records
[10];
227 struct cyapa_tsg_bin_image_head
{
228 u8 head_size
; /* Unit: bytes, including itself. */
229 u8 ttda_driver_major_version
; /* Reserved as 0. */
230 u8 ttda_driver_minor_version
; /* Reserved as 0. */
233 u8 fw_revision_control_number
[8];
242 struct cyapa_tsg_bin_image_data_record
{
245 /* The number of bytes of flash data contained in this record. */
247 /* The flash program data. */
248 u8 record_data
[CYAPA_TSG_FW_ROW_SIZE
];
251 struct cyapa_tsg_bin_image
{
252 struct cyapa_tsg_bin_image_head image_head
;
253 struct cyapa_tsg_bin_image_data_record records
[0];
256 struct pip_bl_packet_start
{
257 u8 sop
; /* Start of packet, must be 01h */
259 __le16 data_length
; /* Size of data parameter start from data[0] */
262 struct pip_bl_packet_end
{
264 u8 eop
; /* End of packet, must be 17h */
267 struct pip_bl_cmd_head
{
268 __le16 addr
; /* Output report register address, must be 0004h */
269 /* Size of packet not including output report register address */
271 u8 report_id
; /* Bootloader output report id, must be 40h */
272 u8 rsvd
; /* Reserved, must be 0 */
273 struct pip_bl_packet_start packet_start
;
274 u8 data
[0]; /* Command data variable based on commands */
277 /* Initiate bootload command data structure. */
278 struct pip_bl_initiate_cmd_data
{
279 /* Key must be "A5h 01h 02h 03h FFh FEh FDh 5Ah" */
280 u8 key
[CYAPA_TSG_BL_KEY_SIZE
];
281 u8 metadata_raw_parameter
[CYAPA_TSG_FLASH_MAP_METADATA_SIZE
];
285 struct tsg_bl_metadata_row_params
{
292 __le32 upgrade_start
;
294 __le16 entry_row_crc
;
295 u8 padding
[36]; /* Padding data must be 0 */
296 __le16 metadata_crc
; /* CRC starts at offset of 60 */
299 /* Bootload program and verify row command data structure */
300 struct tsg_bl_flash_row_head
{
306 struct pip_app_cmd_head
{
307 __le16 addr
; /* Output report register address, must be 0004h */
308 /* Size of packet not including output report register address */
310 u8 report_id
; /* Application output report id, must be 2Fh */
311 u8 rsvd
; /* Reserved, must be 0 */
313 * Bit 7: reserved, must be 0.
314 * Bit 6-0: command code.
317 u8 parameter_data
[0]; /* Parameter data variable based on cmd_code */
320 /* Application get/set parameter command data structure */
321 struct gen5_app_set_parameter_data
{
327 struct gen5_app_get_parameter_data
{
331 struct gen5_retrieve_panel_scan_data
{
333 __le16 read_elements
;
337 u8 pip_read_sys_info
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x02 };
338 u8 pip_bl_read_app_info
[] = { 0x04, 0x00, 0x0b, 0x00, 0x40, 0x00,
339 0x01, 0x3c, 0x00, 0x00, 0xb0, 0x42, 0x17
342 static u8 cyapa_pip_bl_cmd_key
[] = { 0xa5, 0x01, 0x02, 0x03,
343 0xff, 0xfe, 0xfd, 0x5a };
345 int cyapa_pip_cmd_state_initialize(struct cyapa
*cyapa
)
347 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
349 init_completion(&pip
->cmd_ready
);
350 atomic_set(&pip
->cmd_issued
, 0);
351 mutex_init(&pip
->cmd_lock
);
353 pip
->resp_sort_func
= NULL
;
354 pip
->in_progress_cmd
= PIP_INVALID_CMD
;
355 pip
->resp_data
= NULL
;
356 pip
->resp_len
= NULL
;
358 cyapa
->dev_pwr_mode
= UNINIT_PWR_MODE
;
359 cyapa
->dev_sleep_time
= UNINIT_SLEEP_TIME
;
364 /* Return negative errno, or else the number of bytes read. */
365 ssize_t
cyapa_i2c_pip_read(struct cyapa
*cyapa
, u8
*buf
, size_t size
)
372 if (!buf
|| size
> CYAPA_REG_MAP_SIZE
)
375 ret
= i2c_master_recv(cyapa
->client
, buf
, size
);
378 return (ret
< 0) ? ret
: -EIO
;
383 * Return a negative errno code else zero on success.
385 ssize_t
cyapa_i2c_pip_write(struct cyapa
*cyapa
, u8
*buf
, size_t size
)
392 ret
= i2c_master_send(cyapa
->client
, buf
, size
);
395 return (ret
< 0) ? ret
: -EIO
;
401 * This function is aimed to dump all not read data in Gen5 trackpad
402 * before send any command, otherwise, the interrupt line will be blocked.
404 int cyapa_empty_pip_output_data(struct cyapa
*cyapa
,
405 u8
*buf
, int *len
, cb_sort func
)
407 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
416 buf_len
= (*len
< CYAPA_REG_MAP_SIZE
) ?
417 *len
: CYAPA_REG_MAP_SIZE
;
421 report_count
= 8; /* max 7 pending data before command response data */
425 * Depending on testing in cyapa driver, there are max 5 "02 00"
426 * packets between two valid buffered data report in firmware.
427 * So in order to dump all buffered data out and
428 * make interrupt line release for reassert again,
429 * we must set the empty_count check value bigger than 5 to
430 * make it work. Otherwise, in some situation,
431 * the interrupt line may unable to reactive again,
432 * which will cause trackpad device unable to
433 * report data any more.
434 * for example, it may happen in EFT and ESD testing.
439 error
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
,
440 PIP_RESP_LENGTH_SIZE
);
444 length
= get_unaligned_le16(pip
->empty_buf
);
445 if (length
== PIP_RESP_LENGTH_SIZE
) {
448 } else if (length
> CYAPA_REG_MAP_SIZE
) {
449 /* Should not happen */
451 } else if (length
== 0) {
452 /* Application or bootloader launch data polled out. */
453 length
= PIP_RESP_LENGTH_SIZE
;
454 if (buf
&& buf_len
&& func
&&
455 func(cyapa
, pip
->empty_buf
, length
)) {
456 length
= min(buf_len
, length
);
457 memcpy(buf
, pip
->empty_buf
, length
);
459 /* Response found, success. */
465 error
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
, length
);
471 length
= get_unaligned_le16(pip
->empty_buf
);
472 if (length
<= PIP_RESP_LENGTH_SIZE
) {
474 } else if (buf
&& buf_len
&& func
&&
475 func(cyapa
, pip
->empty_buf
, length
)) {
476 length
= min(buf_len
, length
);
477 memcpy(buf
, pip
->empty_buf
, length
);
479 /* Response found, success. */
484 } while (report_count
);
489 static int cyapa_do_i2c_pip_cmd_irq_sync(
491 u8
*cmd
, size_t cmd_len
,
492 unsigned long timeout
)
494 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
497 /* Wait for interrupt to set ready completion */
498 init_completion(&pip
->cmd_ready
);
500 atomic_inc(&pip
->cmd_issued
);
501 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
503 atomic_dec(&pip
->cmd_issued
);
504 return (error
< 0) ? error
: -EIO
;
507 /* Wait for interrupt to indicate command is completed. */
508 timeout
= wait_for_completion_timeout(&pip
->cmd_ready
,
509 msecs_to_jiffies(timeout
));
511 atomic_dec(&pip
->cmd_issued
);
518 static int cyapa_do_i2c_pip_cmd_polling(
520 u8
*cmd
, size_t cmd_len
,
521 u8
*resp_data
, int *resp_len
,
522 unsigned long timeout
,
525 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
530 atomic_inc(&pip
->cmd_issued
);
531 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
533 atomic_dec(&pip
->cmd_issued
);
534 return error
< 0 ? error
: -EIO
;
537 length
= resp_len
? *resp_len
: 0;
538 if (resp_data
&& resp_len
&& length
!= 0 && func
) {
541 usleep_range(3000, 5000);
543 error
= cyapa_empty_pip_output_data(cyapa
,
544 resp_data
, resp_len
, func
);
545 if (error
|| *resp_len
== 0)
549 } while (--tries
> 0);
550 if ((error
|| *resp_len
== 0) || tries
<= 0)
551 error
= error
? error
: -ETIMEDOUT
;
554 atomic_dec(&pip
->cmd_issued
);
558 int cyapa_i2c_pip_cmd_irq_sync(
560 u8
*cmd
, int cmd_len
,
561 u8
*resp_data
, int *resp_len
,
562 unsigned long timeout
,
566 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
569 if (!cmd
|| !cmd_len
)
572 /* Commands must be serialized. */
573 error
= mutex_lock_interruptible(&pip
->cmd_lock
);
577 pip
->resp_sort_func
= func
;
578 pip
->resp_data
= resp_data
;
579 pip
->resp_len
= resp_len
;
581 if (cmd_len
>= PIP_MIN_APP_CMD_LENGTH
&&
582 cmd
[4] == PIP_APP_CMD_REPORT_ID
) {
583 /* Application command */
584 pip
->in_progress_cmd
= cmd
[6] & 0x7f;
585 } else if (cmd_len
>= PIP_MIN_BL_CMD_LENGTH
&&
586 cmd
[4] == PIP_BL_CMD_REPORT_ID
) {
587 /* Bootloader command */
588 pip
->in_progress_cmd
= cmd
[7];
591 /* Send command data, wait and read output response data's length. */
593 pip
->is_irq_mode
= true;
594 error
= cyapa_do_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
596 if (error
== -ETIMEDOUT
&& resp_data
&&
597 resp_len
&& *resp_len
!= 0 && func
) {
599 * For some old version, there was no interrupt for
600 * the command response data, so need to poll here
601 * to try to get the response data.
603 error
= cyapa_empty_pip_output_data(cyapa
,
604 resp_data
, resp_len
, func
);
605 if (error
|| *resp_len
== 0)
606 error
= error
? error
: -ETIMEDOUT
;
609 pip
->is_irq_mode
= false;
610 error
= cyapa_do_i2c_pip_cmd_polling(cyapa
, cmd
, cmd_len
,
611 resp_data
, resp_len
, timeout
, func
);
614 pip
->resp_sort_func
= NULL
;
615 pip
->resp_data
= NULL
;
616 pip
->resp_len
= NULL
;
617 pip
->in_progress_cmd
= PIP_INVALID_CMD
;
619 mutex_unlock(&pip
->cmd_lock
);
623 bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa
*cyapa
,
626 if (!data
|| len
< PIP_MIN_BL_RESP_LENGTH
)
629 /* Bootloader input report id 30h */
630 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_BL_RESP_REPORT_ID
&&
631 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
632 data
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
)
638 bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa
*cyapa
,
641 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
644 if (!data
|| len
< PIP_MIN_APP_RESP_LENGTH
)
647 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_APP_RESP_REPORT_ID
&&
648 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
) {
649 resp_len
= get_unaligned_le16(&data
[PIP_RESP_LENGTH_OFFSET
]);
650 if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) == 0x00 &&
651 resp_len
== PIP_UNSUPPORTED_CMD_RESP_LENGTH
&&
652 data
[5] == pip
->in_progress_cmd
) {
653 /* Unsupported command code */
655 } else if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) ==
656 pip
->in_progress_cmd
) {
657 /* Correct command response received */
665 static bool cyapa_sort_pip_application_launch_data(struct cyapa
*cyapa
,
668 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
672 * After reset or power on, trackpad device always sets to 0x00 0x00
673 * to indicate a reset or power on event.
675 if (buf
[0] == 0 && buf
[1] == 0)
681 static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa
*cyapa
,
687 /* Check hid descriptor. */
688 if (len
!= PIP_HID_DESCRIPTOR_SIZE
)
691 resp_len
= get_unaligned_le16(&buf
[PIP_RESP_LENGTH_OFFSET
]);
692 max_output_len
= get_unaligned_le16(&buf
[16]);
693 if (resp_len
== PIP_HID_DESCRIPTOR_SIZE
) {
694 if (buf
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_HID_BL_REPORT_ID
&&
695 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
696 /* BL mode HID Descriptor */
698 } else if ((buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
699 PIP_HID_APP_REPORT_ID
) &&
700 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
701 /* APP mode HID Descriptor */
709 static bool cyapa_sort_pip_deep_sleep_data(struct cyapa
*cyapa
,
712 if (len
== PIP_DEEP_SLEEP_RESP_LENGTH
&&
713 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
714 PIP_APP_DEEP_SLEEP_REPORT_ID
&&
715 (buf
[4] & PIP_DEEP_SLEEP_OPCODE_MASK
) ==
716 PIP_DEEP_SLEEP_OPCODE
)
721 static int gen5_idle_state_parse(struct cyapa
*cyapa
)
723 u8 resp_data
[PIP_HID_DESCRIPTOR_SIZE
];
731 * Dump all buffered data firstly for the situation
732 * when the trackpad is just power on the cyapa go here.
734 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
736 memset(resp_data
, 0, sizeof(resp_data
));
737 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
, 3);
739 return ret
< 0 ? ret
: -EIO
;
741 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
742 if (length
== PIP_RESP_LENGTH_SIZE
) {
743 /* Normal state of Gen5 with no data to response */
744 cyapa
->gen
= CYAPA_GEN5
;
746 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
748 /* Read description from trackpad device */
751 length
= PIP_HID_DESCRIPTOR_SIZE
;
752 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
753 cmd
, PIP_RESP_LENGTH_SIZE
,
756 cyapa_sort_gen5_hid_descriptor_data
,
761 length
= get_unaligned_le16(
762 &resp_data
[PIP_RESP_LENGTH_OFFSET
]);
763 max_output_len
= get_unaligned_le16(&resp_data
[16]);
764 if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
765 length
== PIP_RESP_LENGTH_SIZE
) &&
766 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
767 PIP_HID_BL_REPORT_ID
) &&
768 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
769 /* BL mode HID Description read */
770 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
771 } else if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
772 length
== PIP_RESP_LENGTH_SIZE
) &&
773 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
774 PIP_HID_APP_REPORT_ID
) &&
775 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
776 /* APP mode HID Description read */
777 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
779 /* Should not happen!!! */
780 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
787 static int gen5_hid_description_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
794 /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
795 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
797 * Must read HID Description content through out,
798 * otherwise Gen5 trackpad cannot response next command
799 * or report any touch or button data.
801 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
,
802 PIP_HID_DESCRIPTOR_SIZE
);
803 if (ret
!= PIP_HID_DESCRIPTOR_SIZE
)
804 return ret
< 0 ? ret
: -EIO
;
805 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
806 max_output_len
= get_unaligned_le16(&resp_data
[16]);
807 if (length
== PIP_RESP_LENGTH_SIZE
) {
808 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
809 PIP_HID_BL_REPORT_ID
) {
811 * BL mode HID Description has been previously
814 cyapa
->gen
= CYAPA_GEN5
;
815 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
818 * APP mode HID Description has been previously
821 cyapa
->gen
= CYAPA_GEN5
;
822 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
824 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
825 resp_data
[2] == PIP_HID_BL_REPORT_ID
&&
826 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
827 /* BL mode HID Description read. */
828 cyapa
->gen
= CYAPA_GEN5
;
829 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
830 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
831 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
832 PIP_HID_APP_REPORT_ID
) &&
833 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
834 /* APP mode HID Description read. */
835 cyapa
->gen
= CYAPA_GEN5
;
836 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
838 /* Should not happen!!! */
839 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
845 static int gen5_report_data_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
849 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
850 switch (reg_data
[PIP_RESP_REPORT_ID_OFFSET
]) {
851 case PIP_TOUCH_REPORT_ID
:
852 if (length
< PIP_TOUCH_REPORT_HEAD_SIZE
||
853 length
> PIP_TOUCH_REPORT_MAX_SIZE
)
856 case PIP_BTN_REPORT_ID
:
857 case GEN5_OLD_PUSH_BTN_REPORT_ID
:
858 case PIP_PUSH_BTN_REPORT_ID
:
859 if (length
< PIP_BTN_REPORT_HEAD_SIZE
||
860 length
> PIP_BTN_REPORT_MAX_SIZE
)
863 case PIP_WAKEUP_EVENT_REPORT_ID
:
864 if (length
!= PIP_WAKEUP_EVENT_SIZE
)
871 cyapa
->gen
= CYAPA_GEN5
;
872 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
876 static int gen5_cmd_resp_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
878 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
883 * Must read report data through out,
884 * otherwise Gen5 trackpad cannot response next command
885 * or report any touch or button data.
887 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
888 ret
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
, length
);
890 return ret
< 0 ? ret
: -EIO
;
892 if (length
== PIP_RESP_LENGTH_SIZE
) {
893 /* Previous command has read the data through out. */
894 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
895 PIP_BL_RESP_REPORT_ID
) {
896 /* Gen5 BL command response data detected */
897 cyapa
->gen
= CYAPA_GEN5
;
898 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
900 /* Gen5 APP command response data detected */
901 cyapa
->gen
= CYAPA_GEN5
;
902 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
904 } else if ((pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
905 PIP_BL_RESP_REPORT_ID
) &&
906 (pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
907 PIP_RESP_RSVD_KEY
) &&
908 (pip
->empty_buf
[PIP_RESP_BL_SOP_OFFSET
] ==
910 (pip
->empty_buf
[length
- 1] ==
912 /* Gen5 BL command response data detected */
913 cyapa
->gen
= CYAPA_GEN5
;
914 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
915 } else if (pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
916 PIP_APP_RESP_REPORT_ID
&&
917 pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
919 /* Gen5 APP command response data detected */
920 cyapa
->gen
= CYAPA_GEN5
;
921 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
923 /* Should not happen!!! */
924 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
930 static int cyapa_gen5_state_parse(struct cyapa
*cyapa
, u8
*reg_data
, int len
)
934 if (!reg_data
|| len
< 3)
937 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
939 /* Parse based on Gen5 characteristic registers and bits */
940 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
941 if (length
== 0 || length
== PIP_RESP_LENGTH_SIZE
) {
942 gen5_idle_state_parse(cyapa
);
943 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
944 (reg_data
[2] == PIP_HID_BL_REPORT_ID
||
945 reg_data
[2] == PIP_HID_APP_REPORT_ID
)) {
946 gen5_hid_description_header_parse(cyapa
, reg_data
);
947 } else if ((length
== GEN5_APP_REPORT_DESCRIPTOR_SIZE
||
948 length
== GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE
) &&
949 reg_data
[2] == GEN5_APP_REPORT_DESCRIPTOR_ID
) {
950 /* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
951 cyapa
->gen
= CYAPA_GEN5
;
952 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
953 } else if (length
== GEN5_BL_REPORT_DESCRIPTOR_SIZE
&&
954 reg_data
[2] == GEN5_BL_REPORT_DESCRIPTOR_ID
) {
955 /* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */
956 cyapa
->gen
= CYAPA_GEN5
;
957 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
958 } else if (reg_data
[2] == PIP_TOUCH_REPORT_ID
||
959 reg_data
[2] == PIP_BTN_REPORT_ID
||
960 reg_data
[2] == GEN5_OLD_PUSH_BTN_REPORT_ID
||
961 reg_data
[2] == PIP_PUSH_BTN_REPORT_ID
||
962 reg_data
[2] == PIP_WAKEUP_EVENT_REPORT_ID
) {
963 gen5_report_data_header_parse(cyapa
, reg_data
);
964 } else if (reg_data
[2] == PIP_BL_RESP_REPORT_ID
||
965 reg_data
[2] == PIP_APP_RESP_REPORT_ID
) {
966 gen5_cmd_resp_header_parse(cyapa
, reg_data
);
969 if (cyapa
->gen
== CYAPA_GEN5
) {
971 * Must read the content (e.g.: report description and so on)
972 * from trackpad device throughout. Otherwise,
973 * Gen5 trackpad cannot response to next command or
974 * report any touch or button data later.
976 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
978 if (cyapa
->state
== CYAPA_STATE_GEN5_APP
||
979 cyapa
->state
== CYAPA_STATE_GEN5_BL
)
986 static struct cyapa_tsg_bin_image_data_record
*
987 cyapa_get_image_record_data_num(const struct firmware
*fw
,
992 head_size
= fw
->data
[0] + 1;
993 *record_num
= (fw
->size
- head_size
) /
994 sizeof(struct cyapa_tsg_bin_image_data_record
);
995 return (struct cyapa_tsg_bin_image_data_record
*)&fw
->data
[head_size
];
998 int cyapa_pip_bl_initiate(struct cyapa
*cyapa
, const struct firmware
*fw
)
1000 struct cyapa_tsg_bin_image_data_record
*image_records
;
1001 struct pip_bl_cmd_head
*bl_cmd_head
;
1002 struct pip_bl_packet_start
*bl_packet_start
;
1003 struct pip_bl_initiate_cmd_data
*cmd_data
;
1004 struct pip_bl_packet_end
*bl_packet_end
;
1005 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1009 u16 meta_data_crc
= 0;
1016 /* Try to dump all buffered report data before any send command. */
1017 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1019 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1020 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1021 cmd_data_len
= CYAPA_TSG_BL_KEY_SIZE
+ CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
;
1022 cmd_len
= sizeof(struct pip_bl_cmd_head
) + cmd_data_len
+
1023 sizeof(struct pip_bl_packet_end
);
1025 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1026 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1027 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1029 bl_packet_start
= &bl_cmd_head
->packet_start
;
1030 bl_packet_start
->sop
= PIP_SOP_KEY
;
1031 bl_packet_start
->cmd_code
= PIP_BL_CMD_INITIATE_BL
;
1032 /* 8 key bytes and 128 bytes block size */
1033 put_unaligned_le16(cmd_data_len
, &bl_packet_start
->data_length
);
1035 cmd_data
= (struct pip_bl_initiate_cmd_data
*)bl_cmd_head
->data
;
1036 memcpy(cmd_data
->key
, cyapa_pip_bl_cmd_key
, CYAPA_TSG_BL_KEY_SIZE
);
1038 image_records
= cyapa_get_image_record_data_num(fw
, &records_num
);
1040 /* APP_INTEGRITY row is always the last row block */
1041 data
= image_records
[records_num
- 1].record_data
;
1042 memcpy(cmd_data
->metadata_raw_parameter
, data
,
1043 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1045 meta_data_crc
= crc_itu_t(0xffff, cmd_data
->metadata_raw_parameter
,
1046 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1047 put_unaligned_le16(meta_data_crc
, &cmd_data
->metadata_crc
);
1049 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1051 cmd_crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1052 sizeof(struct pip_bl_packet_start
) + cmd_data_len
);
1053 put_unaligned_le16(cmd_crc
, &bl_packet_end
->crc
);
1054 bl_packet_end
->eop
= PIP_EOP_KEY
;
1056 resp_len
= sizeof(resp_data
);
1057 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1059 resp_data
, &resp_len
, 12000,
1060 cyapa_sort_tsg_pip_bl_resp_data
, true);
1061 if (error
|| resp_len
!= PIP_BL_INITIATE_RESP_LEN
||
1062 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1063 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1064 return error
? error
: -EAGAIN
;
1069 static bool cyapa_sort_pip_bl_exit_data(struct cyapa
*cyapa
, u8
*buf
, int len
)
1071 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
1074 if (buf
[0] == 0 && buf
[1] == 0)
1077 /* Exit bootloader failed for some reason. */
1078 if (len
== PIP_BL_FAIL_EXIT_RESP_LEN
&&
1079 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
1080 PIP_BL_RESP_REPORT_ID
&&
1081 buf
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
1082 buf
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
&&
1083 buf
[10] == PIP_EOP_KEY
)
1089 int cyapa_pip_bl_exit(struct cyapa
*cyapa
)
1092 u8 bl_gen5_bl_exit
[] = { 0x04, 0x00,
1093 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00,
1100 resp_len
= sizeof(resp_data
);
1101 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1102 bl_gen5_bl_exit
, sizeof(bl_gen5_bl_exit
),
1103 resp_data
, &resp_len
,
1104 5000, cyapa_sort_pip_bl_exit_data
, false);
1108 if (resp_len
== PIP_BL_FAIL_EXIT_RESP_LEN
||
1109 resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
1110 PIP_BL_RESP_REPORT_ID
)
1113 if (resp_data
[0] == 0x00 && resp_data
[1] == 0x00)
1119 int cyapa_pip_bl_enter(struct cyapa
*cyapa
)
1121 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 };
1126 error
= cyapa_poll_state(cyapa
, 500);
1130 /* Already in bootloader mode, Skipping exit. */
1131 if (cyapa_is_pip_bl_mode(cyapa
))
1133 else if (!cyapa_is_pip_app_mode(cyapa
))
1136 /* Try to dump all buffered report data before any send command. */
1137 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1140 * Send bootloader enter command to trackpad device,
1141 * after enter bootloader, the response data is two bytes of 0x00 0x00.
1143 resp_len
= sizeof(resp_data
);
1144 memset(resp_data
, 0, resp_len
);
1145 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1147 resp_data
, &resp_len
,
1148 5000, cyapa_sort_pip_application_launch_data
,
1150 if (error
|| resp_data
[0] != 0x00 || resp_data
[1] != 0x00)
1151 return error
< 0 ? error
: -EAGAIN
;
1153 cyapa
->operational
= false;
1154 if (cyapa
->gen
== CYAPA_GEN5
)
1155 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
1156 else if (cyapa
->gen
== CYAPA_GEN6
)
1157 cyapa
->state
= CYAPA_STATE_GEN6_BL
;
1161 static int cyapa_pip_fw_head_check(struct cyapa
*cyapa
,
1162 struct cyapa_tsg_bin_image_head
*image_head
)
1164 if (image_head
->head_size
!= 0x0C && image_head
->head_size
!= 0x12)
1167 switch (cyapa
->gen
) {
1169 if (image_head
->family_id
!= 0x9B ||
1170 image_head
->silicon_id_hi
!= 0x0B)
1174 /* Gen5 without proximity support. */
1175 if (cyapa
->platform_ver
< 2) {
1176 if (image_head
->head_size
== 0x0C)
1181 if (image_head
->family_id
!= 0x91 ||
1182 image_head
->silicon_id_hi
!= 0x02)
1192 int cyapa_pip_check_fw(struct cyapa
*cyapa
, const struct firmware
*fw
)
1194 struct device
*dev
= &cyapa
->client
->dev
;
1195 struct cyapa_tsg_bin_image_data_record
*image_records
;
1196 const struct cyapa_tsg_bin_image_data_record
*app_integrity
;
1197 const struct tsg_bl_metadata_row_params
*metadata
;
1198 int flash_records_count
;
1199 u32 fw_app_start
, fw_upgrade_start
;
1200 u16 fw_app_len
, fw_upgrade_len
;
1202 u16 app_integrity_crc
;
1205 /* Verify the firmware image not miss-used for Gen5 and Gen6. */
1206 if (cyapa_pip_fw_head_check(cyapa
,
1207 (struct cyapa_tsg_bin_image_head
*)fw
->data
)) {
1208 dev_err(dev
, "%s: firmware image not match TP device.\n",
1214 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1217 * APP_INTEGRITY row is always the last row block,
1218 * and the row id must be 0x01ff.
1220 app_integrity
= &image_records
[flash_records_count
- 1];
1222 if (app_integrity
->flash_array_id
!= 0x00 ||
1223 get_unaligned_be16(&app_integrity
->row_number
) != 0x01ff) {
1224 dev_err(dev
, "%s: invalid app_integrity data.\n", __func__
);
1228 metadata
= (const void *)app_integrity
->record_data
;
1230 /* Verify app_integrity crc */
1231 app_integrity_crc
= crc_itu_t(0xffff, app_integrity
->record_data
,
1232 CYAPA_TSG_APP_INTEGRITY_SIZE
);
1233 if (app_integrity_crc
!= get_unaligned_le16(&metadata
->metadata_crc
)) {
1234 dev_err(dev
, "%s: invalid app_integrity crc.\n", __func__
);
1238 fw_app_start
= get_unaligned_le32(&metadata
->app_start
);
1239 fw_app_len
= get_unaligned_le16(&metadata
->app_len
);
1240 fw_upgrade_start
= get_unaligned_le32(&metadata
->upgrade_start
);
1241 fw_upgrade_len
= get_unaligned_le16(&metadata
->upgrade_len
);
1243 if (fw_app_start
% CYAPA_TSG_FW_ROW_SIZE
||
1244 fw_app_len
% CYAPA_TSG_FW_ROW_SIZE
||
1245 fw_upgrade_start
% CYAPA_TSG_FW_ROW_SIZE
||
1246 fw_upgrade_len
% CYAPA_TSG_FW_ROW_SIZE
) {
1247 dev_err(dev
, "%s: invalid image alignment.\n", __func__
);
1251 /* Verify application image CRC. */
1253 for (i
= 0; i
< fw_app_len
/ CYAPA_TSG_FW_ROW_SIZE
; i
++) {
1254 const u8
*data
= image_records
[i
].record_data
;
1256 app_crc
= crc_itu_t(app_crc
, data
, CYAPA_TSG_FW_ROW_SIZE
);
1259 if (app_crc
!= get_unaligned_le16(&metadata
->app_crc
)) {
1260 dev_err(dev
, "%s: invalid firmware app crc check.\n", __func__
);
1267 static int cyapa_pip_write_fw_block(struct cyapa
*cyapa
,
1268 struct cyapa_tsg_bin_image_data_record
*flash_record
)
1270 struct pip_bl_cmd_head
*bl_cmd_head
;
1271 struct pip_bl_packet_start
*bl_packet_start
;
1272 struct tsg_bl_flash_row_head
*flash_row_head
;
1273 struct pip_bl_packet_end
*bl_packet_end
;
1274 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1286 flash_array_id
= flash_record
->flash_array_id
;
1287 flash_row_id
= get_unaligned_be16(&flash_record
->row_number
);
1288 record_len
= get_unaligned_be16(&flash_record
->record_len
);
1289 record_data
= flash_record
->record_data
;
1291 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1292 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1293 bl_packet_start
= &bl_cmd_head
->packet_start
;
1294 cmd_len
= sizeof(struct pip_bl_cmd_head
) +
1295 sizeof(struct tsg_bl_flash_row_head
) +
1296 CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
+
1297 sizeof(struct pip_bl_packet_end
);
1299 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1300 /* Don't include 2 bytes register address */
1301 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1302 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1303 bl_packet_start
->sop
= PIP_SOP_KEY
;
1304 bl_packet_start
->cmd_code
= PIP_BL_CMD_PROGRAM_VERIFY_ROW
;
1306 /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */
1307 data_len
= sizeof(struct tsg_bl_flash_row_head
) + record_len
;
1308 put_unaligned_le16(data_len
, &bl_packet_start
->data_length
);
1310 flash_row_head
= (struct tsg_bl_flash_row_head
*)bl_cmd_head
->data
;
1311 flash_row_head
->flash_array_id
= flash_array_id
;
1312 put_unaligned_le16(flash_row_id
, &flash_row_head
->flash_row_id
);
1313 memcpy(flash_row_head
->flash_data
, record_data
, record_len
);
1315 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1317 crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1318 sizeof(struct pip_bl_packet_start
) + data_len
);
1319 put_unaligned_le16(crc
, &bl_packet_end
->crc
);
1320 bl_packet_end
->eop
= PIP_EOP_KEY
;
1322 resp_len
= sizeof(resp_data
);
1323 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1324 resp_data
, &resp_len
,
1325 500, cyapa_sort_tsg_pip_bl_resp_data
, true);
1326 if (error
|| resp_len
!= PIP_BL_BLOCK_WRITE_RESP_LEN
||
1327 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1328 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1329 return error
< 0 ? error
: -EAGAIN
;
1334 int cyapa_pip_do_fw_update(struct cyapa
*cyapa
,
1335 const struct firmware
*fw
)
1337 struct device
*dev
= &cyapa
->client
->dev
;
1338 struct cyapa_tsg_bin_image_data_record
*image_records
;
1339 int flash_records_count
;
1343 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1346 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1349 * The last flash row 0x01ff has been written through bl_initiate
1350 * command, so DO NOT write flash 0x01ff to trackpad device.
1352 for (i
= 0; i
< (flash_records_count
- 1); i
++) {
1353 error
= cyapa_pip_write_fw_block(cyapa
, &image_records
[i
]);
1355 dev_err(dev
, "%s: Gen5 FW update aborted: %d\n",
1364 static int cyapa_gen5_change_power_state(struct cyapa
*cyapa
, u8 power_state
)
1366 u8 cmd
[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 };
1371 cmd
[7] = power_state
;
1372 resp_len
= sizeof(resp_data
);
1373 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1374 resp_data
, &resp_len
,
1375 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1376 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x08) ||
1377 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1378 return error
< 0 ? error
: -EINVAL
;
1383 static int cyapa_gen5_set_interval_time(struct cyapa
*cyapa
,
1384 u8 parameter_id
, u16 interval_time
)
1386 struct pip_app_cmd_head
*app_cmd_head
;
1387 struct gen5_app_set_parameter_data
*parameter_data
;
1388 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1395 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1396 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1397 parameter_data
= (struct gen5_app_set_parameter_data
*)
1398 app_cmd_head
->parameter_data
;
1399 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1400 sizeof(struct gen5_app_set_parameter_data
);
1402 switch (parameter_id
) {
1403 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1404 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1406 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1407 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1409 case GEN5_PARAMETER_LP_INTRVL_ID
:
1410 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1416 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1418 * Don't include unused parameter value bytes and
1419 * 2 bytes register address.
1421 put_unaligned_le16(cmd_len
- (4 - parameter_size
) - 2,
1422 &app_cmd_head
->length
);
1423 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1424 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1425 parameter_data
->parameter_id
= parameter_id
;
1426 parameter_data
->parameter_size
= parameter_size
;
1427 put_unaligned_le32((u32
)interval_time
, ¶meter_data
->value
);
1428 resp_len
= sizeof(resp_data
);
1429 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1430 resp_data
, &resp_len
,
1431 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1432 if (error
|| resp_data
[5] != parameter_id
||
1433 resp_data
[6] != parameter_size
||
1434 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
))
1435 return error
< 0 ? error
: -EINVAL
;
1440 static int cyapa_gen5_get_interval_time(struct cyapa
*cyapa
,
1441 u8 parameter_id
, u16
*interval_time
)
1443 struct pip_app_cmd_head
*app_cmd_head
;
1444 struct gen5_app_get_parameter_data
*parameter_data
;
1445 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1453 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1454 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1455 parameter_data
= (struct gen5_app_get_parameter_data
*)
1456 app_cmd_head
->parameter_data
;
1457 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1458 sizeof(struct gen5_app_get_parameter_data
);
1461 switch (parameter_id
) {
1462 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1463 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1465 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1466 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1468 case GEN5_PARAMETER_LP_INTRVL_ID
:
1469 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1475 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1476 /* Don't include 2 bytes register address */
1477 put_unaligned_le16(cmd_len
- 2, &app_cmd_head
->length
);
1478 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1479 app_cmd_head
->cmd_code
= GEN5_CMD_GET_PARAMETER
;
1480 parameter_data
->parameter_id
= parameter_id
;
1482 resp_len
= sizeof(resp_data
);
1483 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1484 resp_data
, &resp_len
,
1485 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1486 if (error
|| resp_data
[5] != parameter_id
|| resp_data
[6] == 0 ||
1487 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_GET_PARAMETER
))
1488 return error
< 0 ? error
: -EINVAL
;
1491 for (i
= 0; i
< parameter_size
; i
++)
1492 mask
|= (0xff << (i
* 8));
1493 *interval_time
= get_unaligned_le16(&resp_data
[7]) & mask
;
1498 static int cyapa_gen5_disable_pip_report(struct cyapa
*cyapa
)
1500 struct pip_app_cmd_head
*app_cmd_head
;
1506 memset(cmd
, 0, sizeof(cmd
));
1507 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1509 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1510 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1511 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1512 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1513 app_cmd_head
->parameter_data
[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT
;
1514 app_cmd_head
->parameter_data
[1] = 0x01;
1515 app_cmd_head
->parameter_data
[2] = 0x01;
1516 resp_len
= sizeof(resp_data
);
1517 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1518 resp_data
, &resp_len
,
1519 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1520 if (error
|| resp_data
[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT
||
1521 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
) ||
1522 resp_data
[6] != 0x01)
1523 return error
< 0 ? error
: -EINVAL
;
1528 int cyapa_pip_set_proximity(struct cyapa
*cyapa
, bool enable
)
1530 u8 cmd
[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY
,
1537 resp_len
= sizeof(resp_data
);
1538 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1539 resp_data
, &resp_len
,
1540 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1541 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_SET_PROXIMITY
) ||
1542 !PIP_CMD_COMPLETE_SUCCESS(resp_data
)) {
1543 error
= (error
== -ETIMEDOUT
) ? -EOPNOTSUPP
: error
;
1544 return error
< 0 ? error
: -EINVAL
;
1550 int cyapa_pip_deep_sleep(struct cyapa
*cyapa
, u8 state
)
1552 u8 cmd
[] = { 0x05, 0x00, 0x00, 0x08};
1557 cmd
[2] = state
& PIP_DEEP_SLEEP_STATE_MASK
;
1558 resp_len
= sizeof(resp_data
);
1559 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1560 resp_data
, &resp_len
,
1561 500, cyapa_sort_pip_deep_sleep_data
, false);
1562 if (error
|| ((resp_data
[3] & PIP_DEEP_SLEEP_STATE_MASK
) != state
))
1568 static int cyapa_gen5_set_power_mode(struct cyapa
*cyapa
,
1569 u8 power_mode
, u16 sleep_time
, bool is_suspend
)
1571 struct device
*dev
= &cyapa
->client
->dev
;
1575 if (cyapa
->state
!= CYAPA_STATE_GEN5_APP
)
1578 if (PIP_DEV_GET_PWR_STATE(cyapa
) == UNINIT_PWR_MODE
) {
1580 * Assume TP in deep sleep mode when driver is loaded,
1581 * avoid driver unload and reload command IO issue caused by TP
1582 * has been set into deep sleep mode when unloading.
1584 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1587 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) &&
1588 PIP_DEV_GET_PWR_STATE(cyapa
) != PWR_MODE_OFF
)
1589 if (cyapa_gen5_get_interval_time(cyapa
,
1590 GEN5_PARAMETER_LP_INTRVL_ID
,
1591 &cyapa
->dev_sleep_time
) != 0)
1592 PIP_DEV_SET_SLEEP_TIME(cyapa
, UNINIT_SLEEP_TIME
);
1594 if (PIP_DEV_GET_PWR_STATE(cyapa
) == power_mode
) {
1595 if (power_mode
== PWR_MODE_OFF
||
1596 power_mode
== PWR_MODE_FULL_ACTIVE
||
1597 power_mode
== PWR_MODE_BTN_ONLY
||
1598 PIP_DEV_GET_SLEEP_TIME(cyapa
) == sleep_time
) {
1599 /* Has in correct power mode state, early return. */
1604 if (power_mode
== PWR_MODE_OFF
) {
1605 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_OFF
);
1607 dev_err(dev
, "enter deep sleep fail: %d\n", error
);
1611 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1616 * When trackpad in power off mode, it cannot change to other power
1617 * state directly, must be wake up from sleep firstly, then
1618 * continue to do next power sate change.
1620 if (PIP_DEV_GET_PWR_STATE(cyapa
) == PWR_MODE_OFF
) {
1621 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_ON
);
1623 dev_err(dev
, "deep sleep wake fail: %d\n", error
);
1628 if (power_mode
== PWR_MODE_FULL_ACTIVE
) {
1629 error
= cyapa_gen5_change_power_state(cyapa
,
1630 GEN5_POWER_STATE_ACTIVE
);
1632 dev_err(dev
, "change to active fail: %d\n", error
);
1636 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_FULL_ACTIVE
);
1637 } else if (power_mode
== PWR_MODE_BTN_ONLY
) {
1638 error
= cyapa_gen5_change_power_state(cyapa
,
1639 GEN5_POWER_STATE_BTN_ONLY
);
1641 dev_err(dev
, "fail to button only mode: %d\n", error
);
1645 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_BTN_ONLY
);
1648 * Continue to change power mode even failed to set
1649 * interval time, it won't affect the power mode change.
1650 * except the sleep interval time is not correct.
1652 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) ||
1653 sleep_time
!= PIP_DEV_GET_SLEEP_TIME(cyapa
))
1654 if (cyapa_gen5_set_interval_time(cyapa
,
1655 GEN5_PARAMETER_LP_INTRVL_ID
,
1657 PIP_DEV_SET_SLEEP_TIME(cyapa
, sleep_time
);
1659 if (sleep_time
<= GEN5_POWER_READY_MAX_INTRVL_TIME
)
1660 power_state
= GEN5_POWER_STATE_READY
;
1662 power_state
= GEN5_POWER_STATE_IDLE
;
1663 error
= cyapa_gen5_change_power_state(cyapa
, power_state
);
1665 dev_err(dev
, "set power state to 0x%02x failed: %d\n",
1666 power_state
, error
);
1671 * Disable pip report for a little time, firmware will
1672 * re-enable it automatically. It's used to fix the issue
1673 * that trackpad unable to report signal to wake system up
1674 * in the special situation that system is in suspending, and
1675 * at the same time, user touch trackpad to wake system up.
1676 * This function can avoid the data to be buffered when system
1677 * is suspending which may cause interrupt line unable to be
1681 cyapa_gen5_disable_pip_report(cyapa
);
1683 PIP_DEV_SET_PWR_STATE(cyapa
,
1684 cyapa_sleep_time_to_pwr_cmd(sleep_time
));
1690 int cyapa_pip_resume_scanning(struct cyapa
*cyapa
)
1692 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
1697 /* Try to dump all buffered data before doing command. */
1698 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1700 resp_len
= sizeof(resp_data
);
1701 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1703 resp_data
, &resp_len
,
1704 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1705 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x04))
1708 /* Try to dump all buffered data when resuming scanning. */
1709 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1714 int cyapa_pip_suspend_scanning(struct cyapa
*cyapa
)
1716 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
1721 /* Try to dump all buffered data before doing command. */
1722 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1724 resp_len
= sizeof(resp_data
);
1725 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1727 resp_data
, &resp_len
,
1728 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1729 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x03))
1732 /* Try to dump all buffered data when suspending scanning. */
1733 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1738 static int cyapa_pip_calibrate_pwcs(struct cyapa
*cyapa
,
1739 u8 calibrate_sensing_mode_type
)
1741 struct pip_app_cmd_head
*app_cmd_head
;
1747 /* Try to dump all buffered data before doing command. */
1748 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1750 memset(cmd
, 0, sizeof(cmd
));
1751 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1752 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1753 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1754 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1755 app_cmd_head
->cmd_code
= PIP_CMD_CALIBRATE
;
1756 app_cmd_head
->parameter_data
[0] = calibrate_sensing_mode_type
;
1757 resp_len
= sizeof(resp_data
);
1758 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1760 resp_data
, &resp_len
,
1761 5000, cyapa_sort_tsg_pip_app_resp_data
, true);
1762 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_CMD_CALIBRATE
) ||
1763 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1764 return error
< 0 ? error
: -EAGAIN
;
1769 ssize_t
cyapa_pip_do_calibrate(struct device
*dev
,
1770 struct device_attribute
*attr
,
1771 const char *buf
, size_t count
)
1773 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
1774 int error
, calibrate_error
;
1776 /* 1. Suspend Scanning*/
1777 error
= cyapa_pip_suspend_scanning(cyapa
);
1781 /* 2. Do mutual capacitance fine calibrate. */
1782 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1783 PIP_SENSING_MODE_MUTUAL_CAP_FINE
);
1784 if (calibrate_error
)
1785 goto resume_scanning
;
1787 /* 3. Do self capacitance calibrate. */
1788 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1789 PIP_SENSING_MODE_SELF_CAP
);
1790 if (calibrate_error
)
1791 goto resume_scanning
;
1794 /* 4. Resume Scanning*/
1795 error
= cyapa_pip_resume_scanning(cyapa
);
1796 if (error
|| calibrate_error
)
1797 return error
? error
: calibrate_error
;
1802 static s32
twos_complement_to_s32(s32 value
, int num_bits
)
1804 if (value
>> (num_bits
- 1))
1805 value
|= -1 << num_bits
;
1809 static s32
cyapa_parse_structure_data(u8 data_format
, u8
*buf
, int buf_len
)
1816 data_size
= (data_format
& 0x07);
1817 big_endian
= ((data_format
& 0x10) == 0x00);
1818 unsigned_type
= ((data_format
& 0x20) == 0x00);
1820 if (buf_len
< data_size
)
1823 switch (data_size
) {
1829 value
= get_unaligned_be16(buf
);
1831 value
= get_unaligned_le16(buf
);
1835 value
= get_unaligned_be32(buf
);
1837 value
= get_unaligned_le32(buf
);
1840 /* Should not happen, just as default case here. */
1846 value
= twos_complement_to_s32(value
, data_size
* 8);
1851 static void cyapa_gen5_guess_electrodes(struct cyapa
*cyapa
,
1852 int *electrodes_rx
, int *electrodes_tx
)
1854 if (cyapa
->electrodes_rx
!= 0) {
1855 *electrodes_rx
= cyapa
->electrodes_rx
;
1856 *electrodes_tx
= (cyapa
->electrodes_x
== *electrodes_rx
) ?
1857 cyapa
->electrodes_y
: cyapa
->electrodes_x
;
1859 *electrodes_tx
= min(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1860 *electrodes_rx
= max(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1865 * Read all the global mutual or self idac data or mutual or self local PWC
1866 * data based on the @idac_data_type.
1867 * If the input value of @data_size is 0, then means read global mutual or
1868 * self idac data. For read global mutual idac data, @idac_max, @idac_min and
1869 * @idac_ave are in order used to return the max value of global mutual idac
1870 * data, the min value of global mutual idac and the average value of the
1871 * global mutual idac data. For read global self idac data, @idac_max is used
1872 * to return the global self cap idac data in Rx direction, @idac_min is used
1873 * to return the global self cap idac data in Tx direction. @idac_ave is not
1875 * If the input value of @data_size is not 0, than means read the mutual or
1876 * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
1877 * return the max, min and average value of the mutual or self local PWC data.
1878 * Note, in order to read mutual local PWC data, must read invoke this function
1879 * to read the mutual global idac data firstly to set the correct Rx number
1880 * value, otherwise, the read mutual idac and PWC data may not correct.
1882 static int cyapa_gen5_read_idac_data(struct cyapa
*cyapa
,
1883 u8 cmd_code
, u8 idac_data_type
, int *data_size
,
1884 int *idac_max
, int *idac_min
, int *idac_ave
)
1886 struct pip_app_cmd_head
*cmd_head
;
1894 bool read_global_idac
;
1895 int sum
, count
, max_element_cnt
;
1896 int tmp_max
, tmp_min
, tmp_ave
, tmp_sum
, tmp_count
;
1897 int electrodes_rx
, electrodes_tx
;
1901 if (cmd_code
!= PIP_RETRIEVE_DATA_STRUCTURE
||
1902 (idac_data_type
!= GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
1903 idac_data_type
!= GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) ||
1904 !data_size
|| !idac_max
|| !idac_min
|| !idac_ave
)
1907 *idac_max
= INT_MIN
;
1908 *idac_min
= INT_MAX
;
1909 sum
= count
= tmp_count
= 0;
1910 electrodes_rx
= electrodes_tx
= 0;
1911 if (*data_size
== 0) {
1913 * Read global idac values firstly.
1914 * Currently, no idac data exceed 4 bytes.
1916 read_global_idac
= true;
1921 tmp_ave
= tmp_sum
= tmp_count
= 0;
1923 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1924 if (cyapa
->aligned_electrodes_rx
== 0) {
1925 cyapa_gen5_guess_electrodes(cyapa
,
1926 &electrodes_rx
, &electrodes_tx
);
1927 cyapa
->aligned_electrodes_rx
=
1928 (electrodes_rx
+ 3) & ~3u;
1931 (cyapa
->aligned_electrodes_rx
+ 7) & ~7u;
1933 max_element_cnt
= 2;
1936 read_global_idac
= false;
1939 /* Calculate the start offset in bytes of local PWC data. */
1940 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1941 offset
= cyapa
->aligned_electrodes_rx
* (*data_size
);
1942 if (cyapa
->electrodes_rx
== cyapa
->electrodes_x
)
1943 electrodes_tx
= cyapa
->electrodes_y
;
1945 electrodes_tx
= cyapa
->electrodes_x
;
1946 max_element_cnt
= ((cyapa
->aligned_electrodes_rx
+ 7) &
1947 ~7u) * electrodes_tx
;
1950 max_element_cnt
= cyapa
->electrodes_x
+
1951 cyapa
->electrodes_y
;
1952 max_element_cnt
= (max_element_cnt
+ 3) & ~3u;
1956 memset(cmd
, 0, sizeof(cmd
));
1957 cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1958 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &cmd_head
->addr
);
1959 put_unaligned_le16(sizeof(cmd
) - 2, &cmd_head
->length
);
1960 cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1961 cmd_head
->cmd_code
= cmd_code
;
1963 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) /
1965 read_elements
= min(read_elements
, max_element_cnt
- count
);
1966 read_len
= read_elements
* (*data_size
);
1968 put_unaligned_le16(offset
, &cmd_head
->parameter_data
[0]);
1969 put_unaligned_le16(read_len
, &cmd_head
->parameter_data
[2]);
1970 cmd_head
->parameter_data
[4] = idac_data_type
;
1971 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
1972 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1974 resp_data
, &resp_len
,
1975 500, cyapa_sort_tsg_pip_app_resp_data
,
1977 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
1978 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
1979 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
1980 resp_data
[6] != idac_data_type
)
1981 return (error
< 0) ? error
: -EAGAIN
;
1982 read_len
= get_unaligned_le16(&resp_data
[7]);
1986 *data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
1987 if (read_len
< *data_size
)
1990 if (read_global_idac
&&
1991 idac_data_type
== GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) {
1992 /* Rx's self global idac data. */
1993 *idac_max
= cyapa_parse_structure_data(
1995 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
],
1997 /* Tx's self global idac data. */
1998 *idac_min
= cyapa_parse_structure_data(
2000 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
+
2006 /* Read mutual global idac or local mutual/self PWC data. */
2008 for (i
= 10; i
< (read_len
+ GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2010 value
= cyapa_parse_structure_data(resp_data
[9],
2011 &resp_data
[i
], *data_size
);
2012 *idac_min
= min(value
, *idac_min
);
2013 *idac_max
= max(value
, *idac_max
);
2015 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
2016 tmp_count
< cyapa
->aligned_electrodes_rx
&&
2019 * The value gap between global and local mutual
2020 * idac data must bigger than 50%.
2021 * Normally, global value bigger than 50,
2022 * local values less than 10.
2024 if (!tmp_ave
|| value
> tmp_ave
/ 2) {
2025 tmp_min
= min(value
, tmp_min
);
2026 tmp_max
= max(value
, tmp_max
);
2030 tmp_ave
= tmp_sum
/ tmp_count
;
2037 if (count
>= max_element_cnt
)
2043 *idac_ave
= count
? (sum
/ count
) : 0;
2045 if (read_global_idac
&&
2046 idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
2050 if (tmp_count
== cyapa
->aligned_electrodes_rx
) {
2051 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2052 cyapa
->electrodes_rx
: electrodes_rx
;
2053 } else if (tmp_count
== electrodes_rx
) {
2054 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2055 cyapa
->electrodes_rx
: electrodes_rx
;
2056 cyapa
->aligned_electrodes_rx
= electrodes_rx
;
2058 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2059 cyapa
->electrodes_rx
: electrodes_tx
;
2060 cyapa
->aligned_electrodes_rx
= tmp_count
;
2063 *idac_min
= tmp_min
;
2064 *idac_max
= tmp_max
;
2065 *idac_ave
= tmp_ave
;
2071 static int cyapa_gen5_read_mutual_idac_data(struct cyapa
*cyapa
,
2072 int *gidac_mutual_max
, int *gidac_mutual_min
, int *gidac_mutual_ave
,
2073 int *lidac_mutual_max
, int *lidac_mutual_min
, int *lidac_mutual_ave
)
2078 *gidac_mutual_max
= *gidac_mutual_min
= *gidac_mutual_ave
= 0;
2079 *lidac_mutual_max
= *lidac_mutual_min
= *lidac_mutual_ave
= 0;
2082 error
= cyapa_gen5_read_idac_data(cyapa
,
2083 PIP_RETRIEVE_DATA_STRUCTURE
,
2084 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2086 gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
);
2090 error
= cyapa_gen5_read_idac_data(cyapa
,
2091 PIP_RETRIEVE_DATA_STRUCTURE
,
2092 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2094 lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
);
2098 static int cyapa_gen5_read_self_idac_data(struct cyapa
*cyapa
,
2099 int *gidac_self_rx
, int *gidac_self_tx
,
2100 int *lidac_self_max
, int *lidac_self_min
, int *lidac_self_ave
)
2105 *gidac_self_rx
= *gidac_self_tx
= 0;
2106 *lidac_self_max
= *lidac_self_min
= *lidac_self_ave
= 0;
2109 error
= cyapa_gen5_read_idac_data(cyapa
,
2110 PIP_RETRIEVE_DATA_STRUCTURE
,
2111 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2113 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2116 *gidac_self_rx
= *lidac_self_max
;
2117 *gidac_self_tx
= *lidac_self_min
;
2119 error
= cyapa_gen5_read_idac_data(cyapa
,
2120 PIP_RETRIEVE_DATA_STRUCTURE
,
2121 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2123 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2127 static ssize_t
cyapa_gen5_execute_panel_scan(struct cyapa
*cyapa
)
2129 struct pip_app_cmd_head
*app_cmd_head
;
2135 memset(cmd
, 0, sizeof(cmd
));
2136 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2137 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2138 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2139 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2140 app_cmd_head
->cmd_code
= GEN5_CMD_EXECUTE_PANEL_SCAN
;
2141 resp_len
= sizeof(resp_data
);
2142 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2144 resp_data
, &resp_len
,
2145 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2146 if (error
|| resp_len
!= sizeof(resp_data
) ||
2147 !VALID_CMD_RESP_HEADER(resp_data
,
2148 GEN5_CMD_EXECUTE_PANEL_SCAN
) ||
2149 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2150 return error
? error
: -EAGAIN
;
2155 static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa
*cyapa
,
2156 u8 cmd_code
, u8 raw_data_type
, int raw_data_max_num
,
2157 int *raw_data_max
, int *raw_data_min
, int *raw_data_ave
,
2160 struct pip_app_cmd_head
*app_cmd_head
;
2161 struct gen5_retrieve_panel_scan_data
*panel_sacn_data
;
2163 u8 resp_data
[256]; /* Max bytes can transfer one time. */
2175 if (cmd_code
!= GEN5_CMD_RETRIEVE_PANEL_SCAN
||
2176 (raw_data_type
> GEN5_PANEL_SCAN_SELF_DIFFCOUNT
) ||
2177 !raw_data_max
|| !raw_data_min
|| !raw_data_ave
)
2180 intp
= (s32
*)buffer
;
2181 *raw_data_max
= INT_MIN
;
2182 *raw_data_min
= INT_MAX
;
2185 /* Assume max element size is 4 currently. */
2186 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) / 4;
2187 read_len
= read_elements
* 4;
2188 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2189 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2190 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2191 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2192 app_cmd_head
->cmd_code
= cmd_code
;
2193 panel_sacn_data
= (struct gen5_retrieve_panel_scan_data
*)
2194 app_cmd_head
->parameter_data
;
2196 put_unaligned_le16(offset
, &panel_sacn_data
->read_offset
);
2197 put_unaligned_le16(read_elements
,
2198 &panel_sacn_data
->read_elements
);
2199 panel_sacn_data
->data_id
= raw_data_type
;
2201 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
2202 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2204 resp_data
, &resp_len
,
2205 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2206 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
2207 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
2208 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
2209 resp_data
[6] != raw_data_type
)
2210 return error
? error
: -EAGAIN
;
2212 read_elements
= get_unaligned_le16(&resp_data
[7]);
2213 if (read_elements
== 0)
2216 data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
2217 offset
+= read_elements
;
2218 if (read_elements
) {
2219 for (i
= GEN5_RESP_DATA_STRUCTURE_OFFSET
;
2220 i
< (read_elements
* data_size
+
2221 GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2223 value
= cyapa_parse_structure_data(resp_data
[9],
2224 &resp_data
[i
], data_size
);
2225 *raw_data_min
= min(value
, *raw_data_min
);
2226 *raw_data_max
= max(value
, *raw_data_max
);
2229 put_unaligned_le32(value
, &intp
[count
]);
2237 if (count
>= raw_data_max_num
)
2240 read_elements
= (sizeof(resp_data
) -
2241 GEN5_RESP_DATA_STRUCTURE_OFFSET
) / data_size
;
2242 read_len
= read_elements
* data_size
;
2245 *raw_data_ave
= count
? (sum
/ count
) : 0;
2250 static ssize_t
cyapa_gen5_show_baseline(struct device
*dev
,
2251 struct device_attribute
*attr
, char *buf
)
2253 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
2254 int gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
;
2255 int lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
;
2256 int gidac_self_rx
, gidac_self_tx
;
2257 int lidac_self_max
, lidac_self_min
, lidac_self_ave
;
2258 int raw_cap_mutual_max
, raw_cap_mutual_min
, raw_cap_mutual_ave
;
2259 int raw_cap_self_max
, raw_cap_self_min
, raw_cap_self_ave
;
2260 int mutual_diffdata_max
, mutual_diffdata_min
, mutual_diffdata_ave
;
2261 int self_diffdata_max
, self_diffdata_min
, self_diffdata_ave
;
2262 int mutual_baseline_max
, mutual_baseline_min
, mutual_baseline_ave
;
2263 int self_baseline_max
, self_baseline_min
, self_baseline_ave
;
2264 int error
, resume_error
;
2267 if (!cyapa_is_pip_app_mode(cyapa
))
2270 /* 1. Suspend Scanning*/
2271 error
= cyapa_pip_suspend_scanning(cyapa
);
2275 /* 2. Read global and local mutual IDAC data. */
2276 gidac_self_rx
= gidac_self_tx
= 0;
2277 error
= cyapa_gen5_read_mutual_idac_data(cyapa
,
2278 &gidac_mutual_max
, &gidac_mutual_min
,
2279 &gidac_mutual_ave
, &lidac_mutual_max
,
2280 &lidac_mutual_min
, &lidac_mutual_ave
);
2282 goto resume_scanning
;
2284 /* 3. Read global and local self IDAC data. */
2285 error
= cyapa_gen5_read_self_idac_data(cyapa
,
2286 &gidac_self_rx
, &gidac_self_tx
,
2287 &lidac_self_max
, &lidac_self_min
,
2290 goto resume_scanning
;
2292 /* 4. Execute panel scan. It must be executed before read data. */
2293 error
= cyapa_gen5_execute_panel_scan(cyapa
);
2295 goto resume_scanning
;
2297 /* 5. Retrieve panel scan, mutual cap raw data. */
2298 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2299 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2300 GEN5_PANEL_SCAN_MUTUAL_RAW_DATA
,
2301 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2302 &raw_cap_mutual_max
, &raw_cap_mutual_min
,
2303 &raw_cap_mutual_ave
,
2306 goto resume_scanning
;
2308 /* 6. Retrieve panel scan, self cap raw data. */
2309 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2310 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2311 GEN5_PANEL_SCAN_SELF_RAW_DATA
,
2312 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2313 &raw_cap_self_max
, &raw_cap_self_min
,
2317 goto resume_scanning
;
2319 /* 7. Retrieve panel scan, mutual cap diffcount raw data. */
2320 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2321 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2322 GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT
,
2323 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2324 &mutual_diffdata_max
, &mutual_diffdata_min
,
2325 &mutual_diffdata_ave
,
2328 goto resume_scanning
;
2330 /* 8. Retrieve panel scan, self cap diffcount raw data. */
2331 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2332 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2333 GEN5_PANEL_SCAN_SELF_DIFFCOUNT
,
2334 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2335 &self_diffdata_max
, &self_diffdata_min
,
2339 goto resume_scanning
;
2341 /* 9. Retrieve panel scan, mutual cap baseline raw data. */
2342 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2343 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2344 GEN5_PANEL_SCAN_MUTUAL_BASELINE
,
2345 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2346 &mutual_baseline_max
, &mutual_baseline_min
,
2347 &mutual_baseline_ave
,
2350 goto resume_scanning
;
2352 /* 10. Retrieve panel scan, self cap baseline raw data. */
2353 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2354 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2355 GEN5_PANEL_SCAN_SELF_BASELINE
,
2356 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2357 &self_baseline_max
, &self_baseline_min
,
2361 goto resume_scanning
;
2364 /* 11. Resume Scanning*/
2365 resume_error
= cyapa_pip_resume_scanning(cyapa
);
2366 if (resume_error
|| error
)
2367 return resume_error
? resume_error
: error
;
2369 /* 12. Output data strings */
2370 size
= scnprintf(buf
, PAGE_SIZE
, "%d %d %d %d %d %d %d %d %d %d %d ",
2371 gidac_mutual_min
, gidac_mutual_max
, gidac_mutual_ave
,
2372 lidac_mutual_min
, lidac_mutual_max
, lidac_mutual_ave
,
2373 gidac_self_rx
, gidac_self_tx
,
2374 lidac_self_min
, lidac_self_max
, lidac_self_ave
);
2375 size
+= scnprintf(buf
+ size
, PAGE_SIZE
- size
,
2376 "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
2377 raw_cap_mutual_min
, raw_cap_mutual_max
, raw_cap_mutual_ave
,
2378 raw_cap_self_min
, raw_cap_self_max
, raw_cap_self_ave
,
2379 mutual_diffdata_min
, mutual_diffdata_max
, mutual_diffdata_ave
,
2380 self_diffdata_min
, self_diffdata_max
, self_diffdata_ave
,
2381 mutual_baseline_min
, mutual_baseline_max
, mutual_baseline_ave
,
2382 self_baseline_min
, self_baseline_max
, self_baseline_ave
);
2386 bool cyapa_pip_sort_system_info_data(struct cyapa
*cyapa
,
2389 /* Check the report id and command code */
2390 if (VALID_CMD_RESP_HEADER(buf
, 0x02))
2396 static int cyapa_gen5_bl_query_data(struct cyapa
*cyapa
)
2398 u8 resp_data
[PIP_BL_APP_INFO_RESP_LENGTH
];
2402 resp_len
= sizeof(resp_data
);
2403 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2404 pip_bl_read_app_info
, PIP_BL_READ_APP_INFO_CMD_LENGTH
,
2405 resp_data
, &resp_len
,
2406 500, cyapa_sort_tsg_pip_bl_resp_data
, false);
2407 if (error
|| resp_len
< PIP_BL_APP_INFO_RESP_LENGTH
||
2408 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2409 return error
? error
: -EIO
;
2411 memcpy(&cyapa
->product_id
[0], &resp_data
[8], 5);
2412 cyapa
->product_id
[5] = '-';
2413 memcpy(&cyapa
->product_id
[6], &resp_data
[13], 6);
2414 cyapa
->product_id
[12] = '-';
2415 memcpy(&cyapa
->product_id
[13], &resp_data
[19], 2);
2416 cyapa
->product_id
[15] = '\0';
2418 cyapa
->fw_maj_ver
= resp_data
[22];
2419 cyapa
->fw_min_ver
= resp_data
[23];
2421 cyapa
->platform_ver
= (resp_data
[26] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2422 PIP_BL_PLATFORM_VER_MASK
;
2427 static int cyapa_gen5_get_query_data(struct cyapa
*cyapa
)
2429 u8 resp_data
[PIP_READ_SYS_INFO_RESP_LENGTH
];
2434 resp_len
= sizeof(resp_data
);
2435 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2436 pip_read_sys_info
, PIP_READ_SYS_INFO_CMD_LENGTH
,
2437 resp_data
, &resp_len
,
2438 2000, cyapa_pip_sort_system_info_data
, false);
2439 if (error
|| resp_len
< sizeof(resp_data
))
2440 return error
? error
: -EIO
;
2442 product_family
= get_unaligned_le16(&resp_data
[7]);
2443 if ((product_family
& PIP_PRODUCT_FAMILY_MASK
) !=
2444 PIP_PRODUCT_FAMILY_TRACKPAD
)
2447 cyapa
->platform_ver
= (resp_data
[49] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2448 PIP_BL_PLATFORM_VER_MASK
;
2449 if (cyapa
->gen
== CYAPA_GEN5
&& cyapa
->platform_ver
< 2) {
2450 /* Gen5 firmware that does not support proximity. */
2451 cyapa
->fw_maj_ver
= resp_data
[15];
2452 cyapa
->fw_min_ver
= resp_data
[16];
2454 cyapa
->fw_maj_ver
= resp_data
[9];
2455 cyapa
->fw_min_ver
= resp_data
[10];
2458 cyapa
->electrodes_x
= resp_data
[52];
2459 cyapa
->electrodes_y
= resp_data
[53];
2461 cyapa
->physical_size_x
= get_unaligned_le16(&resp_data
[54]) / 100;
2462 cyapa
->physical_size_y
= get_unaligned_le16(&resp_data
[56]) / 100;
2464 cyapa
->max_abs_x
= get_unaligned_le16(&resp_data
[58]);
2465 cyapa
->max_abs_y
= get_unaligned_le16(&resp_data
[60]);
2467 cyapa
->max_z
= get_unaligned_le16(&resp_data
[62]);
2469 cyapa
->x_origin
= resp_data
[64] & 0x01;
2470 cyapa
->y_origin
= resp_data
[65] & 0x01;
2472 cyapa
->btn_capability
= (resp_data
[70] << 3) & CAPABILITY_BTN_MASK
;
2474 memcpy(&cyapa
->product_id
[0], &resp_data
[33], 5);
2475 cyapa
->product_id
[5] = '-';
2476 memcpy(&cyapa
->product_id
[6], &resp_data
[38], 6);
2477 cyapa
->product_id
[12] = '-';
2478 memcpy(&cyapa
->product_id
[13], &resp_data
[44], 2);
2479 cyapa
->product_id
[15] = '\0';
2481 if (!cyapa
->electrodes_x
|| !cyapa
->electrodes_y
||
2482 !cyapa
->physical_size_x
|| !cyapa
->physical_size_y
||
2483 !cyapa
->max_abs_x
|| !cyapa
->max_abs_y
|| !cyapa
->max_z
)
2489 static int cyapa_gen5_do_operational_check(struct cyapa
*cyapa
)
2491 struct device
*dev
= &cyapa
->client
->dev
;
2494 if (cyapa
->gen
!= CYAPA_GEN5
)
2497 switch (cyapa
->state
) {
2498 case CYAPA_STATE_GEN5_BL
:
2499 error
= cyapa_pip_bl_exit(cyapa
);
2501 /* Try to update trackpad product information. */
2502 cyapa_gen5_bl_query_data(cyapa
);
2506 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
2508 case CYAPA_STATE_GEN5_APP
:
2510 * If trackpad device in deep sleep mode,
2511 * the app command will fail.
2512 * So always try to reset trackpad device to full active when
2513 * the device state is required.
2515 error
= cyapa_gen5_set_power_mode(cyapa
,
2516 PWR_MODE_FULL_ACTIVE
, 0, false);
2518 dev_warn(dev
, "%s: failed to set power active mode.\n",
2521 /* By default, the trackpad proximity function is enabled. */
2522 if (cyapa
->platform_ver
>= 2) {
2523 error
= cyapa_pip_set_proximity(cyapa
, true);
2526 "%s: failed to enable proximity.\n",
2530 /* Get trackpad product information. */
2531 error
= cyapa_gen5_get_query_data(cyapa
);
2534 /* Only support product ID starting with CYTRA */
2535 if (memcmp(cyapa
->product_id
, product_id
,
2536 strlen(product_id
)) != 0) {
2537 dev_err(dev
, "%s: unknown product ID (%s)\n",
2538 __func__
, cyapa
->product_id
);
2551 * Return false, do not continue process
2552 * Return true, continue process.
2554 bool cyapa_pip_irq_cmd_handler(struct cyapa
*cyapa
)
2556 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
2559 if (atomic_read(&pip
->cmd_issued
)) {
2560 /* Polling command response data. */
2561 if (pip
->is_irq_mode
== false)
2565 * Read out all none command response data.
2566 * these output data may caused by user put finger on
2567 * trackpad when host waiting the command response.
2569 cyapa_i2c_pip_read(cyapa
, pip
->irq_cmd_buf
,
2570 PIP_RESP_LENGTH_SIZE
);
2571 length
= get_unaligned_le16(pip
->irq_cmd_buf
);
2572 length
= (length
<= PIP_RESP_LENGTH_SIZE
) ?
2573 PIP_RESP_LENGTH_SIZE
: length
;
2574 if (length
> PIP_RESP_LENGTH_SIZE
)
2575 cyapa_i2c_pip_read(cyapa
,
2576 pip
->irq_cmd_buf
, length
);
2577 if (!(pip
->resp_sort_func
&&
2578 pip
->resp_sort_func(cyapa
,
2579 pip
->irq_cmd_buf
, length
))) {
2581 * Cover the Gen5 V1 firmware issue.
2582 * The issue is no interrupt would be asserted from
2583 * trackpad device to host for the command response
2584 * ready event. Because when there was a finger touch
2585 * on trackpad device, and the firmware output queue
2586 * won't be empty (always with touch report data), so
2587 * the interrupt signal won't be asserted again until
2588 * the output queue was previous emptied.
2589 * This issue would happen in the scenario that
2590 * user always has his/her fingers touched on the
2591 * trackpad device during system booting/rebooting.
2595 length
= *pip
->resp_len
;
2596 cyapa_empty_pip_output_data(cyapa
,
2599 pip
->resp_sort_func
);
2600 if (pip
->resp_len
&& length
!= 0) {
2601 *pip
->resp_len
= length
;
2602 atomic_dec(&pip
->cmd_issued
);
2603 complete(&pip
->cmd_ready
);
2608 if (pip
->resp_data
&& pip
->resp_len
) {
2609 *pip
->resp_len
= (*pip
->resp_len
< length
) ?
2610 *pip
->resp_len
: length
;
2611 memcpy(pip
->resp_data
, pip
->irq_cmd_buf
,
2614 atomic_dec(&pip
->cmd_issued
);
2615 complete(&pip
->cmd_ready
);
2622 static void cyapa_pip_report_buttons(struct cyapa
*cyapa
,
2623 const struct cyapa_pip_report_data
*report_data
)
2625 struct input_dev
*input
= cyapa
->input
;
2626 u8 buttons
= report_data
->report_head
[PIP_BUTTONS_OFFSET
];
2628 buttons
= (buttons
<< CAPABILITY_BTN_SHIFT
) & CAPABILITY_BTN_MASK
;
2630 if (cyapa
->btn_capability
& CAPABILITY_LEFT_BTN_MASK
) {
2631 input_report_key(input
, BTN_LEFT
,
2632 !!(buttons
& CAPABILITY_LEFT_BTN_MASK
));
2634 if (cyapa
->btn_capability
& CAPABILITY_MIDDLE_BTN_MASK
) {
2635 input_report_key(input
, BTN_MIDDLE
,
2636 !!(buttons
& CAPABILITY_MIDDLE_BTN_MASK
));
2638 if (cyapa
->btn_capability
& CAPABILITY_RIGHT_BTN_MASK
) {
2639 input_report_key(input
, BTN_RIGHT
,
2640 !!(buttons
& CAPABILITY_RIGHT_BTN_MASK
));
2646 static void cyapa_pip_report_proximity(struct cyapa
*cyapa
,
2647 const struct cyapa_pip_report_data
*report_data
)
2649 struct input_dev
*input
= cyapa
->input
;
2650 u8 distance
= report_data
->report_head
[PIP_PROXIMITY_DISTANCE_OFFSET
] &
2651 PIP_PROXIMITY_DISTANCE_MASK
;
2653 input_report_abs(input
, ABS_DISTANCE
, distance
);
2657 static void cyapa_pip_report_slot_data(struct cyapa
*cyapa
,
2658 const struct cyapa_pip_touch_record
*touch
)
2660 struct input_dev
*input
= cyapa
->input
;
2661 u8 event_id
= PIP_GET_EVENT_ID(touch
->touch_tip_event_id
);
2662 int slot
= PIP_GET_TOUCH_ID(touch
->touch_tip_event_id
);
2665 if (event_id
== RECORD_EVENT_LIFTOFF
)
2668 input_mt_slot(input
, slot
);
2669 input_mt_report_slot_state(input
, MT_TOOL_FINGER
, true);
2670 x
= (touch
->x_hi
<< 8) | touch
->x_lo
;
2671 if (cyapa
->x_origin
)
2672 x
= cyapa
->max_abs_x
- x
;
2673 y
= (touch
->y_hi
<< 8) | touch
->y_lo
;
2674 if (cyapa
->y_origin
)
2675 y
= cyapa
->max_abs_y
- y
;
2676 input_report_abs(input
, ABS_MT_POSITION_X
, x
);
2677 input_report_abs(input
, ABS_MT_POSITION_Y
, y
);
2678 input_report_abs(input
, ABS_DISTANCE
, 0);
2679 input_report_abs(input
, ABS_MT_PRESSURE
,
2681 input_report_abs(input
, ABS_MT_TOUCH_MAJOR
,
2682 touch
->major_axis_len
);
2683 input_report_abs(input
, ABS_MT_TOUCH_MINOR
,
2684 touch
->minor_axis_len
);
2686 input_report_abs(input
, ABS_MT_WIDTH_MAJOR
,
2687 touch
->major_tool_len
);
2688 input_report_abs(input
, ABS_MT_WIDTH_MINOR
,
2689 touch
->minor_tool_len
);
2691 input_report_abs(input
, ABS_MT_ORIENTATION
,
2692 touch
->orientation
);
2695 static void cyapa_pip_report_touches(struct cyapa
*cyapa
,
2696 const struct cyapa_pip_report_data
*report_data
)
2698 struct input_dev
*input
= cyapa
->input
;
2699 unsigned int touch_num
;
2702 touch_num
= report_data
->report_head
[PIP_NUMBER_OF_TOUCH_OFFSET
] &
2703 PIP_NUMBER_OF_TOUCH_MASK
;
2705 for (i
= 0; i
< touch_num
; i
++)
2706 cyapa_pip_report_slot_data(cyapa
,
2707 &report_data
->touch_records
[i
]);
2709 input_mt_sync_frame(input
);
2713 int cyapa_pip_irq_handler(struct cyapa
*cyapa
)
2715 struct device
*dev
= &cyapa
->client
->dev
;
2716 struct cyapa_pip_report_data report_data
;
2717 unsigned int report_len
;
2721 if (!cyapa_is_pip_app_mode(cyapa
)) {
2722 dev_err(dev
, "invalid device state, gen=%d, state=0x%02x\n",
2723 cyapa
->gen
, cyapa
->state
);
2727 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
,
2728 PIP_RESP_LENGTH_SIZE
);
2729 if (ret
!= PIP_RESP_LENGTH_SIZE
) {
2730 dev_err(dev
, "failed to read length bytes, (%d)\n", ret
);
2734 report_len
= get_unaligned_le16(
2735 &report_data
.report_head
[PIP_RESP_LENGTH_OFFSET
]);
2736 if (report_len
< PIP_RESP_LENGTH_SIZE
) {
2737 /* Invalid length or internal reset happened. */
2738 dev_err(dev
, "invalid report_len=%d. bytes: %02x %02x\n",
2739 report_len
, report_data
.report_head
[0],
2740 report_data
.report_head
[1]);
2744 /* Idle, no data for report. */
2745 if (report_len
== PIP_RESP_LENGTH_SIZE
)
2748 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
, report_len
);
2749 if (ret
!= report_len
) {
2750 dev_err(dev
, "failed to read %d bytes report data, (%d)\n",
2755 report_id
= report_data
.report_head
[PIP_RESP_REPORT_ID_OFFSET
];
2756 if (report_id
== PIP_WAKEUP_EVENT_REPORT_ID
&&
2757 report_len
== PIP_WAKEUP_EVENT_SIZE
) {
2759 * Device wake event from deep sleep mode for touch.
2760 * This interrupt event is used to wake system up.
2763 * It will introduce about 20~40 ms additional delay
2764 * time in receiving for first valid touch report data.
2765 * The time is used to execute device runtime resume
2768 pm_runtime_get_sync(dev
);
2769 pm_runtime_mark_last_busy(dev
);
2770 pm_runtime_put_sync_autosuspend(dev
);
2772 } else if (report_id
!= PIP_TOUCH_REPORT_ID
&&
2773 report_id
!= PIP_BTN_REPORT_ID
&&
2774 report_id
!= GEN5_OLD_PUSH_BTN_REPORT_ID
&&
2775 report_id
!= PIP_PUSH_BTN_REPORT_ID
&&
2776 report_id
!= PIP_PROXIMITY_REPORT_ID
) {
2777 /* Running in BL mode or unknown response data read. */
2778 dev_err(dev
, "invalid report_id=0x%02x\n", report_id
);
2782 if (report_id
== PIP_TOUCH_REPORT_ID
&&
2783 (report_len
< PIP_TOUCH_REPORT_HEAD_SIZE
||
2784 report_len
> PIP_TOUCH_REPORT_MAX_SIZE
)) {
2785 /* Invalid report data length for finger packet. */
2786 dev_err(dev
, "invalid touch packet length=%d\n", report_len
);
2790 if ((report_id
== PIP_BTN_REPORT_ID
||
2791 report_id
== GEN5_OLD_PUSH_BTN_REPORT_ID
||
2792 report_id
== PIP_PUSH_BTN_REPORT_ID
) &&
2793 (report_len
< PIP_BTN_REPORT_HEAD_SIZE
||
2794 report_len
> PIP_BTN_REPORT_MAX_SIZE
)) {
2795 /* Invalid report data length of button packet. */
2796 dev_err(dev
, "invalid button packet length=%d\n", report_len
);
2800 if (report_id
== PIP_PROXIMITY_REPORT_ID
&&
2801 report_len
!= PIP_PROXIMITY_REPORT_SIZE
) {
2802 /* Invalid report data length of proximity packet. */
2803 dev_err(dev
, "invalid proximity data, length=%d\n", report_len
);
2807 if (report_id
== PIP_TOUCH_REPORT_ID
)
2808 cyapa_pip_report_touches(cyapa
, &report_data
);
2809 else if (report_id
== PIP_PROXIMITY_REPORT_ID
)
2810 cyapa_pip_report_proximity(cyapa
, &report_data
);
2812 cyapa_pip_report_buttons(cyapa
, &report_data
);
2817 int cyapa_pip_bl_activate(struct cyapa
*cyapa
) { return 0; }
2818 int cyapa_pip_bl_deactivate(struct cyapa
*cyapa
) { return 0; }
2821 const struct cyapa_dev_ops cyapa_gen5_ops
= {
2822 .check_fw
= cyapa_pip_check_fw
,
2823 .bl_enter
= cyapa_pip_bl_enter
,
2824 .bl_initiate
= cyapa_pip_bl_initiate
,
2825 .update_fw
= cyapa_pip_do_fw_update
,
2826 .bl_activate
= cyapa_pip_bl_activate
,
2827 .bl_deactivate
= cyapa_pip_bl_deactivate
,
2829 .show_baseline
= cyapa_gen5_show_baseline
,
2830 .calibrate_store
= cyapa_pip_do_calibrate
,
2832 .initialize
= cyapa_pip_cmd_state_initialize
,
2834 .state_parse
= cyapa_gen5_state_parse
,
2835 .operational_check
= cyapa_gen5_do_operational_check
,
2837 .irq_handler
= cyapa_pip_irq_handler
,
2838 .irq_cmd_handler
= cyapa_pip_irq_cmd_handler
,
2839 .sort_empty_output_data
= cyapa_empty_pip_output_data
,
2840 .set_power_mode
= cyapa_gen5_set_power_mode
,
2842 .set_proximity
= cyapa_pip_set_proximity
,