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 static int cyapa_pip_event_process(struct cyapa
*cyapa
,
346 struct cyapa_pip_report_data
*report_data
);
348 int cyapa_pip_cmd_state_initialize(struct cyapa
*cyapa
)
350 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
352 init_completion(&pip
->cmd_ready
);
353 atomic_set(&pip
->cmd_issued
, 0);
354 mutex_init(&pip
->cmd_lock
);
356 mutex_init(&pip
->pm_stage_lock
);
357 pip
->pm_stage
= CYAPA_PM_DEACTIVE
;
359 pip
->resp_sort_func
= NULL
;
360 pip
->in_progress_cmd
= PIP_INVALID_CMD
;
361 pip
->resp_data
= NULL
;
362 pip
->resp_len
= NULL
;
364 cyapa
->dev_pwr_mode
= UNINIT_PWR_MODE
;
365 cyapa
->dev_sleep_time
= UNINIT_SLEEP_TIME
;
370 /* Return negative errno, or else the number of bytes read. */
371 ssize_t
cyapa_i2c_pip_read(struct cyapa
*cyapa
, u8
*buf
, size_t size
)
378 if (!buf
|| size
> CYAPA_REG_MAP_SIZE
)
381 ret
= i2c_master_recv(cyapa
->client
, buf
, size
);
384 return (ret
< 0) ? ret
: -EIO
;
389 * Return a negative errno code else zero on success.
391 ssize_t
cyapa_i2c_pip_write(struct cyapa
*cyapa
, u8
*buf
, size_t size
)
398 ret
= i2c_master_send(cyapa
->client
, buf
, size
);
401 return (ret
< 0) ? ret
: -EIO
;
406 static void cyapa_set_pip_pm_state(struct cyapa
*cyapa
,
407 enum cyapa_pm_stage pm_stage
)
409 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
411 mutex_lock(&pip
->pm_stage_lock
);
412 pip
->pm_stage
= pm_stage
;
413 mutex_unlock(&pip
->pm_stage_lock
);
416 static void cyapa_reset_pip_pm_state(struct cyapa
*cyapa
)
418 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
420 /* Indicates the pip->pm_stage is not valid. */
421 mutex_lock(&pip
->pm_stage_lock
);
422 pip
->pm_stage
= CYAPA_PM_DEACTIVE
;
423 mutex_unlock(&pip
->pm_stage_lock
);
426 static enum cyapa_pm_stage
cyapa_get_pip_pm_state(struct cyapa
*cyapa
)
428 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
429 enum cyapa_pm_stage pm_stage
;
431 mutex_lock(&pip
->pm_stage_lock
);
432 pm_stage
= pip
->pm_stage
;
433 mutex_unlock(&pip
->pm_stage_lock
);
439 * This function is aimed to dump all not read data in Gen5 trackpad
440 * before send any command, otherwise, the interrupt line will be blocked.
442 int cyapa_empty_pip_output_data(struct cyapa
*cyapa
,
443 u8
*buf
, int *len
, cb_sort func
)
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
);
456 buf_len
= (*len
< CYAPA_REG_MAP_SIZE
) ?
457 *len
: CYAPA_REG_MAP_SIZE
;
461 report_count
= 8; /* max 7 pending data before command response data */
465 * Depending on testing in cyapa driver, there are max 5 "02 00"
466 * packets between two valid buffered data report in firmware.
467 * So in order to dump all buffered data out and
468 * make interrupt line release for reassert again,
469 * we must set the empty_count check value bigger than 5 to
470 * make it work. Otherwise, in some situation,
471 * the interrupt line may unable to reactive again,
472 * which will cause trackpad device unable to
473 * report data any more.
474 * for example, it may happen in EFT and ESD testing.
479 error
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
,
480 PIP_RESP_LENGTH_SIZE
);
484 length
= get_unaligned_le16(pip
->empty_buf
);
485 if (length
== PIP_RESP_LENGTH_SIZE
) {
488 } else if (length
> CYAPA_REG_MAP_SIZE
) {
489 /* Should not happen */
491 } else if (length
== 0) {
492 /* Application or bootloader launch data polled out. */
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
);
499 /* Response found, success. */
505 error
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
, length
);
511 length
= get_unaligned_le16(pip
->empty_buf
);
512 if (length
<= PIP_RESP_LENGTH_SIZE
) {
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
);
519 /* Response found, success. */
521 } else if (cyapa
->operational
&& input
&& input
->users
&&
522 (pm_stage
== CYAPA_PM_RUNTIME_RESUME
||
523 pm_stage
== CYAPA_PM_RUNTIME_SUSPEND
)) {
524 /* Parse the data and report it if it's valid. */
525 cyapa_pip_event_process(cyapa
,
526 (struct cyapa_pip_report_data
*)pip
->empty_buf
);
530 } while (report_count
);
535 static int cyapa_do_i2c_pip_cmd_irq_sync(
537 u8
*cmd
, size_t cmd_len
,
538 unsigned long timeout
)
540 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
543 /* Wait for interrupt to set ready completion */
544 init_completion(&pip
->cmd_ready
);
546 atomic_inc(&pip
->cmd_issued
);
547 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
549 atomic_dec(&pip
->cmd_issued
);
550 return (error
< 0) ? error
: -EIO
;
553 /* Wait for interrupt to indicate command is completed. */
554 timeout
= wait_for_completion_timeout(&pip
->cmd_ready
,
555 msecs_to_jiffies(timeout
));
557 atomic_dec(&pip
->cmd_issued
);
564 static int cyapa_do_i2c_pip_cmd_polling(
566 u8
*cmd
, size_t cmd_len
,
567 u8
*resp_data
, int *resp_len
,
568 unsigned long timeout
,
571 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
576 atomic_inc(&pip
->cmd_issued
);
577 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
579 atomic_dec(&pip
->cmd_issued
);
580 return error
< 0 ? error
: -EIO
;
583 length
= resp_len
? *resp_len
: 0;
584 if (resp_data
&& resp_len
&& length
!= 0 && func
) {
587 usleep_range(3000, 5000);
589 error
= cyapa_empty_pip_output_data(cyapa
,
590 resp_data
, resp_len
, func
);
591 if (error
|| *resp_len
== 0)
595 } while (--tries
> 0);
596 if ((error
|| *resp_len
== 0) || tries
<= 0)
597 error
= error
? error
: -ETIMEDOUT
;
600 atomic_dec(&pip
->cmd_issued
);
604 int cyapa_i2c_pip_cmd_irq_sync(
606 u8
*cmd
, int cmd_len
,
607 u8
*resp_data
, int *resp_len
,
608 unsigned long timeout
,
612 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
615 if (!cmd
|| !cmd_len
)
618 /* Commands must be serialized. */
619 error
= mutex_lock_interruptible(&pip
->cmd_lock
);
623 pip
->resp_sort_func
= func
;
624 pip
->resp_data
= resp_data
;
625 pip
->resp_len
= resp_len
;
627 if (cmd_len
>= PIP_MIN_APP_CMD_LENGTH
&&
628 cmd
[4] == PIP_APP_CMD_REPORT_ID
) {
629 /* Application command */
630 pip
->in_progress_cmd
= cmd
[6] & 0x7f;
631 } else if (cmd_len
>= PIP_MIN_BL_CMD_LENGTH
&&
632 cmd
[4] == PIP_BL_CMD_REPORT_ID
) {
633 /* Bootloader command */
634 pip
->in_progress_cmd
= cmd
[7];
637 /* Send command data, wait and read output response data's length. */
639 pip
->is_irq_mode
= true;
640 error
= cyapa_do_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
642 if (error
== -ETIMEDOUT
&& resp_data
&&
643 resp_len
&& *resp_len
!= 0 && func
) {
645 * For some old version, there was no interrupt for
646 * the command response data, so need to poll here
647 * to try to get the response data.
649 error
= cyapa_empty_pip_output_data(cyapa
,
650 resp_data
, resp_len
, func
);
651 if (error
|| *resp_len
== 0)
652 error
= error
? error
: -ETIMEDOUT
;
655 pip
->is_irq_mode
= false;
656 error
= cyapa_do_i2c_pip_cmd_polling(cyapa
, cmd
, cmd_len
,
657 resp_data
, resp_len
, timeout
, func
);
660 pip
->resp_sort_func
= NULL
;
661 pip
->resp_data
= NULL
;
662 pip
->resp_len
= NULL
;
663 pip
->in_progress_cmd
= PIP_INVALID_CMD
;
665 mutex_unlock(&pip
->cmd_lock
);
669 bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa
*cyapa
,
672 if (!data
|| len
< PIP_MIN_BL_RESP_LENGTH
)
675 /* Bootloader input report id 30h */
676 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_BL_RESP_REPORT_ID
&&
677 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
678 data
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
)
684 bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa
*cyapa
,
687 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
690 if (!data
|| len
< PIP_MIN_APP_RESP_LENGTH
)
693 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_APP_RESP_REPORT_ID
&&
694 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
) {
695 resp_len
= get_unaligned_le16(&data
[PIP_RESP_LENGTH_OFFSET
]);
696 if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) == 0x00 &&
697 resp_len
== PIP_UNSUPPORTED_CMD_RESP_LENGTH
&&
698 data
[5] == pip
->in_progress_cmd
) {
699 /* Unsupported command code */
701 } else if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) ==
702 pip
->in_progress_cmd
) {
703 /* Correct command response received */
711 static bool cyapa_sort_pip_application_launch_data(struct cyapa
*cyapa
,
714 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
718 * After reset or power on, trackpad device always sets to 0x00 0x00
719 * to indicate a reset or power on event.
721 if (buf
[0] == 0 && buf
[1] == 0)
727 static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa
*cyapa
,
733 /* Check hid descriptor. */
734 if (len
!= PIP_HID_DESCRIPTOR_SIZE
)
737 resp_len
= get_unaligned_le16(&buf
[PIP_RESP_LENGTH_OFFSET
]);
738 max_output_len
= get_unaligned_le16(&buf
[16]);
739 if (resp_len
== PIP_HID_DESCRIPTOR_SIZE
) {
740 if (buf
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_HID_BL_REPORT_ID
&&
741 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
742 /* BL mode HID Descriptor */
744 } else if ((buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
745 PIP_HID_APP_REPORT_ID
) &&
746 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
747 /* APP mode HID Descriptor */
755 static bool cyapa_sort_pip_deep_sleep_data(struct cyapa
*cyapa
,
758 if (len
== PIP_DEEP_SLEEP_RESP_LENGTH
&&
759 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
760 PIP_APP_DEEP_SLEEP_REPORT_ID
&&
761 (buf
[4] & PIP_DEEP_SLEEP_OPCODE_MASK
) ==
762 PIP_DEEP_SLEEP_OPCODE
)
767 static int gen5_idle_state_parse(struct cyapa
*cyapa
)
769 u8 resp_data
[PIP_HID_DESCRIPTOR_SIZE
];
777 * Dump all buffered data firstly for the situation
778 * when the trackpad is just power on the cyapa go here.
780 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
782 memset(resp_data
, 0, sizeof(resp_data
));
783 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
, 3);
785 return ret
< 0 ? ret
: -EIO
;
787 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
788 if (length
== PIP_RESP_LENGTH_SIZE
) {
789 /* Normal state of Gen5 with no data to response */
790 cyapa
->gen
= CYAPA_GEN5
;
792 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
794 /* Read description from trackpad device */
797 length
= PIP_HID_DESCRIPTOR_SIZE
;
798 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
799 cmd
, PIP_RESP_LENGTH_SIZE
,
802 cyapa_sort_gen5_hid_descriptor_data
,
807 length
= get_unaligned_le16(
808 &resp_data
[PIP_RESP_LENGTH_OFFSET
]);
809 max_output_len
= get_unaligned_le16(&resp_data
[16]);
810 if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
811 length
== PIP_RESP_LENGTH_SIZE
) &&
812 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
813 PIP_HID_BL_REPORT_ID
) &&
814 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
815 /* BL mode HID Description read */
816 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
817 } else if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
818 length
== PIP_RESP_LENGTH_SIZE
) &&
819 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
820 PIP_HID_APP_REPORT_ID
) &&
821 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
822 /* APP mode HID Description read */
823 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
825 /* Should not happen!!! */
826 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
833 static int gen5_hid_description_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
840 /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
841 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
843 * Must read HID Description content through out,
844 * otherwise Gen5 trackpad cannot response next command
845 * or report any touch or button data.
847 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
,
848 PIP_HID_DESCRIPTOR_SIZE
);
849 if (ret
!= PIP_HID_DESCRIPTOR_SIZE
)
850 return ret
< 0 ? ret
: -EIO
;
851 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
852 max_output_len
= get_unaligned_le16(&resp_data
[16]);
853 if (length
== PIP_RESP_LENGTH_SIZE
) {
854 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
855 PIP_HID_BL_REPORT_ID
) {
857 * BL mode HID Description has been previously
860 cyapa
->gen
= CYAPA_GEN5
;
861 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
864 * APP mode HID Description has been previously
867 cyapa
->gen
= CYAPA_GEN5
;
868 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
870 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
871 resp_data
[2] == PIP_HID_BL_REPORT_ID
&&
872 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
873 /* BL mode HID Description read. */
874 cyapa
->gen
= CYAPA_GEN5
;
875 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
876 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
877 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
878 PIP_HID_APP_REPORT_ID
) &&
879 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
880 /* APP mode HID Description read. */
881 cyapa
->gen
= CYAPA_GEN5
;
882 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
884 /* Should not happen!!! */
885 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
891 static int gen5_report_data_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
895 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
896 switch (reg_data
[PIP_RESP_REPORT_ID_OFFSET
]) {
897 case PIP_TOUCH_REPORT_ID
:
898 if (length
< PIP_TOUCH_REPORT_HEAD_SIZE
||
899 length
> PIP_TOUCH_REPORT_MAX_SIZE
)
902 case PIP_BTN_REPORT_ID
:
903 case GEN5_OLD_PUSH_BTN_REPORT_ID
:
904 case PIP_PUSH_BTN_REPORT_ID
:
905 if (length
< PIP_BTN_REPORT_HEAD_SIZE
||
906 length
> PIP_BTN_REPORT_MAX_SIZE
)
909 case PIP_WAKEUP_EVENT_REPORT_ID
:
910 if (length
!= PIP_WAKEUP_EVENT_SIZE
)
917 cyapa
->gen
= CYAPA_GEN5
;
918 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
922 static int gen5_cmd_resp_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
924 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
929 * Must read report data through out,
930 * otherwise Gen5 trackpad cannot response next command
931 * or report any touch or button data.
933 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
934 ret
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
, length
);
936 return ret
< 0 ? ret
: -EIO
;
938 if (length
== PIP_RESP_LENGTH_SIZE
) {
939 /* Previous command has read the data through out. */
940 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
941 PIP_BL_RESP_REPORT_ID
) {
942 /* Gen5 BL command response data detected */
943 cyapa
->gen
= CYAPA_GEN5
;
944 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
946 /* Gen5 APP command response data detected */
947 cyapa
->gen
= CYAPA_GEN5
;
948 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
950 } else if ((pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
951 PIP_BL_RESP_REPORT_ID
) &&
952 (pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
953 PIP_RESP_RSVD_KEY
) &&
954 (pip
->empty_buf
[PIP_RESP_BL_SOP_OFFSET
] ==
956 (pip
->empty_buf
[length
- 1] ==
958 /* Gen5 BL command response data detected */
959 cyapa
->gen
= CYAPA_GEN5
;
960 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
961 } else if (pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
962 PIP_APP_RESP_REPORT_ID
&&
963 pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
965 /* Gen5 APP command response data detected */
966 cyapa
->gen
= CYAPA_GEN5
;
967 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
969 /* Should not happen!!! */
970 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
976 static int cyapa_gen5_state_parse(struct cyapa
*cyapa
, u8
*reg_data
, int len
)
980 if (!reg_data
|| len
< 3)
983 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
985 /* Parse based on Gen5 characteristic registers and bits */
986 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
987 if (length
== 0 || length
== PIP_RESP_LENGTH_SIZE
) {
988 gen5_idle_state_parse(cyapa
);
989 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
990 (reg_data
[2] == PIP_HID_BL_REPORT_ID
||
991 reg_data
[2] == PIP_HID_APP_REPORT_ID
)) {
992 gen5_hid_description_header_parse(cyapa
, reg_data
);
993 } else if ((length
== GEN5_APP_REPORT_DESCRIPTOR_SIZE
||
994 length
== GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE
) &&
995 reg_data
[2] == GEN5_APP_REPORT_DESCRIPTOR_ID
) {
996 /* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
997 cyapa
->gen
= CYAPA_GEN5
;
998 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
999 } else if (length
== GEN5_BL_REPORT_DESCRIPTOR_SIZE
&&
1000 reg_data
[2] == GEN5_BL_REPORT_DESCRIPTOR_ID
) {
1001 /* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */
1002 cyapa
->gen
= CYAPA_GEN5
;
1003 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
1004 } else if (reg_data
[2] == PIP_TOUCH_REPORT_ID
||
1005 reg_data
[2] == PIP_BTN_REPORT_ID
||
1006 reg_data
[2] == GEN5_OLD_PUSH_BTN_REPORT_ID
||
1007 reg_data
[2] == PIP_PUSH_BTN_REPORT_ID
||
1008 reg_data
[2] == PIP_WAKEUP_EVENT_REPORT_ID
) {
1009 gen5_report_data_header_parse(cyapa
, reg_data
);
1010 } else if (reg_data
[2] == PIP_BL_RESP_REPORT_ID
||
1011 reg_data
[2] == PIP_APP_RESP_REPORT_ID
) {
1012 gen5_cmd_resp_header_parse(cyapa
, reg_data
);
1015 if (cyapa
->gen
== CYAPA_GEN5
) {
1017 * Must read the content (e.g.: report description and so on)
1018 * from trackpad device throughout. Otherwise,
1019 * Gen5 trackpad cannot response to next command or
1020 * report any touch or button data later.
1022 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1024 if (cyapa
->state
== CYAPA_STATE_GEN5_APP
||
1025 cyapa
->state
== CYAPA_STATE_GEN5_BL
)
1032 static struct cyapa_tsg_bin_image_data_record
*
1033 cyapa_get_image_record_data_num(const struct firmware
*fw
,
1038 head_size
= fw
->data
[0] + 1;
1039 *record_num
= (fw
->size
- head_size
) /
1040 sizeof(struct cyapa_tsg_bin_image_data_record
);
1041 return (struct cyapa_tsg_bin_image_data_record
*)&fw
->data
[head_size
];
1044 int cyapa_pip_bl_initiate(struct cyapa
*cyapa
, const struct firmware
*fw
)
1046 struct cyapa_tsg_bin_image_data_record
*image_records
;
1047 struct pip_bl_cmd_head
*bl_cmd_head
;
1048 struct pip_bl_packet_start
*bl_packet_start
;
1049 struct pip_bl_initiate_cmd_data
*cmd_data
;
1050 struct pip_bl_packet_end
*bl_packet_end
;
1051 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1055 u16 meta_data_crc
= 0;
1062 /* Try to dump all buffered report data before any send command. */
1063 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1065 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1066 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1067 cmd_data_len
= CYAPA_TSG_BL_KEY_SIZE
+ CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
;
1068 cmd_len
= sizeof(struct pip_bl_cmd_head
) + cmd_data_len
+
1069 sizeof(struct pip_bl_packet_end
);
1071 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1072 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1073 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1075 bl_packet_start
= &bl_cmd_head
->packet_start
;
1076 bl_packet_start
->sop
= PIP_SOP_KEY
;
1077 bl_packet_start
->cmd_code
= PIP_BL_CMD_INITIATE_BL
;
1078 /* 8 key bytes and 128 bytes block size */
1079 put_unaligned_le16(cmd_data_len
, &bl_packet_start
->data_length
);
1081 cmd_data
= (struct pip_bl_initiate_cmd_data
*)bl_cmd_head
->data
;
1082 memcpy(cmd_data
->key
, cyapa_pip_bl_cmd_key
, CYAPA_TSG_BL_KEY_SIZE
);
1084 image_records
= cyapa_get_image_record_data_num(fw
, &records_num
);
1086 /* APP_INTEGRITY row is always the last row block */
1087 data
= image_records
[records_num
- 1].record_data
;
1088 memcpy(cmd_data
->metadata_raw_parameter
, data
,
1089 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1091 meta_data_crc
= crc_itu_t(0xffff, cmd_data
->metadata_raw_parameter
,
1092 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1093 put_unaligned_le16(meta_data_crc
, &cmd_data
->metadata_crc
);
1095 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1097 cmd_crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1098 sizeof(struct pip_bl_packet_start
) + cmd_data_len
);
1099 put_unaligned_le16(cmd_crc
, &bl_packet_end
->crc
);
1100 bl_packet_end
->eop
= PIP_EOP_KEY
;
1102 resp_len
= sizeof(resp_data
);
1103 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1105 resp_data
, &resp_len
, 12000,
1106 cyapa_sort_tsg_pip_bl_resp_data
, true);
1107 if (error
|| resp_len
!= PIP_BL_INITIATE_RESP_LEN
||
1108 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1109 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1110 return error
? error
: -EAGAIN
;
1115 static bool cyapa_sort_pip_bl_exit_data(struct cyapa
*cyapa
, u8
*buf
, int len
)
1117 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
1120 if (buf
[0] == 0 && buf
[1] == 0)
1123 /* Exit bootloader failed for some reason. */
1124 if (len
== PIP_BL_FAIL_EXIT_RESP_LEN
&&
1125 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
1126 PIP_BL_RESP_REPORT_ID
&&
1127 buf
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
1128 buf
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
&&
1129 buf
[10] == PIP_EOP_KEY
)
1135 int cyapa_pip_bl_exit(struct cyapa
*cyapa
)
1138 u8 bl_gen5_bl_exit
[] = { 0x04, 0x00,
1139 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00,
1146 resp_len
= sizeof(resp_data
);
1147 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1148 bl_gen5_bl_exit
, sizeof(bl_gen5_bl_exit
),
1149 resp_data
, &resp_len
,
1150 5000, cyapa_sort_pip_bl_exit_data
, false);
1154 if (resp_len
== PIP_BL_FAIL_EXIT_RESP_LEN
||
1155 resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
1156 PIP_BL_RESP_REPORT_ID
)
1159 if (resp_data
[0] == 0x00 && resp_data
[1] == 0x00)
1165 int cyapa_pip_bl_enter(struct cyapa
*cyapa
)
1167 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 };
1172 error
= cyapa_poll_state(cyapa
, 500);
1176 /* Already in bootloader mode, Skipping exit. */
1177 if (cyapa_is_pip_bl_mode(cyapa
))
1179 else if (!cyapa_is_pip_app_mode(cyapa
))
1182 /* Try to dump all buffered report data before any send command. */
1183 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1186 * Send bootloader enter command to trackpad device,
1187 * after enter bootloader, the response data is two bytes of 0x00 0x00.
1189 resp_len
= sizeof(resp_data
);
1190 memset(resp_data
, 0, resp_len
);
1191 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1193 resp_data
, &resp_len
,
1194 5000, cyapa_sort_pip_application_launch_data
,
1196 if (error
|| resp_data
[0] != 0x00 || resp_data
[1] != 0x00)
1197 return error
< 0 ? error
: -EAGAIN
;
1199 cyapa
->operational
= false;
1200 if (cyapa
->gen
== CYAPA_GEN5
)
1201 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
1202 else if (cyapa
->gen
== CYAPA_GEN6
)
1203 cyapa
->state
= CYAPA_STATE_GEN6_BL
;
1207 static int cyapa_pip_fw_head_check(struct cyapa
*cyapa
,
1208 struct cyapa_tsg_bin_image_head
*image_head
)
1210 if (image_head
->head_size
!= 0x0C && image_head
->head_size
!= 0x12)
1213 switch (cyapa
->gen
) {
1215 if (image_head
->family_id
!= 0x9B ||
1216 image_head
->silicon_id_hi
!= 0x0B)
1220 /* Gen5 without proximity support. */
1221 if (cyapa
->platform_ver
< 2) {
1222 if (image_head
->head_size
== 0x0C)
1227 if (image_head
->family_id
!= 0x91 ||
1228 image_head
->silicon_id_hi
!= 0x02)
1238 int cyapa_pip_check_fw(struct cyapa
*cyapa
, const struct firmware
*fw
)
1240 struct device
*dev
= &cyapa
->client
->dev
;
1241 struct cyapa_tsg_bin_image_data_record
*image_records
;
1242 const struct cyapa_tsg_bin_image_data_record
*app_integrity
;
1243 const struct tsg_bl_metadata_row_params
*metadata
;
1244 int flash_records_count
;
1245 u32 fw_app_start
, fw_upgrade_start
;
1246 u16 fw_app_len
, fw_upgrade_len
;
1248 u16 app_integrity_crc
;
1251 /* Verify the firmware image not miss-used for Gen5 and Gen6. */
1252 if (cyapa_pip_fw_head_check(cyapa
,
1253 (struct cyapa_tsg_bin_image_head
*)fw
->data
)) {
1254 dev_err(dev
, "%s: firmware image not match TP device.\n",
1260 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1263 * APP_INTEGRITY row is always the last row block,
1264 * and the row id must be 0x01ff.
1266 app_integrity
= &image_records
[flash_records_count
- 1];
1268 if (app_integrity
->flash_array_id
!= 0x00 ||
1269 get_unaligned_be16(&app_integrity
->row_number
) != 0x01ff) {
1270 dev_err(dev
, "%s: invalid app_integrity data.\n", __func__
);
1274 metadata
= (const void *)app_integrity
->record_data
;
1276 /* Verify app_integrity crc */
1277 app_integrity_crc
= crc_itu_t(0xffff, app_integrity
->record_data
,
1278 CYAPA_TSG_APP_INTEGRITY_SIZE
);
1279 if (app_integrity_crc
!= get_unaligned_le16(&metadata
->metadata_crc
)) {
1280 dev_err(dev
, "%s: invalid app_integrity crc.\n", __func__
);
1284 fw_app_start
= get_unaligned_le32(&metadata
->app_start
);
1285 fw_app_len
= get_unaligned_le16(&metadata
->app_len
);
1286 fw_upgrade_start
= get_unaligned_le32(&metadata
->upgrade_start
);
1287 fw_upgrade_len
= get_unaligned_le16(&metadata
->upgrade_len
);
1289 if (fw_app_start
% CYAPA_TSG_FW_ROW_SIZE
||
1290 fw_app_len
% CYAPA_TSG_FW_ROW_SIZE
||
1291 fw_upgrade_start
% CYAPA_TSG_FW_ROW_SIZE
||
1292 fw_upgrade_len
% CYAPA_TSG_FW_ROW_SIZE
) {
1293 dev_err(dev
, "%s: invalid image alignment.\n", __func__
);
1297 /* Verify application image CRC. */
1299 for (i
= 0; i
< fw_app_len
/ CYAPA_TSG_FW_ROW_SIZE
; i
++) {
1300 const u8
*data
= image_records
[i
].record_data
;
1302 app_crc
= crc_itu_t(app_crc
, data
, CYAPA_TSG_FW_ROW_SIZE
);
1305 if (app_crc
!= get_unaligned_le16(&metadata
->app_crc
)) {
1306 dev_err(dev
, "%s: invalid firmware app crc check.\n", __func__
);
1313 static int cyapa_pip_write_fw_block(struct cyapa
*cyapa
,
1314 struct cyapa_tsg_bin_image_data_record
*flash_record
)
1316 struct pip_bl_cmd_head
*bl_cmd_head
;
1317 struct pip_bl_packet_start
*bl_packet_start
;
1318 struct tsg_bl_flash_row_head
*flash_row_head
;
1319 struct pip_bl_packet_end
*bl_packet_end
;
1320 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1332 flash_array_id
= flash_record
->flash_array_id
;
1333 flash_row_id
= get_unaligned_be16(&flash_record
->row_number
);
1334 record_len
= get_unaligned_be16(&flash_record
->record_len
);
1335 record_data
= flash_record
->record_data
;
1337 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1338 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1339 bl_packet_start
= &bl_cmd_head
->packet_start
;
1340 cmd_len
= sizeof(struct pip_bl_cmd_head
) +
1341 sizeof(struct tsg_bl_flash_row_head
) +
1342 CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
+
1343 sizeof(struct pip_bl_packet_end
);
1345 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1346 /* Don't include 2 bytes register address */
1347 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1348 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1349 bl_packet_start
->sop
= PIP_SOP_KEY
;
1350 bl_packet_start
->cmd_code
= PIP_BL_CMD_PROGRAM_VERIFY_ROW
;
1352 /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */
1353 data_len
= sizeof(struct tsg_bl_flash_row_head
) + record_len
;
1354 put_unaligned_le16(data_len
, &bl_packet_start
->data_length
);
1356 flash_row_head
= (struct tsg_bl_flash_row_head
*)bl_cmd_head
->data
;
1357 flash_row_head
->flash_array_id
= flash_array_id
;
1358 put_unaligned_le16(flash_row_id
, &flash_row_head
->flash_row_id
);
1359 memcpy(flash_row_head
->flash_data
, record_data
, record_len
);
1361 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1363 crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1364 sizeof(struct pip_bl_packet_start
) + data_len
);
1365 put_unaligned_le16(crc
, &bl_packet_end
->crc
);
1366 bl_packet_end
->eop
= PIP_EOP_KEY
;
1368 resp_len
= sizeof(resp_data
);
1369 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1370 resp_data
, &resp_len
,
1371 500, cyapa_sort_tsg_pip_bl_resp_data
, true);
1372 if (error
|| resp_len
!= PIP_BL_BLOCK_WRITE_RESP_LEN
||
1373 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1374 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1375 return error
< 0 ? error
: -EAGAIN
;
1380 int cyapa_pip_do_fw_update(struct cyapa
*cyapa
,
1381 const struct firmware
*fw
)
1383 struct device
*dev
= &cyapa
->client
->dev
;
1384 struct cyapa_tsg_bin_image_data_record
*image_records
;
1385 int flash_records_count
;
1389 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1392 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1395 * The last flash row 0x01ff has been written through bl_initiate
1396 * command, so DO NOT write flash 0x01ff to trackpad device.
1398 for (i
= 0; i
< (flash_records_count
- 1); i
++) {
1399 error
= cyapa_pip_write_fw_block(cyapa
, &image_records
[i
]);
1401 dev_err(dev
, "%s: Gen5 FW update aborted: %d\n",
1410 static int cyapa_gen5_change_power_state(struct cyapa
*cyapa
, u8 power_state
)
1412 u8 cmd
[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 };
1417 cmd
[7] = power_state
;
1418 resp_len
= sizeof(resp_data
);
1419 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1420 resp_data
, &resp_len
,
1421 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1422 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x08) ||
1423 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1424 return error
< 0 ? error
: -EINVAL
;
1429 static int cyapa_gen5_set_interval_time(struct cyapa
*cyapa
,
1430 u8 parameter_id
, u16 interval_time
)
1432 struct pip_app_cmd_head
*app_cmd_head
;
1433 struct gen5_app_set_parameter_data
*parameter_data
;
1434 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1441 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1442 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1443 parameter_data
= (struct gen5_app_set_parameter_data
*)
1444 app_cmd_head
->parameter_data
;
1445 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1446 sizeof(struct gen5_app_set_parameter_data
);
1448 switch (parameter_id
) {
1449 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1450 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1452 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1453 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1455 case GEN5_PARAMETER_LP_INTRVL_ID
:
1456 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1462 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1464 * Don't include unused parameter value bytes and
1465 * 2 bytes register address.
1467 put_unaligned_le16(cmd_len
- (4 - parameter_size
) - 2,
1468 &app_cmd_head
->length
);
1469 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1470 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1471 parameter_data
->parameter_id
= parameter_id
;
1472 parameter_data
->parameter_size
= parameter_size
;
1473 put_unaligned_le32((u32
)interval_time
, ¶meter_data
->value
);
1474 resp_len
= sizeof(resp_data
);
1475 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1476 resp_data
, &resp_len
,
1477 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1478 if (error
|| resp_data
[5] != parameter_id
||
1479 resp_data
[6] != parameter_size
||
1480 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
))
1481 return error
< 0 ? error
: -EINVAL
;
1486 static int cyapa_gen5_get_interval_time(struct cyapa
*cyapa
,
1487 u8 parameter_id
, u16
*interval_time
)
1489 struct pip_app_cmd_head
*app_cmd_head
;
1490 struct gen5_app_get_parameter_data
*parameter_data
;
1491 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1499 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1500 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1501 parameter_data
= (struct gen5_app_get_parameter_data
*)
1502 app_cmd_head
->parameter_data
;
1503 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1504 sizeof(struct gen5_app_get_parameter_data
);
1507 switch (parameter_id
) {
1508 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1509 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1511 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1512 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1514 case GEN5_PARAMETER_LP_INTRVL_ID
:
1515 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1521 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1522 /* Don't include 2 bytes register address */
1523 put_unaligned_le16(cmd_len
- 2, &app_cmd_head
->length
);
1524 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1525 app_cmd_head
->cmd_code
= GEN5_CMD_GET_PARAMETER
;
1526 parameter_data
->parameter_id
= parameter_id
;
1528 resp_len
= sizeof(resp_data
);
1529 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1530 resp_data
, &resp_len
,
1531 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1532 if (error
|| resp_data
[5] != parameter_id
|| resp_data
[6] == 0 ||
1533 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_GET_PARAMETER
))
1534 return error
< 0 ? error
: -EINVAL
;
1537 for (i
= 0; i
< parameter_size
; i
++)
1538 mask
|= (0xff << (i
* 8));
1539 *interval_time
= get_unaligned_le16(&resp_data
[7]) & mask
;
1544 static int cyapa_gen5_disable_pip_report(struct cyapa
*cyapa
)
1546 struct pip_app_cmd_head
*app_cmd_head
;
1552 memset(cmd
, 0, sizeof(cmd
));
1553 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1555 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1556 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1557 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1558 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1559 app_cmd_head
->parameter_data
[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT
;
1560 app_cmd_head
->parameter_data
[1] = 0x01;
1561 app_cmd_head
->parameter_data
[2] = 0x01;
1562 resp_len
= sizeof(resp_data
);
1563 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1564 resp_data
, &resp_len
,
1565 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1566 if (error
|| resp_data
[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT
||
1567 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
) ||
1568 resp_data
[6] != 0x01)
1569 return error
< 0 ? error
: -EINVAL
;
1574 int cyapa_pip_set_proximity(struct cyapa
*cyapa
, bool enable
)
1576 u8 cmd
[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY
,
1583 resp_len
= sizeof(resp_data
);
1584 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1585 resp_data
, &resp_len
,
1586 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1587 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_SET_PROXIMITY
) ||
1588 !PIP_CMD_COMPLETE_SUCCESS(resp_data
)) {
1589 error
= (error
== -ETIMEDOUT
) ? -EOPNOTSUPP
: error
;
1590 return error
< 0 ? error
: -EINVAL
;
1596 int cyapa_pip_deep_sleep(struct cyapa
*cyapa
, u8 state
)
1598 u8 cmd
[] = { 0x05, 0x00, 0x00, 0x08};
1603 cmd
[2] = state
& PIP_DEEP_SLEEP_STATE_MASK
;
1604 resp_len
= sizeof(resp_data
);
1605 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1606 resp_data
, &resp_len
,
1607 500, cyapa_sort_pip_deep_sleep_data
, false);
1608 if (error
|| ((resp_data
[3] & PIP_DEEP_SLEEP_STATE_MASK
) != state
))
1614 static int cyapa_gen5_set_power_mode(struct cyapa
*cyapa
,
1615 u8 power_mode
, u16 sleep_time
, enum cyapa_pm_stage pm_stage
)
1617 struct device
*dev
= &cyapa
->client
->dev
;
1621 if (cyapa
->state
!= CYAPA_STATE_GEN5_APP
)
1624 cyapa_set_pip_pm_state(cyapa
, pm_stage
);
1626 if (PIP_DEV_GET_PWR_STATE(cyapa
) == UNINIT_PWR_MODE
) {
1628 * Assume TP in deep sleep mode when driver is loaded,
1629 * avoid driver unload and reload command IO issue caused by TP
1630 * has been set into deep sleep mode when unloading.
1632 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1635 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) &&
1636 PIP_DEV_GET_PWR_STATE(cyapa
) != PWR_MODE_OFF
)
1637 if (cyapa_gen5_get_interval_time(cyapa
,
1638 GEN5_PARAMETER_LP_INTRVL_ID
,
1639 &cyapa
->dev_sleep_time
) != 0)
1640 PIP_DEV_SET_SLEEP_TIME(cyapa
, UNINIT_SLEEP_TIME
);
1642 if (PIP_DEV_GET_PWR_STATE(cyapa
) == power_mode
) {
1643 if (power_mode
== PWR_MODE_OFF
||
1644 power_mode
== PWR_MODE_FULL_ACTIVE
||
1645 power_mode
== PWR_MODE_BTN_ONLY
||
1646 PIP_DEV_GET_SLEEP_TIME(cyapa
) == sleep_time
) {
1647 /* Has in correct power mode state, early return. */
1652 if (power_mode
== PWR_MODE_OFF
) {
1653 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_OFF
);
1655 dev_err(dev
, "enter deep sleep fail: %d\n", error
);
1659 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1664 * When trackpad in power off mode, it cannot change to other power
1665 * state directly, must be wake up from sleep firstly, then
1666 * continue to do next power sate change.
1668 if (PIP_DEV_GET_PWR_STATE(cyapa
) == PWR_MODE_OFF
) {
1669 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_ON
);
1671 dev_err(dev
, "deep sleep wake fail: %d\n", error
);
1676 if (power_mode
== PWR_MODE_FULL_ACTIVE
) {
1677 error
= cyapa_gen5_change_power_state(cyapa
,
1678 GEN5_POWER_STATE_ACTIVE
);
1680 dev_err(dev
, "change to active fail: %d\n", error
);
1684 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_FULL_ACTIVE
);
1685 } else if (power_mode
== PWR_MODE_BTN_ONLY
) {
1686 error
= cyapa_gen5_change_power_state(cyapa
,
1687 GEN5_POWER_STATE_BTN_ONLY
);
1689 dev_err(dev
, "fail to button only mode: %d\n", error
);
1693 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_BTN_ONLY
);
1696 * Continue to change power mode even failed to set
1697 * interval time, it won't affect the power mode change.
1698 * except the sleep interval time is not correct.
1700 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) ||
1701 sleep_time
!= PIP_DEV_GET_SLEEP_TIME(cyapa
))
1702 if (cyapa_gen5_set_interval_time(cyapa
,
1703 GEN5_PARAMETER_LP_INTRVL_ID
,
1705 PIP_DEV_SET_SLEEP_TIME(cyapa
, sleep_time
);
1707 if (sleep_time
<= GEN5_POWER_READY_MAX_INTRVL_TIME
)
1708 power_state
= GEN5_POWER_STATE_READY
;
1710 power_state
= GEN5_POWER_STATE_IDLE
;
1711 error
= cyapa_gen5_change_power_state(cyapa
, power_state
);
1713 dev_err(dev
, "set power state to 0x%02x failed: %d\n",
1714 power_state
, error
);
1719 * Disable pip report for a little time, firmware will
1720 * re-enable it automatically. It's used to fix the issue
1721 * that trackpad unable to report signal to wake system up
1722 * in the special situation that system is in suspending, and
1723 * at the same time, user touch trackpad to wake system up.
1724 * This function can avoid the data to be buffered when system
1725 * is suspending which may cause interrupt line unable to be
1728 if (pm_stage
== CYAPA_PM_SUSPEND
)
1729 cyapa_gen5_disable_pip_report(cyapa
);
1731 PIP_DEV_SET_PWR_STATE(cyapa
,
1732 cyapa_sleep_time_to_pwr_cmd(sleep_time
));
1736 cyapa_reset_pip_pm_state(cyapa
);
1740 int cyapa_pip_resume_scanning(struct cyapa
*cyapa
)
1742 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
1747 /* Try to dump all buffered data before doing command. */
1748 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1750 resp_len
= sizeof(resp_data
);
1751 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1753 resp_data
, &resp_len
,
1754 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1755 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x04))
1758 /* Try to dump all buffered data when resuming scanning. */
1759 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1764 int cyapa_pip_suspend_scanning(struct cyapa
*cyapa
)
1766 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
1771 /* Try to dump all buffered data before doing command. */
1772 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1774 resp_len
= sizeof(resp_data
);
1775 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1777 resp_data
, &resp_len
,
1778 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1779 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x03))
1782 /* Try to dump all buffered data when suspending scanning. */
1783 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1788 static int cyapa_pip_calibrate_pwcs(struct cyapa
*cyapa
,
1789 u8 calibrate_sensing_mode_type
)
1791 struct pip_app_cmd_head
*app_cmd_head
;
1797 /* Try to dump all buffered data before doing command. */
1798 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1800 memset(cmd
, 0, sizeof(cmd
));
1801 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1802 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1803 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1804 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1805 app_cmd_head
->cmd_code
= PIP_CMD_CALIBRATE
;
1806 app_cmd_head
->parameter_data
[0] = calibrate_sensing_mode_type
;
1807 resp_len
= sizeof(resp_data
);
1808 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1810 resp_data
, &resp_len
,
1811 5000, cyapa_sort_tsg_pip_app_resp_data
, true);
1812 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_CMD_CALIBRATE
) ||
1813 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1814 return error
< 0 ? error
: -EAGAIN
;
1819 ssize_t
cyapa_pip_do_calibrate(struct device
*dev
,
1820 struct device_attribute
*attr
,
1821 const char *buf
, size_t count
)
1823 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
1824 int error
, calibrate_error
;
1826 /* 1. Suspend Scanning*/
1827 error
= cyapa_pip_suspend_scanning(cyapa
);
1831 /* 2. Do mutual capacitance fine calibrate. */
1832 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1833 PIP_SENSING_MODE_MUTUAL_CAP_FINE
);
1834 if (calibrate_error
)
1835 goto resume_scanning
;
1837 /* 3. Do self capacitance calibrate. */
1838 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1839 PIP_SENSING_MODE_SELF_CAP
);
1840 if (calibrate_error
)
1841 goto resume_scanning
;
1844 /* 4. Resume Scanning*/
1845 error
= cyapa_pip_resume_scanning(cyapa
);
1846 if (error
|| calibrate_error
)
1847 return error
? error
: calibrate_error
;
1852 static s32
twos_complement_to_s32(s32 value
, int num_bits
)
1854 if (value
>> (num_bits
- 1))
1855 value
|= -1 << num_bits
;
1859 static s32
cyapa_parse_structure_data(u8 data_format
, u8
*buf
, int buf_len
)
1866 data_size
= (data_format
& 0x07);
1867 big_endian
= ((data_format
& 0x10) == 0x00);
1868 unsigned_type
= ((data_format
& 0x20) == 0x00);
1870 if (buf_len
< data_size
)
1873 switch (data_size
) {
1879 value
= get_unaligned_be16(buf
);
1881 value
= get_unaligned_le16(buf
);
1885 value
= get_unaligned_be32(buf
);
1887 value
= get_unaligned_le32(buf
);
1890 /* Should not happen, just as default case here. */
1896 value
= twos_complement_to_s32(value
, data_size
* 8);
1901 static void cyapa_gen5_guess_electrodes(struct cyapa
*cyapa
,
1902 int *electrodes_rx
, int *electrodes_tx
)
1904 if (cyapa
->electrodes_rx
!= 0) {
1905 *electrodes_rx
= cyapa
->electrodes_rx
;
1906 *electrodes_tx
= (cyapa
->electrodes_x
== *electrodes_rx
) ?
1907 cyapa
->electrodes_y
: cyapa
->electrodes_x
;
1909 *electrodes_tx
= min(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1910 *electrodes_rx
= max(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1915 * Read all the global mutual or self idac data or mutual or self local PWC
1916 * data based on the @idac_data_type.
1917 * If the input value of @data_size is 0, then means read global mutual or
1918 * self idac data. For read global mutual idac data, @idac_max, @idac_min and
1919 * @idac_ave are in order used to return the max value of global mutual idac
1920 * data, the min value of global mutual idac and the average value of the
1921 * global mutual idac data. For read global self idac data, @idac_max is used
1922 * to return the global self cap idac data in Rx direction, @idac_min is used
1923 * to return the global self cap idac data in Tx direction. @idac_ave is not
1925 * If the input value of @data_size is not 0, than means read the mutual or
1926 * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
1927 * return the max, min and average value of the mutual or self local PWC data.
1928 * Note, in order to read mutual local PWC data, must read invoke this function
1929 * to read the mutual global idac data firstly to set the correct Rx number
1930 * value, otherwise, the read mutual idac and PWC data may not correct.
1932 static int cyapa_gen5_read_idac_data(struct cyapa
*cyapa
,
1933 u8 cmd_code
, u8 idac_data_type
, int *data_size
,
1934 int *idac_max
, int *idac_min
, int *idac_ave
)
1936 struct pip_app_cmd_head
*cmd_head
;
1944 bool read_global_idac
;
1945 int sum
, count
, max_element_cnt
;
1946 int tmp_max
, tmp_min
, tmp_ave
, tmp_sum
, tmp_count
;
1947 int electrodes_rx
, electrodes_tx
;
1951 if (cmd_code
!= PIP_RETRIEVE_DATA_STRUCTURE
||
1952 (idac_data_type
!= GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
1953 idac_data_type
!= GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) ||
1954 !data_size
|| !idac_max
|| !idac_min
|| !idac_ave
)
1957 *idac_max
= INT_MIN
;
1958 *idac_min
= INT_MAX
;
1959 sum
= count
= tmp_count
= 0;
1960 electrodes_rx
= electrodes_tx
= 0;
1961 if (*data_size
== 0) {
1963 * Read global idac values firstly.
1964 * Currently, no idac data exceed 4 bytes.
1966 read_global_idac
= true;
1971 tmp_ave
= tmp_sum
= tmp_count
= 0;
1973 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1974 if (cyapa
->aligned_electrodes_rx
== 0) {
1975 cyapa_gen5_guess_electrodes(cyapa
,
1976 &electrodes_rx
, &electrodes_tx
);
1977 cyapa
->aligned_electrodes_rx
=
1978 (electrodes_rx
+ 3) & ~3u;
1981 (cyapa
->aligned_electrodes_rx
+ 7) & ~7u;
1983 max_element_cnt
= 2;
1986 read_global_idac
= false;
1989 /* Calculate the start offset in bytes of local PWC data. */
1990 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1991 offset
= cyapa
->aligned_electrodes_rx
* (*data_size
);
1992 if (cyapa
->electrodes_rx
== cyapa
->electrodes_x
)
1993 electrodes_tx
= cyapa
->electrodes_y
;
1995 electrodes_tx
= cyapa
->electrodes_x
;
1996 max_element_cnt
= ((cyapa
->aligned_electrodes_rx
+ 7) &
1997 ~7u) * electrodes_tx
;
2000 max_element_cnt
= cyapa
->electrodes_x
+
2001 cyapa
->electrodes_y
;
2002 max_element_cnt
= (max_element_cnt
+ 3) & ~3u;
2006 memset(cmd
, 0, sizeof(cmd
));
2007 cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2008 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &cmd_head
->addr
);
2009 put_unaligned_le16(sizeof(cmd
) - 2, &cmd_head
->length
);
2010 cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2011 cmd_head
->cmd_code
= cmd_code
;
2013 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) /
2015 read_elements
= min(read_elements
, max_element_cnt
- count
);
2016 read_len
= read_elements
* (*data_size
);
2018 put_unaligned_le16(offset
, &cmd_head
->parameter_data
[0]);
2019 put_unaligned_le16(read_len
, &cmd_head
->parameter_data
[2]);
2020 cmd_head
->parameter_data
[4] = idac_data_type
;
2021 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
2022 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2024 resp_data
, &resp_len
,
2025 500, cyapa_sort_tsg_pip_app_resp_data
,
2027 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
2028 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
2029 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
2030 resp_data
[6] != idac_data_type
)
2031 return (error
< 0) ? error
: -EAGAIN
;
2032 read_len
= get_unaligned_le16(&resp_data
[7]);
2036 *data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
2037 if (read_len
< *data_size
)
2040 if (read_global_idac
&&
2041 idac_data_type
== GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) {
2042 /* Rx's self global idac data. */
2043 *idac_max
= cyapa_parse_structure_data(
2045 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
],
2047 /* Tx's self global idac data. */
2048 *idac_min
= cyapa_parse_structure_data(
2050 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
+
2056 /* Read mutual global idac or local mutual/self PWC data. */
2058 for (i
= 10; i
< (read_len
+ GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2060 value
= cyapa_parse_structure_data(resp_data
[9],
2061 &resp_data
[i
], *data_size
);
2062 *idac_min
= min(value
, *idac_min
);
2063 *idac_max
= max(value
, *idac_max
);
2065 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
2066 tmp_count
< cyapa
->aligned_electrodes_rx
&&
2069 * The value gap between global and local mutual
2070 * idac data must bigger than 50%.
2071 * Normally, global value bigger than 50,
2072 * local values less than 10.
2074 if (!tmp_ave
|| value
> tmp_ave
/ 2) {
2075 tmp_min
= min(value
, tmp_min
);
2076 tmp_max
= max(value
, tmp_max
);
2080 tmp_ave
= tmp_sum
/ tmp_count
;
2087 if (count
>= max_element_cnt
)
2093 *idac_ave
= count
? (sum
/ count
) : 0;
2095 if (read_global_idac
&&
2096 idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
2100 if (tmp_count
== cyapa
->aligned_electrodes_rx
) {
2101 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2102 cyapa
->electrodes_rx
: electrodes_rx
;
2103 } else if (tmp_count
== electrodes_rx
) {
2104 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2105 cyapa
->electrodes_rx
: electrodes_rx
;
2106 cyapa
->aligned_electrodes_rx
= electrodes_rx
;
2108 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2109 cyapa
->electrodes_rx
: electrodes_tx
;
2110 cyapa
->aligned_electrodes_rx
= tmp_count
;
2113 *idac_min
= tmp_min
;
2114 *idac_max
= tmp_max
;
2115 *idac_ave
= tmp_ave
;
2121 static int cyapa_gen5_read_mutual_idac_data(struct cyapa
*cyapa
,
2122 int *gidac_mutual_max
, int *gidac_mutual_min
, int *gidac_mutual_ave
,
2123 int *lidac_mutual_max
, int *lidac_mutual_min
, int *lidac_mutual_ave
)
2128 *gidac_mutual_max
= *gidac_mutual_min
= *gidac_mutual_ave
= 0;
2129 *lidac_mutual_max
= *lidac_mutual_min
= *lidac_mutual_ave
= 0;
2132 error
= cyapa_gen5_read_idac_data(cyapa
,
2133 PIP_RETRIEVE_DATA_STRUCTURE
,
2134 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2136 gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
);
2140 error
= cyapa_gen5_read_idac_data(cyapa
,
2141 PIP_RETRIEVE_DATA_STRUCTURE
,
2142 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2144 lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
);
2148 static int cyapa_gen5_read_self_idac_data(struct cyapa
*cyapa
,
2149 int *gidac_self_rx
, int *gidac_self_tx
,
2150 int *lidac_self_max
, int *lidac_self_min
, int *lidac_self_ave
)
2155 *gidac_self_rx
= *gidac_self_tx
= 0;
2156 *lidac_self_max
= *lidac_self_min
= *lidac_self_ave
= 0;
2159 error
= cyapa_gen5_read_idac_data(cyapa
,
2160 PIP_RETRIEVE_DATA_STRUCTURE
,
2161 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2163 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2166 *gidac_self_rx
= *lidac_self_max
;
2167 *gidac_self_tx
= *lidac_self_min
;
2169 error
= cyapa_gen5_read_idac_data(cyapa
,
2170 PIP_RETRIEVE_DATA_STRUCTURE
,
2171 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2173 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2177 static ssize_t
cyapa_gen5_execute_panel_scan(struct cyapa
*cyapa
)
2179 struct pip_app_cmd_head
*app_cmd_head
;
2185 memset(cmd
, 0, sizeof(cmd
));
2186 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2187 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2188 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2189 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2190 app_cmd_head
->cmd_code
= GEN5_CMD_EXECUTE_PANEL_SCAN
;
2191 resp_len
= sizeof(resp_data
);
2192 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2194 resp_data
, &resp_len
,
2195 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2196 if (error
|| resp_len
!= sizeof(resp_data
) ||
2197 !VALID_CMD_RESP_HEADER(resp_data
,
2198 GEN5_CMD_EXECUTE_PANEL_SCAN
) ||
2199 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2200 return error
? error
: -EAGAIN
;
2205 static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa
*cyapa
,
2206 u8 cmd_code
, u8 raw_data_type
, int raw_data_max_num
,
2207 int *raw_data_max
, int *raw_data_min
, int *raw_data_ave
,
2210 struct pip_app_cmd_head
*app_cmd_head
;
2211 struct gen5_retrieve_panel_scan_data
*panel_sacn_data
;
2213 u8 resp_data
[256]; /* Max bytes can transfer one time. */
2225 if (cmd_code
!= GEN5_CMD_RETRIEVE_PANEL_SCAN
||
2226 (raw_data_type
> GEN5_PANEL_SCAN_SELF_DIFFCOUNT
) ||
2227 !raw_data_max
|| !raw_data_min
|| !raw_data_ave
)
2230 intp
= (s32
*)buffer
;
2231 *raw_data_max
= INT_MIN
;
2232 *raw_data_min
= INT_MAX
;
2235 /* Assume max element size is 4 currently. */
2236 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) / 4;
2237 read_len
= read_elements
* 4;
2238 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2239 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2240 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2241 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2242 app_cmd_head
->cmd_code
= cmd_code
;
2243 panel_sacn_data
= (struct gen5_retrieve_panel_scan_data
*)
2244 app_cmd_head
->parameter_data
;
2246 put_unaligned_le16(offset
, &panel_sacn_data
->read_offset
);
2247 put_unaligned_le16(read_elements
,
2248 &panel_sacn_data
->read_elements
);
2249 panel_sacn_data
->data_id
= raw_data_type
;
2251 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
2252 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2254 resp_data
, &resp_len
,
2255 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2256 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
2257 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
2258 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
2259 resp_data
[6] != raw_data_type
)
2260 return error
? error
: -EAGAIN
;
2262 read_elements
= get_unaligned_le16(&resp_data
[7]);
2263 if (read_elements
== 0)
2266 data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
2267 offset
+= read_elements
;
2268 if (read_elements
) {
2269 for (i
= GEN5_RESP_DATA_STRUCTURE_OFFSET
;
2270 i
< (read_elements
* data_size
+
2271 GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2273 value
= cyapa_parse_structure_data(resp_data
[9],
2274 &resp_data
[i
], data_size
);
2275 *raw_data_min
= min(value
, *raw_data_min
);
2276 *raw_data_max
= max(value
, *raw_data_max
);
2279 put_unaligned_le32(value
, &intp
[count
]);
2287 if (count
>= raw_data_max_num
)
2290 read_elements
= (sizeof(resp_data
) -
2291 GEN5_RESP_DATA_STRUCTURE_OFFSET
) / data_size
;
2292 read_len
= read_elements
* data_size
;
2295 *raw_data_ave
= count
? (sum
/ count
) : 0;
2300 static ssize_t
cyapa_gen5_show_baseline(struct device
*dev
,
2301 struct device_attribute
*attr
, char *buf
)
2303 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
2304 int gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
;
2305 int lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
;
2306 int gidac_self_rx
, gidac_self_tx
;
2307 int lidac_self_max
, lidac_self_min
, lidac_self_ave
;
2308 int raw_cap_mutual_max
, raw_cap_mutual_min
, raw_cap_mutual_ave
;
2309 int raw_cap_self_max
, raw_cap_self_min
, raw_cap_self_ave
;
2310 int mutual_diffdata_max
, mutual_diffdata_min
, mutual_diffdata_ave
;
2311 int self_diffdata_max
, self_diffdata_min
, self_diffdata_ave
;
2312 int mutual_baseline_max
, mutual_baseline_min
, mutual_baseline_ave
;
2313 int self_baseline_max
, self_baseline_min
, self_baseline_ave
;
2314 int error
, resume_error
;
2317 if (!cyapa_is_pip_app_mode(cyapa
))
2320 /* 1. Suspend Scanning*/
2321 error
= cyapa_pip_suspend_scanning(cyapa
);
2325 /* 2. Read global and local mutual IDAC data. */
2326 gidac_self_rx
= gidac_self_tx
= 0;
2327 error
= cyapa_gen5_read_mutual_idac_data(cyapa
,
2328 &gidac_mutual_max
, &gidac_mutual_min
,
2329 &gidac_mutual_ave
, &lidac_mutual_max
,
2330 &lidac_mutual_min
, &lidac_mutual_ave
);
2332 goto resume_scanning
;
2334 /* 3. Read global and local self IDAC data. */
2335 error
= cyapa_gen5_read_self_idac_data(cyapa
,
2336 &gidac_self_rx
, &gidac_self_tx
,
2337 &lidac_self_max
, &lidac_self_min
,
2340 goto resume_scanning
;
2342 /* 4. Execute panel scan. It must be executed before read data. */
2343 error
= cyapa_gen5_execute_panel_scan(cyapa
);
2345 goto resume_scanning
;
2347 /* 5. Retrieve panel scan, mutual cap raw data. */
2348 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2349 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2350 GEN5_PANEL_SCAN_MUTUAL_RAW_DATA
,
2351 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2352 &raw_cap_mutual_max
, &raw_cap_mutual_min
,
2353 &raw_cap_mutual_ave
,
2356 goto resume_scanning
;
2358 /* 6. Retrieve panel scan, self cap raw data. */
2359 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2360 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2361 GEN5_PANEL_SCAN_SELF_RAW_DATA
,
2362 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2363 &raw_cap_self_max
, &raw_cap_self_min
,
2367 goto resume_scanning
;
2369 /* 7. Retrieve panel scan, mutual cap diffcount raw data. */
2370 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2371 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2372 GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT
,
2373 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2374 &mutual_diffdata_max
, &mutual_diffdata_min
,
2375 &mutual_diffdata_ave
,
2378 goto resume_scanning
;
2380 /* 8. Retrieve panel scan, self cap diffcount raw data. */
2381 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2382 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2383 GEN5_PANEL_SCAN_SELF_DIFFCOUNT
,
2384 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2385 &self_diffdata_max
, &self_diffdata_min
,
2389 goto resume_scanning
;
2391 /* 9. Retrieve panel scan, mutual cap baseline raw data. */
2392 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2393 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2394 GEN5_PANEL_SCAN_MUTUAL_BASELINE
,
2395 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2396 &mutual_baseline_max
, &mutual_baseline_min
,
2397 &mutual_baseline_ave
,
2400 goto resume_scanning
;
2402 /* 10. Retrieve panel scan, self cap baseline raw data. */
2403 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2404 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2405 GEN5_PANEL_SCAN_SELF_BASELINE
,
2406 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2407 &self_baseline_max
, &self_baseline_min
,
2411 goto resume_scanning
;
2414 /* 11. Resume Scanning*/
2415 resume_error
= cyapa_pip_resume_scanning(cyapa
);
2416 if (resume_error
|| error
)
2417 return resume_error
? resume_error
: error
;
2419 /* 12. Output data strings */
2420 size
= scnprintf(buf
, PAGE_SIZE
, "%d %d %d %d %d %d %d %d %d %d %d ",
2421 gidac_mutual_min
, gidac_mutual_max
, gidac_mutual_ave
,
2422 lidac_mutual_min
, lidac_mutual_max
, lidac_mutual_ave
,
2423 gidac_self_rx
, gidac_self_tx
,
2424 lidac_self_min
, lidac_self_max
, lidac_self_ave
);
2425 size
+= scnprintf(buf
+ size
, PAGE_SIZE
- size
,
2426 "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
2427 raw_cap_mutual_min
, raw_cap_mutual_max
, raw_cap_mutual_ave
,
2428 raw_cap_self_min
, raw_cap_self_max
, raw_cap_self_ave
,
2429 mutual_diffdata_min
, mutual_diffdata_max
, mutual_diffdata_ave
,
2430 self_diffdata_min
, self_diffdata_max
, self_diffdata_ave
,
2431 mutual_baseline_min
, mutual_baseline_max
, mutual_baseline_ave
,
2432 self_baseline_min
, self_baseline_max
, self_baseline_ave
);
2436 bool cyapa_pip_sort_system_info_data(struct cyapa
*cyapa
,
2439 /* Check the report id and command code */
2440 if (VALID_CMD_RESP_HEADER(buf
, 0x02))
2446 static int cyapa_gen5_bl_query_data(struct cyapa
*cyapa
)
2448 u8 resp_data
[PIP_BL_APP_INFO_RESP_LENGTH
];
2452 resp_len
= sizeof(resp_data
);
2453 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2454 pip_bl_read_app_info
, PIP_BL_READ_APP_INFO_CMD_LENGTH
,
2455 resp_data
, &resp_len
,
2456 500, cyapa_sort_tsg_pip_bl_resp_data
, false);
2457 if (error
|| resp_len
< PIP_BL_APP_INFO_RESP_LENGTH
||
2458 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2459 return error
? error
: -EIO
;
2461 memcpy(&cyapa
->product_id
[0], &resp_data
[8], 5);
2462 cyapa
->product_id
[5] = '-';
2463 memcpy(&cyapa
->product_id
[6], &resp_data
[13], 6);
2464 cyapa
->product_id
[12] = '-';
2465 memcpy(&cyapa
->product_id
[13], &resp_data
[19], 2);
2466 cyapa
->product_id
[15] = '\0';
2468 cyapa
->fw_maj_ver
= resp_data
[22];
2469 cyapa
->fw_min_ver
= resp_data
[23];
2471 cyapa
->platform_ver
= (resp_data
[26] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2472 PIP_BL_PLATFORM_VER_MASK
;
2477 static int cyapa_gen5_get_query_data(struct cyapa
*cyapa
)
2479 u8 resp_data
[PIP_READ_SYS_INFO_RESP_LENGTH
];
2484 resp_len
= sizeof(resp_data
);
2485 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2486 pip_read_sys_info
, PIP_READ_SYS_INFO_CMD_LENGTH
,
2487 resp_data
, &resp_len
,
2488 2000, cyapa_pip_sort_system_info_data
, false);
2489 if (error
|| resp_len
< sizeof(resp_data
))
2490 return error
? error
: -EIO
;
2492 product_family
= get_unaligned_le16(&resp_data
[7]);
2493 if ((product_family
& PIP_PRODUCT_FAMILY_MASK
) !=
2494 PIP_PRODUCT_FAMILY_TRACKPAD
)
2497 cyapa
->platform_ver
= (resp_data
[49] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2498 PIP_BL_PLATFORM_VER_MASK
;
2499 if (cyapa
->gen
== CYAPA_GEN5
&& cyapa
->platform_ver
< 2) {
2500 /* Gen5 firmware that does not support proximity. */
2501 cyapa
->fw_maj_ver
= resp_data
[15];
2502 cyapa
->fw_min_ver
= resp_data
[16];
2504 cyapa
->fw_maj_ver
= resp_data
[9];
2505 cyapa
->fw_min_ver
= resp_data
[10];
2508 cyapa
->electrodes_x
= resp_data
[52];
2509 cyapa
->electrodes_y
= resp_data
[53];
2511 cyapa
->physical_size_x
= get_unaligned_le16(&resp_data
[54]) / 100;
2512 cyapa
->physical_size_y
= get_unaligned_le16(&resp_data
[56]) / 100;
2514 cyapa
->max_abs_x
= get_unaligned_le16(&resp_data
[58]);
2515 cyapa
->max_abs_y
= get_unaligned_le16(&resp_data
[60]);
2517 cyapa
->max_z
= get_unaligned_le16(&resp_data
[62]);
2519 cyapa
->x_origin
= resp_data
[64] & 0x01;
2520 cyapa
->y_origin
= resp_data
[65] & 0x01;
2522 cyapa
->btn_capability
= (resp_data
[70] << 3) & CAPABILITY_BTN_MASK
;
2524 memcpy(&cyapa
->product_id
[0], &resp_data
[33], 5);
2525 cyapa
->product_id
[5] = '-';
2526 memcpy(&cyapa
->product_id
[6], &resp_data
[38], 6);
2527 cyapa
->product_id
[12] = '-';
2528 memcpy(&cyapa
->product_id
[13], &resp_data
[44], 2);
2529 cyapa
->product_id
[15] = '\0';
2531 if (!cyapa
->electrodes_x
|| !cyapa
->electrodes_y
||
2532 !cyapa
->physical_size_x
|| !cyapa
->physical_size_y
||
2533 !cyapa
->max_abs_x
|| !cyapa
->max_abs_y
|| !cyapa
->max_z
)
2539 static int cyapa_gen5_do_operational_check(struct cyapa
*cyapa
)
2541 struct device
*dev
= &cyapa
->client
->dev
;
2544 if (cyapa
->gen
!= CYAPA_GEN5
)
2547 switch (cyapa
->state
) {
2548 case CYAPA_STATE_GEN5_BL
:
2549 error
= cyapa_pip_bl_exit(cyapa
);
2551 /* Try to update trackpad product information. */
2552 cyapa_gen5_bl_query_data(cyapa
);
2556 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
2559 case CYAPA_STATE_GEN5_APP
:
2561 * If trackpad device in deep sleep mode,
2562 * the app command will fail.
2563 * So always try to reset trackpad device to full active when
2564 * the device state is required.
2566 error
= cyapa_gen5_set_power_mode(cyapa
,
2567 PWR_MODE_FULL_ACTIVE
, 0, CYAPA_PM_ACTIVE
);
2569 dev_warn(dev
, "%s: failed to set power active mode.\n",
2572 /* By default, the trackpad proximity function is enabled. */
2573 if (cyapa
->platform_ver
>= 2) {
2574 error
= cyapa_pip_set_proximity(cyapa
, true);
2577 "%s: failed to enable proximity.\n",
2581 /* Get trackpad product information. */
2582 error
= cyapa_gen5_get_query_data(cyapa
);
2585 /* Only support product ID starting with CYTRA */
2586 if (memcmp(cyapa
->product_id
, product_id
,
2587 strlen(product_id
)) != 0) {
2588 dev_err(dev
, "%s: unknown product ID (%s)\n",
2589 __func__
, cyapa
->product_id
);
2602 * Return false, do not continue process
2603 * Return true, continue process.
2605 bool cyapa_pip_irq_cmd_handler(struct cyapa
*cyapa
)
2607 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
2610 if (atomic_read(&pip
->cmd_issued
)) {
2611 /* Polling command response data. */
2612 if (pip
->is_irq_mode
== false)
2616 * Read out all none command response data.
2617 * these output data may caused by user put finger on
2618 * trackpad when host waiting the command response.
2620 cyapa_i2c_pip_read(cyapa
, pip
->irq_cmd_buf
,
2621 PIP_RESP_LENGTH_SIZE
);
2622 length
= get_unaligned_le16(pip
->irq_cmd_buf
);
2623 length
= (length
<= PIP_RESP_LENGTH_SIZE
) ?
2624 PIP_RESP_LENGTH_SIZE
: length
;
2625 if (length
> PIP_RESP_LENGTH_SIZE
)
2626 cyapa_i2c_pip_read(cyapa
,
2627 pip
->irq_cmd_buf
, length
);
2628 if (!(pip
->resp_sort_func
&&
2629 pip
->resp_sort_func(cyapa
,
2630 pip
->irq_cmd_buf
, length
))) {
2632 * Cover the Gen5 V1 firmware issue.
2633 * The issue is no interrupt would be asserted from
2634 * trackpad device to host for the command response
2635 * ready event. Because when there was a finger touch
2636 * on trackpad device, and the firmware output queue
2637 * won't be empty (always with touch report data), so
2638 * the interrupt signal won't be asserted again until
2639 * the output queue was previous emptied.
2640 * This issue would happen in the scenario that
2641 * user always has his/her fingers touched on the
2642 * trackpad device during system booting/rebooting.
2646 length
= *pip
->resp_len
;
2647 cyapa_empty_pip_output_data(cyapa
,
2650 pip
->resp_sort_func
);
2651 if (pip
->resp_len
&& length
!= 0) {
2652 *pip
->resp_len
= length
;
2653 atomic_dec(&pip
->cmd_issued
);
2654 complete(&pip
->cmd_ready
);
2659 if (pip
->resp_data
&& pip
->resp_len
) {
2660 *pip
->resp_len
= (*pip
->resp_len
< length
) ?
2661 *pip
->resp_len
: length
;
2662 memcpy(pip
->resp_data
, pip
->irq_cmd_buf
,
2665 atomic_dec(&pip
->cmd_issued
);
2666 complete(&pip
->cmd_ready
);
2673 static void cyapa_pip_report_buttons(struct cyapa
*cyapa
,
2674 const struct cyapa_pip_report_data
*report_data
)
2676 struct input_dev
*input
= cyapa
->input
;
2677 u8 buttons
= report_data
->report_head
[PIP_BUTTONS_OFFSET
];
2679 buttons
= (buttons
<< CAPABILITY_BTN_SHIFT
) & CAPABILITY_BTN_MASK
;
2681 if (cyapa
->btn_capability
& CAPABILITY_LEFT_BTN_MASK
) {
2682 input_report_key(input
, BTN_LEFT
,
2683 !!(buttons
& CAPABILITY_LEFT_BTN_MASK
));
2685 if (cyapa
->btn_capability
& CAPABILITY_MIDDLE_BTN_MASK
) {
2686 input_report_key(input
, BTN_MIDDLE
,
2687 !!(buttons
& CAPABILITY_MIDDLE_BTN_MASK
));
2689 if (cyapa
->btn_capability
& CAPABILITY_RIGHT_BTN_MASK
) {
2690 input_report_key(input
, BTN_RIGHT
,
2691 !!(buttons
& CAPABILITY_RIGHT_BTN_MASK
));
2697 static void cyapa_pip_report_proximity(struct cyapa
*cyapa
,
2698 const struct cyapa_pip_report_data
*report_data
)
2700 struct input_dev
*input
= cyapa
->input
;
2701 u8 distance
= report_data
->report_head
[PIP_PROXIMITY_DISTANCE_OFFSET
] &
2702 PIP_PROXIMITY_DISTANCE_MASK
;
2704 input_report_abs(input
, ABS_DISTANCE
, distance
);
2708 static void cyapa_pip_report_slot_data(struct cyapa
*cyapa
,
2709 const struct cyapa_pip_touch_record
*touch
)
2711 struct input_dev
*input
= cyapa
->input
;
2712 u8 event_id
= PIP_GET_EVENT_ID(touch
->touch_tip_event_id
);
2713 int slot
= PIP_GET_TOUCH_ID(touch
->touch_tip_event_id
);
2716 if (event_id
== RECORD_EVENT_LIFTOFF
)
2719 input_mt_slot(input
, slot
);
2720 input_mt_report_slot_state(input
, MT_TOOL_FINGER
, true);
2721 x
= (touch
->x_hi
<< 8) | touch
->x_lo
;
2722 if (cyapa
->x_origin
)
2723 x
= cyapa
->max_abs_x
- x
;
2724 y
= (touch
->y_hi
<< 8) | touch
->y_lo
;
2725 if (cyapa
->y_origin
)
2726 y
= cyapa
->max_abs_y
- y
;
2727 input_report_abs(input
, ABS_MT_POSITION_X
, x
);
2728 input_report_abs(input
, ABS_MT_POSITION_Y
, y
);
2729 input_report_abs(input
, ABS_DISTANCE
, 0);
2730 input_report_abs(input
, ABS_MT_PRESSURE
,
2732 input_report_abs(input
, ABS_MT_TOUCH_MAJOR
,
2733 touch
->major_axis_len
);
2734 input_report_abs(input
, ABS_MT_TOUCH_MINOR
,
2735 touch
->minor_axis_len
);
2737 input_report_abs(input
, ABS_MT_WIDTH_MAJOR
,
2738 touch
->major_tool_len
);
2739 input_report_abs(input
, ABS_MT_WIDTH_MINOR
,
2740 touch
->minor_tool_len
);
2742 input_report_abs(input
, ABS_MT_ORIENTATION
,
2743 touch
->orientation
);
2746 static void cyapa_pip_report_touches(struct cyapa
*cyapa
,
2747 const struct cyapa_pip_report_data
*report_data
)
2749 struct input_dev
*input
= cyapa
->input
;
2750 unsigned int touch_num
;
2753 touch_num
= report_data
->report_head
[PIP_NUMBER_OF_TOUCH_OFFSET
] &
2754 PIP_NUMBER_OF_TOUCH_MASK
;
2756 for (i
= 0; i
< touch_num
; i
++)
2757 cyapa_pip_report_slot_data(cyapa
,
2758 &report_data
->touch_records
[i
]);
2760 input_mt_sync_frame(input
);
2764 int cyapa_pip_irq_handler(struct cyapa
*cyapa
)
2766 struct device
*dev
= &cyapa
->client
->dev
;
2767 struct cyapa_pip_report_data report_data
;
2768 unsigned int report_len
;
2771 if (!cyapa_is_pip_app_mode(cyapa
)) {
2772 dev_err(dev
, "invalid device state, gen=%d, state=0x%02x\n",
2773 cyapa
->gen
, cyapa
->state
);
2777 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
,
2778 PIP_RESP_LENGTH_SIZE
);
2779 if (ret
!= PIP_RESP_LENGTH_SIZE
) {
2780 dev_err(dev
, "failed to read length bytes, (%d)\n", ret
);
2784 report_len
= get_unaligned_le16(
2785 &report_data
.report_head
[PIP_RESP_LENGTH_OFFSET
]);
2786 if (report_len
< PIP_RESP_LENGTH_SIZE
) {
2787 /* Invalid length or internal reset happened. */
2788 dev_err(dev
, "invalid report_len=%d. bytes: %02x %02x\n",
2789 report_len
, report_data
.report_head
[0],
2790 report_data
.report_head
[1]);
2794 /* Idle, no data for report. */
2795 if (report_len
== PIP_RESP_LENGTH_SIZE
)
2798 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
, report_len
);
2799 if (ret
!= report_len
) {
2800 dev_err(dev
, "failed to read %d bytes report data, (%d)\n",
2805 return cyapa_pip_event_process(cyapa
, &report_data
);
2808 static int cyapa_pip_event_process(struct cyapa
*cyapa
,
2809 struct cyapa_pip_report_data
*report_data
)
2811 struct device
*dev
= &cyapa
->client
->dev
;
2812 unsigned int report_len
;
2815 report_len
= get_unaligned_le16(
2816 &report_data
->report_head
[PIP_RESP_LENGTH_OFFSET
]);
2817 /* Idle, no data for report. */
2818 if (report_len
== PIP_RESP_LENGTH_SIZE
)
2821 report_id
= report_data
->report_head
[PIP_RESP_REPORT_ID_OFFSET
];
2822 if (report_id
== PIP_WAKEUP_EVENT_REPORT_ID
&&
2823 report_len
== PIP_WAKEUP_EVENT_SIZE
) {
2825 * Device wake event from deep sleep mode for touch.
2826 * This interrupt event is used to wake system up.
2829 * It will introduce about 20~40 ms additional delay
2830 * time in receiving for first valid touch report data.
2831 * The time is used to execute device runtime resume
2834 pm_runtime_get_sync(dev
);
2835 pm_runtime_mark_last_busy(dev
);
2836 pm_runtime_put_sync_autosuspend(dev
);
2838 } else if (report_id
!= PIP_TOUCH_REPORT_ID
&&
2839 report_id
!= PIP_BTN_REPORT_ID
&&
2840 report_id
!= GEN5_OLD_PUSH_BTN_REPORT_ID
&&
2841 report_id
!= PIP_PUSH_BTN_REPORT_ID
&&
2842 report_id
!= PIP_PROXIMITY_REPORT_ID
) {
2843 /* Running in BL mode or unknown response data read. */
2844 dev_err(dev
, "invalid report_id=0x%02x\n", report_id
);
2848 if (report_id
== PIP_TOUCH_REPORT_ID
&&
2849 (report_len
< PIP_TOUCH_REPORT_HEAD_SIZE
||
2850 report_len
> PIP_TOUCH_REPORT_MAX_SIZE
)) {
2851 /* Invalid report data length for finger packet. */
2852 dev_err(dev
, "invalid touch packet length=%d\n", report_len
);
2856 if ((report_id
== PIP_BTN_REPORT_ID
||
2857 report_id
== GEN5_OLD_PUSH_BTN_REPORT_ID
||
2858 report_id
== PIP_PUSH_BTN_REPORT_ID
) &&
2859 (report_len
< PIP_BTN_REPORT_HEAD_SIZE
||
2860 report_len
> PIP_BTN_REPORT_MAX_SIZE
)) {
2861 /* Invalid report data length of button packet. */
2862 dev_err(dev
, "invalid button packet length=%d\n", report_len
);
2866 if (report_id
== PIP_PROXIMITY_REPORT_ID
&&
2867 report_len
!= PIP_PROXIMITY_REPORT_SIZE
) {
2868 /* Invalid report data length of proximity packet. */
2869 dev_err(dev
, "invalid proximity data, length=%d\n", report_len
);
2873 if (report_id
== PIP_TOUCH_REPORT_ID
)
2874 cyapa_pip_report_touches(cyapa
, report_data
);
2875 else if (report_id
== PIP_PROXIMITY_REPORT_ID
)
2876 cyapa_pip_report_proximity(cyapa
, report_data
);
2878 cyapa_pip_report_buttons(cyapa
, report_data
);
2883 int cyapa_pip_bl_activate(struct cyapa
*cyapa
) { return 0; }
2884 int cyapa_pip_bl_deactivate(struct cyapa
*cyapa
) { return 0; }
2887 const struct cyapa_dev_ops cyapa_gen5_ops
= {
2888 .check_fw
= cyapa_pip_check_fw
,
2889 .bl_enter
= cyapa_pip_bl_enter
,
2890 .bl_initiate
= cyapa_pip_bl_initiate
,
2891 .update_fw
= cyapa_pip_do_fw_update
,
2892 .bl_activate
= cyapa_pip_bl_activate
,
2893 .bl_deactivate
= cyapa_pip_bl_deactivate
,
2895 .show_baseline
= cyapa_gen5_show_baseline
,
2896 .calibrate_store
= cyapa_pip_do_calibrate
,
2898 .initialize
= cyapa_pip_cmd_state_initialize
,
2900 .state_parse
= cyapa_gen5_state_parse
,
2901 .operational_check
= cyapa_gen5_do_operational_check
,
2903 .irq_handler
= cyapa_pip_irq_handler
,
2904 .irq_cmd_handler
= cyapa_pip_irq_cmd_handler
,
2905 .sort_empty_output_data
= cyapa_empty_pip_output_data
,
2906 .set_power_mode
= cyapa_gen5_set_power_mode
,
2908 .set_proximity
= cyapa_pip_set_proximity
,