1 /* 2 * Cypress APA trackpad with I2C interface 3 * 4 * Author: Dudley Du <dudl@cypress.com> 5 * 6 * Copyright (C) 2014-2015 Cypress Semiconductor, Inc. 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 */ 12 13 #include <linux/delay.h> 14 #include <linux/i2c.h> 15 #include <linux/input.h> 16 #include <linux/input/mt.h> 17 #include <linux/mutex.h> 18 #include <linux/completion.h> 19 #include <linux/slab.h> 20 #include <asm/unaligned.h> 21 #include <linux/crc-itu-t.h> 22 #include <linux/pm_runtime.h> 23 #include "cyapa.h" 24 25 26 /* 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 40 41 #define CYAPA_TSG_MAX_CMD_SIZE 256 42 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 50 51 #define PIP_TOUCH_REPORT_ID 0x01 52 #define PIP_BTN_REPORT_ID 0x03 53 #define PIP_WAKEUP_EVENT_REPORT_ID 0x04 54 #define PIP_PUSH_BTN_REPORT_ID 0x06 55 #define GEN5_OLD_PUSH_BTN_REPORT_ID 0x05 /* Special for old Gen5 TP. */ 56 #define PIP_PROXIMITY_REPORT_ID 0x07 57 58 #define PIP_PROXIMITY_REPORT_SIZE 6 59 #define PIP_PROXIMITY_DISTANCE_OFFSET 0x05 60 #define PIP_PROXIMITY_DISTANCE_MASK 0x01 61 62 #define PIP_TOUCH_REPORT_HEAD_SIZE 7 63 #define PIP_TOUCH_REPORT_MAX_SIZE 127 64 #define PIP_BTN_REPORT_HEAD_SIZE 6 65 #define PIP_BTN_REPORT_MAX_SIZE 14 66 #define PIP_WAKEUP_EVENT_SIZE 4 67 68 #define PIP_NUMBER_OF_TOUCH_OFFSET 5 69 #define PIP_NUMBER_OF_TOUCH_MASK 0x1f 70 #define PIP_BUTTONS_OFFSET 5 71 #define PIP_BUTTONS_MASK 0x0f 72 #define PIP_GET_EVENT_ID(reg) (((reg) >> 5) & 0x03) 73 #define PIP_GET_TOUCH_ID(reg) ((reg) & 0x1f) 74 #define PIP_TOUCH_TYPE_FINGER 0x00 75 #define PIP_TOUCH_TYPE_PROXIMITY 0x01 76 #define PIP_TOUCH_TYPE_HOVER 0x02 77 #define PIP_GET_TOUCH_TYPE(reg) ((reg) & 0x07) 78 79 #define RECORD_EVENT_NONE 0 80 #define RECORD_EVENT_TOUCHDOWN 1 81 #define RECORD_EVENT_DISPLACE 2 82 #define RECORD_EVENT_LIFTOFF 3 83 84 #define PIP_SENSING_MODE_MUTUAL_CAP_FINE 0x00 85 #define PIP_SENSING_MODE_SELF_CAP 0x02 86 87 #define PIP_SET_PROXIMITY 0x49 88 89 /* Macro of Gen5 */ 90 #define GEN5_BL_MAX_OUTPUT_LENGTH 0x0100 91 #define GEN5_APP_MAX_OUTPUT_LENGTH 0x00fe 92 93 #define GEN5_POWER_STATE_ACTIVE 0x01 94 #define GEN5_POWER_STATE_LOOK_FOR_TOUCH 0x02 95 #define GEN5_POWER_STATE_READY 0x03 96 #define GEN5_POWER_STATE_IDLE 0x04 97 #define GEN5_POWER_STATE_BTN_ONLY 0x05 98 #define GEN5_POWER_STATE_OFF 0x06 99 100 #define GEN5_POWER_READY_MAX_INTRVL_TIME 50 /* Unit: ms */ 101 #define GEN5_POWER_IDLE_MAX_INTRVL_TIME 250 /* Unit: ms */ 102 103 #define GEN5_CMD_GET_PARAMETER 0x05 104 #define GEN5_CMD_SET_PARAMETER 0x06 105 #define GEN5_PARAMETER_ACT_INTERVL_ID 0x4d 106 #define GEN5_PARAMETER_ACT_INTERVL_SIZE 1 107 #define GEN5_PARAMETER_ACT_LFT_INTERVL_ID 0x4f 108 #define GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE 2 109 #define GEN5_PARAMETER_LP_INTRVL_ID 0x4c 110 #define GEN5_PARAMETER_LP_INTRVL_SIZE 2 111 112 #define GEN5_PARAMETER_DISABLE_PIP_REPORT 0x08 113 114 #define GEN5_BL_REPORT_DESCRIPTOR_SIZE 0x1d 115 #define GEN5_BL_REPORT_DESCRIPTOR_ID 0xfe 116 #define GEN5_APP_REPORT_DESCRIPTOR_SIZE 0xee 117 #define GEN5_APP_CONTRACT_REPORT_DESCRIPTOR_SIZE 0xfa 118 #define GEN5_APP_REPORT_DESCRIPTOR_ID 0xf6 119 120 #define GEN5_RETRIEVE_MUTUAL_PWC_DATA 0x00 121 #define GEN5_RETRIEVE_SELF_CAP_PWC_DATA 0x01 122 123 #define GEN5_RETRIEVE_DATA_ELEMENT_SIZE_MASK 0x07 124 125 #define GEN5_CMD_EXECUTE_PANEL_SCAN 0x2a 126 #define GEN5_CMD_RETRIEVE_PANEL_SCAN 0x2b 127 #define GEN5_PANEL_SCAN_MUTUAL_RAW_DATA 0x00 128 #define GEN5_PANEL_SCAN_MUTUAL_BASELINE 0x01 129 #define GEN5_PANEL_SCAN_MUTUAL_DIFFCOUNT 0x02 130 #define GEN5_PANEL_SCAN_SELF_RAW_DATA 0x03 131 #define GEN5_PANEL_SCAN_SELF_BASELINE 0x04 132 #define GEN5_PANEL_SCAN_SELF_DIFFCOUNT 0x05 133 134 /* 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 137 138 139 struct cyapa_pip_touch_record { 140 /* 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.) 146 * 3 - 15 : reserved. 147 */ 148 u8 touch_type; 149 150 /* 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 155 * 0 : no event 156 * 1 : touchdown 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. 161 */ 162 u8 touch_tip_event_id; 163 164 /* Bit 7 - 0 of X-axis coordinate of the touch in pixel. */ 165 u8 x_lo; 166 167 /* Bit 15 - 8 of X-axis coordinate of the touch in pixel. */ 168 u8 x_hi; 169 170 /* Bit 7 - 0 of Y-axis coordinate of the touch in pixel. */ 171 u8 y_lo; 172 173 /* Bit 15 - 8 of Y-axis coordinate of the touch in pixel. */ 174 u8 y_hi; 175 176 /* 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 182 * the surface. 183 **/ 184 u8 z; 185 186 /* 187 * The length of the major axis of the ellipse of contact between 188 * the finger and the panel (ABS_MT_TOUCH_MAJOR). 189 */ 190 u8 major_axis_len; 191 192 /* 193 * The length of the minor axis of the ellipse of contact between 194 * the finger and the panel (ABS_MT_TOUCH_MINOR). 195 */ 196 u8 minor_axis_len; 197 198 /* 199 * The length of the major axis of the approaching tool. 200 * (ABS_MT_WIDTH_MAJOR) 201 */ 202 u8 major_tool_len; 203 204 /* 205 * The length of the minor axis of the approaching tool. 206 * (ABS_MT_WIDTH_MINOR) 207 */ 208 u8 minor_tool_len; 209 210 /* 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. 218 */ 219 u8 orientation; 220 } __packed; 221 222 struct cyapa_pip_report_data { 223 u8 report_head[PIP_TOUCH_REPORT_HEAD_SIZE]; 224 struct cyapa_pip_touch_record touch_records[10]; 225 } __packed; 226 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. */ 231 u8 fw_major_version; 232 u8 fw_minor_version; 233 u8 fw_revision_control_number[8]; 234 u8 silicon_id_hi; 235 u8 silicon_id_lo; 236 u8 chip_revision; 237 u8 family_id; 238 u8 bl_ver_maj; 239 u8 bl_ver_min; 240 } __packed; 241 242 struct cyapa_tsg_bin_image_data_record { 243 u8 flash_array_id; 244 __be16 row_number; 245 /* The number of bytes of flash data contained in this record. */ 246 __be16 record_len; 247 /* The flash program data. */ 248 u8 record_data[CYAPA_TSG_FW_ROW_SIZE]; 249 } __packed; 250 251 struct cyapa_tsg_bin_image { 252 struct cyapa_tsg_bin_image_head image_head; 253 struct cyapa_tsg_bin_image_data_record records[]; 254 } __packed; 255 256 struct pip_bl_packet_start { 257 u8 sop; /* Start of packet, must be 01h */ 258 u8 cmd_code; 259 __le16 data_length; /* Size of data parameter start from data[0] */ 260 } __packed; 261 262 struct pip_bl_packet_end { 263 __le16 crc; 264 u8 eop; /* End of packet, must be 17h */ 265 } __packed; 266 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 */ 270 __le16 length; 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 */ 275 } __packed; 276 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]; 282 __le16 metadata_crc; 283 } __packed; 284 285 struct tsg_bl_metadata_row_params { 286 __le16 size; 287 __le16 maximum_size; 288 __le32 app_start; 289 __le16 app_len; 290 __le16 app_crc; 291 __le32 app_entry; 292 __le32 upgrade_start; 293 __le16 upgrade_len; 294 __le16 entry_row_crc; 295 u8 padding[36]; /* Padding data must be 0 */ 296 __le16 metadata_crc; /* CRC starts at offset of 60 */ 297 } __packed; 298 299 /* Bootload program and verify row command data structure */ 300 struct tsg_bl_flash_row_head { 301 u8 flash_array_id; 302 __le16 flash_row_id; 303 u8 flash_data[]; 304 } __packed; 305 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 */ 309 __le16 length; 310 u8 report_id; /* Application output report id, must be 2Fh */ 311 u8 rsvd; /* Reserved, must be 0 */ 312 /* 313 * Bit 7: reserved, must be 0. 314 * Bit 6-0: command code. 315 */ 316 u8 cmd_code; 317 u8 parameter_data[]; /* Parameter data variable based on cmd_code */ 318 } __packed; 319 320 /* Application get/set parameter command data structure */ 321 struct gen5_app_set_parameter_data { 322 u8 parameter_id; 323 u8 parameter_size; 324 __le32 value; 325 } __packed; 326 327 struct gen5_app_get_parameter_data { 328 u8 parameter_id; 329 } __packed; 330 331 struct gen5_retrieve_panel_scan_data { 332 __le16 read_offset; 333 __le16 read_elements; 334 u8 data_id; 335 } __packed; 336 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 340 }; 341 342 static u8 cyapa_pip_bl_cmd_key[] = { 0xa5, 0x01, 0x02, 0x03, 343 0xff, 0xfe, 0xfd, 0x5a }; 344 345 static int cyapa_pip_event_process(struct cyapa *cyapa, 346 struct cyapa_pip_report_data *report_data); 347 348 int cyapa_pip_cmd_state_initialize(struct cyapa *cyapa) 349 { 350 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 351 352 init_completion(&pip->cmd_ready); 353 atomic_set(&pip->cmd_issued, 0); 354 mutex_init(&pip->cmd_lock); 355 356 mutex_init(&pip->pm_stage_lock); 357 pip->pm_stage = CYAPA_PM_DEACTIVE; 358 359 pip->resp_sort_func = NULL; 360 pip->in_progress_cmd = PIP_INVALID_CMD; 361 pip->resp_data = NULL; 362 pip->resp_len = NULL; 363 364 cyapa->dev_pwr_mode = UNINIT_PWR_MODE; 365 cyapa->dev_sleep_time = UNINIT_SLEEP_TIME; 366 367 return 0; 368 } 369 370 /* 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) 372 { 373 int ret; 374 375 if (size == 0) 376 return 0; 377 378 if (!buf || size > CYAPA_REG_MAP_SIZE) 379 return -EINVAL; 380 381 ret = i2c_master_recv(cyapa->client, buf, size); 382 383 if (ret != size) 384 return (ret < 0) ? ret : -EIO; 385 return size; 386 } 387 388 /** 389 * Return a negative errno code else zero on success. 390 */ 391 ssize_t cyapa_i2c_pip_write(struct cyapa *cyapa, u8 *buf, size_t size) 392 { 393 int ret; 394 395 if (!buf || !size) 396 return -EINVAL; 397 398 ret = i2c_master_send(cyapa->client, buf, size); 399 400 if (ret != size) 401 return (ret < 0) ? ret : -EIO; 402 403 return 0; 404 } 405 406 static void cyapa_set_pip_pm_state(struct cyapa *cyapa, 407 enum cyapa_pm_stage pm_stage) 408 { 409 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 410 411 mutex_lock(&pip->pm_stage_lock); 412 pip->pm_stage = pm_stage; 413 mutex_unlock(&pip->pm_stage_lock); 414 } 415 416 static void cyapa_reset_pip_pm_state(struct cyapa *cyapa) 417 { 418 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 419 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); 424 } 425 426 static enum cyapa_pm_stage cyapa_get_pip_pm_state(struct cyapa *cyapa) 427 { 428 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 429 enum cyapa_pm_stage pm_stage; 430 431 mutex_lock(&pip->pm_stage_lock); 432 pm_stage = pip->pm_stage; 433 mutex_unlock(&pip->pm_stage_lock); 434 435 return pm_stage; 436 } 437 438 /** 439 * 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. 441 */ 442 int cyapa_empty_pip_output_data(struct cyapa *cyapa, 443 u8 *buf, int *len, cb_sort func) 444 { 445 struct input_dev *input = cyapa->input; 446 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 447 enum cyapa_pm_stage pm_stage = cyapa_get_pip_pm_state(cyapa); 448 int length; 449 int report_count; 450 int empty_count; 451 int buf_len; 452 int error; 453 454 buf_len = 0; 455 if (len) { 456 buf_len = (*len < CYAPA_REG_MAP_SIZE) ? 457 *len : CYAPA_REG_MAP_SIZE; 458 *len = 0; 459 } 460 461 report_count = 8; /* max 7 pending data before command response data */ 462 empty_count = 0; 463 do { 464 /* 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. 475 */ 476 if (empty_count > 5) 477 return 0; 478 479 error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, 480 PIP_RESP_LENGTH_SIZE); 481 if (error < 0) 482 return error; 483 484 length = get_unaligned_le16(pip->empty_buf); 485 if (length == PIP_RESP_LENGTH_SIZE) { 486 empty_count++; 487 continue; 488 } else if (length > CYAPA_REG_MAP_SIZE) { 489 /* Should not happen */ 490 return -EINVAL; 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); 498 *len = length; 499 /* Response found, success. */ 500 return 0; 501 } 502 continue; 503 } 504 505 error = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length); 506 if (error < 0) 507 return error; 508 509 report_count--; 510 empty_count = 0; 511 length = get_unaligned_le16(pip->empty_buf); 512 if (length <= PIP_RESP_LENGTH_SIZE) { 513 empty_count++; 514 } else if (buf && buf_len && func && 515 func(cyapa, pip->empty_buf, length)) { 516 length = min(buf_len, length); 517 memcpy(buf, pip->empty_buf, length); 518 *len = length; 519 /* Response found, success. */ 520 return 0; 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); 527 } 528 529 error = -EINVAL; 530 } while (report_count); 531 532 return error; 533 } 534 535 static int cyapa_do_i2c_pip_cmd_irq_sync( 536 struct cyapa *cyapa, 537 u8 *cmd, size_t cmd_len, 538 unsigned long timeout) 539 { 540 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 541 int error; 542 543 /* Wait for interrupt to set ready completion */ 544 init_completion(&pip->cmd_ready); 545 546 atomic_inc(&pip->cmd_issued); 547 error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); 548 if (error) { 549 atomic_dec(&pip->cmd_issued); 550 return (error < 0) ? error : -EIO; 551 } 552 553 /* Wait for interrupt to indicate command is completed. */ 554 timeout = wait_for_completion_timeout(&pip->cmd_ready, 555 msecs_to_jiffies(timeout)); 556 if (timeout == 0) { 557 atomic_dec(&pip->cmd_issued); 558 return -ETIMEDOUT; 559 } 560 561 return 0; 562 } 563 564 static int cyapa_do_i2c_pip_cmd_polling( 565 struct cyapa *cyapa, 566 u8 *cmd, size_t cmd_len, 567 u8 *resp_data, int *resp_len, 568 unsigned long timeout, 569 cb_sort func) 570 { 571 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 572 int tries; 573 int length; 574 int error; 575 576 atomic_inc(&pip->cmd_issued); 577 error = cyapa_i2c_pip_write(cyapa, cmd, cmd_len); 578 if (error) { 579 atomic_dec(&pip->cmd_issued); 580 return error < 0 ? error : -EIO; 581 } 582 583 length = resp_len ? *resp_len : 0; 584 if (resp_data && resp_len && length != 0 && func) { 585 tries = timeout / 5; 586 do { 587 usleep_range(3000, 5000); 588 *resp_len = length; 589 error = cyapa_empty_pip_output_data(cyapa, 590 resp_data, resp_len, func); 591 if (error || *resp_len == 0) 592 continue; 593 else 594 break; 595 } while (--tries > 0); 596 if ((error || *resp_len == 0) || tries <= 0) 597 error = error ? error : -ETIMEDOUT; 598 } 599 600 atomic_dec(&pip->cmd_issued); 601 return error; 602 } 603 604 int cyapa_i2c_pip_cmd_irq_sync( 605 struct cyapa *cyapa, 606 u8 *cmd, int cmd_len, 607 u8 *resp_data, int *resp_len, 608 unsigned long timeout, 609 cb_sort func, 610 bool irq_mode) 611 { 612 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 613 int error; 614 615 if (!cmd || !cmd_len) 616 return -EINVAL; 617 618 /* Commands must be serialized. */ 619 error = mutex_lock_interruptible(&pip->cmd_lock); 620 if (error) 621 return error; 622 623 pip->resp_sort_func = func; 624 pip->resp_data = resp_data; 625 pip->resp_len = resp_len; 626 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]; 635 } 636 637 /* Send command data, wait and read output response data's length. */ 638 if (irq_mode) { 639 pip->is_irq_mode = true; 640 error = cyapa_do_i2c_pip_cmd_irq_sync(cyapa, cmd, cmd_len, 641 timeout); 642 if (error == -ETIMEDOUT && resp_data && 643 resp_len && *resp_len != 0 && func) { 644 /* 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. 648 */ 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; 653 } 654 } else { 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); 658 } 659 660 pip->resp_sort_func = NULL; 661 pip->resp_data = NULL; 662 pip->resp_len = NULL; 663 pip->in_progress_cmd = PIP_INVALID_CMD; 664 665 mutex_unlock(&pip->cmd_lock); 666 return error; 667 } 668 669 bool cyapa_sort_tsg_pip_bl_resp_data(struct cyapa *cyapa, 670 u8 *data, int len) 671 { 672 if (!data || len < PIP_MIN_BL_RESP_LENGTH) 673 return false; 674 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) 679 return true; 680 681 return false; 682 } 683 684 bool cyapa_sort_tsg_pip_app_resp_data(struct cyapa *cyapa, 685 u8 *data, int len) 686 { 687 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 688 int resp_len; 689 690 if (!data || len < PIP_MIN_APP_RESP_LENGTH) 691 return false; 692 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 */ 700 return false; 701 } else if (GET_PIP_CMD_CODE(data[PIP_RESP_APP_CMD_OFFSET]) == 702 pip->in_progress_cmd) { 703 /* Correct command response received */ 704 return true; 705 } 706 } 707 708 return false; 709 } 710 711 static bool cyapa_sort_pip_application_launch_data(struct cyapa *cyapa, 712 u8 *buf, int len) 713 { 714 if (buf == NULL || len < PIP_RESP_LENGTH_SIZE) 715 return false; 716 717 /* 718 * After reset or power on, trackpad device always sets to 0x00 0x00 719 * to indicate a reset or power on event. 720 */ 721 if (buf[0] == 0 && buf[1] == 0) 722 return true; 723 724 return false; 725 } 726 727 static bool cyapa_sort_gen5_hid_descriptor_data(struct cyapa *cyapa, 728 u8 *buf, int len) 729 { 730 int resp_len; 731 int max_output_len; 732 733 /* Check hid descriptor. */ 734 if (len != PIP_HID_DESCRIPTOR_SIZE) 735 return false; 736 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 */ 743 return true; 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 */ 748 return true; 749 } 750 } 751 752 return false; 753 } 754 755 static bool cyapa_sort_pip_deep_sleep_data(struct cyapa *cyapa, 756 u8 *buf, int len) 757 { 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) 763 return true; 764 return false; 765 } 766 767 static int gen5_idle_state_parse(struct cyapa *cyapa) 768 { 769 u8 resp_data[PIP_HID_DESCRIPTOR_SIZE]; 770 int max_output_len; 771 int length; 772 u8 cmd[2]; 773 int ret; 774 int error; 775 776 /* 777 * Dump all buffered data firstly for the situation 778 * when the trackpad is just power on the cyapa go here. 779 */ 780 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 781 782 memset(resp_data, 0, sizeof(resp_data)); 783 ret = cyapa_i2c_pip_read(cyapa, resp_data, 3); 784 if (ret != 3) 785 return ret < 0 ? ret : -EIO; 786 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; 791 792 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 793 794 /* Read description from trackpad device */ 795 cmd[0] = 0x01; 796 cmd[1] = 0x00; 797 length = PIP_HID_DESCRIPTOR_SIZE; 798 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 799 cmd, PIP_RESP_LENGTH_SIZE, 800 resp_data, &length, 801 300, 802 cyapa_sort_gen5_hid_descriptor_data, 803 false); 804 if (error) 805 return error; 806 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; 824 } else { 825 /* Should not happen!!! */ 826 cyapa->state = CYAPA_STATE_NO_DEVICE; 827 } 828 } 829 830 return 0; 831 } 832 833 static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data) 834 { 835 int length; 836 u8 resp_data[32]; 837 int max_output_len; 838 int ret; 839 840 /* 0x20 0x00 0xF7 is Gen5 Application HID Description Header; 841 * 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header. 842 * 843 * Must read HID Description content through out, 844 * otherwise Gen5 trackpad cannot response next command 845 * or report any touch or button data. 846 */ 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) { 856 /* 857 * BL mode HID Description has been previously 858 * read out. 859 */ 860 cyapa->gen = CYAPA_GEN5; 861 cyapa->state = CYAPA_STATE_GEN5_BL; 862 } else { 863 /* 864 * APP mode HID Description has been previously 865 * read out. 866 */ 867 cyapa->gen = CYAPA_GEN5; 868 cyapa->state = CYAPA_STATE_GEN5_APP; 869 } 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; 883 } else { 884 /* Should not happen!!! */ 885 cyapa->state = CYAPA_STATE_NO_DEVICE; 886 } 887 888 return 0; 889 } 890 891 static int gen5_report_data_header_parse(struct cyapa *cyapa, u8 *reg_data) 892 { 893 int length; 894 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) 900 return -EINVAL; 901 break; 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) 907 return -EINVAL; 908 break; 909 case PIP_WAKEUP_EVENT_REPORT_ID: 910 if (length != PIP_WAKEUP_EVENT_SIZE) 911 return -EINVAL; 912 break; 913 default: 914 return -EINVAL; 915 } 916 917 cyapa->gen = CYAPA_GEN5; 918 cyapa->state = CYAPA_STATE_GEN5_APP; 919 return 0; 920 } 921 922 static int gen5_cmd_resp_header_parse(struct cyapa *cyapa, u8 *reg_data) 923 { 924 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 925 int length; 926 int ret; 927 928 /* 929 * Must read report data through out, 930 * otherwise Gen5 trackpad cannot response next command 931 * or report any touch or button data. 932 */ 933 length = get_unaligned_le16(®_data[PIP_RESP_LENGTH_OFFSET]); 934 ret = cyapa_i2c_pip_read(cyapa, pip->empty_buf, length); 935 if (ret != length) 936 return ret < 0 ? ret : -EIO; 937 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; 945 } else { 946 /* Gen5 APP command response data detected */ 947 cyapa->gen = CYAPA_GEN5; 948 cyapa->state = CYAPA_STATE_GEN5_APP; 949 } 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] == 955 PIP_SOP_KEY) && 956 (pip->empty_buf[length - 1] == 957 PIP_EOP_KEY)) { 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] == 964 PIP_RESP_RSVD_KEY) { 965 /* Gen5 APP command response data detected */ 966 cyapa->gen = CYAPA_GEN5; 967 cyapa->state = CYAPA_STATE_GEN5_APP; 968 } else { 969 /* Should not happen!!! */ 970 cyapa->state = CYAPA_STATE_NO_DEVICE; 971 } 972 973 return 0; 974 } 975 976 static int cyapa_gen5_state_parse(struct cyapa *cyapa, u8 *reg_data, int len) 977 { 978 int length; 979 980 if (!reg_data || len < 3) 981 return -EINVAL; 982 983 cyapa->state = CYAPA_STATE_NO_DEVICE; 984 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); 1013 } 1014 1015 if (cyapa->gen == CYAPA_GEN5) { 1016 /* 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. 1021 */ 1022 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1023 1024 if (cyapa->state == CYAPA_STATE_GEN5_APP || 1025 cyapa->state == CYAPA_STATE_GEN5_BL) 1026 return 0; 1027 } 1028 1029 return -EAGAIN; 1030 } 1031 1032 static struct cyapa_tsg_bin_image_data_record * 1033 cyapa_get_image_record_data_num(const struct firmware *fw, 1034 int *record_num) 1035 { 1036 int head_size; 1037 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]; 1042 } 1043 1044 int cyapa_pip_bl_initiate(struct cyapa *cyapa, const struct firmware *fw) 1045 { 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]; 1052 int cmd_len; 1053 u16 cmd_data_len; 1054 u16 cmd_crc = 0; 1055 u16 meta_data_crc = 0; 1056 u8 resp_data[11]; 1057 int resp_len; 1058 int records_num; 1059 u8 *data; 1060 int error; 1061 1062 /* Try to dump all buffered report data before any send command. */ 1063 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1064 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); 1070 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; 1074 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); 1080 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); 1083 1084 image_records = cyapa_get_image_record_data_num(fw, &records_num); 1085 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); 1090 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); 1094 1095 bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data + 1096 cmd_data_len); 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; 1101 1102 resp_len = sizeof(resp_data); 1103 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1104 cmd, cmd_len, 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; 1111 1112 return 0; 1113 } 1114 1115 static bool cyapa_sort_pip_bl_exit_data(struct cyapa *cyapa, u8 *buf, int len) 1116 { 1117 if (buf == NULL || len < PIP_RESP_LENGTH_SIZE) 1118 return false; 1119 1120 if (buf[0] == 0 && buf[1] == 0) 1121 return true; 1122 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) 1130 return true; 1131 1132 return false; 1133 } 1134 1135 int cyapa_pip_bl_exit(struct cyapa *cyapa) 1136 { 1137 1138 u8 bl_gen5_bl_exit[] = { 0x04, 0x00, 1139 0x0B, 0x00, 0x40, 0x00, 0x01, 0x3b, 0x00, 0x00, 1140 0x20, 0xc7, 0x17 1141 }; 1142 u8 resp_data[11]; 1143 int resp_len; 1144 int error; 1145 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); 1151 if (error) 1152 return error; 1153 1154 if (resp_len == PIP_BL_FAIL_EXIT_RESP_LEN || 1155 resp_data[PIP_RESP_REPORT_ID_OFFSET] == 1156 PIP_BL_RESP_REPORT_ID) 1157 return -EAGAIN; 1158 1159 if (resp_data[0] == 0x00 && resp_data[1] == 0x00) 1160 return 0; 1161 1162 return -ENODEV; 1163 } 1164 1165 int cyapa_pip_bl_enter(struct cyapa *cyapa) 1166 { 1167 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2F, 0x00, 0x01 }; 1168 u8 resp_data[2]; 1169 int resp_len; 1170 int error; 1171 1172 error = cyapa_poll_state(cyapa, 500); 1173 if (error < 0) 1174 return error; 1175 1176 /* Already in bootloader mode, Skipping exit. */ 1177 if (cyapa_is_pip_bl_mode(cyapa)) 1178 return 0; 1179 else if (!cyapa_is_pip_app_mode(cyapa)) 1180 return -EINVAL; 1181 1182 /* Try to dump all buffered report data before any send command. */ 1183 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1184 1185 /* 1186 * Send bootloader enter command to trackpad device, 1187 * after enter bootloader, the response data is two bytes of 0x00 0x00. 1188 */ 1189 resp_len = sizeof(resp_data); 1190 memset(resp_data, 0, resp_len); 1191 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1192 cmd, sizeof(cmd), 1193 resp_data, &resp_len, 1194 5000, cyapa_sort_pip_application_launch_data, 1195 true); 1196 if (error || resp_data[0] != 0x00 || resp_data[1] != 0x00) 1197 return error < 0 ? error : -EAGAIN; 1198 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; 1204 return 0; 1205 } 1206 1207 static int cyapa_pip_fw_head_check(struct cyapa *cyapa, 1208 struct cyapa_tsg_bin_image_head *image_head) 1209 { 1210 if (image_head->head_size != 0x0C && image_head->head_size != 0x12) 1211 return -EINVAL; 1212 1213 switch (cyapa->gen) { 1214 case CYAPA_GEN6: 1215 if (image_head->family_id != 0x9B || 1216 image_head->silicon_id_hi != 0x0B) 1217 return -EINVAL; 1218 break; 1219 case CYAPA_GEN5: 1220 /* Gen5 without proximity support. */ 1221 if (cyapa->platform_ver < 2) { 1222 if (image_head->head_size == 0x0C) 1223 break; 1224 return -EINVAL; 1225 } 1226 1227 if (image_head->family_id != 0x91 || 1228 image_head->silicon_id_hi != 0x02) 1229 return -EINVAL; 1230 break; 1231 default: 1232 return -EINVAL; 1233 } 1234 1235 return 0; 1236 } 1237 1238 int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw) 1239 { 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; 1247 u16 app_crc; 1248 u16 app_integrity_crc; 1249 int i; 1250 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", 1255 __func__); 1256 return -EINVAL; 1257 } 1258 1259 image_records = 1260 cyapa_get_image_record_data_num(fw, &flash_records_count); 1261 1262 /* 1263 * APP_INTEGRITY row is always the last row block, 1264 * and the row id must be 0x01ff. 1265 */ 1266 app_integrity = &image_records[flash_records_count - 1]; 1267 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__); 1271 return -EINVAL; 1272 } 1273 1274 metadata = (const void *)app_integrity->record_data; 1275 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__); 1281 return -EINVAL; 1282 } 1283 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); 1288 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__); 1294 return -EINVAL; 1295 } 1296 1297 /* Verify application image CRC. */ 1298 app_crc = 0xffffU; 1299 for (i = 0; i < fw_app_len / CYAPA_TSG_FW_ROW_SIZE; i++) { 1300 const u8 *data = image_records[i].record_data; 1301 1302 app_crc = crc_itu_t(app_crc, data, CYAPA_TSG_FW_ROW_SIZE); 1303 } 1304 1305 if (app_crc != get_unaligned_le16(&metadata->app_crc)) { 1306 dev_err(dev, "%s: invalid firmware app crc check.\n", __func__); 1307 return -EINVAL; 1308 } 1309 1310 return 0; 1311 } 1312 1313 static int cyapa_pip_write_fw_block(struct cyapa *cyapa, 1314 struct cyapa_tsg_bin_image_data_record *flash_record) 1315 { 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]; 1321 u16 cmd_len; 1322 u8 flash_array_id; 1323 u16 flash_row_id; 1324 u16 record_len; 1325 u8 *record_data; 1326 u16 data_len; 1327 u16 crc; 1328 u8 resp_data[11]; 1329 int resp_len; 1330 int error; 1331 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; 1336 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); 1344 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; 1351 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); 1355 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); 1360 1361 bl_packet_end = (struct pip_bl_packet_end *)(bl_cmd_head->data + 1362 data_len); 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; 1367 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; 1376 1377 return 0; 1378 } 1379 1380 int cyapa_pip_do_fw_update(struct cyapa *cyapa, 1381 const struct firmware *fw) 1382 { 1383 struct device *dev = &cyapa->client->dev; 1384 struct cyapa_tsg_bin_image_data_record *image_records; 1385 int flash_records_count; 1386 int i; 1387 int error; 1388 1389 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1390 1391 image_records = 1392 cyapa_get_image_record_data_num(fw, &flash_records_count); 1393 1394 /* 1395 * The last flash row 0x01ff has been written through bl_initiate 1396 * command, so DO NOT write flash 0x01ff to trackpad device. 1397 */ 1398 for (i = 0; i < (flash_records_count - 1); i++) { 1399 error = cyapa_pip_write_fw_block(cyapa, &image_records[i]); 1400 if (error) { 1401 dev_err(dev, "%s: Gen5 FW update aborted: %d\n", 1402 __func__, error); 1403 return error; 1404 } 1405 } 1406 1407 return 0; 1408 } 1409 1410 static int cyapa_gen5_change_power_state(struct cyapa *cyapa, u8 power_state) 1411 { 1412 u8 cmd[8] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, 0x08, 0x01 }; 1413 u8 resp_data[6]; 1414 int resp_len; 1415 int error; 1416 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; 1425 1426 return 0; 1427 } 1428 1429 static int cyapa_gen5_set_interval_time(struct cyapa *cyapa, 1430 u8 parameter_id, u16 interval_time) 1431 { 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]; 1435 int cmd_len; 1436 u8 resp_data[7]; 1437 int resp_len; 1438 u8 parameter_size; 1439 int error; 1440 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); 1447 1448 switch (parameter_id) { 1449 case GEN5_PARAMETER_ACT_INTERVL_ID: 1450 parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE; 1451 break; 1452 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID: 1453 parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE; 1454 break; 1455 case GEN5_PARAMETER_LP_INTRVL_ID: 1456 parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE; 1457 break; 1458 default: 1459 return -EINVAL; 1460 } 1461 1462 put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &app_cmd_head->addr); 1463 /* 1464 * Don't include unused parameter value bytes and 1465 * 2 bytes register address. 1466 */ 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; 1482 1483 return 0; 1484 } 1485 1486 static int cyapa_gen5_get_interval_time(struct cyapa *cyapa, 1487 u8 parameter_id, u16 *interval_time) 1488 { 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]; 1492 int cmd_len; 1493 u8 resp_data[11]; 1494 int resp_len; 1495 u8 parameter_size; 1496 u16 mask, i; 1497 int error; 1498 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); 1505 1506 *interval_time = 0; 1507 switch (parameter_id) { 1508 case GEN5_PARAMETER_ACT_INTERVL_ID: 1509 parameter_size = GEN5_PARAMETER_ACT_INTERVL_SIZE; 1510 break; 1511 case GEN5_PARAMETER_ACT_LFT_INTERVL_ID: 1512 parameter_size = GEN5_PARAMETER_ACT_LFT_INTERVL_SIZE; 1513 break; 1514 case GEN5_PARAMETER_LP_INTRVL_ID: 1515 parameter_size = GEN5_PARAMETER_LP_INTRVL_SIZE; 1516 break; 1517 default: 1518 return -EINVAL; 1519 } 1520 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; 1527 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; 1535 1536 mask = 0; 1537 for (i = 0; i < parameter_size; i++) 1538 mask |= (0xff << (i * 8)); 1539 *interval_time = get_unaligned_le16(&resp_data[7]) & mask; 1540 1541 return 0; 1542 } 1543 1544 static int cyapa_gen5_disable_pip_report(struct cyapa *cyapa) 1545 { 1546 struct pip_app_cmd_head *app_cmd_head; 1547 u8 cmd[10]; 1548 u8 resp_data[7]; 1549 int resp_len; 1550 int error; 1551 1552 memset(cmd, 0, sizeof(cmd)); 1553 app_cmd_head = (struct pip_app_cmd_head *)cmd; 1554 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; 1570 1571 return 0; 1572 } 1573 1574 int cyapa_pip_set_proximity(struct cyapa *cyapa, bool enable) 1575 { 1576 u8 cmd[] = { 0x04, 0x00, 0x06, 0x00, 0x2f, 0x00, PIP_SET_PROXIMITY, 1577 (u8)!!enable 1578 }; 1579 u8 resp_data[6]; 1580 int resp_len; 1581 int error; 1582 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; 1591 } 1592 1593 return 0; 1594 } 1595 1596 int cyapa_pip_deep_sleep(struct cyapa *cyapa, u8 state) 1597 { 1598 u8 cmd[] = { 0x05, 0x00, 0x00, 0x08}; 1599 u8 resp_data[5]; 1600 int resp_len; 1601 int error; 1602 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)) 1609 return -EINVAL; 1610 1611 return 0; 1612 } 1613 1614 static int cyapa_gen5_set_power_mode(struct cyapa *cyapa, 1615 u8 power_mode, u16 sleep_time, enum cyapa_pm_stage pm_stage) 1616 { 1617 struct device *dev = &cyapa->client->dev; 1618 u8 power_state; 1619 int error = 0; 1620 1621 if (cyapa->state != CYAPA_STATE_GEN5_APP) 1622 return 0; 1623 1624 cyapa_set_pip_pm_state(cyapa, pm_stage); 1625 1626 if (PIP_DEV_GET_PWR_STATE(cyapa) == UNINIT_PWR_MODE) { 1627 /* 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. 1631 */ 1632 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); 1633 } 1634 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); 1641 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. */ 1648 goto out; 1649 } 1650 } 1651 1652 if (power_mode == PWR_MODE_OFF) { 1653 error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_OFF); 1654 if (error) { 1655 dev_err(dev, "enter deep sleep fail: %d\n", error); 1656 goto out; 1657 } 1658 1659 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_OFF); 1660 goto out; 1661 } 1662 1663 /* 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. 1667 */ 1668 if (PIP_DEV_GET_PWR_STATE(cyapa) == PWR_MODE_OFF) { 1669 error = cyapa_pip_deep_sleep(cyapa, PIP_DEEP_SLEEP_STATE_ON); 1670 if (error) { 1671 dev_err(dev, "deep sleep wake fail: %d\n", error); 1672 goto out; 1673 } 1674 } 1675 1676 if (power_mode == PWR_MODE_FULL_ACTIVE) { 1677 error = cyapa_gen5_change_power_state(cyapa, 1678 GEN5_POWER_STATE_ACTIVE); 1679 if (error) { 1680 dev_err(dev, "change to active fail: %d\n", error); 1681 goto out; 1682 } 1683 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); 1688 if (error) { 1689 dev_err(dev, "fail to button only mode: %d\n", error); 1690 goto out; 1691 } 1692 1693 PIP_DEV_SET_PWR_STATE(cyapa, PWR_MODE_BTN_ONLY); 1694 } else { 1695 /* 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. 1699 */ 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, 1704 sleep_time) == 0) 1705 PIP_DEV_SET_SLEEP_TIME(cyapa, sleep_time); 1706 1707 if (sleep_time <= GEN5_POWER_READY_MAX_INTRVL_TIME) 1708 power_state = GEN5_POWER_STATE_READY; 1709 else 1710 power_state = GEN5_POWER_STATE_IDLE; 1711 error = cyapa_gen5_change_power_state(cyapa, power_state); 1712 if (error) { 1713 dev_err(dev, "set power state to 0x%02x failed: %d\n", 1714 power_state, error); 1715 goto out; 1716 } 1717 1718 /* 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 1726 * asserted again. 1727 */ 1728 if (pm_stage == CYAPA_PM_SUSPEND) 1729 cyapa_gen5_disable_pip_report(cyapa); 1730 1731 PIP_DEV_SET_PWR_STATE(cyapa, 1732 cyapa_sleep_time_to_pwr_cmd(sleep_time)); 1733 } 1734 1735 out: 1736 cyapa_reset_pip_pm_state(cyapa); 1737 return error; 1738 } 1739 1740 int cyapa_pip_resume_scanning(struct cyapa *cyapa) 1741 { 1742 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x04 }; 1743 u8 resp_data[6]; 1744 int resp_len; 1745 int error; 1746 1747 /* Try to dump all buffered data before doing command. */ 1748 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1749 1750 resp_len = sizeof(resp_data); 1751 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1752 cmd, sizeof(cmd), 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)) 1756 return -EINVAL; 1757 1758 /* Try to dump all buffered data when resuming scanning. */ 1759 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1760 1761 return 0; 1762 } 1763 1764 int cyapa_pip_suspend_scanning(struct cyapa *cyapa) 1765 { 1766 u8 cmd[] = { 0x04, 0x00, 0x05, 0x00, 0x2f, 0x00, 0x03 }; 1767 u8 resp_data[6]; 1768 int resp_len; 1769 int error; 1770 1771 /* Try to dump all buffered data before doing command. */ 1772 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1773 1774 resp_len = sizeof(resp_data); 1775 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 1776 cmd, sizeof(cmd), 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)) 1780 return -EINVAL; 1781 1782 /* Try to dump all buffered data when suspending scanning. */ 1783 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1784 1785 return 0; 1786 } 1787 1788 static int cyapa_pip_calibrate_pwcs(struct cyapa *cyapa, 1789 u8 calibrate_sensing_mode_type) 1790 { 1791 struct pip_app_cmd_head *app_cmd_head; 1792 u8 cmd[8]; 1793 u8 resp_data[6]; 1794 int resp_len; 1795 int error; 1796 1797 /* Try to dump all buffered data before doing command. */ 1798 cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL); 1799 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, 1809 cmd, sizeof(cmd), 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; 1815 1816 return 0; 1817 } 1818 1819 ssize_t cyapa_pip_do_calibrate(struct device *dev, 1820 struct device_attribute *attr, 1821 const char *buf, size_t count) 1822 { 1823 struct cyapa *cyapa = dev_get_drvdata(dev); 1824 int error, calibrate_error; 1825 1826 /* 1. Suspend Scanning*/ 1827 error = cyapa_pip_suspend_scanning(cyapa); 1828 if (error) 1829 return error; 1830 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; 1836 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; 1842 1843 resume_scanning: 1844 /* 4. Resume Scanning*/ 1845 error = cyapa_pip_resume_scanning(cyapa); 1846 if (error || calibrate_error) 1847 return error ? error : calibrate_error; 1848 1849 return count; 1850 } 1851 1852 static s32 twos_complement_to_s32(s32 value, int num_bits) 1853 { 1854 if (value >> (num_bits - 1)) 1855 value |= -1 << num_bits; 1856 return value; 1857 } 1858 1859 static s32 cyapa_parse_structure_data(u8 data_format, u8 *buf, int buf_len) 1860 { 1861 int data_size; 1862 bool big_endian; 1863 bool unsigned_type; 1864 s32 value; 1865 1866 data_size = (data_format & 0x07); 1867 big_endian = ((data_format & 0x10) == 0x00); 1868 unsigned_type = ((data_format & 0x20) == 0x00); 1869 1870 if (buf_len < data_size) 1871 return 0; 1872 1873 switch (data_size) { 1874 case 1: 1875 value = buf[0]; 1876 break; 1877 case 2: 1878 if (big_endian) 1879 value = get_unaligned_be16(buf); 1880 else 1881 value = get_unaligned_le16(buf); 1882 break; 1883 case 4: 1884 if (big_endian) 1885 value = get_unaligned_be32(buf); 1886 else 1887 value = get_unaligned_le32(buf); 1888 break; 1889 default: 1890 /* Should not happen, just as default case here. */ 1891 value = 0; 1892 break; 1893 } 1894 1895 if (!unsigned_type) 1896 value = twos_complement_to_s32(value, data_size * 8); 1897 1898 return value; 1899 } 1900 1901 static void cyapa_gen5_guess_electrodes(struct cyapa *cyapa, 1902 int *electrodes_rx, int *electrodes_tx) 1903 { 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; 1908 } else { 1909 *electrodes_tx = min(cyapa->electrodes_x, cyapa->electrodes_y); 1910 *electrodes_rx = max(cyapa->electrodes_x, cyapa->electrodes_y); 1911 } 1912 } 1913 1914 /* 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 1924 * used. 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. 1931 */ 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) 1935 { 1936 struct pip_app_cmd_head *cmd_head; 1937 u8 cmd[12]; 1938 u8 resp_data[256]; 1939 int resp_len; 1940 int read_len; 1941 int value; 1942 u16 offset; 1943 int read_elements; 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; 1948 int i; 1949 int error; 1950 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) 1955 return -EINVAL; 1956 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) { 1962 /* 1963 * Read global idac values firstly. 1964 * Currently, no idac data exceed 4 bytes. 1965 */ 1966 read_global_idac = true; 1967 offset = 0; 1968 *data_size = 4; 1969 tmp_max = INT_MIN; 1970 tmp_min = INT_MAX; 1971 tmp_ave = tmp_sum = tmp_count = 0; 1972 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; 1979 } 1980 max_element_cnt = 1981 (cyapa->aligned_electrodes_rx + 7) & ~7u; 1982 } else { 1983 max_element_cnt = 2; 1984 } 1985 } else { 1986 read_global_idac = false; 1987 if (*data_size > 4) 1988 *data_size = 4; 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; 1994 else 1995 electrodes_tx = cyapa->electrodes_x; 1996 max_element_cnt = ((cyapa->aligned_electrodes_rx + 7) & 1997 ~7u) * electrodes_tx; 1998 } else { 1999 offset = 2; 2000 max_element_cnt = cyapa->electrodes_x + 2001 cyapa->electrodes_y; 2002 max_element_cnt = (max_element_cnt + 3) & ~3u; 2003 } 2004 } 2005 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; 2012 do { 2013 read_elements = (256 - GEN5_RESP_DATA_STRUCTURE_OFFSET) / 2014 (*data_size); 2015 read_elements = min(read_elements, max_element_cnt - count); 2016 read_len = read_elements * (*data_size); 2017 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, 2023 cmd, sizeof(cmd), 2024 resp_data, &resp_len, 2025 500, cyapa_sort_tsg_pip_app_resp_data, 2026 true); 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]); 2033 if (read_len == 0) 2034 break; 2035 2036 *data_size = (resp_data[9] & GEN5_PWC_DATA_ELEMENT_SIZE_MASK); 2037 if (read_len < *data_size) 2038 return -EINVAL; 2039 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( 2044 resp_data[9], 2045 &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET], 2046 *data_size); 2047 /* Tx's self global idac data. */ 2048 *idac_min = cyapa_parse_structure_data( 2049 resp_data[9], 2050 &resp_data[GEN5_RESP_DATA_STRUCTURE_OFFSET + 2051 *data_size], 2052 *data_size); 2053 break; 2054 } 2055 2056 /* Read mutual global idac or local mutual/self PWC data. */ 2057 offset += read_len; 2058 for (i = 10; i < (read_len + GEN5_RESP_DATA_STRUCTURE_OFFSET); 2059 i += *data_size) { 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); 2064 2065 if (idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA && 2066 tmp_count < cyapa->aligned_electrodes_rx && 2067 read_global_idac) { 2068 /* 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. 2073 */ 2074 if (!tmp_ave || value > tmp_ave / 2) { 2075 tmp_min = min(value, tmp_min); 2076 tmp_max = max(value, tmp_max); 2077 tmp_sum += value; 2078 tmp_count++; 2079 2080 tmp_ave = tmp_sum / tmp_count; 2081 } 2082 } 2083 2084 sum += value; 2085 count++; 2086 2087 if (count >= max_element_cnt) 2088 goto out; 2089 } 2090 } while (true); 2091 2092 out: 2093 *idac_ave = count ? (sum / count) : 0; 2094 2095 if (read_global_idac && 2096 idac_data_type == GEN5_RETRIEVE_MUTUAL_PWC_DATA) { 2097 if (tmp_count == 0) 2098 return 0; 2099 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; 2107 } else { 2108 cyapa->electrodes_rx = cyapa->electrodes_rx ? 2109 cyapa->electrodes_rx : electrodes_tx; 2110 cyapa->aligned_electrodes_rx = tmp_count; 2111 } 2112 2113 *idac_min = tmp_min; 2114 *idac_max = tmp_max; 2115 *idac_ave = tmp_ave; 2116 } 2117 2118 return 0; 2119 } 2120 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) 2124 { 2125 int data_size; 2126 int error; 2127 2128 *gidac_mutual_max = *gidac_mutual_min = *gidac_mutual_ave = 0; 2129 *lidac_mutual_max = *lidac_mutual_min = *lidac_mutual_ave = 0; 2130 2131 data_size = 0; 2132 error = cyapa_gen5_read_idac_data(cyapa, 2133 PIP_RETRIEVE_DATA_STRUCTURE, 2134 GEN5_RETRIEVE_MUTUAL_PWC_DATA, 2135 &data_size, 2136 gidac_mutual_max, gidac_mutual_min, gidac_mutual_ave); 2137 if (error) 2138 return error; 2139 2140 error = cyapa_gen5_read_idac_data(cyapa, 2141 PIP_RETRIEVE_DATA_STRUCTURE, 2142 GEN5_RETRIEVE_MUTUAL_PWC_DATA, 2143 &data_size, 2144 lidac_mutual_max, lidac_mutual_min, lidac_mutual_ave); 2145 return error; 2146 } 2147 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) 2151 { 2152 int data_size; 2153 int error; 2154 2155 *gidac_self_rx = *gidac_self_tx = 0; 2156 *lidac_self_max = *lidac_self_min = *lidac_self_ave = 0; 2157 2158 data_size = 0; 2159 error = cyapa_gen5_read_idac_data(cyapa, 2160 PIP_RETRIEVE_DATA_STRUCTURE, 2161 GEN5_RETRIEVE_SELF_CAP_PWC_DATA, 2162 &data_size, 2163 lidac_self_max, lidac_self_min, lidac_self_ave); 2164 if (error) 2165 return error; 2166 *gidac_self_rx = *lidac_self_max; 2167 *gidac_self_tx = *lidac_self_min; 2168 2169 error = cyapa_gen5_read_idac_data(cyapa, 2170 PIP_RETRIEVE_DATA_STRUCTURE, 2171 GEN5_RETRIEVE_SELF_CAP_PWC_DATA, 2172 &data_size, 2173 lidac_self_max, lidac_self_min, lidac_self_ave); 2174 return error; 2175 } 2176 2177 static ssize_t cyapa_gen5_execute_panel_scan(struct cyapa *cyapa) 2178 { 2179 struct pip_app_cmd_head *app_cmd_head; 2180 u8 cmd[7]; 2181 u8 resp_data[6]; 2182 int resp_len; 2183 int error; 2184 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, 2193 cmd, sizeof(cmd), 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; 2201 2202 return 0; 2203 } 2204 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, 2208 u8 *buffer) 2209 { 2210 struct pip_app_cmd_head *app_cmd_head; 2211 struct gen5_retrieve_panel_scan_data *panel_sacn_data; 2212 u8 cmd[12]; 2213 u8 resp_data[256]; /* Max bytes can transfer one time. */ 2214 int resp_len; 2215 int read_elements; 2216 int read_len; 2217 u16 offset; 2218 s32 value; 2219 int sum, count; 2220 int data_size; 2221 s32 *intp; 2222 int i; 2223 int error; 2224 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) 2228 return -EINVAL; 2229 2230 intp = (s32 *)buffer; 2231 *raw_data_max = INT_MIN; 2232 *raw_data_min = INT_MAX; 2233 sum = count = 0; 2234 offset = 0; 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; 2245 do { 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; 2250 2251 resp_len = GEN5_RESP_DATA_STRUCTURE_OFFSET + read_len; 2252 error = cyapa_i2c_pip_cmd_irq_sync(cyapa, 2253 cmd, sizeof(cmd), 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; 2261 2262 read_elements = get_unaligned_le16(&resp_data[7]); 2263 if (read_elements == 0) 2264 break; 2265 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); 2272 i += data_size) { 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); 2277 2278 if (intp) 2279 put_unaligned_le32(value, &intp[count]); 2280 2281 sum += value; 2282 count++; 2283 2284 } 2285 } 2286 2287 if (count >= raw_data_max_num) 2288 break; 2289 2290 read_elements = (sizeof(resp_data) - 2291 GEN5_RESP_DATA_STRUCTURE_OFFSET) / data_size; 2292 read_len = read_elements * data_size; 2293 } while (true); 2294 2295 *raw_data_ave = count ? (sum / count) : 0; 2296 2297 return 0; 2298 } 2299 2300 static ssize_t cyapa_gen5_show_baseline(struct device *dev, 2301 struct device_attribute *attr, char *buf) 2302 { 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; 2315 int size; 2316 2317 if (!cyapa_is_pip_app_mode(cyapa)) 2318 return -EBUSY; 2319 2320 /* 1. Suspend Scanning*/ 2321 error = cyapa_pip_suspend_scanning(cyapa); 2322 if (error) 2323 return error; 2324 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); 2331 if (error) 2332 goto resume_scanning; 2333 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, 2338 &lidac_self_ave); 2339 if (error) 2340 goto resume_scanning; 2341 2342 /* 4. Execute panel scan. It must be executed before read data. */ 2343 error = cyapa_gen5_execute_panel_scan(cyapa); 2344 if (error) 2345 goto resume_scanning; 2346 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, 2354 NULL); 2355 if (error) 2356 goto resume_scanning; 2357 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, 2364 &raw_cap_self_ave, 2365 NULL); 2366 if (error) 2367 goto resume_scanning; 2368 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, 2376 NULL); 2377 if (error) 2378 goto resume_scanning; 2379 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, 2386 &self_diffdata_ave, 2387 NULL); 2388 if (error) 2389 goto resume_scanning; 2390 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, 2398 NULL); 2399 if (error) 2400 goto resume_scanning; 2401 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, 2408 &self_baseline_ave, 2409 NULL); 2410 if (error) 2411 goto resume_scanning; 2412 2413 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; 2418 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); 2433 return size; 2434 } 2435 2436 bool cyapa_pip_sort_system_info_data(struct cyapa *cyapa, 2437 u8 *buf, int len) 2438 { 2439 /* Check the report id and command code */ 2440 if (VALID_CMD_RESP_HEADER(buf, 0x02)) 2441 return true; 2442 2443 return false; 2444 } 2445 2446 static int cyapa_gen5_bl_query_data(struct cyapa *cyapa) 2447 { 2448 u8 resp_data[PIP_BL_APP_INFO_RESP_LENGTH]; 2449 int resp_len; 2450 int error; 2451 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; 2460 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'; 2467 2468 cyapa->fw_maj_ver = resp_data[22]; 2469 cyapa->fw_min_ver = resp_data[23]; 2470 2471 cyapa->platform_ver = (resp_data[26] >> PIP_BL_PLATFORM_VER_SHIFT) & 2472 PIP_BL_PLATFORM_VER_MASK; 2473 2474 return 0; 2475 } 2476 2477 static int cyapa_gen5_get_query_data(struct cyapa *cyapa) 2478 { 2479 u8 resp_data[PIP_READ_SYS_INFO_RESP_LENGTH]; 2480 int resp_len; 2481 u16 product_family; 2482 int error; 2483 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; 2491 2492 product_family = get_unaligned_le16(&resp_data[7]); 2493 if ((product_family & PIP_PRODUCT_FAMILY_MASK) != 2494 PIP_PRODUCT_FAMILY_TRACKPAD) 2495 return -EINVAL; 2496 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]; 2503 } else { 2504 cyapa->fw_maj_ver = resp_data[9]; 2505 cyapa->fw_min_ver = resp_data[10]; 2506 } 2507 2508 cyapa->electrodes_x = resp_data[52]; 2509 cyapa->electrodes_y = resp_data[53]; 2510 2511 cyapa->physical_size_x = get_unaligned_le16(&resp_data[54]) / 100; 2512 cyapa->physical_size_y = get_unaligned_le16(&resp_data[56]) / 100; 2513 2514 cyapa->max_abs_x = get_unaligned_le16(&resp_data[58]); 2515 cyapa->max_abs_y = get_unaligned_le16(&resp_data[60]); 2516 2517 cyapa->max_z = get_unaligned_le16(&resp_data[62]); 2518 2519 cyapa->x_origin = resp_data[64] & 0x01; 2520 cyapa->y_origin = resp_data[65] & 0x01; 2521 2522 cyapa->btn_capability = (resp_data[70] << 3) & CAPABILITY_BTN_MASK; 2523 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'; 2530 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) 2534 return -EINVAL; 2535 2536 return 0; 2537 } 2538 2539 static int cyapa_gen5_do_operational_check(struct cyapa *cyapa) 2540 { 2541 struct device *dev = &cyapa->client->dev; 2542 int error; 2543 2544 if (cyapa->gen != CYAPA_GEN5) 2545 return -ENODEV; 2546 2547 switch (cyapa->state) { 2548 case CYAPA_STATE_GEN5_BL: 2549 error = cyapa_pip_bl_exit(cyapa); 2550 if (error) { 2551 /* Try to update trackpad product information. */ 2552 cyapa_gen5_bl_query_data(cyapa); 2553 goto out; 2554 } 2555 2556 cyapa->state = CYAPA_STATE_GEN5_APP; 2557 fallthrough; 2558 2559 case CYAPA_STATE_GEN5_APP: 2560 /* 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. 2565 */ 2566 error = cyapa_gen5_set_power_mode(cyapa, 2567 PWR_MODE_FULL_ACTIVE, 0, CYAPA_PM_ACTIVE); 2568 if (error) 2569 dev_warn(dev, "%s: failed to set power active mode.\n", 2570 __func__); 2571 2572 /* By default, the trackpad proximity function is enabled. */ 2573 if (cyapa->platform_ver >= 2) { 2574 error = cyapa_pip_set_proximity(cyapa, true); 2575 if (error) 2576 dev_warn(dev, 2577 "%s: failed to enable proximity.\n", 2578 __func__); 2579 } 2580 2581 /* Get trackpad product information. */ 2582 error = cyapa_gen5_get_query_data(cyapa); 2583 if (error) 2584 goto out; 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); 2590 error = -EINVAL; 2591 } 2592 break; 2593 default: 2594 error = -EINVAL; 2595 } 2596 2597 out: 2598 return error; 2599 } 2600 2601 /* 2602 * Return false, do not continue process 2603 * Return true, continue process. 2604 */ 2605 bool cyapa_pip_irq_cmd_handler(struct cyapa *cyapa) 2606 { 2607 struct cyapa_pip_cmd_states *pip = &cyapa->cmd_states.pip; 2608 int length; 2609 2610 if (atomic_read(&pip->cmd_issued)) { 2611 /* Polling command response data. */ 2612 if (pip->is_irq_mode == false) 2613 return false; 2614 2615 /* 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. 2619 */ 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))) { 2631 /* 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. 2643 */ 2644 length = 0; 2645 if (pip->resp_len) 2646 length = *pip->resp_len; 2647 cyapa_empty_pip_output_data(cyapa, 2648 pip->resp_data, 2649 &length, 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); 2655 } 2656 return false; 2657 } 2658 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, 2663 *pip->resp_len); 2664 } 2665 atomic_dec(&pip->cmd_issued); 2666 complete(&pip->cmd_ready); 2667 return false; 2668 } 2669 2670 return true; 2671 } 2672 2673 static void cyapa_pip_report_buttons(struct cyapa *cyapa, 2674 const struct cyapa_pip_report_data *report_data) 2675 { 2676 struct input_dev *input = cyapa->input; 2677 u8 buttons = report_data->report_head[PIP_BUTTONS_OFFSET]; 2678 2679 buttons = (buttons << CAPABILITY_BTN_SHIFT) & CAPABILITY_BTN_MASK; 2680 2681 if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) { 2682 input_report_key(input, BTN_LEFT, 2683 !!(buttons & CAPABILITY_LEFT_BTN_MASK)); 2684 } 2685 if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) { 2686 input_report_key(input, BTN_MIDDLE, 2687 !!(buttons & CAPABILITY_MIDDLE_BTN_MASK)); 2688 } 2689 if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) { 2690 input_report_key(input, BTN_RIGHT, 2691 !!(buttons & CAPABILITY_RIGHT_BTN_MASK)); 2692 } 2693 2694 input_sync(input); 2695 } 2696 2697 static void cyapa_pip_report_proximity(struct cyapa *cyapa, 2698 const struct cyapa_pip_report_data *report_data) 2699 { 2700 struct input_dev *input = cyapa->input; 2701 u8 distance = report_data->report_head[PIP_PROXIMITY_DISTANCE_OFFSET] & 2702 PIP_PROXIMITY_DISTANCE_MASK; 2703 2704 input_report_abs(input, ABS_DISTANCE, distance); 2705 input_sync(input); 2706 } 2707 2708 static void cyapa_pip_report_slot_data(struct cyapa *cyapa, 2709 const struct cyapa_pip_touch_record *touch) 2710 { 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); 2714 int x, y; 2715 2716 if (event_id == RECORD_EVENT_LIFTOFF) 2717 return; 2718 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, 2731 touch->z); 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); 2736 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); 2741 2742 input_report_abs(input, ABS_MT_ORIENTATION, 2743 touch->orientation); 2744 } 2745 2746 static void cyapa_pip_report_touches(struct cyapa *cyapa, 2747 const struct cyapa_pip_report_data *report_data) 2748 { 2749 struct input_dev *input = cyapa->input; 2750 unsigned int touch_num; 2751 int i; 2752 2753 touch_num = report_data->report_head[PIP_NUMBER_OF_TOUCH_OFFSET] & 2754 PIP_NUMBER_OF_TOUCH_MASK; 2755 2756 for (i = 0; i < touch_num; i++) 2757 cyapa_pip_report_slot_data(cyapa, 2758 &report_data->touch_records[i]); 2759 2760 input_mt_sync_frame(input); 2761 input_sync(input); 2762 } 2763 2764 int cyapa_pip_irq_handler(struct cyapa *cyapa) 2765 { 2766 struct device *dev = &cyapa->client->dev; 2767 struct cyapa_pip_report_data report_data; 2768 unsigned int report_len; 2769 int ret; 2770 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); 2774 return -EINVAL; 2775 } 2776 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); 2781 return -EINVAL; 2782 } 2783 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]); 2791 return -EINVAL; 2792 } 2793 2794 /* Idle, no data for report. */ 2795 if (report_len == PIP_RESP_LENGTH_SIZE) 2796 return 0; 2797 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", 2801 report_len, ret); 2802 return -EINVAL; 2803 } 2804 2805 return cyapa_pip_event_process(cyapa, &report_data); 2806 } 2807 2808 static int cyapa_pip_event_process(struct cyapa *cyapa, 2809 struct cyapa_pip_report_data *report_data) 2810 { 2811 struct device *dev = &cyapa->client->dev; 2812 unsigned int report_len; 2813 u8 report_id; 2814 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) 2819 return 0; 2820 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) { 2824 /* 2825 * Device wake event from deep sleep mode for touch. 2826 * This interrupt event is used to wake system up. 2827 * 2828 * Note: 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 2832 * process. 2833 */ 2834 pm_runtime_get_sync(dev); 2835 pm_runtime_mark_last_busy(dev); 2836 pm_runtime_put_sync_autosuspend(dev); 2837 return 0; 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); 2845 return -EINVAL; 2846 } 2847 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); 2853 return 0; 2854 } 2855 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); 2863 return 0; 2864 } 2865 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); 2870 return 0; 2871 } 2872 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); 2877 else 2878 cyapa_pip_report_buttons(cyapa, report_data); 2879 2880 return 0; 2881 } 2882 2883 int cyapa_pip_bl_activate(struct cyapa *cyapa) { return 0; } 2884 int cyapa_pip_bl_deactivate(struct cyapa *cyapa) { return 0; } 2885 2886 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, 2894 2895 .show_baseline = cyapa_gen5_show_baseline, 2896 .calibrate_store = cyapa_pip_do_calibrate, 2897 2898 .initialize = cyapa_pip_cmd_state_initialize, 2899 2900 .state_parse = cyapa_gen5_state_parse, 2901 .operational_check = cyapa_gen5_do_operational_check, 2902 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, 2907 2908 .set_proximity = cyapa_pip_set_proximity, 2909 }; 2910