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