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