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