| /* |
| * Goodix Gesture Module |
| * |
| * Copyright (C) 2019 - 2020 Goodix, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be a reference |
| * to you, when you are integrating the GOODiX's CTP IC into your system, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| */ |
| #ifndef _GOODIX_TS_CORE_H_ |
| #define _GOODIX_TS_CORE_H_ |
| #include <asm/unaligned.h> |
| #include <linux/completion.h> |
| #include <linux/delay.h> |
| #include <linux/firmware.h> |
| #include <linux/init.h> |
| #include <linux/input.h> |
| #include <linux/interrupt.h> |
| #include <linux/kernel.h> |
| #include <linux/kthread.h> |
| #include <linux/module.h> |
| #include <linux/mutex.h> |
| #include <linux/of_irq.h> |
| #include <linux/platform_device.h> |
| #include <linux/slab.h> |
| #include <linux/vmalloc.h> |
| #include <drm/drm_panel.h> |
| #if IS_ENABLED(CONFIG_OF) |
| #include <linux/of_gpio.h> |
| #include <linux/regulator/consumer.h> |
| #endif |
| #if IS_ENABLED(CONFIG_FB) |
| #include <linux/fb.h> |
| #include <linux/notifier.h> |
| #endif |
| #include "touch_apis.h" |
| #if IS_ENABLED(CONFIG_TOUCHSCREEN_MOTION_FILTER) |
| #include "touch_mf_mode.h" |
| #endif |
| #if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE) |
| #include <goog_touch_interface.h> |
| #endif |
| #if IS_ENABLED(CONFIG_VH_SYSTRACE) |
| #include "../../../gs-google/drivers/soc/google/vh/kernel/systrace.h" |
| #else |
| #define ATRACE_BEGIN(f) |
| #define ATRACE_END() |
| #endif |
| |
| #define GOODIX_CORE_DRIVER_NAME "goodix_ts" |
| #define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen" |
| #define GOODIX_DRIVER_VERSION "v1.2.4" |
| #define GOODIX_MAX_TOUCH 10 |
| #define GOODIX_PEN_MAX_PRESSURE 4096 |
| #define GOODIX_MAX_PEN_KEY 2 |
| #define GOODIX_PEN_MAX_TILT 90 |
| #define GOODIX_CFG_MAX_SIZE 4096 |
| #define GOODIX_FW_MAX_SIEZE (300 * 1024) |
| #define GOODIX_MAX_STR_LABEL_LEN 32 |
| #define GOODIX_MAX_FRAMEDATA_LEN (3 * 1024) |
| #define GOODIX_GESTURE_DATA_LEN 16 |
| #define GOODIX_REQUEST_DATA_LEN 16 |
| #define GOODIX_NORMAL_RESET_DELAY_MS 100 |
| #define GOODIX_HOLD_CPU_RESET_DELAY_MS 5 |
| |
| #define GOODIX_RETRY_3 3 |
| #define GOODIX_RETRY_5 5 |
| #define GOODIX_RETRY_10 10 |
| |
| #define GOODIX_GESTURE_UNKNOWN 0x00 |
| #define GOODIX_GESTURE_DOUBLE_TAP 0xCC |
| #define GOODIX_GESTURE_SINGLE_TAP 0x4C |
| #define GOODIX_GESTURE_FOD_DOWN 0x46 |
| #define GOODIX_GESTURE_FOD_UP 0x55 |
| |
| #define TS_DEFAULT_FIRMWARE "goodix_firmware.bin" |
| #define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin" |
| #define TS_DEFAULT_TEST_LIMITS "goodix_test_limits_255.csv" |
| |
| enum GOODIX_GESTURE_TYP { |
| GESTURE_SINGLE_TAP = (1 << 0), |
| GESTURE_DOUBLE_TAP = (1 << 1), |
| GESTURE_FOD_PRESS = (1 << 2) |
| }; |
| |
| enum CORD_PROB_STA { |
| CORE_MODULE_UNPROBED = 0, |
| CORE_MODULE_PROB_SUCCESS = 1, |
| CORE_MODULE_PROB_FAILED = -1, |
| CORE_MODULE_REMOVED = -2, |
| }; |
| |
| enum GOODIX_ERR_CODE { |
| GOODIX_EBUS = (1 << 0), |
| GOODIX_ECHECKSUM = (1 << 1), |
| GOODIX_EVERSION = (1 << 2), |
| GOODIX_ETIMEOUT = (1 << 3), |
| GOODIX_EMEMCMP = (1 << 4), |
| |
| GOODIX_EOTHER = (1 << 7) |
| }; |
| |
| /* MAIN-ID */ |
| enum IC_TYPE_ID { |
| IC_TYPE_NONE, |
| IC_TYPE_NORMANDY, |
| IC_TYPE_NANJING, |
| IC_TYPE_YELLOWSTONE, |
| IC_TYPE_BERLIN_A, |
| IC_TYPE_BERLIN_B, |
| IC_TYPE_BERLIN_D, |
| IC_TYPE_NOTTINGHAM |
| }; |
| |
| /* SUB-ID |
| * sub type of berlinB serial IC. |
| * for convenience we put the MAIN-ID on the hith bits, |
| * hith 8 bits is MAIN-ID, low 8 bits is MIN-ID |
| */ |
| enum BERLIN_B_SUB_ID { |
| IC_TYPE_SUB_B2 = (IC_TYPE_BERLIN_B << 8) | 0x2, |
| }; |
| |
| enum GOODIX_IC_CONFIG_TYPE { |
| CONFIG_TYPE_TEST = 0, |
| CONFIG_TYPE_NORMAL = 1, |
| CONFIG_TYPE_HIGHSENSE = 2, |
| CONFIG_TYPE_CHARGER = 3, |
| CONFIG_TYPE_CHARGER_HS = 4, |
| CONFIG_TYPE_HOLSTER = 5, |
| CONFIG_TYPE_HOSTER_CH = 6, |
| CONFIG_TYPE_OTHER = 7, |
| /* keep this at the last */ |
| GOODIX_MAX_CONFIG_GROUP = 8, |
| }; |
| |
| enum CHECKSUM_MODE { |
| CHECKSUM_MODE_U8_LE, |
| CHECKSUM_MODE_U16_LE, |
| }; |
| |
| enum PINCTRL_MODE { |
| PINCTRL_MODE_ACTIVE, |
| PINCTRL_MODE_SUSPEND, |
| }; |
| |
| enum raw_scan_mode : u8 { |
| RAW_SCAN_MODE_AUTO = 0, |
| RAW_SCAN_MODE_NORMAL_ACTIVE, |
| RAW_SCAN_MODE_NORMAL_IDLE, |
| RAW_SCAN_MODE_LOW_POWER_ACTIVE, |
| RAW_SCAN_MODE_LOW_POWER_IDLE, |
| RAW_SCAN_MODE_SLEEP, |
| }; |
| |
| enum frame_data_type : u8 { |
| FRAME_DATA_TYPE_RAW = 0x81, |
| FRAME_DATA_TYPE_DIFF = 0x82, |
| FRAME_DATA_TYPE_BASE = 0x83, |
| }; |
| |
| #define MAX_SCAN_FREQ_NUM 8 |
| #define MAX_SCAN_RATE_NUM 8 |
| #define MAX_FREQ_NUM_STYLUS 8 |
| #define MAX_STYLUS_SCAN_FREQ_NUM 6 |
| #pragma pack(1) |
| struct frame_head { |
| uint8_t sync; |
| uint16_t frame_index; |
| uint16_t cur_frame_len; |
| uint16_t next_frame_len; |
| uint32_t data_en; /* 0- 7 for pack_en; 8 - 31 for type en */ |
| uint8_t touch_pack_index; |
| uint8_t stylus_pack_index; |
| uint8_t res; |
| uint16_t checksum; |
| }; |
| |
| struct goodix_fw_version { |
| u8 rom_pid[6]; /* rom PID */ |
| u8 rom_vid[3]; /* Mask VID */ |
| u8 rom_vid_reserved; |
| u8 patch_pid[8]; /* Patch PID */ |
| u8 patch_vid[4]; /* Patch VID */ |
| u8 patch_vid_reserved; |
| u8 sensor_id; |
| u8 reserved[2]; |
| u16 checksum; |
| }; |
| |
| struct goodix_ic_info_version { |
| u8 info_customer_id; |
| u8 info_version_id; |
| u8 ic_die_id; |
| u8 ic_version_id; |
| u32 config_id; |
| u8 config_version; |
| u8 frame_data_customer_id; |
| u8 frame_data_version_id; |
| u8 touch_data_customer_id; |
| u8 touch_data_version_id; |
| u8 reserved[3]; |
| }; |
| |
| struct goodix_ic_info_feature { /* feature info*/ |
| u16 freqhop_feature; |
| u16 calibration_feature; |
| u16 gesture_feature; |
| u16 side_touch_feature; |
| u16 stylus_feature; |
| }; |
| |
| struct goodix_ic_info_param { /* param */ |
| u8 drv_num; |
| u8 sen_num; |
| u8 button_num; |
| u8 force_num; |
| u8 active_scan_rate_num; |
| u16 active_scan_rate[MAX_SCAN_RATE_NUM]; |
| u8 mutual_freq_num; |
| u16 mutual_freq[MAX_SCAN_FREQ_NUM]; |
| u8 self_tx_freq_num; |
| u16 self_tx_freq[MAX_SCAN_FREQ_NUM]; |
| u8 self_rx_freq_num; |
| u16 self_rx_freq[MAX_SCAN_FREQ_NUM]; |
| u8 stylus_freq_num; |
| u16 stylus_freq[MAX_FREQ_NUM_STYLUS]; |
| }; |
| |
| struct goodix_ic_info_misc { /* other data */ |
| u32 cmd_addr; |
| u16 cmd_max_len; |
| u32 cmd_reply_addr; |
| u16 cmd_reply_len; |
| u32 fw_state_addr; |
| u16 fw_state_len; |
| u32 fw_buffer_addr; |
| u16 fw_buffer_max_len; |
| u32 frame_data_addr; |
| u16 frame_data_head_len; |
| u16 fw_attr_len; |
| u16 fw_log_len; |
| u8 pack_max_num; |
| u8 pack_compress_version; |
| u16 stylus_struct_len; |
| u16 mutual_struct_len; |
| u16 self_struct_len; |
| u16 noise_struct_len; |
| u32 touch_data_addr; |
| u16 touch_data_head_len; |
| u16 point_struct_len; |
| u16 reserved1; |
| u16 reserved2; |
| u32 mutual_rawdata_addr; |
| u32 mutual_diffdata_addr; |
| u32 mutual_refdata_addr; |
| u32 self_rawdata_addr; |
| u32 self_diffdata_addr; |
| u32 self_refdata_addr; |
| u32 iq_rawdata_addr; |
| u32 iq_refdata_addr; |
| u32 im_rawdata_addr; |
| u16 im_readata_len; |
| u32 noise_rawdata_addr; |
| u16 noise_rawdata_len; |
| u32 stylus_rawdata_addr; |
| u16 stylus_rawdata_len; |
| u32 noise_data_addr; |
| u32 esd_addr; |
| u32 auto_scan_cmd_addr; |
| u32 auto_scan_info_addr; |
| }; |
| |
| struct goodix_ic_info { |
| u16 length; |
| struct goodix_ic_info_version version; |
| struct goodix_ic_info_feature feature; |
| struct goodix_ic_info_param parm; |
| struct goodix_ic_info_misc misc; |
| }; |
| #pragma pack() |
| |
| /* |
| * struct ts_rawdata_info |
| * |
| */ |
| #define TS_RAWDATA_BUFF_MAX 7000 |
| #define TS_RAWDATA_RESULT_MAX 100 |
| struct ts_rawdata_info { |
| int used_size; // fill in rawdata size |
| s16 buff[TS_RAWDATA_BUFF_MAX]; |
| char result[TS_RAWDATA_RESULT_MAX]; |
| }; |
| |
| /* |
| * struct goodix_module - external modules container |
| * @head: external modules list |
| * @initialized: whether this struct is initialized |
| * @mutex: mutex lock |
| * @wq: workqueue to do register work |
| * @core_data: core_data pointer |
| */ |
| struct goodix_module { |
| struct list_head head; |
| bool initialized; |
| struct mutex mutex; |
| struct workqueue_struct *wq; |
| struct goodix_ts_core *core_data; |
| }; |
| |
| /* |
| * struct goodix_ts_board_data - board data |
| * @avdd_name: name of analoy regulator |
| * @iovdd_name: name of analoy regulator |
| * @reset_gpio: reset gpio number |
| * @irq_gpio: interrupt gpio number |
| * @irq_flag: irq trigger type |
| * @swap_axis: whether swaw x y axis |
| * @panel_max_x/y/w/p: resolution and size |
| * @panel_height_mm: the height of display in mm |
| * @pannel_key_map: key map |
| * @fw_name: name of the firmware image |
| */ |
| struct goodix_ts_board_data { |
| char avdd_name[GOODIX_MAX_STR_LABEL_LEN]; |
| char iovdd_name[GOODIX_MAX_STR_LABEL_LEN]; |
| int reset_gpio; |
| int irq_gpio; |
| int avdd_gpio; |
| int iovdd_gpio; |
| unsigned int irq_flags; |
| |
| struct pinctrl *pinctrl; |
| struct pinctrl_state *state_active; |
| struct pinctrl_state *state_suspend; |
| |
| unsigned int swap_axis; |
| unsigned int panel_max_x; |
| unsigned int panel_max_y; |
| unsigned int panel_max_w; /*major and minor*/ |
| unsigned int panel_max_p; /*pressure*/ |
| unsigned int panel_height_mm; |
| unsigned int udfps_x; |
| unsigned int udfps_y; |
| |
| bool pen_enable; |
| bool sleep_enable; |
| bool use_one_binary; |
| char fw_name[GOODIX_MAX_STR_LABEL_LEN]; |
| char cfg_bin_name[GOODIX_MAX_STR_LABEL_LEN]; |
| char test_limits_name[GOODIX_MAX_STR_LABEL_LEN]; |
| }; |
| |
| enum goodix_fw_update_mode { |
| UPDATE_MODE_DEFAULT = 0, |
| UPDATE_MODE_FORCE = (1 << 0), /* force update mode */ |
| UPDATE_MODE_BLOCK = (1 << 1), /* update in block mode */ |
| UPDATE_MODE_FLASH_CFG = (1 << 2), /* reflash config */ |
| UPDATE_MODE_SRC_SYSFS = (1 << 4), /* firmware file from sysfs */ |
| UPDATE_MODE_SRC_HEAD = (1 << 5), /* firmware file from head file */ |
| UPDATE_MODE_SRC_REQUEST = (1 << 6), /* request firmware */ |
| UPDATE_MODE_SRC_ARGS = (1 << 7), /* firmware data from function args */ |
| }; |
| |
| #define MAX_CMD_DATA_LEN 10 |
| #define MAX_CMD_BUF_LEN 16 |
| #pragma pack(1) |
| struct goodix_ts_cmd { |
| union { |
| struct { |
| u8 state; |
| u8 ack; |
| u8 len; |
| u8 cmd; |
| u8 data[MAX_CMD_DATA_LEN]; |
| }; |
| u8 buf[MAX_CMD_BUF_LEN]; |
| }; |
| }; |
| |
| struct goodix_status_data { |
| u8 water_change : 1; |
| u8 hop_change : 1; |
| u8 base_update : 1; |
| u8 soft_reset : 1; |
| u8 palm_change : 1; |
| u8 noise_lv_change : 1; |
| u8 grip_change : 1; |
| u8 water_sta; |
| u8 before_factorA; |
| u8 after_factorA; |
| u8 base_update_type; |
| u8 soft_reset_type; |
| u8 palm_sta; |
| u8 noise_lv; |
| u8 grip_type; |
| u8 res[9]; |
| u8 event_id; |
| u8 checksum; |
| }; |
| |
| struct goodix_stylus_data { |
| u8 stylus_protocol; |
| u8 sample_mode; |
| u8 stylus_key; |
| u16 stylus_pressure; |
| u16 stylus_freqA; |
| u16 stylus_freqB; |
| u8 res; |
| u16 stylus_next_freqA; |
| u16 stylus_next_freqB; |
| u16 stylus_noise_value[4]; |
| s16 angle_coord_x; |
| s16 angle_coord_y; |
| s16 delta_x; |
| s16 delta_y; |
| u8 freq_indexA; |
| u8 freq_indexB; |
| u16 tx1[32]; |
| u16 rx1[39]; |
| u16 tx2[32]; |
| u16 rx2[39]; |
| }; |
| #pragma pack() |
| |
| /* interrupt event type */ |
| enum ts_event_type { |
| EVENT_INVALID = 0, |
| EVENT_TOUCH = (1 << 0), /* finger touch event */ |
| EVENT_PEN = (1 << 1), /* pen event */ |
| EVENT_REQUEST = (1 << 2), |
| EVENT_GESTURE = (1 << 3), |
| EVENT_STATUS = (1 << 4), |
| }; |
| |
| enum ts_request_type { |
| REQUEST_TYPE_CONFIG = 1, |
| REQUEST_TYPE_RESET = 3, |
| REQUEST_TYPE_UPDATE = 5, |
| REQUEST_PEN_FREQ_HOP = 0x10 |
| }; |
| |
| /* notifier event */ |
| enum ts_notify_event { |
| NOTIFY_FWUPDATE_START, |
| NOTIFY_FWUPDATE_FAILED, |
| NOTIFY_FWUPDATE_SUCCESS, |
| NOTIFY_SUSPEND, |
| NOTIFY_RESUME, |
| NOTIFY_ESD_OFF, |
| NOTIFY_ESD_ON, |
| NOTIFY_CFG_BIN_FAILED, |
| NOTIFY_CFG_BIN_SUCCESS, |
| }; |
| |
| enum touch_point_status { |
| TS_NONE, |
| TS_RELEASE, |
| TS_TOUCH, |
| }; |
| /* coordinate package */ |
| struct goodix_ts_coords { |
| int status; /* NONE, RELEASE, TOUCH */ |
| unsigned int x, y, major, minor, p, w; |
| signed char angle; |
| }; |
| |
| struct goodix_pen_coords { |
| int status; /* NONE, RELEASE, TOUCH */ |
| int tool_type; /* BTN_TOOL_RUBBER BTN_TOOL_PEN */ |
| unsigned int x, y, p; |
| signed char tilt_x; |
| signed char tilt_y; |
| }; |
| |
| /* touch event data */ |
| struct goodix_touch_data { |
| int touch_num; |
| struct goodix_ts_coords coords[GOODIX_MAX_TOUCH]; |
| }; |
| |
| /* gesture event data */ |
| struct goodix_gesture_data { |
| u8 gesture_type; |
| int touches; |
| u8 data[GOODIX_GESTURE_DATA_LEN]; |
| }; |
| |
| struct goodix_ts_key { |
| int status; |
| int code; |
| }; |
| |
| struct goodix_pen_data { |
| struct goodix_pen_coords coords; |
| struct goodix_ts_key keys[GOODIX_MAX_PEN_KEY]; |
| }; |
| |
| /* |
| * struct goodix_ts_event - touch event struct |
| * @clear_count1: clear count for old firmware |
| * @clear_count2: clear count for latest firmware |
| * @event_type: touch event type, touch data or |
| * request event |
| * @event_data: event data |
| */ |
| struct goodix_ts_event { |
| enum ts_event_type event_type; |
| u8 clear_count1; |
| u8 clear_count2; |
| u8 fp_flag; /* finger print DOWN flag */ |
| u8 request_code; /* represent the request type */ |
| u8 request_data[GOODIX_REQUEST_DATA_LEN]; |
| struct goodix_gesture_data gesture_data; |
| struct goodix_touch_data touch_data; |
| struct goodix_pen_data pen_data; |
| struct goodix_status_data status_data; |
| }; |
| |
| struct goodix_ts_event_data { |
| u8 reserved1 : 1; |
| u8 status_changed : 1; |
| u8 reserved2 : 1; |
| u8 fp_flag : 1; |
| u8 type : 4; |
| u8 int_count; |
| u8 reserved3; |
| u8 reserved4 : 4; |
| u8 clear_count1 : 4; |
| u8 reserved5; |
| u8 reserved6 : 4; |
| u8 clear_count2 : 4; |
| }; |
| |
| struct goodix_ts_request_event_data { |
| u8 reserved1 : 1; |
| u8 status_changed : 1; |
| u8 reserved2 : 1; |
| u8 fp_flag : 1; |
| u8 type : 4; |
| u8 int_count; |
| u8 request_type; |
| u8 reserved3; |
| u8 reserved4; |
| u8 data_len; |
| u16 checksum; |
| u8 data[GOODIX_REQUEST_DATA_LEN]; |
| }; |
| |
| struct goodix_ts_touch_event_data { |
| u8 reserved1 : 1; |
| u8 status_changed : 1; |
| u8 reserved2 : 1; |
| u8 fp_flag : 1; |
| u8 type : 4; |
| u8 int_count; |
| u8 touches : 4; |
| u8 large_touch : 1; |
| u8 hover_approach_flag : 1; |
| u8 edge_flag : 1; |
| u8 reset_int : 1; |
| u8 custom_coor_info_flag : 1; |
| u8 reserved3 : 3; |
| u8 clear_count1 : 4; |
| u8 reserved4; |
| u8 reserved5 : 4; |
| u8 clear_count2 : 4; |
| u16 checksum; |
| u8 data[0]; |
| }; |
| |
| struct goodix_ts_gesture_event_data { |
| u8 reserved1 : 1; |
| u8 status_changed : 1; |
| u8 reserved2 : 1; |
| u8 fp_flag : 1; |
| u8 type : 4; |
| u8 int_count; |
| u8 reserved3 : 4; |
| u8 large_touch : 1; |
| u8 hover_approach_flag : 1; |
| u8 edge_flag : 1; |
| u8 reset_int : 1; |
| u8 touches; |
| u8 gesture_type; |
| u8 reserved4; |
| u16 checksum; |
| u8 data[GOODIX_GESTURE_DATA_LEN]; |
| }; |
| |
| struct goodix_mutual_data { |
| uint16_t duration; |
| uint16_t tx1_freq; |
| uint16_t tx2_freq; |
| uint16_t res; |
| uint16_t data[0]; |
| }; |
| |
| struct goodix_self_sensing_data { |
| uint16_t tx_duration; |
| uint16_t rx_duration; |
| uint16_t tx_freq; |
| uint16_t rx_freq; |
| uint16_t res; |
| uint16_t data[0]; |
| }; |
| |
| struct goodix_rx_package { |
| uint8_t header[8]; |
| uint16_t data[0]; |
| }; |
| |
| enum goodix_ic_bus_type { |
| GOODIX_BUS_TYPE_I2C, |
| GOODIX_BUS_TYPE_SPI, |
| GOODIX_BUS_TYPE_I3C, |
| }; |
| |
| struct goodix_bus_interface { |
| int bus_type; |
| int ic_type; |
| int sub_ic_type; |
| struct device *dev; |
| u8 *rx_buf; |
| u8 *tx_buf; |
| struct mutex mutex; |
| bool dma_mode_enabled; |
| int (*read)(struct device *dev, unsigned int addr, unsigned char *data, |
| unsigned int len); |
| int (*read_fast)(struct device *dev, unsigned int addr, |
| struct goodix_rx_package *package, unsigned int len); |
| int (*write)(struct device *dev, unsigned int addr, unsigned char *data, |
| unsigned int len); |
| }; |
| |
| struct goodix_ts_hw_ops { |
| int (*power_on)(struct goodix_ts_core *cd, bool on); |
| int (*resume)(struct goodix_ts_core *cd); |
| int (*suspend)(struct goodix_ts_core *cd); |
| int (*gesture)(struct goodix_ts_core *cd, int gesture_type); |
| int (*reset)(struct goodix_ts_core *cd, int delay_ms); |
| int (*irq_enable)(struct goodix_ts_core *cd, bool enable); |
| int (*disable_irq_nosync)(struct goodix_ts_core *cd); |
| int (*read)(struct goodix_ts_core *cd, unsigned int addr, |
| unsigned char *data, unsigned int len); |
| int (*read_fast)(struct goodix_ts_core *cd, unsigned int addr, |
| struct goodix_rx_package *package, unsigned int len); |
| int (*write)(struct goodix_ts_core *cd, unsigned int addr, |
| unsigned char *data, unsigned int len); |
| int (*send_cmd)(struct goodix_ts_core *cd, struct goodix_ts_cmd *cmd); |
| int (*send_config)(struct goodix_ts_core *cd, u8 *config, int len); |
| int (*read_config)( |
| struct goodix_ts_core *cd, u8 *config_data, int size); |
| int (*read_version)( |
| struct goodix_ts_core *cd, struct goodix_fw_version *version); |
| int (*get_ic_info)( |
| struct goodix_ts_core *cd, struct goodix_ic_info *ic_info); |
| int (*esd_check)(struct goodix_ts_core *cd); |
| int (*event_handler)( |
| struct goodix_ts_core *cd, struct goodix_ts_event *ts_event); |
| int (*after_event_handler)(struct goodix_ts_core *cd); |
| int (*get_capacitance_data)( |
| struct goodix_ts_core *cd, struct ts_rawdata_info *info); |
| int (*ping)(struct goodix_ts_core *cd); |
| int (*get_scan_mode)(struct goodix_ts_core *cd, enum raw_scan_mode* mode); |
| int (*set_scan_mode)(struct goodix_ts_core *cd, enum raw_scan_mode mode); |
| int (*set_continuously_report_enabled)( |
| struct goodix_ts_core *cd, bool enabled); |
| int (*set_heatmap_enabled)(struct goodix_ts_core *cd, bool enabled); |
| int (*set_palm_enabled)(struct goodix_ts_core *cd, bool enabled); |
| int (*get_palm_enabled)(struct goodix_ts_core *cd, bool* enabled); |
| int (*set_grip_enabled)(struct goodix_ts_core *cd, bool enabled); |
| int (*get_grip_enabled)(struct goodix_ts_core *cd, bool* enabled); |
| int (*set_screen_protector_mode_enabled)( |
| struct goodix_ts_core *cd, bool enabled); |
| int (*get_screen_protector_mode_enabled)( |
| struct goodix_ts_core *cd, bool* enabled); |
| int (*get_mutual_data)( |
| struct goodix_ts_core *cd, enum frame_data_type type); |
| int (*get_self_sensing_data)( |
| struct goodix_ts_core *cd, enum frame_data_type type); |
| int (*set_coord_filter_enabled)( |
| struct goodix_ts_core *cd, bool enabled); |
| int (*get_coord_filter_enabled)( |
| struct goodix_ts_core *cd, bool* enabled); |
| int (*set_report_rate)(struct goodix_ts_core *cd, u32 rate); |
| }; |
| |
| /* |
| * struct goodix_ts_esd - esd protector structure |
| * @esd_work: esd delayed work |
| * @esd_on: 1 - turn on esd protection, 0 - turn |
| * off esd protection |
| * @skip_once: skip once if the check is no need this time. |
| */ |
| struct goodix_ts_esd { |
| bool skip_once; |
| atomic_t esd_on; |
| struct delayed_work esd_work; |
| struct notifier_block esd_notifier; |
| struct goodix_ts_core *ts_core; |
| }; |
| |
| enum goodix_core_init_stage { |
| CORE_UNINIT, |
| CORE_INIT_FAIL, |
| CORE_INIT_STAGE1, |
| CORE_INIT_STAGE2 |
| }; |
| |
| struct goodix_ic_config { |
| int len; |
| u8 data[GOODIX_CFG_MAX_SIZE]; |
| }; |
| |
| struct goodix_ts_core { |
| int init_stage; |
| struct platform_device *pdev; |
| struct goodix_fw_version fw_version; |
| struct goodix_ic_info ic_info; |
| struct goodix_bus_interface *bus; |
| struct goodix_ts_board_data board_data; |
| struct touch_apis_data apis_data; |
| struct goodix_ts_hw_ops *hw_ops; |
| struct input_dev *input_dev; |
| struct input_dev *pen_dev; |
| struct mutex cmd_lock; |
| /* TODO counld we remove this from core data? */ |
| struct goodix_ts_event ts_event; |
| struct workqueue_struct *event_wq; |
| struct delayed_work monitor_gesture_work; |
| ktime_t gesture_down_timeout; |
| ktime_t gesture_up_timeout; |
| |
| /* every pointer of this array represent a kind of config */ |
| struct goodix_ic_config *ic_configs[GOODIX_MAX_CONFIG_GROUP]; |
| struct regulator *avdd; |
| struct regulator *iovdd; |
| unsigned char gesture_type; |
| struct goodix_rx_package *touch_frame_package; |
| size_t touch_frame_size; |
| uint16_t *mutual_data; |
| uint16_t *self_sensing_data; |
| uint16_t *mutual_data_manual; |
| uint16_t *self_sensing_data_manual; |
| |
| int power_on; |
| int irq; |
| size_t irq_trig_cnt; |
| |
| atomic_t irq_enabled; |
| atomic_t suspended; |
| bool screen_protector_mode_enabled; |
| /* when this flag is true, driver should not clean the sync flag */ |
| bool tools_ctrl_sync; |
| |
| struct notifier_block ts_notifier; |
| struct goodix_ts_esd ts_esd; |
| |
| #if IS_ENABLED(CONFIG_FB) |
| struct notifier_block fb_notifier; |
| #endif |
| #if IS_ENABLED(CONFIG_TOUCHSCREEN_MOTION_FILTER) |
| struct touch_mf tmf; |
| #endif |
| #if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE) |
| struct goog_touch_interface *gti; |
| #endif |
| |
| /* Time that the event was first received from the touch IC, |
| * acquired during hard interrupt, in CLOCK_MONOTONIC. |
| */ |
| ktime_t isr_timestamp; |
| ktime_t coords_timestamp; |
| }; |
| |
| /* external module structures */ |
| enum goodix_ext_priority { |
| EXTMOD_PRIO_RESERVED = 0, |
| EXTMOD_PRIO_FWUPDATE, |
| EXTMOD_PRIO_GESTURE, |
| EXTMOD_PRIO_HOTKNOT, |
| EXTMOD_PRIO_DBGTOOL, |
| EXTMOD_PRIO_DEFAULT, |
| }; |
| |
| #define EVT_HANDLED 0 |
| #define EVT_CONTINUE 0 |
| #define EVT_CANCEL 1 |
| #define EVT_CANCEL_IRQEVT 1 |
| #define EVT_CANCEL_SUSPEND 1 |
| #define EVT_CANCEL_RESUME 1 |
| #define EVT_CANCEL_RESET 1 |
| |
| struct goodix_ext_module; |
| /* external module's operations callback */ |
| struct goodix_ext_module_funcs { |
| int (*init)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*exit)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*before_reset)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*after_reset)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*before_suspend)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*after_suspend)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*before_resume)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*after_resume)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| int (*irq_event)(struct goodix_ts_core *core_data, |
| struct goodix_ext_module *module); |
| }; |
| |
| /* |
| * struct goodix_ext_module - external module struct |
| * @list: list used to link into modules manager |
| * @name: name of external module |
| * @priority: module priority value, zero is invalid |
| * @funcs: operations callback |
| * @priv_data: private data region |
| * @kobj: kobject |
| * @work: used to queue one work to do registration |
| */ |
| struct goodix_ext_module { |
| struct list_head list; |
| char *name; |
| enum goodix_ext_priority priority; |
| const struct goodix_ext_module_funcs *funcs; |
| void *priv_data; |
| struct kobject kobj; |
| struct work_struct work; |
| }; |
| |
| /* |
| * struct goodix_ext_attribute - exteranl attribute struct |
| * @attr: attribute |
| * @show: show interface of external attribute |
| * @store: store interface of external attribute |
| */ |
| struct goodix_ext_attribute { |
| struct attribute attr; |
| ssize_t (*show)(struct goodix_ext_module *module, char *buf); |
| ssize_t (*store)( |
| struct goodix_ext_module *module, const char *buf, size_t len); |
| }; |
| |
| /* external attrs helper macro */ |
| #define __EXTMOD_ATTR(_name, _mode, _show, _store) \ |
| { \ |
| .attr = { .name = __stringify(_name), .mode = _mode }, \ |
| .show = _show, .store = _store, \ |
| } |
| |
| /* external attrs helper macro, used to define external attrs */ |
| #define DEFINE_EXTMOD_ATTR(_name, _mode, _show, _store) \ |
| static struct goodix_ext_attribute ext_attr_##_name = \ |
| __EXTMOD_ATTR(_name, _mode, _show, _store) |
| |
| /* log macro */ |
| extern bool debug_log_flag; |
| #define ts_info(fmt, arg...) \ |
| pr_info("[GTP-INF][%s:%d] " fmt "\n", __func__, __LINE__, ##arg) |
| #define ts_err(fmt, arg...) \ |
| pr_err("[GTP-ERR][%s:%d] " fmt "\n", __func__, __LINE__, ##arg) |
| #define ts_debug(fmt, arg...) \ |
| { \ |
| if (debug_log_flag) \ |
| pr_info("[GTP-DBG][%s:%d] " fmt "\n", __func__, \ |
| __LINE__, ##arg); \ |
| } |
| |
| /* |
| * get board data pointer |
| */ |
| static inline struct goodix_ts_board_data *board_data( |
| struct goodix_ts_core *core) |
| { |
| if (!core) |
| return NULL; |
| return &(core->board_data); |
| } |
| |
| /** |
| * goodix_register_ext_module - interface for external module |
| * to register into touch core modules structure |
| * |
| * @module: pointer to external module to be register |
| * return: 0 ok, <0 failed |
| */ |
| int goodix_register_ext_module(struct goodix_ext_module *module); |
| /* register module no wait */ |
| int goodix_register_ext_module_no_wait(struct goodix_ext_module *module); |
| /** |
| * goodix_unregister_ext_module - interface for external module |
| * to unregister external modules |
| * |
| * @module: pointer to external module |
| * return: 0 ok, <0 failed |
| */ |
| int goodix_unregister_ext_module(struct goodix_ext_module *module); |
| /* remove all registered ext module |
| * return 0 on success, otherwise return < 0 |
| */ |
| int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v); |
| struct kobj_type *goodix_get_default_ktype(void); |
| struct kobject *goodix_get_default_kobj(void); |
| |
| struct goodix_ts_hw_ops *goodix_get_hw_ops(void); |
| int goodix_get_config_proc(struct goodix_ts_core *cd); |
| |
| int goodix_spi_bus_init(void); |
| void goodix_spi_bus_exit(void); |
| int goodix_i2c_bus_init(void); |
| void goodix_i2c_bus_exit(void); |
| |
| u32 goodix_append_checksum(u8 *data, int len, int mode); |
| int checksum_cmp(const u8 *data, int size, int mode); |
| int is_risk_data(const u8 *data, int size); |
| u32 goodix_get_file_config_id(u8 *ic_config); |
| void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest); |
| |
| int goodix_fw_update_init(struct goodix_ts_core *core_data); |
| void goodix_fw_update_uninit(void); |
| int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode); |
| |
| int goodix_get_ic_type( |
| struct device_node *node, struct goodix_bus_interface *bus_inf); |
| int gesture_module_init(void); |
| void gesture_module_exit(void); |
| int inspect_module_init(void); |
| void inspect_module_exit(void); |
| int goodix_tools_init(void); |
| void goodix_tools_exit(void); |
| |
| int driver_test_selftest(char* buf); |
| int driver_test_proc_init(struct goodix_ts_core *core_data); |
| void driver_test_proc_remove(void); |
| int goodix_do_inspect(struct goodix_ts_core *cd, struct ts_rawdata_info *info); |
| void goodix_ts_report_status(struct goodix_ts_core *core_data, |
| struct goodix_ts_event *ts_event); |
| int goodix_update_pen_freq(struct goodix_ts_core *cd, u8 *data, int len); |
| |
| #endif |