root/drivers/input/mouse/cyapa_gen5.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cyapa_pip_cmd_state_initialize
  2. cyapa_i2c_pip_read
  3. cyapa_i2c_pip_write
  4. cyapa_set_pip_pm_state
  5. cyapa_reset_pip_pm_state
  6. cyapa_get_pip_pm_state
  7. cyapa_empty_pip_output_data
  8. cyapa_do_i2c_pip_cmd_irq_sync
  9. cyapa_do_i2c_pip_cmd_polling
  10. cyapa_i2c_pip_cmd_irq_sync
  11. cyapa_sort_tsg_pip_bl_resp_data
  12. cyapa_sort_tsg_pip_app_resp_data
  13. cyapa_sort_pip_application_launch_data
  14. cyapa_sort_gen5_hid_descriptor_data
  15. cyapa_sort_pip_deep_sleep_data
  16. gen5_idle_state_parse
  17. gen5_hid_description_header_parse
  18. gen5_report_data_header_parse
  19. gen5_cmd_resp_header_parse
  20. cyapa_gen5_state_parse
  21. cyapa_get_image_record_data_num
  22. cyapa_pip_bl_initiate
  23. cyapa_sort_pip_bl_exit_data
  24. cyapa_pip_bl_exit
  25. cyapa_pip_bl_enter
  26. cyapa_pip_fw_head_check
  27. cyapa_pip_check_fw
  28. cyapa_pip_write_fw_block
  29. cyapa_pip_do_fw_update
  30. cyapa_gen5_change_power_state
  31. cyapa_gen5_set_interval_time
  32. cyapa_gen5_get_interval_time
  33. cyapa_gen5_disable_pip_report
  34. cyapa_pip_set_proximity
  35. cyapa_pip_deep_sleep
  36. cyapa_gen5_set_power_mode
  37. cyapa_pip_resume_scanning
  38. cyapa_pip_suspend_scanning
  39. cyapa_pip_calibrate_pwcs
  40. cyapa_pip_do_calibrate
  41. twos_complement_to_s32
  42. cyapa_parse_structure_data
  43. cyapa_gen5_guess_electrodes
  44. cyapa_gen5_read_idac_data
  45. cyapa_gen5_read_mutual_idac_data
  46. cyapa_gen5_read_self_idac_data
  47. cyapa_gen5_execute_panel_scan
  48. cyapa_gen5_read_panel_scan_raw_data
  49. cyapa_gen5_show_baseline
  50. cyapa_pip_sort_system_info_data
  51. cyapa_gen5_bl_query_data
  52. cyapa_gen5_get_query_data
  53. cyapa_gen5_do_operational_check
  54. cyapa_pip_irq_cmd_handler
  55. cyapa_pip_report_buttons
  56. cyapa_pip_report_proximity
  57. cyapa_pip_report_slot_data
  58. cyapa_pip_report_touches
  59. cyapa_pip_irq_handler
  60. cyapa_pip_event_process
  61. cyapa_pip_bl_activate
  62. cyapa_pip_bl_deactivate

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

/* [<][>][^][v][top][bottom][index][help] */