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