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
[];
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
[]; /* 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
[]; /* 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
&&
522 input
&& input_device_enabled(input
) &&
523 (pm_stage
== CYAPA_PM_RUNTIME_RESUME
||
524 pm_stage
== CYAPA_PM_RUNTIME_SUSPEND
)) {
525 /* Parse the data and report it if it's valid. */
526 cyapa_pip_event_process(cyapa
,
527 (struct cyapa_pip_report_data
*)pip
->empty_buf
);
531 } while (report_count
);
536 static int cyapa_do_i2c_pip_cmd_irq_sync(
538 u8
*cmd
, size_t cmd_len
,
539 unsigned long timeout
)
541 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
544 /* Wait for interrupt to set ready completion */
545 init_completion(&pip
->cmd_ready
);
547 atomic_inc(&pip
->cmd_issued
);
548 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
550 atomic_dec(&pip
->cmd_issued
);
551 return (error
< 0) ? error
: -EIO
;
554 /* Wait for interrupt to indicate command is completed. */
555 timeout
= wait_for_completion_timeout(&pip
->cmd_ready
,
556 msecs_to_jiffies(timeout
));
558 atomic_dec(&pip
->cmd_issued
);
565 static int cyapa_do_i2c_pip_cmd_polling(
567 u8
*cmd
, size_t cmd_len
,
568 u8
*resp_data
, int *resp_len
,
569 unsigned long timeout
,
572 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
577 atomic_inc(&pip
->cmd_issued
);
578 error
= cyapa_i2c_pip_write(cyapa
, cmd
, cmd_len
);
580 atomic_dec(&pip
->cmd_issued
);
581 return error
< 0 ? error
: -EIO
;
584 length
= resp_len
? *resp_len
: 0;
585 if (resp_data
&& resp_len
&& length
!= 0 && func
) {
588 usleep_range(3000, 5000);
590 error
= cyapa_empty_pip_output_data(cyapa
,
591 resp_data
, resp_len
, func
);
592 if (error
|| *resp_len
== 0)
596 } while (--tries
> 0);
597 if ((error
|| *resp_len
== 0) || tries
<= 0)
598 error
= error
? error
: -ETIMEDOUT
;
601 atomic_dec(&pip
->cmd_issued
);
605 int cyapa_i2c_pip_cmd_irq_sync(
607 u8
*cmd
, int cmd_len
,
608 u8
*resp_data
, int *resp_len
,
609 unsigned long timeout
,
613 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
616 if (!cmd
|| !cmd_len
)
619 /* Commands must be serialized. */
620 error
= mutex_lock_interruptible(&pip
->cmd_lock
);
624 pip
->resp_sort_func
= func
;
625 pip
->resp_data
= resp_data
;
626 pip
->resp_len
= resp_len
;
628 if (cmd_len
>= PIP_MIN_APP_CMD_LENGTH
&&
629 cmd
[4] == PIP_APP_CMD_REPORT_ID
) {
630 /* Application command */
631 pip
->in_progress_cmd
= cmd
[6] & 0x7f;
632 } else if (cmd_len
>= PIP_MIN_BL_CMD_LENGTH
&&
633 cmd
[4] == PIP_BL_CMD_REPORT_ID
) {
634 /* Bootloader command */
635 pip
->in_progress_cmd
= cmd
[7];
638 /* Send command data, wait and read output response data's length. */
640 pip
->is_irq_mode
= true;
641 error
= cyapa_do_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
643 if (error
== -ETIMEDOUT
&& resp_data
&&
644 resp_len
&& *resp_len
!= 0 && func
) {
646 * For some old version, there was no interrupt for
647 * the command response data, so need to poll here
648 * to try to get the response data.
650 error
= cyapa_empty_pip_output_data(cyapa
,
651 resp_data
, resp_len
, func
);
652 if (error
|| *resp_len
== 0)
653 error
= error
? error
: -ETIMEDOUT
;
656 pip
->is_irq_mode
= false;
657 error
= cyapa_do_i2c_pip_cmd_polling(cyapa
, cmd
, cmd_len
,
658 resp_data
, resp_len
, timeout
, func
);
661 pip
->resp_sort_func
= NULL
;
662 pip
->resp_data
= NULL
;
663 pip
->resp_len
= NULL
;
664 pip
->in_progress_cmd
= PIP_INVALID_CMD
;
666 mutex_unlock(&pip
->cmd_lock
);
670 bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa
*cyapa
,
673 if (!data
|| len
< PIP_MIN_BL_RESP_LENGTH
)
676 /* Bootloader input report id 30h */
677 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_BL_RESP_REPORT_ID
&&
678 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
679 data
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
)
685 bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa
*cyapa
,
688 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
691 if (!data
|| len
< PIP_MIN_APP_RESP_LENGTH
)
694 if (data
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_APP_RESP_REPORT_ID
&&
695 data
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
) {
696 resp_len
= get_unaligned_le16(&data
[PIP_RESP_LENGTH_OFFSET
]);
697 if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) == 0x00 &&
698 resp_len
== PIP_UNSUPPORTED_CMD_RESP_LENGTH
&&
699 data
[5] == pip
->in_progress_cmd
) {
700 /* Unsupported command code */
702 } else if (GET_PIP_CMD_CODE(data
[PIP_RESP_APP_CMD_OFFSET
]) ==
703 pip
->in_progress_cmd
) {
704 /* Correct command response received */
712 static bool cyapa_sort_pip_application_launch_data(struct cyapa
*cyapa
,
715 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
719 * After reset or power on, trackpad device always sets to 0x00 0x00
720 * to indicate a reset or power on event.
722 if (buf
[0] == 0 && buf
[1] == 0)
728 static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa
*cyapa
,
734 /* Check hid descriptor. */
735 if (len
!= PIP_HID_DESCRIPTOR_SIZE
)
738 resp_len
= get_unaligned_le16(&buf
[PIP_RESP_LENGTH_OFFSET
]);
739 max_output_len
= get_unaligned_le16(&buf
[16]);
740 if (resp_len
== PIP_HID_DESCRIPTOR_SIZE
) {
741 if (buf
[PIP_RESP_REPORT_ID_OFFSET
] == PIP_HID_BL_REPORT_ID
&&
742 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
743 /* BL mode HID Descriptor */
745 } else if ((buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
746 PIP_HID_APP_REPORT_ID
) &&
747 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
748 /* APP mode HID Descriptor */
756 static bool cyapa_sort_pip_deep_sleep_data(struct cyapa
*cyapa
,
759 if (len
== PIP_DEEP_SLEEP_RESP_LENGTH
&&
760 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
761 PIP_APP_DEEP_SLEEP_REPORT_ID
&&
762 (buf
[4] & PIP_DEEP_SLEEP_OPCODE_MASK
) ==
763 PIP_DEEP_SLEEP_OPCODE
)
768 static int gen5_idle_state_parse(struct cyapa
*cyapa
)
770 u8 resp_data
[PIP_HID_DESCRIPTOR_SIZE
];
778 * Dump all buffered data firstly for the situation
779 * when the trackpad is just power on the cyapa go here.
781 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
783 memset(resp_data
, 0, sizeof(resp_data
));
784 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
, 3);
786 return ret
< 0 ? ret
: -EIO
;
788 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
789 if (length
== PIP_RESP_LENGTH_SIZE
) {
790 /* Normal state of Gen5 with no data to response */
791 cyapa
->gen
= CYAPA_GEN5
;
793 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
795 /* Read description from trackpad device */
798 length
= PIP_HID_DESCRIPTOR_SIZE
;
799 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
800 cmd
, PIP_RESP_LENGTH_SIZE
,
803 cyapa_sort_gen5_hid_descriptor_data
,
808 length
= get_unaligned_le16(
809 &resp_data
[PIP_RESP_LENGTH_OFFSET
]);
810 max_output_len
= get_unaligned_le16(&resp_data
[16]);
811 if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
812 length
== PIP_RESP_LENGTH_SIZE
) &&
813 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
814 PIP_HID_BL_REPORT_ID
) &&
815 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
816 /* BL mode HID Description read */
817 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
818 } else if ((length
== PIP_HID_DESCRIPTOR_SIZE
||
819 length
== PIP_RESP_LENGTH_SIZE
) &&
820 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
821 PIP_HID_APP_REPORT_ID
) &&
822 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
823 /* APP mode HID Description read */
824 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
826 /* Should not happen!!! */
827 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
834 static int gen5_hid_description_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
841 /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
842 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
844 * Must read HID Description content through out,
845 * otherwise Gen5 trackpad cannot response next command
846 * or report any touch or button data.
848 ret
= cyapa_i2c_pip_read(cyapa
, resp_data
,
849 PIP_HID_DESCRIPTOR_SIZE
);
850 if (ret
!= PIP_HID_DESCRIPTOR_SIZE
)
851 return ret
< 0 ? ret
: -EIO
;
852 length
= get_unaligned_le16(&resp_data
[PIP_RESP_LENGTH_OFFSET
]);
853 max_output_len
= get_unaligned_le16(&resp_data
[16]);
854 if (length
== PIP_RESP_LENGTH_SIZE
) {
855 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
856 PIP_HID_BL_REPORT_ID
) {
858 * BL mode HID Description has been previously
861 cyapa
->gen
= CYAPA_GEN5
;
862 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
865 * APP mode HID Description has been previously
868 cyapa
->gen
= CYAPA_GEN5
;
869 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
871 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
872 resp_data
[2] == PIP_HID_BL_REPORT_ID
&&
873 max_output_len
== GEN5_BL_MAX_OUTPUT_LENGTH
) {
874 /* BL mode HID Description read. */
875 cyapa
->gen
= CYAPA_GEN5
;
876 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
877 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
878 (resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
879 PIP_HID_APP_REPORT_ID
) &&
880 max_output_len
== GEN5_APP_MAX_OUTPUT_LENGTH
) {
881 /* APP mode HID Description read. */
882 cyapa
->gen
= CYAPA_GEN5
;
883 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
885 /* Should not happen!!! */
886 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
892 static int gen5_report_data_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
896 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
897 switch (reg_data
[PIP_RESP_REPORT_ID_OFFSET
]) {
898 case PIP_TOUCH_REPORT_ID
:
899 if (length
< PIP_TOUCH_REPORT_HEAD_SIZE
||
900 length
> PIP_TOUCH_REPORT_MAX_SIZE
)
903 case PIP_BTN_REPORT_ID
:
904 case GEN5_OLD_PUSH_BTN_REPORT_ID
:
905 case PIP_PUSH_BTN_REPORT_ID
:
906 if (length
< PIP_BTN_REPORT_HEAD_SIZE
||
907 length
> PIP_BTN_REPORT_MAX_SIZE
)
910 case PIP_WAKEUP_EVENT_REPORT_ID
:
911 if (length
!= PIP_WAKEUP_EVENT_SIZE
)
918 cyapa
->gen
= CYAPA_GEN5
;
919 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
923 static int gen5_cmd_resp_header_parse(struct cyapa
*cyapa
, u8
*reg_data
)
925 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
930 * Must read report data through out,
931 * otherwise Gen5 trackpad cannot response next command
932 * or report any touch or button data.
934 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
935 ret
= cyapa_i2c_pip_read(cyapa
, pip
->empty_buf
, length
);
937 return ret
< 0 ? ret
: -EIO
;
939 if (length
== PIP_RESP_LENGTH_SIZE
) {
940 /* Previous command has read the data through out. */
941 if (reg_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
942 PIP_BL_RESP_REPORT_ID
) {
943 /* Gen5 BL command response data detected */
944 cyapa
->gen
= CYAPA_GEN5
;
945 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
947 /* Gen5 APP command response data detected */
948 cyapa
->gen
= CYAPA_GEN5
;
949 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
951 } else if ((pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
952 PIP_BL_RESP_REPORT_ID
) &&
953 (pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
954 PIP_RESP_RSVD_KEY
) &&
955 (pip
->empty_buf
[PIP_RESP_BL_SOP_OFFSET
] ==
957 (pip
->empty_buf
[length
- 1] ==
959 /* Gen5 BL command response data detected */
960 cyapa
->gen
= CYAPA_GEN5
;
961 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
962 } else if (pip
->empty_buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
963 PIP_APP_RESP_REPORT_ID
&&
964 pip
->empty_buf
[PIP_RESP_RSVD_OFFSET
] ==
966 /* Gen5 APP command response data detected */
967 cyapa
->gen
= CYAPA_GEN5
;
968 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
970 /* Should not happen!!! */
971 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
977 static int cyapa_gen5_state_parse(struct cyapa
*cyapa
, u8
*reg_data
, int len
)
981 if (!reg_data
|| len
< 3)
984 cyapa
->state
= CYAPA_STATE_NO_DEVICE
;
986 /* Parse based on Gen5 characteristic registers and bits */
987 length
= get_unaligned_le16(®_data
[PIP_RESP_LENGTH_OFFSET
]);
988 if (length
== 0 || length
== PIP_RESP_LENGTH_SIZE
) {
989 gen5_idle_state_parse(cyapa
);
990 } else if (length
== PIP_HID_DESCRIPTOR_SIZE
&&
991 (reg_data
[2] == PIP_HID_BL_REPORT_ID
||
992 reg_data
[2] == PIP_HID_APP_REPORT_ID
)) {
993 gen5_hid_description_header_parse(cyapa
, reg_data
);
994 } else if ((length
== GEN5_APP_REPORT_DESCRIPTOR_SIZE
||
995 length
== GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE
) &&
996 reg_data
[2] == GEN5_APP_REPORT_DESCRIPTOR_ID
) {
997 /* 0xEE 0x00 0xF6 is Gen5 APP report description header. */
998 cyapa
->gen
= CYAPA_GEN5
;
999 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
1000 } else if (length
== GEN5_BL_REPORT_DESCRIPTOR_SIZE
&&
1001 reg_data
[2] == GEN5_BL_REPORT_DESCRIPTOR_ID
) {
1002 /* 0x1D 0x00 0xFE is Gen5 BL report descriptor header. */
1003 cyapa
->gen
= CYAPA_GEN5
;
1004 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
1005 } else if (reg_data
[2] == PIP_TOUCH_REPORT_ID
||
1006 reg_data
[2] == PIP_BTN_REPORT_ID
||
1007 reg_data
[2] == GEN5_OLD_PUSH_BTN_REPORT_ID
||
1008 reg_data
[2] == PIP_PUSH_BTN_REPORT_ID
||
1009 reg_data
[2] == PIP_WAKEUP_EVENT_REPORT_ID
) {
1010 gen5_report_data_header_parse(cyapa
, reg_data
);
1011 } else if (reg_data
[2] == PIP_BL_RESP_REPORT_ID
||
1012 reg_data
[2] == PIP_APP_RESP_REPORT_ID
) {
1013 gen5_cmd_resp_header_parse(cyapa
, reg_data
);
1016 if (cyapa
->gen
== CYAPA_GEN5
) {
1018 * Must read the content (e.g.: report description and so on)
1019 * from trackpad device throughout. Otherwise,
1020 * Gen5 trackpad cannot response to next command or
1021 * report any touch or button data later.
1023 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1025 if (cyapa
->state
== CYAPA_STATE_GEN5_APP
||
1026 cyapa
->state
== CYAPA_STATE_GEN5_BL
)
1033 static struct cyapa_tsg_bin_image_data_record
*
1034 cyapa_get_image_record_data_num(const struct firmware
*fw
,
1039 head_size
= fw
->data
[0] + 1;
1040 *record_num
= (fw
->size
- head_size
) /
1041 sizeof(struct cyapa_tsg_bin_image_data_record
);
1042 return (struct cyapa_tsg_bin_image_data_record
*)&fw
->data
[head_size
];
1045 int cyapa_pip_bl_initiate(struct cyapa
*cyapa
, const struct firmware
*fw
)
1047 struct cyapa_tsg_bin_image_data_record
*image_records
;
1048 struct pip_bl_cmd_head
*bl_cmd_head
;
1049 struct pip_bl_packet_start
*bl_packet_start
;
1050 struct pip_bl_initiate_cmd_data
*cmd_data
;
1051 struct pip_bl_packet_end
*bl_packet_end
;
1052 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1056 u16 meta_data_crc
= 0;
1063 /* Try to dump all buffered report data before any send command. */
1064 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1066 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1067 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1068 cmd_data_len
= CYAPA_TSG_BL_KEY_SIZE
+ CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
;
1069 cmd_len
= sizeof(struct pip_bl_cmd_head
) + cmd_data_len
+
1070 sizeof(struct pip_bl_packet_end
);
1072 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1073 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1074 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1076 bl_packet_start
= &bl_cmd_head
->packet_start
;
1077 bl_packet_start
->sop
= PIP_SOP_KEY
;
1078 bl_packet_start
->cmd_code
= PIP_BL_CMD_INITIATE_BL
;
1079 /* 8 key bytes and 128 bytes block size */
1080 put_unaligned_le16(cmd_data_len
, &bl_packet_start
->data_length
);
1082 cmd_data
= (struct pip_bl_initiate_cmd_data
*)bl_cmd_head
->data
;
1083 memcpy(cmd_data
->key
, cyapa_pip_bl_cmd_key
, CYAPA_TSG_BL_KEY_SIZE
);
1085 image_records
= cyapa_get_image_record_data_num(fw
, &records_num
);
1087 /* APP_INTEGRITY row is always the last row block */
1088 data
= image_records
[records_num
- 1].record_data
;
1089 memcpy(cmd_data
->metadata_raw_parameter
, data
,
1090 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1092 meta_data_crc
= crc_itu_t(0xffff, cmd_data
->metadata_raw_parameter
,
1093 CYAPA_TSG_FLASH_MAP_METADATA_SIZE
);
1094 put_unaligned_le16(meta_data_crc
, &cmd_data
->metadata_crc
);
1096 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1098 cmd_crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1099 sizeof(struct pip_bl_packet_start
) + cmd_data_len
);
1100 put_unaligned_le16(cmd_crc
, &bl_packet_end
->crc
);
1101 bl_packet_end
->eop
= PIP_EOP_KEY
;
1103 resp_len
= sizeof(resp_data
);
1104 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1106 resp_data
, &resp_len
, 12000,
1107 cyapa_sort_tsg_pip_bl_resp_data
, true);
1108 if (error
|| resp_len
!= PIP_BL_INITIATE_RESP_LEN
||
1109 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1110 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1111 return error
? error
: -EAGAIN
;
1116 static bool cyapa_sort_pip_bl_exit_data(struct cyapa
*cyapa
, u8
*buf
, int len
)
1118 if (buf
== NULL
|| len
< PIP_RESP_LENGTH_SIZE
)
1121 if (buf
[0] == 0 && buf
[1] == 0)
1124 /* Exit bootloader failed for some reason. */
1125 if (len
== PIP_BL_FAIL_EXIT_RESP_LEN
&&
1126 buf
[PIP_RESP_REPORT_ID_OFFSET
] ==
1127 PIP_BL_RESP_REPORT_ID
&&
1128 buf
[PIP_RESP_RSVD_OFFSET
] == PIP_RESP_RSVD_KEY
&&
1129 buf
[PIP_RESP_BL_SOP_OFFSET
] == PIP_SOP_KEY
&&
1130 buf
[10] == PIP_EOP_KEY
)
1136 int cyapa_pip_bl_exit(struct cyapa
*cyapa
)
1139 u8 bl_gen5_bl_exit
[] = { 0x04, 0x00,
1140 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00,
1147 resp_len
= sizeof(resp_data
);
1148 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1149 bl_gen5_bl_exit
, sizeof(bl_gen5_bl_exit
),
1150 resp_data
, &resp_len
,
1151 5000, cyapa_sort_pip_bl_exit_data
, false);
1155 if (resp_len
== PIP_BL_FAIL_EXIT_RESP_LEN
||
1156 resp_data
[PIP_RESP_REPORT_ID_OFFSET
] ==
1157 PIP_BL_RESP_REPORT_ID
)
1160 if (resp_data
[0] == 0x00 && resp_data
[1] == 0x00)
1166 int cyapa_pip_bl_enter(struct cyapa
*cyapa
)
1168 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 };
1173 error
= cyapa_poll_state(cyapa
, 500);
1177 /* Already in bootloader mode, Skipping exit. */
1178 if (cyapa_is_pip_bl_mode(cyapa
))
1180 else if (!cyapa_is_pip_app_mode(cyapa
))
1183 /* Try to dump all buffered report data before any send command. */
1184 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1187 * Send bootloader enter command to trackpad device,
1188 * after enter bootloader, the response data is two bytes of 0x00 0x00.
1190 resp_len
= sizeof(resp_data
);
1191 memset(resp_data
, 0, resp_len
);
1192 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1194 resp_data
, &resp_len
,
1195 5000, cyapa_sort_pip_application_launch_data
,
1197 if (error
|| resp_data
[0] != 0x00 || resp_data
[1] != 0x00)
1198 return error
< 0 ? error
: -EAGAIN
;
1200 cyapa
->operational
= false;
1201 if (cyapa
->gen
== CYAPA_GEN5
)
1202 cyapa
->state
= CYAPA_STATE_GEN5_BL
;
1203 else if (cyapa
->gen
== CYAPA_GEN6
)
1204 cyapa
->state
= CYAPA_STATE_GEN6_BL
;
1208 static int cyapa_pip_fw_head_check(struct cyapa
*cyapa
,
1209 struct cyapa_tsg_bin_image_head
*image_head
)
1211 if (image_head
->head_size
!= 0x0C && image_head
->head_size
!= 0x12)
1214 switch (cyapa
->gen
) {
1216 if (image_head
->family_id
!= 0x9B ||
1217 image_head
->silicon_id_hi
!= 0x0B)
1221 /* Gen5 without proximity support. */
1222 if (cyapa
->platform_ver
< 2) {
1223 if (image_head
->head_size
== 0x0C)
1228 if (image_head
->family_id
!= 0x91 ||
1229 image_head
->silicon_id_hi
!= 0x02)
1239 int cyapa_pip_check_fw(struct cyapa
*cyapa
, const struct firmware
*fw
)
1241 struct device
*dev
= &cyapa
->client
->dev
;
1242 struct cyapa_tsg_bin_image_data_record
*image_records
;
1243 const struct cyapa_tsg_bin_image_data_record
*app_integrity
;
1244 const struct tsg_bl_metadata_row_params
*metadata
;
1245 int flash_records_count
;
1246 u32 fw_app_start
, fw_upgrade_start
;
1247 u16 fw_app_len
, fw_upgrade_len
;
1249 u16 app_integrity_crc
;
1252 /* Verify the firmware image not miss-used for Gen5 and Gen6. */
1253 if (cyapa_pip_fw_head_check(cyapa
,
1254 (struct cyapa_tsg_bin_image_head
*)fw
->data
)) {
1255 dev_err(dev
, "%s: firmware image not match TP device.\n",
1261 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1264 * APP_INTEGRITY row is always the last row block,
1265 * and the row id must be 0x01ff.
1267 app_integrity
= &image_records
[flash_records_count
- 1];
1269 if (app_integrity
->flash_array_id
!= 0x00 ||
1270 get_unaligned_be16(&app_integrity
->row_number
) != 0x01ff) {
1271 dev_err(dev
, "%s: invalid app_integrity data.\n", __func__
);
1275 metadata
= (const void *)app_integrity
->record_data
;
1277 /* Verify app_integrity crc */
1278 app_integrity_crc
= crc_itu_t(0xffff, app_integrity
->record_data
,
1279 CYAPA_TSG_APP_INTEGRITY_SIZE
);
1280 if (app_integrity_crc
!= get_unaligned_le16(&metadata
->metadata_crc
)) {
1281 dev_err(dev
, "%s: invalid app_integrity crc.\n", __func__
);
1285 fw_app_start
= get_unaligned_le32(&metadata
->app_start
);
1286 fw_app_len
= get_unaligned_le16(&metadata
->app_len
);
1287 fw_upgrade_start
= get_unaligned_le32(&metadata
->upgrade_start
);
1288 fw_upgrade_len
= get_unaligned_le16(&metadata
->upgrade_len
);
1290 if (fw_app_start
% CYAPA_TSG_FW_ROW_SIZE
||
1291 fw_app_len
% CYAPA_TSG_FW_ROW_SIZE
||
1292 fw_upgrade_start
% CYAPA_TSG_FW_ROW_SIZE
||
1293 fw_upgrade_len
% CYAPA_TSG_FW_ROW_SIZE
) {
1294 dev_err(dev
, "%s: invalid image alignment.\n", __func__
);
1298 /* Verify application image CRC. */
1300 for (i
= 0; i
< fw_app_len
/ CYAPA_TSG_FW_ROW_SIZE
; i
++) {
1301 const u8
*data
= image_records
[i
].record_data
;
1303 app_crc
= crc_itu_t(app_crc
, data
, CYAPA_TSG_FW_ROW_SIZE
);
1306 if (app_crc
!= get_unaligned_le16(&metadata
->app_crc
)) {
1307 dev_err(dev
, "%s: invalid firmware app crc check.\n", __func__
);
1314 static int cyapa_pip_write_fw_block(struct cyapa
*cyapa
,
1315 struct cyapa_tsg_bin_image_data_record
*flash_record
)
1317 struct pip_bl_cmd_head
*bl_cmd_head
;
1318 struct pip_bl_packet_start
*bl_packet_start
;
1319 struct tsg_bl_flash_row_head
*flash_row_head
;
1320 struct pip_bl_packet_end
*bl_packet_end
;
1321 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1333 flash_array_id
= flash_record
->flash_array_id
;
1334 flash_row_id
= get_unaligned_be16(&flash_record
->row_number
);
1335 record_len
= get_unaligned_be16(&flash_record
->record_len
);
1336 record_data
= flash_record
->record_data
;
1338 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1339 bl_cmd_head
= (struct pip_bl_cmd_head
*)cmd
;
1340 bl_packet_start
= &bl_cmd_head
->packet_start
;
1341 cmd_len
= sizeof(struct pip_bl_cmd_head
) +
1342 sizeof(struct tsg_bl_flash_row_head
) +
1343 CYAPA_TSG_FLASH_MAP_BLOCK_SIZE
+
1344 sizeof(struct pip_bl_packet_end
);
1346 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &bl_cmd_head
->addr
);
1347 /* Don't include 2 bytes register address */
1348 put_unaligned_le16(cmd_len
- 2, &bl_cmd_head
->length
);
1349 bl_cmd_head
->report_id
= PIP_BL_CMD_REPORT_ID
;
1350 bl_packet_start
->sop
= PIP_SOP_KEY
;
1351 bl_packet_start
->cmd_code
= PIP_BL_CMD_PROGRAM_VERIFY_ROW
;
1353 /* 1 (Flash Array ID) + 2 (Flash Row ID) + 128 (flash data) */
1354 data_len
= sizeof(struct tsg_bl_flash_row_head
) + record_len
;
1355 put_unaligned_le16(data_len
, &bl_packet_start
->data_length
);
1357 flash_row_head
= (struct tsg_bl_flash_row_head
*)bl_cmd_head
->data
;
1358 flash_row_head
->flash_array_id
= flash_array_id
;
1359 put_unaligned_le16(flash_row_id
, &flash_row_head
->flash_row_id
);
1360 memcpy(flash_row_head
->flash_data
, record_data
, record_len
);
1362 bl_packet_end
= (struct pip_bl_packet_end
*)(bl_cmd_head
->data
+
1364 crc
= crc_itu_t(0xffff, (u8
*)bl_packet_start
,
1365 sizeof(struct pip_bl_packet_start
) + data_len
);
1366 put_unaligned_le16(crc
, &bl_packet_end
->crc
);
1367 bl_packet_end
->eop
= PIP_EOP_KEY
;
1369 resp_len
= sizeof(resp_data
);
1370 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1371 resp_data
, &resp_len
,
1372 500, cyapa_sort_tsg_pip_bl_resp_data
, true);
1373 if (error
|| resp_len
!= PIP_BL_BLOCK_WRITE_RESP_LEN
||
1374 resp_data
[2] != PIP_BL_RESP_REPORT_ID
||
1375 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1376 return error
< 0 ? error
: -EAGAIN
;
1381 int cyapa_pip_do_fw_update(struct cyapa
*cyapa
,
1382 const struct firmware
*fw
)
1384 struct device
*dev
= &cyapa
->client
->dev
;
1385 struct cyapa_tsg_bin_image_data_record
*image_records
;
1386 int flash_records_count
;
1390 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1393 cyapa_get_image_record_data_num(fw
, &flash_records_count
);
1396 * The last flash row 0x01ff has been written through bl_initiate
1397 * command, so DO NOT write flash 0x01ff to trackpad device.
1399 for (i
= 0; i
< (flash_records_count
- 1); i
++) {
1400 error
= cyapa_pip_write_fw_block(cyapa
, &image_records
[i
]);
1402 dev_err(dev
, "%s: Gen5 FW update aborted: %d\n",
1411 static int cyapa_gen5_change_power_state(struct cyapa
*cyapa
, u8 power_state
)
1413 u8 cmd
[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 };
1418 cmd
[7] = power_state
;
1419 resp_len
= sizeof(resp_data
);
1420 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1421 resp_data
, &resp_len
,
1422 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1423 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x08) ||
1424 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1425 return error
< 0 ? error
: -EINVAL
;
1430 static int cyapa_gen5_set_interval_time(struct cyapa
*cyapa
,
1431 u8 parameter_id
, u16 interval_time
)
1433 struct pip_app_cmd_head
*app_cmd_head
;
1434 struct gen5_app_set_parameter_data
*parameter_data
;
1435 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1442 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1443 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1444 parameter_data
= (struct gen5_app_set_parameter_data
*)
1445 app_cmd_head
->parameter_data
;
1446 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1447 sizeof(struct gen5_app_set_parameter_data
);
1449 switch (parameter_id
) {
1450 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1451 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1453 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1454 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1456 case GEN5_PARAMETER_LP_INTRVL_ID
:
1457 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1463 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1465 * Don't include unused parameter value bytes and
1466 * 2 bytes register address.
1468 put_unaligned_le16(cmd_len
- (4 - parameter_size
) - 2,
1469 &app_cmd_head
->length
);
1470 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1471 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1472 parameter_data
->parameter_id
= parameter_id
;
1473 parameter_data
->parameter_size
= parameter_size
;
1474 put_unaligned_le32((u32
)interval_time
, ¶meter_data
->value
);
1475 resp_len
= sizeof(resp_data
);
1476 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1477 resp_data
, &resp_len
,
1478 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1479 if (error
|| resp_data
[5] != parameter_id
||
1480 resp_data
[6] != parameter_size
||
1481 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
))
1482 return error
< 0 ? error
: -EINVAL
;
1487 static int cyapa_gen5_get_interval_time(struct cyapa
*cyapa
,
1488 u8 parameter_id
, u16
*interval_time
)
1490 struct pip_app_cmd_head
*app_cmd_head
;
1491 struct gen5_app_get_parameter_data
*parameter_data
;
1492 u8 cmd
[CYAPA_TSG_MAX_CMD_SIZE
];
1500 memset(cmd
, 0, CYAPA_TSG_MAX_CMD_SIZE
);
1501 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1502 parameter_data
= (struct gen5_app_get_parameter_data
*)
1503 app_cmd_head
->parameter_data
;
1504 cmd_len
= sizeof(struct pip_app_cmd_head
) +
1505 sizeof(struct gen5_app_get_parameter_data
);
1508 switch (parameter_id
) {
1509 case GEN5_PARAMETER_ACT_INTERVL_ID
:
1510 parameter_size
= GEN5_PARAMETER_ACT_INTERVL_SIZE
;
1512 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID
:
1513 parameter_size
= GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE
;
1515 case GEN5_PARAMETER_LP_INTRVL_ID
:
1516 parameter_size
= GEN5_PARAMETER_LP_INTRVL_SIZE
;
1522 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1523 /* Don't include 2 bytes register address */
1524 put_unaligned_le16(cmd_len
- 2, &app_cmd_head
->length
);
1525 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1526 app_cmd_head
->cmd_code
= GEN5_CMD_GET_PARAMETER
;
1527 parameter_data
->parameter_id
= parameter_id
;
1529 resp_len
= sizeof(resp_data
);
1530 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, cmd_len
,
1531 resp_data
, &resp_len
,
1532 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1533 if (error
|| resp_data
[5] != parameter_id
|| resp_data
[6] == 0 ||
1534 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_GET_PARAMETER
))
1535 return error
< 0 ? error
: -EINVAL
;
1538 for (i
= 0; i
< parameter_size
; i
++)
1539 mask
|= (0xff << (i
* 8));
1540 *interval_time
= get_unaligned_le16(&resp_data
[7]) & mask
;
1545 static int cyapa_gen5_disable_pip_report(struct cyapa
*cyapa
)
1547 struct pip_app_cmd_head
*app_cmd_head
;
1553 memset(cmd
, 0, sizeof(cmd
));
1554 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1556 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1557 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1558 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1559 app_cmd_head
->cmd_code
= GEN5_CMD_SET_PARAMETER
;
1560 app_cmd_head
->parameter_data
[0] = GEN5_PARAMETER_DISABLE_PIP_REPORT
;
1561 app_cmd_head
->parameter_data
[1] = 0x01;
1562 app_cmd_head
->parameter_data
[2] = 0x01;
1563 resp_len
= sizeof(resp_data
);
1564 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1565 resp_data
, &resp_len
,
1566 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1567 if (error
|| resp_data
[5] != GEN5_PARAMETER_DISABLE_PIP_REPORT
||
1568 !VALID_CMD_RESP_HEADER(resp_data
, GEN5_CMD_SET_PARAMETER
) ||
1569 resp_data
[6] != 0x01)
1570 return error
< 0 ? error
: -EINVAL
;
1575 int cyapa_pip_set_proximity(struct cyapa
*cyapa
, bool enable
)
1577 u8 cmd
[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY
,
1584 resp_len
= sizeof(resp_data
);
1585 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1586 resp_data
, &resp_len
,
1587 500, cyapa_sort_tsg_pip_app_resp_data
, false);
1588 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_SET_PROXIMITY
) ||
1589 !PIP_CMD_COMPLETE_SUCCESS(resp_data
)) {
1590 error
= (error
== -ETIMEDOUT
) ? -EOPNOTSUPP
: error
;
1591 return error
< 0 ? error
: -EINVAL
;
1597 int cyapa_pip_deep_sleep(struct cyapa
*cyapa
, u8 state
)
1599 u8 cmd
[] = { 0x05, 0x00, 0x00, 0x08};
1604 cmd
[2] = state
& PIP_DEEP_SLEEP_STATE_MASK
;
1605 resp_len
= sizeof(resp_data
);
1606 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
, cmd
, sizeof(cmd
),
1607 resp_data
, &resp_len
,
1608 500, cyapa_sort_pip_deep_sleep_data
, false);
1609 if (error
|| ((resp_data
[3] & PIP_DEEP_SLEEP_STATE_MASK
) != state
))
1615 static int cyapa_gen5_set_power_mode(struct cyapa
*cyapa
,
1616 u8 power_mode
, u16 sleep_time
, enum cyapa_pm_stage pm_stage
)
1618 struct device
*dev
= &cyapa
->client
->dev
;
1622 if (cyapa
->state
!= CYAPA_STATE_GEN5_APP
)
1625 cyapa_set_pip_pm_state(cyapa
, pm_stage
);
1627 if (PIP_DEV_GET_PWR_STATE(cyapa
) == UNINIT_PWR_MODE
) {
1629 * Assume TP in deep sleep mode when driver is loaded,
1630 * avoid driver unload and reload command IO issue caused by TP
1631 * has been set into deep sleep mode when unloading.
1633 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1636 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) &&
1637 PIP_DEV_GET_PWR_STATE(cyapa
) != PWR_MODE_OFF
)
1638 if (cyapa_gen5_get_interval_time(cyapa
,
1639 GEN5_PARAMETER_LP_INTRVL_ID
,
1640 &cyapa
->dev_sleep_time
) != 0)
1641 PIP_DEV_SET_SLEEP_TIME(cyapa
, UNINIT_SLEEP_TIME
);
1643 if (PIP_DEV_GET_PWR_STATE(cyapa
) == power_mode
) {
1644 if (power_mode
== PWR_MODE_OFF
||
1645 power_mode
== PWR_MODE_FULL_ACTIVE
||
1646 power_mode
== PWR_MODE_BTN_ONLY
||
1647 PIP_DEV_GET_SLEEP_TIME(cyapa
) == sleep_time
) {
1648 /* Has in correct power mode state, early return. */
1653 if (power_mode
== PWR_MODE_OFF
) {
1654 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_OFF
);
1656 dev_err(dev
, "enter deep sleep fail: %d\n", error
);
1660 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_OFF
);
1665 * When trackpad in power off mode, it cannot change to other power
1666 * state directly, must be wake up from sleep firstly, then
1667 * continue to do next power sate change.
1669 if (PIP_DEV_GET_PWR_STATE(cyapa
) == PWR_MODE_OFF
) {
1670 error
= cyapa_pip_deep_sleep(cyapa
, PIP_DEEP_SLEEP_STATE_ON
);
1672 dev_err(dev
, "deep sleep wake fail: %d\n", error
);
1677 if (power_mode
== PWR_MODE_FULL_ACTIVE
) {
1678 error
= cyapa_gen5_change_power_state(cyapa
,
1679 GEN5_POWER_STATE_ACTIVE
);
1681 dev_err(dev
, "change to active fail: %d\n", error
);
1685 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_FULL_ACTIVE
);
1686 } else if (power_mode
== PWR_MODE_BTN_ONLY
) {
1687 error
= cyapa_gen5_change_power_state(cyapa
,
1688 GEN5_POWER_STATE_BTN_ONLY
);
1690 dev_err(dev
, "fail to button only mode: %d\n", error
);
1694 PIP_DEV_SET_PWR_STATE(cyapa
, PWR_MODE_BTN_ONLY
);
1697 * Continue to change power mode even failed to set
1698 * interval time, it won't affect the power mode change.
1699 * except the sleep interval time is not correct.
1701 if (PIP_DEV_UNINIT_SLEEP_TIME(cyapa
) ||
1702 sleep_time
!= PIP_DEV_GET_SLEEP_TIME(cyapa
))
1703 if (cyapa_gen5_set_interval_time(cyapa
,
1704 GEN5_PARAMETER_LP_INTRVL_ID
,
1706 PIP_DEV_SET_SLEEP_TIME(cyapa
, sleep_time
);
1708 if (sleep_time
<= GEN5_POWER_READY_MAX_INTRVL_TIME
)
1709 power_state
= GEN5_POWER_STATE_READY
;
1711 power_state
= GEN5_POWER_STATE_IDLE
;
1712 error
= cyapa_gen5_change_power_state(cyapa
, power_state
);
1714 dev_err(dev
, "set power state to 0x%02x failed: %d\n",
1715 power_state
, error
);
1720 * Disable pip report for a little time, firmware will
1721 * re-enable it automatically. It's used to fix the issue
1722 * that trackpad unable to report signal to wake system up
1723 * in the special situation that system is in suspending, and
1724 * at the same time, user touch trackpad to wake system up.
1725 * This function can avoid the data to be buffered when system
1726 * is suspending which may cause interrupt line unable to be
1729 if (pm_stage
== CYAPA_PM_SUSPEND
)
1730 cyapa_gen5_disable_pip_report(cyapa
);
1732 PIP_DEV_SET_PWR_STATE(cyapa
,
1733 cyapa_sleep_time_to_pwr_cmd(sleep_time
));
1737 cyapa_reset_pip_pm_state(cyapa
);
1741 int cyapa_pip_resume_scanning(struct cyapa
*cyapa
)
1743 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 };
1748 /* Try to dump all buffered data before doing command. */
1749 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1751 resp_len
= sizeof(resp_data
);
1752 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1754 resp_data
, &resp_len
,
1755 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1756 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x04))
1759 /* Try to dump all buffered data when resuming scanning. */
1760 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1765 int cyapa_pip_suspend_scanning(struct cyapa
*cyapa
)
1767 u8 cmd
[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 };
1772 /* Try to dump all buffered data before doing command. */
1773 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1775 resp_len
= sizeof(resp_data
);
1776 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1778 resp_data
, &resp_len
,
1779 500, cyapa_sort_tsg_pip_app_resp_data
, true);
1780 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, 0x03))
1783 /* Try to dump all buffered data when suspending scanning. */
1784 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1789 static int cyapa_pip_calibrate_pwcs(struct cyapa
*cyapa
,
1790 u8 calibrate_sensing_mode_type
)
1792 struct pip_app_cmd_head
*app_cmd_head
;
1798 /* Try to dump all buffered data before doing command. */
1799 cyapa_empty_pip_output_data(cyapa
, NULL
, NULL
, NULL
);
1801 memset(cmd
, 0, sizeof(cmd
));
1802 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
1803 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
1804 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
1805 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
1806 app_cmd_head
->cmd_code
= PIP_CMD_CALIBRATE
;
1807 app_cmd_head
->parameter_data
[0] = calibrate_sensing_mode_type
;
1808 resp_len
= sizeof(resp_data
);
1809 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
1811 resp_data
, &resp_len
,
1812 5000, cyapa_sort_tsg_pip_app_resp_data
, true);
1813 if (error
|| !VALID_CMD_RESP_HEADER(resp_data
, PIP_CMD_CALIBRATE
) ||
1814 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
1815 return error
< 0 ? error
: -EAGAIN
;
1820 ssize_t
cyapa_pip_do_calibrate(struct device
*dev
,
1821 struct device_attribute
*attr
,
1822 const char *buf
, size_t count
)
1824 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
1825 int error
, calibrate_error
;
1827 /* 1. Suspend Scanning*/
1828 error
= cyapa_pip_suspend_scanning(cyapa
);
1832 /* 2. Do mutual capacitance fine calibrate. */
1833 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1834 PIP_SENSING_MODE_MUTUAL_CAP_FINE
);
1835 if (calibrate_error
)
1836 goto resume_scanning
;
1838 /* 3. Do self capacitance calibrate. */
1839 calibrate_error
= cyapa_pip_calibrate_pwcs(cyapa
,
1840 PIP_SENSING_MODE_SELF_CAP
);
1841 if (calibrate_error
)
1842 goto resume_scanning
;
1845 /* 4. Resume Scanning*/
1846 error
= cyapa_pip_resume_scanning(cyapa
);
1847 if (error
|| calibrate_error
)
1848 return error
? error
: calibrate_error
;
1853 static s32
twos_complement_to_s32(s32 value
, int num_bits
)
1855 if (value
>> (num_bits
- 1))
1856 value
|= -1 << num_bits
;
1860 static s32
cyapa_parse_structure_data(u8 data_format
, u8
*buf
, int buf_len
)
1867 data_size
= (data_format
& 0x07);
1868 big_endian
= ((data_format
& 0x10) == 0x00);
1869 unsigned_type
= ((data_format
& 0x20) == 0x00);
1871 if (buf_len
< data_size
)
1874 switch (data_size
) {
1880 value
= get_unaligned_be16(buf
);
1882 value
= get_unaligned_le16(buf
);
1886 value
= get_unaligned_be32(buf
);
1888 value
= get_unaligned_le32(buf
);
1891 /* Should not happen, just as default case here. */
1897 value
= twos_complement_to_s32(value
, data_size
* 8);
1902 static void cyapa_gen5_guess_electrodes(struct cyapa
*cyapa
,
1903 int *electrodes_rx
, int *electrodes_tx
)
1905 if (cyapa
->electrodes_rx
!= 0) {
1906 *electrodes_rx
= cyapa
->electrodes_rx
;
1907 *electrodes_tx
= (cyapa
->electrodes_x
== *electrodes_rx
) ?
1908 cyapa
->electrodes_y
: cyapa
->electrodes_x
;
1910 *electrodes_tx
= min(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1911 *electrodes_rx
= max(cyapa
->electrodes_x
, cyapa
->electrodes_y
);
1916 * Read all the global mutual or self idac data or mutual or self local PWC
1917 * data based on the @idac_data_type.
1918 * If the input value of @data_size is 0, then means read global mutual or
1919 * self idac data. For read global mutual idac data, @idac_max, @idac_min and
1920 * @idac_ave are in order used to return the max value of global mutual idac
1921 * data, the min value of global mutual idac and the average value of the
1922 * global mutual idac data. For read global self idac data, @idac_max is used
1923 * to return the global self cap idac data in Rx direction, @idac_min is used
1924 * to return the global self cap idac data in Tx direction. @idac_ave is not
1926 * If the input value of @data_size is not 0, than means read the mutual or
1927 * self local PWC data. The @idac_max, @idac_min and @idac_ave are used to
1928 * return the max, min and average value of the mutual or self local PWC data.
1929 * Note, in order to read mutual local PWC data, must read invoke this function
1930 * to read the mutual global idac data firstly to set the correct Rx number
1931 * value, otherwise, the read mutual idac and PWC data may not correct.
1933 static int cyapa_gen5_read_idac_data(struct cyapa
*cyapa
,
1934 u8 cmd_code
, u8 idac_data_type
, int *data_size
,
1935 int *idac_max
, int *idac_min
, int *idac_ave
)
1937 struct pip_app_cmd_head
*cmd_head
;
1945 bool read_global_idac
;
1946 int sum
, count
, max_element_cnt
;
1947 int tmp_max
, tmp_min
, tmp_ave
, tmp_sum
, tmp_count
;
1948 int electrodes_rx
, electrodes_tx
;
1952 if (cmd_code
!= PIP_RETRIEVE_DATA_STRUCTURE
||
1953 (idac_data_type
!= GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
1954 idac_data_type
!= GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) ||
1955 !data_size
|| !idac_max
|| !idac_min
|| !idac_ave
)
1958 *idac_max
= INT_MIN
;
1959 *idac_min
= INT_MAX
;
1960 sum
= count
= tmp_count
= 0;
1961 electrodes_rx
= electrodes_tx
= 0;
1962 if (*data_size
== 0) {
1964 * Read global idac values firstly.
1965 * Currently, no idac data exceed 4 bytes.
1967 read_global_idac
= true;
1972 tmp_ave
= tmp_sum
= tmp_count
= 0;
1974 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1975 if (cyapa
->aligned_electrodes_rx
== 0) {
1976 cyapa_gen5_guess_electrodes(cyapa
,
1977 &electrodes_rx
, &electrodes_tx
);
1978 cyapa
->aligned_electrodes_rx
=
1979 (electrodes_rx
+ 3) & ~3u;
1982 (cyapa
->aligned_electrodes_rx
+ 7) & ~7u;
1984 max_element_cnt
= 2;
1987 read_global_idac
= false;
1990 /* Calculate the start offset in bytes of local PWC data. */
1991 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
1992 offset
= cyapa
->aligned_electrodes_rx
* (*data_size
);
1993 if (cyapa
->electrodes_rx
== cyapa
->electrodes_x
)
1994 electrodes_tx
= cyapa
->electrodes_y
;
1996 electrodes_tx
= cyapa
->electrodes_x
;
1997 max_element_cnt
= ((cyapa
->aligned_electrodes_rx
+ 7) &
1998 ~7u) * electrodes_tx
;
2001 max_element_cnt
= cyapa
->electrodes_x
+
2002 cyapa
->electrodes_y
;
2003 max_element_cnt
= (max_element_cnt
+ 3) & ~3u;
2007 memset(cmd
, 0, sizeof(cmd
));
2008 cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2009 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &cmd_head
->addr
);
2010 put_unaligned_le16(sizeof(cmd
) - 2, &cmd_head
->length
);
2011 cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2012 cmd_head
->cmd_code
= cmd_code
;
2014 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) /
2016 read_elements
= min(read_elements
, max_element_cnt
- count
);
2017 read_len
= read_elements
* (*data_size
);
2019 put_unaligned_le16(offset
, &cmd_head
->parameter_data
[0]);
2020 put_unaligned_le16(read_len
, &cmd_head
->parameter_data
[2]);
2021 cmd_head
->parameter_data
[4] = idac_data_type
;
2022 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
2023 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2025 resp_data
, &resp_len
,
2026 500, cyapa_sort_tsg_pip_app_resp_data
,
2028 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
2029 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
2030 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
2031 resp_data
[6] != idac_data_type
)
2032 return (error
< 0) ? error
: -EAGAIN
;
2033 read_len
= get_unaligned_le16(&resp_data
[7]);
2037 *data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
2038 if (read_len
< *data_size
)
2041 if (read_global_idac
&&
2042 idac_data_type
== GEN5_RETRIEVE_SELF_CAP_PWC_DATA
) {
2043 /* Rx's self global idac data. */
2044 *idac_max
= cyapa_parse_structure_data(
2046 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
],
2048 /* Tx's self global idac data. */
2049 *idac_min
= cyapa_parse_structure_data(
2051 &resp_data
[GEN5_RESP_DATA_STRUCTURE_OFFSET
+
2057 /* Read mutual global idac or local mutual/self PWC data. */
2059 for (i
= 10; i
< (read_len
+ GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2061 value
= cyapa_parse_structure_data(resp_data
[9],
2062 &resp_data
[i
], *data_size
);
2063 *idac_min
= min(value
, *idac_min
);
2064 *idac_max
= max(value
, *idac_max
);
2066 if (idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
&&
2067 tmp_count
< cyapa
->aligned_electrodes_rx
&&
2070 * The value gap between global and local mutual
2071 * idac data must bigger than 50%.
2072 * Normally, global value bigger than 50,
2073 * local values less than 10.
2075 if (!tmp_ave
|| value
> tmp_ave
/ 2) {
2076 tmp_min
= min(value
, tmp_min
);
2077 tmp_max
= max(value
, tmp_max
);
2081 tmp_ave
= tmp_sum
/ tmp_count
;
2088 if (count
>= max_element_cnt
)
2094 *idac_ave
= count
? (sum
/ count
) : 0;
2096 if (read_global_idac
&&
2097 idac_data_type
== GEN5_RETRIEVE_MUTUAL_PWC_DATA
) {
2101 if (tmp_count
== cyapa
->aligned_electrodes_rx
) {
2102 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2103 cyapa
->electrodes_rx
: electrodes_rx
;
2104 } else if (tmp_count
== electrodes_rx
) {
2105 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2106 cyapa
->electrodes_rx
: electrodes_rx
;
2107 cyapa
->aligned_electrodes_rx
= electrodes_rx
;
2109 cyapa
->electrodes_rx
= cyapa
->electrodes_rx
?
2110 cyapa
->electrodes_rx
: electrodes_tx
;
2111 cyapa
->aligned_electrodes_rx
= tmp_count
;
2114 *idac_min
= tmp_min
;
2115 *idac_max
= tmp_max
;
2116 *idac_ave
= tmp_ave
;
2122 static int cyapa_gen5_read_mutual_idac_data(struct cyapa
*cyapa
,
2123 int *gidac_mutual_max
, int *gidac_mutual_min
, int *gidac_mutual_ave
,
2124 int *lidac_mutual_max
, int *lidac_mutual_min
, int *lidac_mutual_ave
)
2129 *gidac_mutual_max
= *gidac_mutual_min
= *gidac_mutual_ave
= 0;
2130 *lidac_mutual_max
= *lidac_mutual_min
= *lidac_mutual_ave
= 0;
2133 error
= cyapa_gen5_read_idac_data(cyapa
,
2134 PIP_RETRIEVE_DATA_STRUCTURE
,
2135 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2137 gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
);
2141 error
= cyapa_gen5_read_idac_data(cyapa
,
2142 PIP_RETRIEVE_DATA_STRUCTURE
,
2143 GEN5_RETRIEVE_MUTUAL_PWC_DATA
,
2145 lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
);
2149 static int cyapa_gen5_read_self_idac_data(struct cyapa
*cyapa
,
2150 int *gidac_self_rx
, int *gidac_self_tx
,
2151 int *lidac_self_max
, int *lidac_self_min
, int *lidac_self_ave
)
2156 *gidac_self_rx
= *gidac_self_tx
= 0;
2157 *lidac_self_max
= *lidac_self_min
= *lidac_self_ave
= 0;
2160 error
= cyapa_gen5_read_idac_data(cyapa
,
2161 PIP_RETRIEVE_DATA_STRUCTURE
,
2162 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2164 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2167 *gidac_self_rx
= *lidac_self_max
;
2168 *gidac_self_tx
= *lidac_self_min
;
2170 error
= cyapa_gen5_read_idac_data(cyapa
,
2171 PIP_RETRIEVE_DATA_STRUCTURE
,
2172 GEN5_RETRIEVE_SELF_CAP_PWC_DATA
,
2174 lidac_self_max
, lidac_self_min
, lidac_self_ave
);
2178 static ssize_t
cyapa_gen5_execute_panel_scan(struct cyapa
*cyapa
)
2180 struct pip_app_cmd_head
*app_cmd_head
;
2186 memset(cmd
, 0, sizeof(cmd
));
2187 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2188 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2189 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2190 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2191 app_cmd_head
->cmd_code
= GEN5_CMD_EXECUTE_PANEL_SCAN
;
2192 resp_len
= sizeof(resp_data
);
2193 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2195 resp_data
, &resp_len
,
2196 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2197 if (error
|| resp_len
!= sizeof(resp_data
) ||
2198 !VALID_CMD_RESP_HEADER(resp_data
,
2199 GEN5_CMD_EXECUTE_PANEL_SCAN
) ||
2200 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2201 return error
? error
: -EAGAIN
;
2206 static int cyapa_gen5_read_panel_scan_raw_data(struct cyapa
*cyapa
,
2207 u8 cmd_code
, u8 raw_data_type
, int raw_data_max_num
,
2208 int *raw_data_max
, int *raw_data_min
, int *raw_data_ave
,
2211 struct pip_app_cmd_head
*app_cmd_head
;
2212 struct gen5_retrieve_panel_scan_data
*panel_sacn_data
;
2214 u8 resp_data
[256]; /* Max bytes can transfer one time. */
2226 if (cmd_code
!= GEN5_CMD_RETRIEVE_PANEL_SCAN
||
2227 (raw_data_type
> GEN5_PANEL_SCAN_SELF_DIFFCOUNT
) ||
2228 !raw_data_max
|| !raw_data_min
|| !raw_data_ave
)
2231 intp
= (s32
*)buffer
;
2232 *raw_data_max
= INT_MIN
;
2233 *raw_data_min
= INT_MAX
;
2236 /* Assume max element size is 4 currently. */
2237 read_elements
= (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET
) / 4;
2238 read_len
= read_elements
* 4;
2239 app_cmd_head
= (struct pip_app_cmd_head
*)cmd
;
2240 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR
, &app_cmd_head
->addr
);
2241 put_unaligned_le16(sizeof(cmd
) - 2, &app_cmd_head
->length
);
2242 app_cmd_head
->report_id
= PIP_APP_CMD_REPORT_ID
;
2243 app_cmd_head
->cmd_code
= cmd_code
;
2244 panel_sacn_data
= (struct gen5_retrieve_panel_scan_data
*)
2245 app_cmd_head
->parameter_data
;
2247 put_unaligned_le16(offset
, &panel_sacn_data
->read_offset
);
2248 put_unaligned_le16(read_elements
,
2249 &panel_sacn_data
->read_elements
);
2250 panel_sacn_data
->data_id
= raw_data_type
;
2252 resp_len
= GEN5_RESP_DATA_STRUCTURE_OFFSET
+ read_len
;
2253 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2255 resp_data
, &resp_len
,
2256 500, cyapa_sort_tsg_pip_app_resp_data
, true);
2257 if (error
|| resp_len
< GEN5_RESP_DATA_STRUCTURE_OFFSET
||
2258 !VALID_CMD_RESP_HEADER(resp_data
, cmd_code
) ||
2259 !PIP_CMD_COMPLETE_SUCCESS(resp_data
) ||
2260 resp_data
[6] != raw_data_type
)
2261 return error
? error
: -EAGAIN
;
2263 read_elements
= get_unaligned_le16(&resp_data
[7]);
2264 if (read_elements
== 0)
2267 data_size
= (resp_data
[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK
);
2268 offset
+= read_elements
;
2269 if (read_elements
) {
2270 for (i
= GEN5_RESP_DATA_STRUCTURE_OFFSET
;
2271 i
< (read_elements
* data_size
+
2272 GEN5_RESP_DATA_STRUCTURE_OFFSET
);
2274 value
= cyapa_parse_structure_data(resp_data
[9],
2275 &resp_data
[i
], data_size
);
2276 *raw_data_min
= min(value
, *raw_data_min
);
2277 *raw_data_max
= max(value
, *raw_data_max
);
2280 put_unaligned_le32(value
, &intp
[count
]);
2288 if (count
>= raw_data_max_num
)
2291 read_elements
= (sizeof(resp_data
) -
2292 GEN5_RESP_DATA_STRUCTURE_OFFSET
) / data_size
;
2293 read_len
= read_elements
* data_size
;
2296 *raw_data_ave
= count
? (sum
/ count
) : 0;
2301 static ssize_t
cyapa_gen5_show_baseline(struct device
*dev
,
2302 struct device_attribute
*attr
, char *buf
)
2304 struct cyapa
*cyapa
= dev_get_drvdata(dev
);
2305 int gidac_mutual_max
, gidac_mutual_min
, gidac_mutual_ave
;
2306 int lidac_mutual_max
, lidac_mutual_min
, lidac_mutual_ave
;
2307 int gidac_self_rx
, gidac_self_tx
;
2308 int lidac_self_max
, lidac_self_min
, lidac_self_ave
;
2309 int raw_cap_mutual_max
, raw_cap_mutual_min
, raw_cap_mutual_ave
;
2310 int raw_cap_self_max
, raw_cap_self_min
, raw_cap_self_ave
;
2311 int mutual_diffdata_max
, mutual_diffdata_min
, mutual_diffdata_ave
;
2312 int self_diffdata_max
, self_diffdata_min
, self_diffdata_ave
;
2313 int mutual_baseline_max
, mutual_baseline_min
, mutual_baseline_ave
;
2314 int self_baseline_max
, self_baseline_min
, self_baseline_ave
;
2315 int error
, resume_error
;
2318 if (!cyapa_is_pip_app_mode(cyapa
))
2321 /* 1. Suspend Scanning*/
2322 error
= cyapa_pip_suspend_scanning(cyapa
);
2326 /* 2. Read global and local mutual IDAC data. */
2327 gidac_self_rx
= gidac_self_tx
= 0;
2328 error
= cyapa_gen5_read_mutual_idac_data(cyapa
,
2329 &gidac_mutual_max
, &gidac_mutual_min
,
2330 &gidac_mutual_ave
, &lidac_mutual_max
,
2331 &lidac_mutual_min
, &lidac_mutual_ave
);
2333 goto resume_scanning
;
2335 /* 3. Read global and local self IDAC data. */
2336 error
= cyapa_gen5_read_self_idac_data(cyapa
,
2337 &gidac_self_rx
, &gidac_self_tx
,
2338 &lidac_self_max
, &lidac_self_min
,
2341 goto resume_scanning
;
2343 /* 4. Execute panel scan. It must be executed before read data. */
2344 error
= cyapa_gen5_execute_panel_scan(cyapa
);
2346 goto resume_scanning
;
2348 /* 5. Retrieve panel scan, mutual cap raw data. */
2349 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2350 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2351 GEN5_PANEL_SCAN_MUTUAL_RAW_DATA
,
2352 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2353 &raw_cap_mutual_max
, &raw_cap_mutual_min
,
2354 &raw_cap_mutual_ave
,
2357 goto resume_scanning
;
2359 /* 6. Retrieve panel scan, self cap raw data. */
2360 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2361 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2362 GEN5_PANEL_SCAN_SELF_RAW_DATA
,
2363 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2364 &raw_cap_self_max
, &raw_cap_self_min
,
2368 goto resume_scanning
;
2370 /* 7. Retrieve panel scan, mutual cap diffcount raw data. */
2371 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2372 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2373 GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT
,
2374 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2375 &mutual_diffdata_max
, &mutual_diffdata_min
,
2376 &mutual_diffdata_ave
,
2379 goto resume_scanning
;
2381 /* 8. Retrieve panel scan, self cap diffcount raw data. */
2382 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2383 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2384 GEN5_PANEL_SCAN_SELF_DIFFCOUNT
,
2385 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2386 &self_diffdata_max
, &self_diffdata_min
,
2390 goto resume_scanning
;
2392 /* 9. Retrieve panel scan, mutual cap baseline raw data. */
2393 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2394 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2395 GEN5_PANEL_SCAN_MUTUAL_BASELINE
,
2396 cyapa
->electrodes_x
* cyapa
->electrodes_y
,
2397 &mutual_baseline_max
, &mutual_baseline_min
,
2398 &mutual_baseline_ave
,
2401 goto resume_scanning
;
2403 /* 10. Retrieve panel scan, self cap baseline raw data. */
2404 error
= cyapa_gen5_read_panel_scan_raw_data(cyapa
,
2405 GEN5_CMD_RETRIEVE_PANEL_SCAN
,
2406 GEN5_PANEL_SCAN_SELF_BASELINE
,
2407 cyapa
->electrodes_x
+ cyapa
->electrodes_y
,
2408 &self_baseline_max
, &self_baseline_min
,
2412 goto resume_scanning
;
2415 /* 11. Resume Scanning*/
2416 resume_error
= cyapa_pip_resume_scanning(cyapa
);
2417 if (resume_error
|| error
)
2418 return resume_error
? resume_error
: error
;
2420 /* 12. Output data strings */
2421 size
= scnprintf(buf
, PAGE_SIZE
, "%d %d %d %d %d %d %d %d %d %d %d ",
2422 gidac_mutual_min
, gidac_mutual_max
, gidac_mutual_ave
,
2423 lidac_mutual_min
, lidac_mutual_max
, lidac_mutual_ave
,
2424 gidac_self_rx
, gidac_self_tx
,
2425 lidac_self_min
, lidac_self_max
, lidac_self_ave
);
2426 size
+= scnprintf(buf
+ size
, PAGE_SIZE
- size
,
2427 "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
2428 raw_cap_mutual_min
, raw_cap_mutual_max
, raw_cap_mutual_ave
,
2429 raw_cap_self_min
, raw_cap_self_max
, raw_cap_self_ave
,
2430 mutual_diffdata_min
, mutual_diffdata_max
, mutual_diffdata_ave
,
2431 self_diffdata_min
, self_diffdata_max
, self_diffdata_ave
,
2432 mutual_baseline_min
, mutual_baseline_max
, mutual_baseline_ave
,
2433 self_baseline_min
, self_baseline_max
, self_baseline_ave
);
2437 bool cyapa_pip_sort_system_info_data(struct cyapa
*cyapa
,
2440 /* Check the report id and command code */
2441 if (VALID_CMD_RESP_HEADER(buf
, 0x02))
2447 static int cyapa_gen5_bl_query_data(struct cyapa
*cyapa
)
2449 u8 resp_data
[PIP_BL_APP_INFO_RESP_LENGTH
];
2453 resp_len
= sizeof(resp_data
);
2454 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2455 pip_bl_read_app_info
, PIP_BL_READ_APP_INFO_CMD_LENGTH
,
2456 resp_data
, &resp_len
,
2457 500, cyapa_sort_tsg_pip_bl_resp_data
, false);
2458 if (error
|| resp_len
< PIP_BL_APP_INFO_RESP_LENGTH
||
2459 !PIP_CMD_COMPLETE_SUCCESS(resp_data
))
2460 return error
? error
: -EIO
;
2462 memcpy(&cyapa
->product_id
[0], &resp_data
[8], 5);
2463 cyapa
->product_id
[5] = '-';
2464 memcpy(&cyapa
->product_id
[6], &resp_data
[13], 6);
2465 cyapa
->product_id
[12] = '-';
2466 memcpy(&cyapa
->product_id
[13], &resp_data
[19], 2);
2467 cyapa
->product_id
[15] = '\0';
2469 cyapa
->fw_maj_ver
= resp_data
[22];
2470 cyapa
->fw_min_ver
= resp_data
[23];
2472 cyapa
->platform_ver
= (resp_data
[26] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2473 PIP_BL_PLATFORM_VER_MASK
;
2478 static int cyapa_gen5_get_query_data(struct cyapa
*cyapa
)
2480 u8 resp_data
[PIP_READ_SYS_INFO_RESP_LENGTH
];
2485 resp_len
= sizeof(resp_data
);
2486 error
= cyapa_i2c_pip_cmd_irq_sync(cyapa
,
2487 pip_read_sys_info
, PIP_READ_SYS_INFO_CMD_LENGTH
,
2488 resp_data
, &resp_len
,
2489 2000, cyapa_pip_sort_system_info_data
, false);
2490 if (error
|| resp_len
< sizeof(resp_data
))
2491 return error
? error
: -EIO
;
2493 product_family
= get_unaligned_le16(&resp_data
[7]);
2494 if ((product_family
& PIP_PRODUCT_FAMILY_MASK
) !=
2495 PIP_PRODUCT_FAMILY_TRACKPAD
)
2498 cyapa
->platform_ver
= (resp_data
[49] >> PIP_BL_PLATFORM_VER_SHIFT
) &
2499 PIP_BL_PLATFORM_VER_MASK
;
2500 if (cyapa
->gen
== CYAPA_GEN5
&& cyapa
->platform_ver
< 2) {
2501 /* Gen5 firmware that does not support proximity. */
2502 cyapa
->fw_maj_ver
= resp_data
[15];
2503 cyapa
->fw_min_ver
= resp_data
[16];
2505 cyapa
->fw_maj_ver
= resp_data
[9];
2506 cyapa
->fw_min_ver
= resp_data
[10];
2509 cyapa
->electrodes_x
= resp_data
[52];
2510 cyapa
->electrodes_y
= resp_data
[53];
2512 cyapa
->physical_size_x
= get_unaligned_le16(&resp_data
[54]) / 100;
2513 cyapa
->physical_size_y
= get_unaligned_le16(&resp_data
[56]) / 100;
2515 cyapa
->max_abs_x
= get_unaligned_le16(&resp_data
[58]);
2516 cyapa
->max_abs_y
= get_unaligned_le16(&resp_data
[60]);
2518 cyapa
->max_z
= get_unaligned_le16(&resp_data
[62]);
2520 cyapa
->x_origin
= resp_data
[64] & 0x01;
2521 cyapa
->y_origin
= resp_data
[65] & 0x01;
2523 cyapa
->btn_capability
= (resp_data
[70] << 3) & CAPABILITY_BTN_MASK
;
2525 memcpy(&cyapa
->product_id
[0], &resp_data
[33], 5);
2526 cyapa
->product_id
[5] = '-';
2527 memcpy(&cyapa
->product_id
[6], &resp_data
[38], 6);
2528 cyapa
->product_id
[12] = '-';
2529 memcpy(&cyapa
->product_id
[13], &resp_data
[44], 2);
2530 cyapa
->product_id
[15] = '\0';
2532 if (!cyapa
->electrodes_x
|| !cyapa
->electrodes_y
||
2533 !cyapa
->physical_size_x
|| !cyapa
->physical_size_y
||
2534 !cyapa
->max_abs_x
|| !cyapa
->max_abs_y
|| !cyapa
->max_z
)
2540 static int cyapa_gen5_do_operational_check(struct cyapa
*cyapa
)
2542 struct device
*dev
= &cyapa
->client
->dev
;
2545 if (cyapa
->gen
!= CYAPA_GEN5
)
2548 switch (cyapa
->state
) {
2549 case CYAPA_STATE_GEN5_BL
:
2550 error
= cyapa_pip_bl_exit(cyapa
);
2552 /* Try to update trackpad product information. */
2553 cyapa_gen5_bl_query_data(cyapa
);
2557 cyapa
->state
= CYAPA_STATE_GEN5_APP
;
2560 case CYAPA_STATE_GEN5_APP
:
2562 * If trackpad device in deep sleep mode,
2563 * the app command will fail.
2564 * So always try to reset trackpad device to full active when
2565 * the device state is required.
2567 error
= cyapa_gen5_set_power_mode(cyapa
,
2568 PWR_MODE_FULL_ACTIVE
, 0, CYAPA_PM_ACTIVE
);
2570 dev_warn(dev
, "%s: failed to set power active mode.\n",
2573 /* By default, the trackpad proximity function is enabled. */
2574 if (cyapa
->platform_ver
>= 2) {
2575 error
= cyapa_pip_set_proximity(cyapa
, true);
2578 "%s: failed to enable proximity.\n",
2582 /* Get trackpad product information. */
2583 error
= cyapa_gen5_get_query_data(cyapa
);
2586 /* Only support product ID starting with CYTRA */
2587 if (memcmp(cyapa
->product_id
, product_id
,
2588 strlen(product_id
)) != 0) {
2589 dev_err(dev
, "%s: unknown product ID (%s)\n",
2590 __func__
, cyapa
->product_id
);
2603 * Return false, do not continue process
2604 * Return true, continue process.
2606 bool cyapa_pip_irq_cmd_handler(struct cyapa
*cyapa
)
2608 struct cyapa_pip_cmd_states
*pip
= &cyapa
->cmd_states
.pip
;
2611 if (atomic_read(&pip
->cmd_issued
)) {
2612 /* Polling command response data. */
2613 if (pip
->is_irq_mode
== false)
2617 * Read out all none command response data.
2618 * these output data may caused by user put finger on
2619 * trackpad when host waiting the command response.
2621 cyapa_i2c_pip_read(cyapa
, pip
->irq_cmd_buf
,
2622 PIP_RESP_LENGTH_SIZE
);
2623 length
= get_unaligned_le16(pip
->irq_cmd_buf
);
2624 length
= (length
<= PIP_RESP_LENGTH_SIZE
) ?
2625 PIP_RESP_LENGTH_SIZE
: length
;
2626 if (length
> PIP_RESP_LENGTH_SIZE
)
2627 cyapa_i2c_pip_read(cyapa
,
2628 pip
->irq_cmd_buf
, length
);
2629 if (!(pip
->resp_sort_func
&&
2630 pip
->resp_sort_func(cyapa
,
2631 pip
->irq_cmd_buf
, length
))) {
2633 * Cover the Gen5 V1 firmware issue.
2634 * The issue is no interrupt would be asserted from
2635 * trackpad device to host for the command response
2636 * ready event. Because when there was a finger touch
2637 * on trackpad device, and the firmware output queue
2638 * won't be empty (always with touch report data), so
2639 * the interrupt signal won't be asserted again until
2640 * the output queue was previous emptied.
2641 * This issue would happen in the scenario that
2642 * user always has his/her fingers touched on the
2643 * trackpad device during system booting/rebooting.
2647 length
= *pip
->resp_len
;
2648 cyapa_empty_pip_output_data(cyapa
,
2651 pip
->resp_sort_func
);
2652 if (pip
->resp_len
&& length
!= 0) {
2653 *pip
->resp_len
= length
;
2654 atomic_dec(&pip
->cmd_issued
);
2655 complete(&pip
->cmd_ready
);
2660 if (pip
->resp_data
&& pip
->resp_len
) {
2661 *pip
->resp_len
= (*pip
->resp_len
< length
) ?
2662 *pip
->resp_len
: length
;
2663 memcpy(pip
->resp_data
, pip
->irq_cmd_buf
,
2666 atomic_dec(&pip
->cmd_issued
);
2667 complete(&pip
->cmd_ready
);
2674 static void cyapa_pip_report_buttons(struct cyapa
*cyapa
,
2675 const struct cyapa_pip_report_data
*report_data
)
2677 struct input_dev
*input
= cyapa
->input
;
2678 u8 buttons
= report_data
->report_head
[PIP_BUTTONS_OFFSET
];
2680 buttons
= (buttons
<< CAPABILITY_BTN_SHIFT
) & CAPABILITY_BTN_MASK
;
2682 if (cyapa
->btn_capability
& CAPABILITY_LEFT_BTN_MASK
) {
2683 input_report_key(input
, BTN_LEFT
,
2684 !!(buttons
& CAPABILITY_LEFT_BTN_MASK
));
2686 if (cyapa
->btn_capability
& CAPABILITY_MIDDLE_BTN_MASK
) {
2687 input_report_key(input
, BTN_MIDDLE
,
2688 !!(buttons
& CAPABILITY_MIDDLE_BTN_MASK
));
2690 if (cyapa
->btn_capability
& CAPABILITY_RIGHT_BTN_MASK
) {
2691 input_report_key(input
, BTN_RIGHT
,
2692 !!(buttons
& CAPABILITY_RIGHT_BTN_MASK
));
2698 static void cyapa_pip_report_proximity(struct cyapa
*cyapa
,
2699 const struct cyapa_pip_report_data
*report_data
)
2701 struct input_dev
*input
= cyapa
->input
;
2702 u8 distance
= report_data
->report_head
[PIP_PROXIMITY_DISTANCE_OFFSET
] &
2703 PIP_PROXIMITY_DISTANCE_MASK
;
2705 input_report_abs(input
, ABS_DISTANCE
, distance
);
2709 static void cyapa_pip_report_slot_data(struct cyapa
*cyapa
,
2710 const struct cyapa_pip_touch_record
*touch
)
2712 struct input_dev
*input
= cyapa
->input
;
2713 u8 event_id
= PIP_GET_EVENT_ID(touch
->touch_tip_event_id
);
2714 int slot
= PIP_GET_TOUCH_ID(touch
->touch_tip_event_id
);
2717 if (event_id
== RECORD_EVENT_LIFTOFF
)
2720 input_mt_slot(input
, slot
);
2721 input_mt_report_slot_state(input
, MT_TOOL_FINGER
, true);
2722 x
= (touch
->x_hi
<< 8) | touch
->x_lo
;
2723 if (cyapa
->x_origin
)
2724 x
= cyapa
->max_abs_x
- x
;
2725 y
= (touch
->y_hi
<< 8) | touch
->y_lo
;
2726 if (cyapa
->y_origin
)
2727 y
= cyapa
->max_abs_y
- y
;
2728 input_report_abs(input
, ABS_MT_POSITION_X
, x
);
2729 input_report_abs(input
, ABS_MT_POSITION_Y
, y
);
2730 input_report_abs(input
, ABS_DISTANCE
, 0);
2731 input_report_abs(input
, ABS_MT_PRESSURE
,
2733 input_report_abs(input
, ABS_MT_TOUCH_MAJOR
,
2734 touch
->major_axis_len
);
2735 input_report_abs(input
, ABS_MT_TOUCH_MINOR
,
2736 touch
->minor_axis_len
);
2738 input_report_abs(input
, ABS_MT_WIDTH_MAJOR
,
2739 touch
->major_tool_len
);
2740 input_report_abs(input
, ABS_MT_WIDTH_MINOR
,
2741 touch
->minor_tool_len
);
2743 input_report_abs(input
, ABS_MT_ORIENTATION
,
2744 touch
->orientation
);
2747 static void cyapa_pip_report_touches(struct cyapa
*cyapa
,
2748 const struct cyapa_pip_report_data
*report_data
)
2750 struct input_dev
*input
= cyapa
->input
;
2751 unsigned int touch_num
;
2754 touch_num
= report_data
->report_head
[PIP_NUMBER_OF_TOUCH_OFFSET
] &
2755 PIP_NUMBER_OF_TOUCH_MASK
;
2757 for (i
= 0; i
< touch_num
; i
++)
2758 cyapa_pip_report_slot_data(cyapa
,
2759 &report_data
->touch_records
[i
]);
2761 input_mt_sync_frame(input
);
2765 int cyapa_pip_irq_handler(struct cyapa
*cyapa
)
2767 struct device
*dev
= &cyapa
->client
->dev
;
2768 struct cyapa_pip_report_data report_data
;
2769 unsigned int report_len
;
2772 if (!cyapa_is_pip_app_mode(cyapa
)) {
2773 dev_err(dev
, "invalid device state, gen=%d, state=0x%02x\n",
2774 cyapa
->gen
, cyapa
->state
);
2778 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
,
2779 PIP_RESP_LENGTH_SIZE
);
2780 if (ret
!= PIP_RESP_LENGTH_SIZE
) {
2781 dev_err(dev
, "failed to read length bytes, (%d)\n", ret
);
2785 report_len
= get_unaligned_le16(
2786 &report_data
.report_head
[PIP_RESP_LENGTH_OFFSET
]);
2787 if (report_len
< PIP_RESP_LENGTH_SIZE
) {
2788 /* Invalid length or internal reset happened. */
2789 dev_err(dev
, "invalid report_len=%d. bytes: %02x %02x\n",
2790 report_len
, report_data
.report_head
[0],
2791 report_data
.report_head
[1]);
2795 /* Idle, no data for report. */
2796 if (report_len
== PIP_RESP_LENGTH_SIZE
)
2799 ret
= cyapa_i2c_pip_read(cyapa
, (u8
*)&report_data
, report_len
);
2800 if (ret
!= report_len
) {
2801 dev_err(dev
, "failed to read %d bytes report data, (%d)\n",
2806 return cyapa_pip_event_process(cyapa
, &report_data
);
2809 static int cyapa_pip_event_process(struct cyapa
*cyapa
,
2810 struct cyapa_pip_report_data
*report_data
)
2812 struct device
*dev
= &cyapa
->client
->dev
;
2813 unsigned int report_len
;
2816 report_len
= get_unaligned_le16(
2817 &report_data
->report_head
[PIP_RESP_LENGTH_OFFSET
]);
2818 /* Idle, no data for report. */
2819 if (report_len
== PIP_RESP_LENGTH_SIZE
)
2822 report_id
= report_data
->report_head
[PIP_RESP_REPORT_ID_OFFSET
];
2823 if (report_id
== PIP_WAKEUP_EVENT_REPORT_ID
&&
2824 report_len
== PIP_WAKEUP_EVENT_SIZE
) {
2826 * Device wake event from deep sleep mode for touch.
2827 * This interrupt event is used to wake system up.
2830 * It will introduce about 20~40 ms additional delay
2831 * time in receiving for first valid touch report data.
2832 * The time is used to execute device runtime resume
2835 pm_runtime_get_sync(dev
);
2836 pm_runtime_mark_last_busy(dev
);
2837 pm_runtime_put_sync_autosuspend(dev
);
2839 } else if (report_id
!= PIP_TOUCH_REPORT_ID
&&
2840 report_id
!= PIP_BTN_REPORT_ID
&&
2841 report_id
!= GEN5_OLD_PUSH_BTN_REPORT_ID
&&
2842 report_id
!= PIP_PUSH_BTN_REPORT_ID
&&
2843 report_id
!= PIP_PROXIMITY_REPORT_ID
) {
2844 /* Running in BL mode or unknown response data read. */
2845 dev_err(dev
, "invalid report_id=0x%02x\n", report_id
);
2849 if (report_id
== PIP_TOUCH_REPORT_ID
&&
2850 (report_len
< PIP_TOUCH_REPORT_HEAD_SIZE
||
2851 report_len
> PIP_TOUCH_REPORT_MAX_SIZE
)) {
2852 /* Invalid report data length for finger packet. */
2853 dev_err(dev
, "invalid touch packet length=%d\n", report_len
);
2857 if ((report_id
== PIP_BTN_REPORT_ID
||
2858 report_id
== GEN5_OLD_PUSH_BTN_REPORT_ID
||
2859 report_id
== PIP_PUSH_BTN_REPORT_ID
) &&
2860 (report_len
< PIP_BTN_REPORT_HEAD_SIZE
||
2861 report_len
> PIP_BTN_REPORT_MAX_SIZE
)) {
2862 /* Invalid report data length of button packet. */
2863 dev_err(dev
, "invalid button packet length=%d\n", report_len
);
2867 if (report_id
== PIP_PROXIMITY_REPORT_ID
&&
2868 report_len
!= PIP_PROXIMITY_REPORT_SIZE
) {
2869 /* Invalid report data length of proximity packet. */
2870 dev_err(dev
, "invalid proximity data, length=%d\n", report_len
);
2874 if (report_id
== PIP_TOUCH_REPORT_ID
)
2875 cyapa_pip_report_touches(cyapa
, report_data
);
2876 else if (report_id
== PIP_PROXIMITY_REPORT_ID
)
2877 cyapa_pip_report_proximity(cyapa
, report_data
);
2879 cyapa_pip_report_buttons(cyapa
, report_data
);
2884 int cyapa_pip_bl_activate(struct cyapa
*cyapa
) { return 0; }
2885 int cyapa_pip_bl_deactivate(struct cyapa
*cyapa
) { return 0; }
2888 const struct cyapa_dev_ops cyapa_gen5_ops
= {
2889 .check_fw
= cyapa_pip_check_fw
,
2890 .bl_enter
= cyapa_pip_bl_enter
,
2891 .bl_initiate
= cyapa_pip_bl_initiate
,
2892 .update_fw
= cyapa_pip_do_fw_update
,
2893 .bl_activate
= cyapa_pip_bl_activate
,
2894 .bl_deactivate
= cyapa_pip_bl_deactivate
,
2896 .show_baseline
= cyapa_gen5_show_baseline
,
2897 .calibrate_store
= cyapa_pip_do_calibrate
,
2899 .initialize
= cyapa_pip_cmd_state_initialize
,
2901 .state_parse
= cyapa_gen5_state_parse
,
2902 .operational_check
= cyapa_gen5_do_operational_check
,
2904 .irq_handler
= cyapa_pip_irq_handler
,
2905 .irq_cmd_handler
= cyapa_pip_irq_cmd_handler
,
2906 .sort_empty_output_data
= cyapa_empty_pip_output_data
,
2907 .set_power_mode
= cyapa_gen5_set_power_mode
,
2909 .set_proximity
= cyapa_pip_set_proximity
,