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