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