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