mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Update goodix berlin code to V1.1.21
TP: Update goodix berlin driver code to V1.1.21. Change-Id: I56ac06c10f7c3ea9bb3bf936fe8e791f8753740a Reviewed-on: https://gerrit.mot.com/2027427 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jichao Zou <zoujc@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
05c923e833
commit
d7e576198b
20 changed files with 4629 additions and 1038 deletions
|
|
@ -5,9 +5,4 @@ include $(CLEAR_VARS)
|
|||
LOCAL_MODULE := goodix_brl_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
ifneq ($(findstring goodix_brl_i2c.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/goodix_brl_i2c.ko
|
||||
else
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/goodix_brl_spi.ko
|
||||
endif
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
17
drivers/input/touchscreen/goodix_berlin_mmi/Kbuild
Normal file
17
drivers/input/touchscreen/goodix_berlin_mmi/Kbuild
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include
|
||||
|
||||
obj-m := goodix_brl_mmi.o
|
||||
goodix_brl_mmi-objs := \
|
||||
goodix_brl_i2c.o \
|
||||
goodix_brl_spi.o \
|
||||
goodix_ts_core.o \
|
||||
goodix_brl_hw.o \
|
||||
goodix_cfg_bin.o \
|
||||
goodix_ts_utils.o \
|
||||
goodix_brl_fwupdate.o \
|
||||
goodix_ts_gesture.o \
|
||||
goodix_ts_inspect.o \
|
||||
goodix_ts_tools.o
|
||||
36
drivers/input/touchscreen/goodix_berlin_mmi/Kconfig
Executable file → Normal file
36
drivers/input/touchscreen/goodix_berlin_mmi/Kconfig
Executable file → Normal file
|
|
@ -3,48 +3,18 @@
|
|||
#
|
||||
menuconfig TOUCHSCREEN_GOODIX_BRL
|
||||
tristate "Goodix berlin touchscreen"
|
||||
default y
|
||||
help
|
||||
Say Y here if you have a Goodix berlin series touch controller
|
||||
to your system.
|
||||
|
||||
If build module, say M.
|
||||
If unsure, say N.
|
||||
|
||||
if TOUCHSCREEN_GOODIX_BRL
|
||||
config TOUCHSCREEN_GOODIX_BRL_I2C
|
||||
tristate "support I2C bus connection"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here if the touchscreen is connected via I2C bus.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config TOUCHSCREEN_GOODIX_BRL_SPI
|
||||
tristate "support SPI bus connection"
|
||||
depends on SPI_MASTER
|
||||
bool "support SPI bus connection"
|
||||
help
|
||||
Say Y here if the touchscreen is connected via SPI bus.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config TOUCHSCREEN_GOODIX_TS_TOOLS
|
||||
tristate "Goodix debug tools support"
|
||||
default y
|
||||
help
|
||||
Say Y here to enable debug tools.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
config TOUCHSCREEN_GOODIX_TS_GESTURE
|
||||
tristate "Goodix gesture support"
|
||||
default y
|
||||
help
|
||||
Say Y here to enable gesture.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
To compile this driver as a module, choose M here.
|
||||
Say Y here if the touchscreen is connected via SPI bus.
|
||||
|
||||
endif
|
||||
|
|
|
|||
20
drivers/input/touchscreen/goodix_berlin_mmi/Makefile
Executable file → Normal file
20
drivers/input/touchscreen/goodix_berlin_mmi/Makefile
Executable file → Normal file
|
|
@ -1,6 +1,14 @@
|
|||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BRL_I2C) += goodix_brl_i2c.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI) += goodix_brl_spi.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_BRL) += goodix_core.o
|
||||
goodix_core-y := goodix_ts_core.o goodix_brl_hw.o goodix_cfg_bin.o goodix_ts_utils.o goodix_brl_fwupdate.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_TS_TOOLS) += goodix_ts_tools.o
|
||||
obj-$(CONFIG_TOUCHSCREEN_GOODIX_TS_GESTURE) += goodix_ts_gesture.o
|
||||
all: modules
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
ifneq ($(findstring goodix_brl_i2c.ko,$(BOARD_VENDOR_KERNEL_MODULES)),)
|
||||
KERNEL_CFLAGS += CONFIG_USE_TOUCHSCREEN_MMI_I2C=y
|
||||
LOCAL_MODULE := goodix_brl_i2c.ko
|
||||
else
|
||||
LOCAL_MODULE := goodix_brl_spi.ko
|
||||
endif
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/input/touchscreen/goodix_berlin_mmi/include
|
||||
|
||||
ifneq ($(filter m y,$(CONFIG_USE_TOUCHSCREEN_MMI_I2C)),)
|
||||
obj-m = goodix_brl_i2c.o
|
||||
else
|
||||
obj-m = goodix_brl_spi.o
|
||||
endif
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/input/touchscreen/goodix_berlin_mmi/include
|
||||
|
||||
obj-m += goodix_brl_mmi.o
|
||||
|
||||
goodix_brl_mmi-objs := goodix_brl_fwupdate.o goodix_brl_hw.o goodix_cfg_bin.o goodix_ts_core.o goodix_ts_utils.o
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../goodix_brl_bus/Module.symvers
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
DLKM_DIR := motorola/kernel/modules
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := goodix_brl_tools_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/goodix_brl_mmi.ko
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := goodix_brl_gesture_mmi.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(KERNEL_MODULES_OUT)/goodix_brl_mmi.ko
|
||||
include $(DLKM_DIR)/AndroidKernelModule.mk
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
# add -Wall to try to catch everything we can.
|
||||
EXTRA_CFLAGS += -Wall
|
||||
EXTRA_CFLAGS += \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/include \
|
||||
-I$(ANDROID_BUILD_TOP)/motorola/kernel/modules/drivers/input/touchscreen/goodix_berlin_mmi/include
|
||||
|
||||
obj-m += goodix_brl_tools_mmi.o
|
||||
goodix_brl_tools_mmi-objs = goodix_ts_tools.o
|
||||
|
||||
obj-m += goodix_brl_gesture_mmi.o
|
||||
goodix_brl_gesture_mmi-objs = goodix_ts_gesture.o
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../goodix_brl_core/Module.symvers
|
||||
|
||||
|
|
@ -16,56 +16,130 @@
|
|||
*/
|
||||
#include "goodix_ts_core.h"
|
||||
|
||||
#define TS_DEFAULT_FIRMWARE "goodix_firmware.bin"
|
||||
#define BUS_TYPE_SPI 1
|
||||
#define BUS_TYPE_I2C 0
|
||||
|
||||
#define BUS_TYPE_SPI 0x01
|
||||
#define BUS_TYPE_I2C 0
|
||||
#define GOODIX_BUS_RETRY_TIMES 3
|
||||
|
||||
#define GOODIX_BUS_RETRY_TIMES 3
|
||||
#define FW_HEADER_SIZE_BRA 256
|
||||
#define FW_HEADER_SIZE 512
|
||||
#define FW_SUBSYS_INFO_SIZE 10
|
||||
#define FW_SUBSYS_INFO_OFFSET_BRA 36
|
||||
#define FW_SUBSYS_INFO_OFFSET 42
|
||||
#define FW_SUBSYS_MAX_NUM 47
|
||||
|
||||
#define FW_HEADER_SIZE 256
|
||||
#define FW_SUBSYS_INFO_SIZE 10
|
||||
#define FW_SUBSYS_INFO_OFFSET 36
|
||||
#define FW_SUBSYS_MAX_NUM 28
|
||||
#define ISP_MAX_BUFFERSIZE 4096
|
||||
|
||||
#define ISP_MAX_BUFFERSIZE (1024 * 4)
|
||||
#define FW_PID_LEN 8
|
||||
#define FW_VID_LEN 4
|
||||
#define FLASH_CMD_LEN 11
|
||||
|
||||
#define NO_NEED_UPDATE 99
|
||||
#define FW_FILE_CHECKSUM_OFFSET 8
|
||||
#define CONFIG_DATA_TYPE 4
|
||||
|
||||
#define FW_PID_LEN 8
|
||||
#define FW_VID_LEN 4
|
||||
#define FLASH_CMD_LEN 11
|
||||
#define ISP_RAM_ADDR_BRA 0x18400
|
||||
#define ISP_RAM_ADDR_BRB 0x57000
|
||||
#define ISP_RAM_ADDR_BRD 0x23800
|
||||
#define HW_REG_CPU_RUN_FROM 0x10000
|
||||
#define FLASH_CMD_REG_BRA 0x10400
|
||||
#define FLASH_CMD_REG_BRB 0x13400
|
||||
#define FLASH_CMD_REG_BRD 0x12400
|
||||
#define HW_REG_ISP_BUFFER_BRA 0x10410
|
||||
#define HW_REG_ISP_BUFFER_BRB 0x13410
|
||||
#define HW_REG_ISP_BUFFER_BRD 0x12410
|
||||
#define CONFIG_DATA_ADDR_BRA 0x3E000
|
||||
#define CONFIG_DATA_ADDR_BRB 0x40000
|
||||
#define CONFIG_DATA_ADDR_BRD 0x3E000
|
||||
#define GOODIX_CFG_ID_ADDR_BRA 0x1006E
|
||||
#define GOODIX_CFG_ID_ADDR_BRB 0x10076
|
||||
#define GOODIX_CFG_ID_ADDR_BRD 0x10076
|
||||
|
||||
#define FW_FILE_CHECKSUM_OFFSET 8
|
||||
#define CONFIG_ID_OFFSET 30
|
||||
#define CONFIG_DATA_TYPE 4
|
||||
#define HOLD_CPU_REG_W 0x0002
|
||||
#define HOLD_CPU_REG_R 0x2000
|
||||
#define MISCTL_REG_BRA 0xD807
|
||||
#define MISCTL_REG_BRB 0xD80B
|
||||
#define MISCTL_REG_BRD 0xD804
|
||||
#define ENABLE_MISCTL_BRA 0x08
|
||||
#define ENABLE_MISCTL_BRB 0x40
|
||||
#define ENABLE_MISCTL_BRD 0x20700000
|
||||
#define ESD_KEY_REG 0xCC58
|
||||
#define WATCH_DOG_REG_BRA 0xCC54
|
||||
#define WATCH_DOG_REG_BRB 0xD054
|
||||
#define WATCH_DOG_REG_BRD 0xD040
|
||||
|
||||
#define ISP_RAM_ADDR 0x18400
|
||||
#define HW_REG_CPU_RUN_FROM 0x10000
|
||||
#define FLASH_CMD_REG 0x10400
|
||||
#define HW_REG_ISP_BUFFER 0x10410
|
||||
#define CONFIG_DATA_ADDR 0x3E000
|
||||
#define FLASH_CMD_TYPE_READ 0xAA
|
||||
#define FLASH_CMD_TYPE_WRITE 0xBB
|
||||
#define FLASH_CMD_ACK_CHK_PASS 0xEE
|
||||
#define FLASH_CMD_ACK_CHK_ERROR 0x33
|
||||
#define FLASH_CMD_ACK_IDLE 0x11
|
||||
#define FLASH_CMD_W_STATUS_CHK_PASS 0x22
|
||||
#define FLASH_CMD_W_STATUS_CHK_FAIL 0x33
|
||||
#define FLASH_CMD_W_STATUS_ADDR_ERR 0x44
|
||||
#define FLASH_CMD_W_STATUS_WRITE_ERR 0x55
|
||||
#define FLASH_CMD_W_STATUS_WRITE_OK 0xEE
|
||||
|
||||
#define HOLD_CPU_REG_W 0x0002
|
||||
#define HOLD_CPU_REG_R 0x2000
|
||||
#define MISCTL_REG 0xD807
|
||||
#define ESD_KEY_REG 0xCC58
|
||||
#define WATCH_DOG_REG 0xCC54
|
||||
#define CHIP_TYPE_BRA 0x96
|
||||
#define CHIP_TYPE_BRB 0x97
|
||||
#define CHIP_TYPE_BRD 0x98
|
||||
|
||||
|
||||
#define FLASH_CMD_TYPE_READ 0xAA
|
||||
#define FLASH_CMD_TYPE_WRITE 0xBB
|
||||
#define FLASH_CMD_ACK_CHK_PASS 0xEE
|
||||
#define FLASH_CMD_ACK_CHK_ERROR 0x33
|
||||
#define FLASH_CMD_ACK_IDLE 0x11
|
||||
#define FLASH_CMD_W_STATUS_CHK_PASS 0x22
|
||||
#define FLASH_CMD_W_STATUS_CHK_FAIL 0x33
|
||||
#define FLASH_CMD_W_STATUS_ADDR_ERR 0x44
|
||||
#define FLASH_CMD_W_STATUS_WRITE_ERR 0x55
|
||||
#define FLASH_CMD_W_STATUS_WRITE_OK 0xEE
|
||||
struct update_info_t {
|
||||
int header_size;
|
||||
int subsys_info_offset;
|
||||
u32 isp_ram_reg;
|
||||
u32 flash_cmd_reg;
|
||||
u32 isp_buffer_reg;
|
||||
u32 config_data_reg;
|
||||
u32 misctl_reg;
|
||||
u32 watch_dog_reg;
|
||||
u32 config_id_reg;
|
||||
u32 enable_misctl_val;
|
||||
};
|
||||
|
||||
/* berlinA update into */
|
||||
struct update_info_t update_bra = {
|
||||
FW_HEADER_SIZE_BRA,
|
||||
FW_SUBSYS_INFO_OFFSET_BRA,
|
||||
ISP_RAM_ADDR_BRA,
|
||||
FLASH_CMD_REG_BRA,
|
||||
HW_REG_ISP_BUFFER_BRA,
|
||||
CONFIG_DATA_ADDR_BRA,
|
||||
MISCTL_REG_BRA,
|
||||
WATCH_DOG_REG_BRA,
|
||||
GOODIX_CFG_ID_ADDR_BRA,
|
||||
ENABLE_MISCTL_BRA,
|
||||
};
|
||||
|
||||
/* berlinB update info */
|
||||
struct update_info_t update_brb = {
|
||||
FW_HEADER_SIZE,
|
||||
FW_SUBSYS_INFO_OFFSET,
|
||||
ISP_RAM_ADDR_BRB,
|
||||
FLASH_CMD_REG_BRB,
|
||||
HW_REG_ISP_BUFFER_BRB,
|
||||
CONFIG_DATA_ADDR_BRB,
|
||||
MISCTL_REG_BRB,
|
||||
WATCH_DOG_REG_BRB,
|
||||
GOODIX_CFG_ID_ADDR_BRB,
|
||||
ENABLE_MISCTL_BRB,
|
||||
};
|
||||
|
||||
/* berlinD update info */
|
||||
struct update_info_t update_brd = {
|
||||
FW_HEADER_SIZE,
|
||||
FW_SUBSYS_INFO_OFFSET,
|
||||
ISP_RAM_ADDR_BRD,
|
||||
FLASH_CMD_REG_BRD,
|
||||
HW_REG_ISP_BUFFER_BRD,
|
||||
CONFIG_DATA_ADDR_BRD,
|
||||
MISCTL_REG_BRD,
|
||||
WATCH_DOG_REG_BRD,
|
||||
GOODIX_CFG_ID_ADDR_BRD,
|
||||
ENABLE_MISCTL_BRD,
|
||||
};
|
||||
|
||||
/**
|
||||
* fw_subsys_info - subsytem firmware infomation
|
||||
* fw_subsys_info - subsytem firmware information
|
||||
* @type: sybsystem type
|
||||
* @size: firmware size
|
||||
* @flash_addr: flash address
|
||||
|
|
@ -106,14 +180,14 @@ struct firmware_summary {
|
|||
u8 protocol_ver;
|
||||
u8 bus_type;
|
||||
u8 flash_protect;
|
||||
u8 reserved[2];
|
||||
// u8 reserved[8];
|
||||
struct fw_subsys_info subsys[FW_SUBSYS_MAX_NUM];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
* firmware_data - firmware data structure
|
||||
* @fw_summary: firmware infomation
|
||||
* @fw_summary: firmware information
|
||||
* @firmware: firmware data structure
|
||||
*/
|
||||
struct firmware_data {
|
||||
|
|
@ -128,24 +202,40 @@ struct config_data {
|
|||
|
||||
#pragma pack(1)
|
||||
struct goodix_flash_cmd {
|
||||
union {
|
||||
struct {
|
||||
u8 status;
|
||||
u8 ack;
|
||||
u8 len;
|
||||
u8 cmd;
|
||||
u8 fw_type;
|
||||
u16 fw_len;
|
||||
u32 fw_addr;
|
||||
//u16 checksum;
|
||||
union {
|
||||
struct {
|
||||
u8 status;
|
||||
u8 ack;
|
||||
u8 len;
|
||||
u8 cmd;
|
||||
u8 fw_type;
|
||||
u16 fw_len;
|
||||
u32 fw_addr;
|
||||
//u16 checksum;
|
||||
};
|
||||
u8 buf[16];
|
||||
};
|
||||
u8 buf[16];
|
||||
};
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
enum update_status {
|
||||
UPSTA_NOTWORK = 0,
|
||||
UPSTA_PREPARING,
|
||||
UPSTA_UPDATING,
|
||||
UPSTA_SUCCESS,
|
||||
UPSTA_FAILED
|
||||
};
|
||||
|
||||
enum compare_status {
|
||||
COMPARE_EQUAL = 0,
|
||||
COMPARE_NOCODE,
|
||||
COMPARE_PIDMISMATCH,
|
||||
COMPARE_FW_NOTEQUAL,
|
||||
COMPARE_CFG_NOTEQUAL,
|
||||
};
|
||||
|
||||
/**
|
||||
* fw_update_ctrl - sturcture used to control the
|
||||
* fw_update_ctrl - structure used to control the
|
||||
* firmware update process
|
||||
* @initialized: struct init state
|
||||
* @mode: indicate weather reflash config or not, fw data source,
|
||||
|
|
@ -163,10 +253,13 @@ struct fw_update_ctrl {
|
|||
int initialized;
|
||||
char fw_name[GOODIX_MAX_STR_LABLE_LEN];
|
||||
int mode;
|
||||
enum update_status status;
|
||||
int spend_time;
|
||||
|
||||
struct firmware_data fw_data;
|
||||
struct goodix_ic_config *ic_config;
|
||||
struct goodix_ts_core *core_data;
|
||||
struct update_info_t *update_info;
|
||||
|
||||
struct bin_attribute attr_fwimage;
|
||||
struct kobject *kobj;
|
||||
|
|
@ -211,8 +304,8 @@ static int goodix_reg_read(unsigned int addr,
|
|||
}
|
||||
|
||||
/**
|
||||
* goodix_parse_firmware - parse firmware header infomation
|
||||
* and subsystem infomation from firmware data buffer
|
||||
* goodix_parse_firmware - parse firmware header information
|
||||
* and subsystem information from firmware data buffer
|
||||
*
|
||||
* @fw_data: firmware struct, contains firmware header info
|
||||
* and firmware data.
|
||||
|
|
@ -226,13 +319,19 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
|
|||
struct firmware_summary *fw_summary;
|
||||
unsigned int i, fw_offset, info_offset;
|
||||
u32 checksum;
|
||||
int ic_type =
|
||||
goodix_fw_update_ctrl.core_data->bus->ic_type;
|
||||
int subsys_info_offset =
|
||||
goodix_fw_update_ctrl.update_info->subsys_info_offset;
|
||||
int header_size =
|
||||
goodix_fw_update_ctrl.update_info->header_size;
|
||||
int r = 0;
|
||||
|
||||
fw_summary = &fw_data->fw_summary;
|
||||
|
||||
/* copy firmware head info */
|
||||
firmware = fw_data->firmware;
|
||||
if (firmware->size < FW_SUBSYS_INFO_OFFSET) {
|
||||
if (firmware->size < subsys_info_offset) {
|
||||
ts_err("Invalid firmware size:%zu", firmware->size);
|
||||
r = -EINVAL;
|
||||
goto err_size;
|
||||
|
|
@ -249,7 +348,7 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
|
|||
}
|
||||
|
||||
for (i = FW_FILE_CHECKSUM_OFFSET, checksum = 0;
|
||||
i < firmware->size; i+=2)
|
||||
i < firmware->size; i += 2)
|
||||
checksum += firmware->data[i] + (firmware->data[i+1] << 8);
|
||||
|
||||
/* byte order change, and check */
|
||||
|
|
@ -268,9 +367,9 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
|
|||
}
|
||||
|
||||
/* parse subsystem info */
|
||||
fw_offset = FW_HEADER_SIZE;
|
||||
fw_offset = header_size;
|
||||
for (i = 0; i < fw_summary->subsys_num; i++) {
|
||||
info_offset = FW_SUBSYS_INFO_OFFSET +
|
||||
info_offset = subsys_info_offset +
|
||||
i * FW_SUBSYS_INFO_SIZE;
|
||||
|
||||
fw_summary->subsys[i].type = firmware->data[info_offset];
|
||||
|
|
@ -289,9 +388,9 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
|
|||
}
|
||||
|
||||
ts_info("Firmware package protocol: V%u", fw_summary->protocol_ver);
|
||||
ts_info("Fimware PID:GT%s", fw_summary->fw_pid);
|
||||
ts_info("Fimware VID:%*ph", 4, fw_summary->fw_vid);
|
||||
ts_info("Firmware chip type:%02X", fw_summary->chip_type);
|
||||
ts_info("Firmware PID:GT%s", fw_summary->fw_pid);
|
||||
ts_info("Firmware VID:%*ph", 4, fw_summary->fw_vid);
|
||||
ts_info("Firmware chip type:0x%02X", fw_summary->chip_type);
|
||||
ts_info("Firmware bus type:%s",
|
||||
(fw_summary->bus_type & BUS_TYPE_SPI) ? "SPI" : "I2C");
|
||||
ts_info("Firmware size:%u", fw_summary->size);
|
||||
|
|
@ -307,6 +406,20 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
|
|||
ts_debug("Subsystem Ptr:%p", fw_summary->subsys[i].data);
|
||||
}
|
||||
|
||||
if (fw_summary->chip_type == CHIP_TYPE_BRA &&
|
||||
ic_type != IC_TYPE_BERLIN_A) {
|
||||
ts_err("ic type mismatch!");
|
||||
r = -EINVAL;
|
||||
} else if (fw_summary->chip_type == CHIP_TYPE_BRB &&
|
||||
ic_type != IC_TYPE_BERLIN_B) {
|
||||
ts_err("ic type mismatch!");
|
||||
r = -EINVAL;
|
||||
} else if (fw_summary->chip_type == CHIP_TYPE_BRD &&
|
||||
ic_type != IC_TYPE_BERLIN_D) {
|
||||
ts_err("ic type mismatch!");
|
||||
r = -EINVAL;
|
||||
}
|
||||
|
||||
err_size:
|
||||
return r;
|
||||
}
|
||||
|
|
@ -314,39 +427,61 @@ err_size:
|
|||
/**
|
||||
* goodix_fw_version_compare - compare the active version with
|
||||
* firmware file version.
|
||||
* @fwu_ctrl: firmware infomation to be compared
|
||||
* @fwu_ctrl: firmware information to be compared
|
||||
* return: 0 equal, < 0 unequal
|
||||
*/
|
||||
#define GOODIX_NOCODE "NOCODE"
|
||||
static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl)
|
||||
{
|
||||
int ret = 0;
|
||||
struct goodix_fw_version fw_version = {{0}};
|
||||
struct goodix_fw_version fw_version;
|
||||
struct firmware_summary *fw_summary = &fwu_ctrl->fw_data.fw_summary;
|
||||
u32 config_id_reg = goodix_fw_update_ctrl.update_info->config_id_reg;
|
||||
u32 file_cfg_id;
|
||||
u32 ic_cfg_id;
|
||||
|
||||
/* compare fw_version */
|
||||
ret = get_fw_version_info(&fw_version);
|
||||
if (ret) {
|
||||
ts_info("failed get active fw version");
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (!memcmp(fw_version.rom_pid, GOODIX_NOCODE, 6) ||
|
||||
!memcmp(fw_version.patch_pid, GOODIX_NOCODE, 6)) {
|
||||
ts_info("there is no code in the chip");
|
||||
return COMPARE_NOCODE;
|
||||
}
|
||||
|
||||
if (memcmp(fw_version.patch_pid, fw_summary->fw_pid, FW_PID_LEN)) {
|
||||
ts_err("Product ID mismatch:%s:%s",
|
||||
ts_err("Product ID mismatch:%s != %s",
|
||||
fw_version.patch_pid, fw_summary->fw_pid);
|
||||
return -EINVAL;
|
||||
return COMPARE_PIDMISMATCH;
|
||||
}
|
||||
|
||||
|
||||
ret = memcmp(fw_version.patch_vid, fw_summary->fw_vid, FW_VID_LEN);
|
||||
if (ret) {
|
||||
ts_info("active firmware version:%*ph", FW_VID_LEN,
|
||||
fw_version.patch_vid);
|
||||
ts_info("firmware file version: %*ph", FW_VID_LEN,
|
||||
fw_summary->fw_vid);
|
||||
return -EINVAL;
|
||||
return COMPARE_FW_NOTEQUAL;
|
||||
}
|
||||
ts_info("fw_version equal");
|
||||
|
||||
/* compare config id */
|
||||
if (fwu_ctrl->ic_config && fwu_ctrl->ic_config->len > 0) {
|
||||
file_cfg_id =
|
||||
goodix_get_file_config_id(fwu_ctrl->ic_config->data);
|
||||
goodix_reg_read(config_id_reg,
|
||||
(u8 *)&ic_cfg_id, sizeof(ic_cfg_id));
|
||||
if (ic_cfg_id != file_cfg_id) {
|
||||
ts_info("ic_cfg_id:0x%x != file_cfg_id:0x%x",
|
||||
ic_cfg_id, file_cfg_id);
|
||||
return COMPARE_CFG_NOTEQUAL;
|
||||
}
|
||||
ts_info("config_id equal");
|
||||
}
|
||||
|
||||
ts_info("Firmware version equal");
|
||||
return 0;
|
||||
return COMPARE_EQUAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -359,7 +494,8 @@ static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl)
|
|||
* return: 0 write success and confirm ok
|
||||
* < 0 failed
|
||||
*/
|
||||
static int goodix_reg_write_confirm(unsigned int addr, unsigned char *data, unsigned int len)
|
||||
static int goodix_reg_write_confirm(unsigned int addr,
|
||||
unsigned char *data, unsigned int len)
|
||||
{
|
||||
u8 *cfm = NULL;
|
||||
u8 cfm_buf[32];
|
||||
|
|
@ -367,10 +503,8 @@ static int goodix_reg_write_confirm(unsigned int addr, unsigned char *data, unsi
|
|||
|
||||
if (len > sizeof(cfm_buf)) {
|
||||
cfm = kzalloc(len, GFP_KERNEL);
|
||||
if (!cfm) {
|
||||
ts_err("Mem alloc failed");
|
||||
if (!cfm)
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
cfm = &cfm_buf[0];
|
||||
}
|
||||
|
|
@ -401,23 +535,25 @@ exit:
|
|||
|
||||
|
||||
/**
|
||||
* goodix_load_isp - load ISP program to deivce ram
|
||||
* goodix_load_isp - load ISP program to device ram
|
||||
* @dev: pointer to touch device
|
||||
* @fw_data: firmware data
|
||||
* return 0 ok, <0 error
|
||||
*/
|
||||
static int goodix_load_isp(struct firmware_data *fw_data)
|
||||
{
|
||||
struct goodix_fw_version isp_fw_version = {{0}};
|
||||
struct goodix_fw_version isp_fw_version;
|
||||
struct fw_subsys_info *fw_isp;
|
||||
u32 isp_ram_reg = goodix_fw_update_ctrl.update_info->isp_ram_reg;
|
||||
u8 reg_val[8] = {0x00};
|
||||
int r;
|
||||
|
||||
memset(&isp_fw_version, 0, sizeof(isp_fw_version));
|
||||
fw_isp = &fw_data->fw_summary.subsys[0];
|
||||
|
||||
ts_info("Loading ISP start");
|
||||
r = goodix_reg_write_confirm(ISP_RAM_ADDR,
|
||||
(u8 *)fw_isp->data, fw_isp->size);
|
||||
r = goodix_reg_write_confirm(isp_ram_reg,
|
||||
(u8 *)fw_isp->data, fw_isp->size);
|
||||
if (r < 0) {
|
||||
ts_err("Loading ISP error");
|
||||
return r;
|
||||
|
|
@ -459,6 +595,9 @@ static int goodix_load_isp(struct firmware_data *fw_data)
|
|||
*/
|
||||
static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
|
||||
{
|
||||
u32 misctl_reg = fwu_ctrl->update_info->misctl_reg;
|
||||
u32 watch_dog_reg = fwu_ctrl->update_info->watch_dog_reg;
|
||||
u32 enable_misctl_val = fwu_ctrl->update_info->enable_misctl_val;
|
||||
u8 reg_val[4] = {0};
|
||||
u8 temp_buf[64] = {0};
|
||||
int retry = 20;
|
||||
|
|
@ -494,52 +633,59 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
|
|||
ts_info("Success hold CPU");
|
||||
|
||||
/* enable misctl clock */
|
||||
reg_val[0] = 0x08;
|
||||
r = goodix_reg_write(MISCTL_REG, reg_val, 1);
|
||||
if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D)
|
||||
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 4);
|
||||
else
|
||||
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 1);
|
||||
ts_info("enbale misctl clock");
|
||||
|
||||
/* open ESD_KEY */
|
||||
retry = 20;
|
||||
do {
|
||||
reg_val[0] = 0x95;
|
||||
r = goodix_reg_write(ESD_KEY_REG, reg_val, 1);
|
||||
r |= goodix_reg_read(ESD_KEY_REG, temp_buf, 1);
|
||||
if (!r && temp_buf[0] == 0x01)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
ts_info("retry %d enable esd key, 0x%x", retry, temp_buf[0]);
|
||||
} while (--retry);
|
||||
if (!retry) {
|
||||
ts_err("Failed to enable esd key, return =%d", r);
|
||||
return -2;
|
||||
if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_A) {
|
||||
/* open ESD_KEY */
|
||||
retry = 20;
|
||||
do {
|
||||
reg_val[0] = 0x95;
|
||||
r = goodix_reg_write(ESD_KEY_REG, reg_val, 1);
|
||||
r |= goodix_reg_read(ESD_KEY_REG, temp_buf, 1);
|
||||
if (!r && temp_buf[0] == 0x01)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
ts_info("retry %d enable esd key, 0x%x",
|
||||
retry, temp_buf[0]);
|
||||
} while (--retry);
|
||||
if (!retry) {
|
||||
ts_err("Failed to enable esd key, return =%d", r);
|
||||
return -2;
|
||||
}
|
||||
ts_info("success enable esd key");
|
||||
}
|
||||
ts_info("success enable esd key");
|
||||
|
||||
/* disable watch dog */
|
||||
reg_val[0] = 0x00;
|
||||
r = goodix_reg_write(WATCH_DOG_REG, reg_val, 1);
|
||||
r = goodix_reg_write(watch_dog_reg, reg_val, 1);
|
||||
ts_info("disable watch dog");
|
||||
|
||||
/* load ISP code and run form isp */
|
||||
r = goodix_load_isp(&fwu_ctrl->fw_data);
|
||||
if (r < 0)
|
||||
ts_err("Failed lode and run isp");
|
||||
ts_err("Failed load and run isp");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* goodix_send_flash_cmd: send command to read or write flash data
|
||||
* @flash_cmd: command need to send.
|
||||
* */
|
||||
/* goodix_send_flash_cmd: send command to read or write flash data
|
||||
* @flash_cmd: command need to send.
|
||||
*/
|
||||
static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
|
||||
{
|
||||
int i, ret, retry;
|
||||
struct goodix_flash_cmd tmp_cmd;
|
||||
u32 flash_cmd_reg = goodix_fw_update_ctrl.update_info->flash_cmd_reg;
|
||||
|
||||
ts_info("try send flash cmd:%*ph", (int)sizeof(flash_cmd->buf),
|
||||
flash_cmd->buf);
|
||||
memset(tmp_cmd.buf, 0, sizeof(tmp_cmd));
|
||||
ret = goodix_reg_write(FLASH_CMD_REG, flash_cmd->buf, sizeof(flash_cmd->buf));
|
||||
ret = goodix_reg_write(flash_cmd_reg,
|
||||
flash_cmd->buf, sizeof(flash_cmd->buf));
|
||||
if (ret) {
|
||||
ts_err("failed send flash cmd %d", ret);
|
||||
return ret;
|
||||
|
|
@ -547,14 +693,17 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
|
|||
|
||||
retry = 5;
|
||||
for (i = 0; i < retry; i++) {
|
||||
ret = goodix_reg_read(FLASH_CMD_REG, tmp_cmd.buf, sizeof(tmp_cmd.buf));
|
||||
ret = goodix_reg_read(flash_cmd_reg,
|
||||
tmp_cmd.buf, sizeof(tmp_cmd.buf));
|
||||
if (!ret && tmp_cmd.ack == FLASH_CMD_ACK_CHK_PASS)
|
||||
break;
|
||||
usleep_range(5000, 5100);
|
||||
ts_info("flash cmd ack error retry %d, ack 0x%x, ret %d", i, tmp_cmd.ack, ret);
|
||||
ts_info("flash cmd ack error retry %d, ack 0x%x, ret %d",
|
||||
i, tmp_cmd.ack, ret);
|
||||
}
|
||||
if (tmp_cmd.ack != FLASH_CMD_ACK_CHK_PASS) {
|
||||
ts_err("flash cmd ack error, ack 0x%x, ret %d", tmp_cmd.ack, ret);
|
||||
ts_err("flash cmd ack error, ack 0x%x, ret %d",
|
||||
tmp_cmd.ack, ret);
|
||||
ts_err("data:%*ph", (int)sizeof(tmp_cmd.buf), tmp_cmd.buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -563,7 +712,8 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
|
|||
msleep(80);
|
||||
retry = 20;
|
||||
for (i = 0; i < retry; i++) {
|
||||
ret = goodix_reg_read(FLASH_CMD_REG, tmp_cmd.buf, sizeof(tmp_cmd.buf));
|
||||
ret = goodix_reg_read(flash_cmd_reg,
|
||||
tmp_cmd.buf, sizeof(tmp_cmd.buf));
|
||||
if (!ret && tmp_cmd.ack == FLASH_CMD_ACK_CHK_PASS &&
|
||||
tmp_cmd.status == FLASH_CMD_W_STATUS_WRITE_OK) {
|
||||
ts_info("flash status check pass");
|
||||
|
|
@ -572,7 +722,7 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
|
|||
|
||||
ts_info("flash cmd status not ready, retry %d, ack 0x%x, status 0x%x, ret %d",
|
||||
i, tmp_cmd.ack, tmp_cmd.status, ret);
|
||||
msleep(15);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
ts_err("flash cmd status error %d, ack 0x%x, status 0x%x, ret %d",
|
||||
|
|
@ -583,21 +733,21 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
|
|||
}
|
||||
|
||||
switch (tmp_cmd.status) {
|
||||
case FLASH_CMD_W_STATUS_CHK_PASS:
|
||||
ts_err("data check pass, but failed get follow-up results");
|
||||
return -EFAULT;
|
||||
case FLASH_CMD_W_STATUS_CHK_FAIL:
|
||||
ts_err("data check failed, please retry");
|
||||
return -EAGAIN;
|
||||
case FLASH_CMD_W_STATUS_ADDR_ERR:
|
||||
ts_err("flash target addr error, please check");
|
||||
return -EFAULT;
|
||||
case FLASH_CMD_W_STATUS_WRITE_ERR:
|
||||
ts_err("flash data write err, please retry");
|
||||
return -EAGAIN;
|
||||
default:
|
||||
ts_err("unknown status");
|
||||
return -EFAULT;
|
||||
case FLASH_CMD_W_STATUS_CHK_PASS:
|
||||
ts_err("data check pass, but failed get follow-up results");
|
||||
return -EFAULT;
|
||||
case FLASH_CMD_W_STATUS_CHK_FAIL:
|
||||
ts_err("data check failed, please retry");
|
||||
return -EAGAIN;
|
||||
case FLASH_CMD_W_STATUS_ADDR_ERR:
|
||||
ts_err("flash target addr error, please check");
|
||||
return -EFAULT;
|
||||
case FLASH_CMD_W_STATUS_WRITE_ERR:
|
||||
ts_err("flash data write err, please retry");
|
||||
return -EAGAIN;
|
||||
default:
|
||||
ts_err("unknown status");
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -606,10 +756,11 @@ static int goodix_flash_package(u8 subsys_type, u8 *pkg,
|
|||
{
|
||||
int ret, retry;
|
||||
struct goodix_flash_cmd flash_cmd;
|
||||
u32 isp_buffer_reg = goodix_fw_update_ctrl.update_info->isp_buffer_reg;
|
||||
|
||||
retry = 2;
|
||||
do {
|
||||
ret = goodix_reg_write_confirm(HW_REG_ISP_BUFFER, pkg, pkg_len);
|
||||
ret = goodix_reg_write(isp_buffer_reg, pkg, pkg_len);
|
||||
if (ret < 0) {
|
||||
ts_err("Failed to write firmware packet");
|
||||
return ret;
|
||||
|
|
@ -628,7 +779,8 @@ static int goodix_flash_package(u8 subsys_type, u8 *pkg,
|
|||
|
||||
ret = goodix_send_flash_cmd(&flash_cmd);
|
||||
if (!ret) {
|
||||
ts_info("success write package to 0x%x, len %d", flash_addr, pkg_len - 4);
|
||||
ts_info("success write package to 0x%x, len %d",
|
||||
flash_addr, pkg_len - 4);
|
||||
return 0;
|
||||
}
|
||||
} while (ret == -EAGAIN && --retry);
|
||||
|
|
@ -643,12 +795,12 @@ static int goodix_flash_package(u8 subsys_type, u8 *pkg,
|
|||
* packets, the max size of packet is limited to
|
||||
* @{ISP_MAX_BUFFERSIZE}
|
||||
* @dev: pointer to touch device
|
||||
* @subsys: subsystem infomation
|
||||
* @subsys: subsystem information
|
||||
* return: 0 ok, < 0 error
|
||||
*/
|
||||
static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
|
||||
{
|
||||
u16 data_size, offset;
|
||||
u32 data_size, offset;
|
||||
u32 total_size;
|
||||
//TODO: confirm flash addr ,<< 8??
|
||||
u32 subsys_base_addr = subsys->flash_addr;
|
||||
|
|
@ -706,11 +858,13 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
|
|||
struct firmware_summary *fw_summary;
|
||||
struct fw_subsys_info *fw_x;
|
||||
struct fw_subsys_info subsys_cfg = {0};
|
||||
u32 config_data_reg = fw_ctrl->update_info->config_data_reg;
|
||||
int retry = GOODIX_BUS_RETRY_TIMES;
|
||||
int i, r = 0, fw_num;
|
||||
|
||||
/* start from subsystem 1,
|
||||
* subsystem 0 is the ISP program */
|
||||
/* start from subsystem 1,
|
||||
* subsystem 0 is the ISP program
|
||||
*/
|
||||
|
||||
fw_summary = &fw_data->fw_summary;
|
||||
fw_num = fw_summary->subsys_num;
|
||||
|
|
@ -719,7 +873,7 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
|
|||
if (fw_ctrl->ic_config && fw_ctrl->ic_config->len) {
|
||||
subsys_cfg.data = fw_ctrl->ic_config->data;
|
||||
subsys_cfg.size = fw_ctrl->ic_config->len;
|
||||
subsys_cfg.flash_addr = CONFIG_DATA_ADDR;
|
||||
subsys_cfg.flash_addr = config_data_reg;
|
||||
subsys_cfg.type = CONFIG_DATA_TYPE;
|
||||
r = goodix_flash_subsystem(&subsys_cfg);
|
||||
if (r) {
|
||||
|
|
@ -759,12 +913,15 @@ exit_flash:
|
|||
*/
|
||||
static int goodix_update_finish(struct fw_update_ctrl *fwu_ctrl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (goodix_fw_update_reset(100))
|
||||
ts_err("reset abnormal");
|
||||
if (goodix_fw_version_compare(fwu_ctrl))
|
||||
return -EINVAL;
|
||||
ret = goodix_fw_version_compare(fwu_ctrl);
|
||||
if (ret == COMPARE_EQUAL || ret == COMPARE_CFG_NOTEQUAL)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -789,10 +946,12 @@ int goodix_fw_update_proc(struct fw_update_ctrl *fwu_ctrl)
|
|||
if (!ret) {
|
||||
ts_info("firmware upgraded");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
ts_info("need to upgrade");
|
||||
}
|
||||
|
||||
start_update:
|
||||
fwu_ctrl->status = UPSTA_PREPARING;
|
||||
do {
|
||||
ret = goodix_update_prepare(fwu_ctrl);
|
||||
if (ret) {
|
||||
|
|
@ -806,14 +965,15 @@ start_update:
|
|||
}
|
||||
|
||||
/* progress: 20%~100% */
|
||||
fwu_ctrl->status = UPSTA_UPDATING;
|
||||
ret = goodix_flash_firmware(fwu_ctrl);
|
||||
if (ret == -EAGAIN && --retry1 > 0) {
|
||||
if (ret < 0 && --retry1 > 0) {
|
||||
ts_err("Bus error, retry firmware update:%d",
|
||||
FW_UPDATE_RETRY - retry1);
|
||||
goto start_update;
|
||||
}
|
||||
if (ret)
|
||||
ts_info("flash fw data enter error");
|
||||
ts_err("flash fw data enter error, ret:%d", ret);
|
||||
else
|
||||
ts_info("flash fw data success, need check version");
|
||||
|
||||
|
|
@ -822,7 +982,7 @@ err_fw_prepare:
|
|||
if (!ret)
|
||||
ts_info("Firmware update successfully");
|
||||
else
|
||||
ts_err("Firmware update failed");
|
||||
ts_err("Firmware update failed, ret:%d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -853,13 +1013,15 @@ static ssize_t goodix_sysfs_update_en_store(
|
|||
|
||||
ts_info("set update mode:0x%x", buf[0]);
|
||||
if (buf[0] == '1') {
|
||||
mode = UPDATE_MODE_FORCE|UPDATE_MODE_BLOCK|UPDATE_MODE_SRC_SYSFS;
|
||||
mode = UPDATE_MODE_FORCE | UPDATE_MODE_BLOCK |
|
||||
UPDATE_MODE_SRC_SYSFS;
|
||||
} else if (buf[0] == '2') {
|
||||
mode = UPDATE_MODE_FORCE|UPDATE_MODE_BLOCK|UPDATE_MODE_SRC_REQUEST;
|
||||
mode = UPDATE_MODE_FORCE | UPDATE_MODE_BLOCK |
|
||||
UPDATE_MODE_SRC_REQUEST;
|
||||
} else if (buf[0] == '5') {
|
||||
mode = UPDATE_MODE_FORCE|UPDATE_MODE_SRC_SYSFS;
|
||||
mode = UPDATE_MODE_FORCE | UPDATE_MODE_SRC_SYSFS;
|
||||
} else if (buf[0] == '6') {
|
||||
mode = UPDATE_MODE_FORCE|UPDATE_MODE_SRC_REQUEST;
|
||||
mode = UPDATE_MODE_FORCE | UPDATE_MODE_SRC_REQUEST;
|
||||
} else {
|
||||
ts_err("invalid update mode:0x%x", buf[0]);
|
||||
return -EINVAL;
|
||||
|
|
@ -906,11 +1068,8 @@ static ssize_t goodix_sysfs_fwsize_store(
|
|||
|
||||
/* use vmalloc to alloc huge memory */
|
||||
fw = vmalloc(sizeof(*fw) + size);
|
||||
if (fw == NULL) {
|
||||
ts_err("Failed to alloc memory,size:%zu",
|
||||
size + sizeof(*fw));
|
||||
if (!fw)
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_lock(&fw_ctrl->mutex);
|
||||
memset(fw, 0x00, sizeof(*fw) + size);
|
||||
data = (u8 **)&fw->data;
|
||||
|
|
@ -949,21 +1108,61 @@ static ssize_t goodix_sysfs_fwimage_store(struct file *file,
|
|||
return count;
|
||||
}
|
||||
|
||||
/* return fw_update result */
|
||||
static ssize_t goodix_sysfs_result_show(
|
||||
struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
|
||||
char str[GOODIX_MAX_STR_LABLE_LEN] = {0};
|
||||
int r = -EINVAL;
|
||||
|
||||
if (!fw_ctrl)
|
||||
return r;
|
||||
|
||||
switch (fw_ctrl->status) {
|
||||
case UPSTA_PREPARING:
|
||||
sprintf(str, "preparing");
|
||||
break;
|
||||
case UPSTA_UPDATING:
|
||||
sprintf(str, "updating");
|
||||
break;
|
||||
case UPSTA_SUCCESS:
|
||||
sprintf(str, "success");
|
||||
break;
|
||||
case UPSTA_FAILED:
|
||||
sprintf(str, "failed");
|
||||
break;
|
||||
case UPSTA_NOTWORK:
|
||||
default:
|
||||
sprintf(str, "notwork");
|
||||
break;
|
||||
}
|
||||
|
||||
r = snprintf(buf, PAGE_SIZE, "result:%s spend_time:%dms\n",
|
||||
str, fw_ctrl->spend_time);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(update_en, 0220, NULL, goodix_sysfs_update_en_store);
|
||||
static DEVICE_ATTR(fwsize, 0664, goodix_sysfs_fwsize_show,
|
||||
goodix_sysfs_fwsize_store);
|
||||
static DEVICE_ATTR(result, 0664, goodix_sysfs_result_show, NULL);
|
||||
|
||||
static struct attribute *goodix_fwu_attrs[] = {
|
||||
&dev_attr_update_en.attr,
|
||||
&dev_attr_fwsize.attr,
|
||||
&dev_attr_result.attr
|
||||
};
|
||||
|
||||
static int goodix_fw_sysfs_init(struct goodix_ts_core *core_data, struct fw_update_ctrl *fw_ctrl)
|
||||
static int goodix_fw_sysfs_init(struct goodix_ts_core *core_data,
|
||||
struct fw_update_ctrl *fw_ctrl)
|
||||
{
|
||||
int ret = 0, i;
|
||||
|
||||
fw_ctrl->kobj = kobject_create_and_add("fwupdate", &core_data->pdev->dev.kobj);
|
||||
fw_ctrl->kobj = kobject_create_and_add("fwupdate",
|
||||
&core_data->pdev->dev.kobj);
|
||||
if (!fw_ctrl->kobj) {
|
||||
ts_err("failed create sub dir for fwupdate");
|
||||
return -EINVAL;
|
||||
|
|
@ -982,7 +1181,7 @@ static int goodix_fw_sysfs_init(struct goodix_ts_core *core_data, struct fw_upda
|
|||
}
|
||||
|
||||
fw_ctrl->attr_fwimage.attr.name = "fwimage";
|
||||
fw_ctrl->attr_fwimage.attr.mode = S_IRUGO | S_IWUGO;
|
||||
fw_ctrl->attr_fwimage.attr.mode = 0666;
|
||||
fw_ctrl->attr_fwimage.size = 0;
|
||||
fw_ctrl->attr_fwimage.write = goodix_sysfs_fwimage_store;
|
||||
ret = sysfs_create_bin_file(fw_ctrl->kobj, &fw_ctrl->attr_fwimage);
|
||||
|
|
@ -1025,14 +1224,24 @@ static int goodix_request_firmware(struct firmware_data *fw_data,
|
|||
container_of(fw_data, struct fw_update_ctrl, fw_data);
|
||||
struct device *dev = &(fw_ctrl->core_data->pdev->dev);
|
||||
int r;
|
||||
int retry = GOODIX_RETRY_3;
|
||||
|
||||
ts_info("Request firmware image [%s]", name);
|
||||
r = request_firmware(&fw_data->firmware, name, dev);
|
||||
if (r < 0)
|
||||
|
||||
while (retry--) {
|
||||
r = request_firmware(&fw_data->firmware, name, dev);
|
||||
if (!r)
|
||||
break;
|
||||
ts_info("get fw bin retry:[%d]", GOODIX_RETRY_3 - retry);
|
||||
msleep(200);
|
||||
}
|
||||
if (retry < 0) {
|
||||
ts_err("Firmware image [%s] not available,errno:%d", name, r);
|
||||
else
|
||||
ts_info("Firmware image [%s] is ready", name);
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
ts_info("Firmware image [%s] is ready", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1051,8 +1260,12 @@ static int goodix_fw_update_thread(void *data)
|
|||
{
|
||||
struct fw_update_ctrl *fwu_ctrl = data;
|
||||
struct firmware *temp_firmware = NULL;
|
||||
ktime_t start, end;
|
||||
int r = -EINVAL;
|
||||
|
||||
start = ktime_get();
|
||||
fwu_ctrl->spend_time = 0;
|
||||
fwu_ctrl->status = UPSTA_NOTWORK;
|
||||
mutex_lock(&fwu_ctrl->mutex);
|
||||
|
||||
if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
|
||||
|
|
@ -1095,11 +1308,17 @@ out:
|
|||
|
||||
if (r) {
|
||||
ts_err("fw update failed, %d", r);
|
||||
fwu_ctrl->status = UPSTA_FAILED;
|
||||
goodix_ts_blocking_notify(NOTIFY_FWUPDATE_FAILED, NULL);
|
||||
} else {
|
||||
ts_info("fw update success");
|
||||
fwu_ctrl->status = UPSTA_SUCCESS;
|
||||
goodix_ts_blocking_notify(NOTIFY_FWUPDATE_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
end = ktime_get();
|
||||
fwu_ctrl->spend_time = ktime_to_ms(ktime_sub(end, start));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1147,7 +1366,7 @@ int goodix_fw_update_init(struct goodix_ts_core *core_data)
|
|||
goodix_fw_update_ctrl.core_data = core_data;
|
||||
goodix_fw_update_ctrl.mode = 0;
|
||||
|
||||
strlcpy(goodix_fw_update_ctrl.fw_name, TS_DEFAULT_FIRMWARE,
|
||||
strlcpy(goodix_fw_update_ctrl.fw_name, core_data->board_data.fw_name,
|
||||
sizeof(goodix_fw_update_ctrl.fw_name));
|
||||
|
||||
ret = goodix_fw_sysfs_init(core_data, &goodix_fw_update_ctrl);
|
||||
|
|
@ -1155,6 +1374,13 @@ int goodix_fw_update_init(struct goodix_ts_core *core_data)
|
|||
ts_err("failed create fwupate sysfs node");
|
||||
return ret;
|
||||
}
|
||||
if (core_data->bus->ic_type == IC_TYPE_BERLIN_A)
|
||||
goodix_fw_update_ctrl.update_info = &update_bra;
|
||||
else if (core_data->bus->ic_type == IC_TYPE_BERLIN_B)
|
||||
goodix_fw_update_ctrl.update_info = &update_brb;
|
||||
else
|
||||
goodix_fw_update_ctrl.update_info = &update_brd;
|
||||
|
||||
goodix_fw_update_ctrl.initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -20,8 +20,8 @@
|
|||
|
||||
#include "goodix_ts_core.h"
|
||||
|
||||
#define TS_DRIVER_NAME "gtx8_i2c"
|
||||
#define I2C_MAX_TRANSFER_SIZE 255
|
||||
#define TS_DRIVER_NAME "gtx8_i2c"
|
||||
#define I2C_MAX_TRANSFER_SIZE 60
|
||||
#define GOODIX_BUS_RETRY_TIMES 3
|
||||
#define GOODIX_REG_ADDR_SIZE 4
|
||||
|
||||
|
|
@ -174,6 +174,12 @@ static int goodix_i2c_probe(struct i2c_client *client,
|
|||
if (!ret)
|
||||
return -EIO;
|
||||
|
||||
/* get ic type */
|
||||
ret = goodix_get_ic_type(client->dev.of_node);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
goodix_i2c_bus.ic_type = ret;
|
||||
goodix_i2c_bus.bus_type = GOODIX_BUS_TYPE_I2C;
|
||||
goodix_i2c_bus.dev = &client->dev;
|
||||
goodix_i2c_bus.read = goodix_i2c_read;
|
||||
|
|
@ -188,14 +194,14 @@ static int goodix_i2c_probe(struct i2c_client *client,
|
|||
goodix_pdev->num_resources = 0;
|
||||
/*
|
||||
* you can find this platform dev in
|
||||
* /sys/devices/platfrom/goodix_ts.0
|
||||
* /sys/devices/platform/goodix_ts.0
|
||||
* goodix_pdev->dev.parent = &client->dev;
|
||||
*/
|
||||
goodix_pdev->dev.platform_data = &goodix_i2c_bus;
|
||||
goodix_pdev->dev.release = goodix_pdev_release;
|
||||
|
||||
/* register platform device, then the goodix_ts_core
|
||||
* module will probe the touch deivce.
|
||||
* module will probe the touch device.
|
||||
*/
|
||||
ret = platform_device_register(goodix_pdev);
|
||||
if (ret) {
|
||||
|
|
@ -220,8 +226,9 @@ static int goodix_i2c_remove(struct i2c_client *client)
|
|||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id i2c_matchs[] = {
|
||||
{.compatible = "goodix,brl-generic",},
|
||||
{.compatible = "goodix,gt9897",},
|
||||
{.compatible = "goodix,gt9966",},
|
||||
{.compatible = "goodix,gt9916",},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, i2c_matchs);
|
||||
|
|
@ -244,20 +251,14 @@ static struct i2c_driver goodix_i2c_driver = {
|
|||
.id_table = i2c_id_table,
|
||||
};
|
||||
|
||||
int goodix_bus_init(void)
|
||||
int goodix_i2c_bus_init(void)
|
||||
{
|
||||
ts_info("Goodix i2c driver init");
|
||||
return i2c_add_driver(&goodix_i2c_driver);
|
||||
}
|
||||
EXPORT_SYMBOL(goodix_bus_init);
|
||||
|
||||
void goodix_bus_exit(void)
|
||||
void goodix_i2c_bus_exit(void)
|
||||
{
|
||||
ts_info("Goodix i2c driver exit");
|
||||
i2c_del_driver(&goodix_i2c_driver);
|
||||
}
|
||||
EXPORT_SYMBOL(goodix_bus_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Goodix Touchscreen Hardware Module");
|
||||
MODULE_AUTHOR("Goodix, Inc.");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -34,14 +34,14 @@ static struct platform_device *goodix_pdev;
|
|||
struct goodix_bus_interface goodix_spi_bus;
|
||||
|
||||
/**
|
||||
* goodix_spi_read- read device register through spi bus
|
||||
* goodix_spi_read_bra- read device register through spi bus
|
||||
* @dev: pointer to device data
|
||||
* @addr: register address
|
||||
* @data: read buffer
|
||||
* @len: bytes to read
|
||||
* return: 0 - read ok, < 0 - spi transter error
|
||||
*/
|
||||
int goodix_spi_read(struct device *dev, unsigned int addr,
|
||||
static int goodix_spi_read_bra(struct device *dev, unsigned int addr,
|
||||
unsigned char *data, unsigned int len)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
|
@ -54,7 +54,7 @@ int goodix_spi_read(struct device *dev, unsigned int addr,
|
|||
rx_buf = kzalloc(SPI_READ_PREFIX_LEN + len, GFP_KERNEL);
|
||||
tx_buf = kzalloc(SPI_READ_PREFIX_LEN + len, GFP_KERNEL);
|
||||
if (!rx_buf || !tx_buf) {
|
||||
ts_err("alloc tx/rx_buf failed, size:%d\n",
|
||||
ts_err("alloc tx/rx_buf failed, size:%d",
|
||||
SPI_READ_PREFIX_LEN + len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ int goodix_spi_read(struct device *dev, unsigned int addr,
|
|||
spi_message_init(&spi_msg);
|
||||
memset(&xfers, 0, sizeof(xfers));
|
||||
|
||||
/*spi_read tx_buf format: 0xF1 + addr(2bytes) + data*/
|
||||
/*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/
|
||||
tx_buf[0] = SPI_READ_FLAG;
|
||||
tx_buf[1] = (addr >> 24) & 0xFF;
|
||||
tx_buf[2] = (addr >> 16) & 0xFF;
|
||||
|
|
@ -80,7 +80,7 @@ int goodix_spi_read(struct device *dev, unsigned int addr,
|
|||
spi_message_add_tail(&xfers, &spi_msg);
|
||||
ret = spi_sync(spi, &spi_msg);
|
||||
if (ret < 0) {
|
||||
ts_err("spi transfer error:%d\n",ret);
|
||||
ts_err("spi transfer error:%d",ret);
|
||||
goto exit;
|
||||
}
|
||||
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN], len);
|
||||
|
|
@ -91,6 +91,55 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int goodix_spi_read(struct device *dev, unsigned int addr,
|
||||
unsigned char *data, unsigned int len)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
u8 *rx_buf = NULL;
|
||||
u8 *tx_buf = NULL;
|
||||
struct spi_transfer xfers;
|
||||
struct spi_message spi_msg;
|
||||
int ret = 0;
|
||||
|
||||
rx_buf = kzalloc(SPI_READ_PREFIX_LEN - 1 + len, GFP_KERNEL);
|
||||
tx_buf = kzalloc(SPI_READ_PREFIX_LEN - 1 + len, GFP_KERNEL);
|
||||
if (!rx_buf || !tx_buf) {
|
||||
ts_err("alloc tx/rx_buf failed, size:%d",
|
||||
SPI_READ_PREFIX_LEN - 1 + len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spi_message_init(&spi_msg);
|
||||
memset(&xfers, 0, sizeof(xfers));
|
||||
|
||||
/*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/
|
||||
tx_buf[0] = SPI_READ_FLAG;
|
||||
tx_buf[1] = (addr >> 24) & 0xFF;
|
||||
tx_buf[2] = (addr >> 16) & 0xFF;
|
||||
tx_buf[3] = (addr >> 8) & 0xFF;
|
||||
tx_buf[4] = addr & 0xFF;
|
||||
tx_buf[5] = 0xFF;
|
||||
tx_buf[6] = 0xFF;
|
||||
tx_buf[7] = 0xFF;
|
||||
|
||||
xfers.tx_buf = tx_buf;
|
||||
xfers.rx_buf = rx_buf;
|
||||
xfers.len = SPI_READ_PREFIX_LEN - 1 + len;
|
||||
xfers.cs_change = 0;
|
||||
spi_message_add_tail(&xfers, &spi_msg);
|
||||
ret = spi_sync(spi, &spi_msg);
|
||||
if (ret < 0) {
|
||||
ts_err("spi transfer error:%d",ret);
|
||||
goto exit;
|
||||
}
|
||||
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN - 1], len);
|
||||
|
||||
exit:
|
||||
kfree(rx_buf);
|
||||
kfree(tx_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* goodix_spi_write- write device register through spi bus
|
||||
* @dev: pointer to device data
|
||||
|
|
@ -99,7 +148,7 @@ exit:
|
|||
* @len: bytes to write
|
||||
* return: 0 - write ok; < 0 - spi transter error.
|
||||
*/
|
||||
int goodix_spi_write(struct device *dev, unsigned int addr,
|
||||
static int goodix_spi_write(struct device *dev, unsigned int addr,
|
||||
unsigned char *data, unsigned int len)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
|
|
@ -110,7 +159,7 @@ int goodix_spi_write(struct device *dev, unsigned int addr,
|
|||
|
||||
tx_buf = kzalloc(SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL);
|
||||
if (!tx_buf) {
|
||||
ts_err("alloc tx_buf failed, size:%d\n",
|
||||
ts_err("alloc tx_buf failed, size:%d",
|
||||
SPI_WRITE_PREFIX_LEN + len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -130,7 +179,7 @@ int goodix_spi_write(struct device *dev, unsigned int addr,
|
|||
spi_message_add_tail(&xfers, &spi_msg);
|
||||
ret = spi_sync(spi, &spi_msg);
|
||||
if (ret < 0)
|
||||
ts_err("spi transfer error:%d\n",ret);
|
||||
ts_err("spi transfer error:%d",ret);
|
||||
|
||||
kfree(tx_buf);
|
||||
return ret;
|
||||
|
|
@ -151,7 +200,6 @@ static int goodix_spi_probe(struct spi_device *spi)
|
|||
/* init spi_device */
|
||||
spi->mode = SPI_MODE_0;
|
||||
spi->bits_per_word = 8;
|
||||
spi->max_speed_hz = 1000000;
|
||||
|
||||
ret = spi_setup(spi);
|
||||
if (ret) {
|
||||
|
|
@ -159,9 +207,18 @@ static int goodix_spi_probe(struct spi_device *spi)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* get ic type */
|
||||
ret = goodix_get_ic_type(spi->dev.of_node);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
goodix_spi_bus.ic_type = ret;
|
||||
goodix_spi_bus.bus_type = GOODIX_BUS_TYPE_SPI;
|
||||
goodix_spi_bus.dev = &spi->dev;
|
||||
goodix_spi_bus.read = goodix_spi_read;
|
||||
if (goodix_spi_bus.ic_type == IC_TYPE_BERLIN_A)
|
||||
goodix_spi_bus.read = goodix_spi_read_bra;
|
||||
else
|
||||
goodix_spi_bus.read = goodix_spi_read;
|
||||
goodix_spi_bus.write = goodix_spi_write;
|
||||
/* ts core device */
|
||||
goodix_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
|
||||
|
|
@ -207,6 +264,8 @@ static int goodix_spi_remove(struct spi_device *spi)
|
|||
static const struct of_device_id spi_matchs[] = {
|
||||
{.compatible = "goodix,gt9897S",},
|
||||
{.compatible = "goodix,gt9897T",},
|
||||
{.compatible = "goodix,gt9966S",},
|
||||
{.compatible = "goodix,gt9916S",},
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
|
@ -227,20 +286,14 @@ static struct spi_driver goodix_spi_driver = {
|
|||
.remove = goodix_spi_remove,
|
||||
};
|
||||
|
||||
int goodix_bus_init(void)
|
||||
int goodix_spi_bus_init(void)
|
||||
{
|
||||
ts_info("Goodix spi driver init");
|
||||
return spi_register_driver(&goodix_spi_driver);
|
||||
}
|
||||
EXPORT_SYMBOL(goodix_bus_init);
|
||||
|
||||
void goodix_bus_exit(void)
|
||||
void goodix_spi_bus_exit(void)
|
||||
{
|
||||
ts_info("Goodix spi driver exit");
|
||||
spi_unregister_driver(&goodix_spi_driver);
|
||||
}
|
||||
EXPORT_SYMBOL(goodix_bus_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Goodix Touchscreen Hardware Module");
|
||||
MODULE_AUTHOR("Goodix, Inc.");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -16,17 +16,16 @@
|
|||
*/
|
||||
#include "goodix_ts_core.h"
|
||||
|
||||
#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin"
|
||||
#define TS_BIN_VERSION_START_INDEX 5
|
||||
#define TS_BIN_VERSION_LEN 4
|
||||
#define TS_BIN_VERSION_START_INDEX 5
|
||||
#define TS_BIN_VERSION_LEN 4
|
||||
#define TS_CFG_BIN_HEAD_RESERVED_LEN 6
|
||||
#define TS_CFG_OFFSET_LEN 2
|
||||
#define TS_IC_TYPE_NAME_MAX_LEN 15
|
||||
#define TS_CFG_BIN_HEAD_LEN (sizeof(struct goodix_cfg_bin_head) + \
|
||||
TS_CFG_BIN_HEAD_RESERVED_LEN)
|
||||
#define TS_PKG_CONST_INFO_LEN (sizeof(struct goodix_cfg_pkg_const_info))
|
||||
#define TS_PKG_REG_INFO_LEN (sizeof(struct goodix_cfg_pkg_reg_info))
|
||||
#define TS_PKG_HEAD_LEN (TS_PKG_CONST_INFO_LEN + TS_PKG_REG_INFO_LEN)
|
||||
#define TS_CFG_OFFSET_LEN 2
|
||||
#define TS_IC_TYPE_NAME_MAX_LEN 15
|
||||
#define TS_CFG_BIN_HEAD_LEN (sizeof(struct goodix_cfg_bin_head) + \
|
||||
TS_CFG_BIN_HEAD_RESERVED_LEN)
|
||||
#define TS_PKG_CONST_INFO_LEN (sizeof(struct goodix_cfg_pkg_const_info))
|
||||
#define TS_PKG_REG_INFO_LEN (sizeof(struct goodix_cfg_pkg_reg_info))
|
||||
#define TS_PKG_HEAD_LEN (TS_PKG_CONST_INFO_LEN + TS_PKG_REG_INFO_LEN)
|
||||
|
||||
/*cfg block definitin*/
|
||||
#define TS_CFG_BLOCK_PID_LEN 8
|
||||
|
|
@ -35,8 +34,8 @@
|
|||
#define TS_CFG_BLOCK_FW_PATCH_LEN 4
|
||||
#define TS_CFG_BLOCK_RESERVED_LEN 9
|
||||
|
||||
#define TS_NORMAL_CFG 0x01
|
||||
#define TS_HIGH_SENSE_CFG 0x03
|
||||
#define TS_NORMAL_CFG 0x01
|
||||
#define TS_HIGH_SENSE_CFG 0x03
|
||||
#define TS_RQST_FW_RETRY_TIMES 2
|
||||
|
||||
#pragma pack(1)
|
||||
|
|
@ -101,20 +100,24 @@ struct goodix_cfg_bin {
|
|||
struct goodix_cfg_package *cfg_pkgs;
|
||||
};
|
||||
|
||||
static int goodix_read_cfg_bin(struct device *dev, struct goodix_cfg_bin *cfg_bin)
|
||||
static int goodix_read_cfg_bin(struct device *dev, const char *cfg_name,
|
||||
struct goodix_cfg_bin *cfg_bin)
|
||||
{
|
||||
const struct firmware *firmware = NULL;
|
||||
char cfg_bin_name[GOODIX_MAX_STR_LABLE_LEN] = {0x00};
|
||||
int ret;
|
||||
int retry = GOODIX_RETRY_3;
|
||||
|
||||
/*get cfg_bin_name*/
|
||||
strlcpy(cfg_bin_name, TS_DEFAULT_CFG_BIN, sizeof(cfg_bin_name));
|
||||
ts_info("cfg_bin_name:%s", cfg_bin_name);
|
||||
ts_info("cfg_bin_name:%s", cfg_name);
|
||||
|
||||
ret = request_firmware(&firmware, cfg_bin_name, dev);
|
||||
if (ret) {
|
||||
ts_err("failed get cfg bin[%s] error:%d",
|
||||
cfg_bin_name, ret);
|
||||
while (retry--) {
|
||||
ret = request_firmware(&firmware, cfg_name, dev);
|
||||
if (!ret)
|
||||
break;
|
||||
ts_info("get cfg bin retry:[%d]", GOODIX_RETRY_3 - retry);
|
||||
msleep(200);
|
||||
}
|
||||
if (retry < 0) {
|
||||
ts_err("failed get cfg bin[%s] error:%d", cfg_name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +129,7 @@ static int goodix_read_cfg_bin(struct device *dev, struct goodix_cfg_bin *cfg_bi
|
|||
}
|
||||
|
||||
cfg_bin->bin_data_len = firmware->size;
|
||||
/*allocate memory for cfg_bin->bin_data*/
|
||||
/* allocate memory for cfg_bin->bin_data */
|
||||
cfg_bin->bin_data = kzalloc(cfg_bin->bin_data_len, GFP_KERNEL);
|
||||
if (!cfg_bin->bin_data) {
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -209,8 +212,6 @@ static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin)
|
|||
memcpy(&cfg_bin->cfg_pkgs[i].reg_info,
|
||||
&cfg_bin->bin_data[offset1 + TS_PKG_CONST_INFO_LEN],
|
||||
TS_PKG_REG_INFO_LEN);
|
||||
/*TODO compatible little edition and big edition*/
|
||||
//goodix_cfg_pkg_leToCpu(&cfg_bin->cfg_pkgs[i]);
|
||||
|
||||
/*get configuration data*/
|
||||
cfg_bin->cfg_pkgs[i].cfg = &cfg_bin->bin_data[offset1 + TS_PKG_HEAD_LEN];
|
||||
|
|
@ -290,10 +291,11 @@ err_out:
|
|||
static int goodix_get_config_data(struct goodix_ts_core *cd, u8 sensor_id)
|
||||
{
|
||||
struct goodix_cfg_bin cfg_bin = {0};
|
||||
char *cfg_name = cd->board_data.cfg_bin_name;
|
||||
int ret;
|
||||
|
||||
/*get cfg_bin from file system*/
|
||||
ret = goodix_read_cfg_bin(&cd->pdev->dev, &cfg_bin);
|
||||
ret = goodix_read_cfg_bin(&cd->pdev->dev, cfg_name, &cfg_bin);
|
||||
if (ret) {
|
||||
ts_err("failed get valid config bin data");
|
||||
return ret;
|
||||
|
|
@ -328,3 +330,5 @@ int goodix_get_config_proc(struct goodix_ts_core *cd)
|
|||
|
||||
return goodix_get_config_data(cd, cd->fw_version.sensor_id);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load diff
97
drivers/input/touchscreen/goodix_berlin_mmi/include/goodix_ts_core.h → drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h
Executable file → Normal file
97
drivers/input/touchscreen/goodix_berlin_mmi/include/goodix_ts_core.h → drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_core.h
Executable file → Normal file
|
|
@ -14,7 +14,6 @@
|
|||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/of_irq.h>
|
||||
#ifdef CONFIG_OF
|
||||
#include <linux/of_gpio.h>
|
||||
|
|
@ -25,18 +24,33 @@
|
|||
#include <linux/fb.h>
|
||||
#endif
|
||||
|
||||
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
|
||||
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
|
||||
#define GOODIX_DRIVER_VERSION "v1.0.1"
|
||||
#define GOODIX_MAX_TOUCH 10
|
||||
#define GOODIX_PEN_MAX_PRESSURE 4096
|
||||
#define GOODIX_MAX_PEN_KEY 2
|
||||
#define GOODIX_CFG_MAX_SIZE 4096
|
||||
#define GOODIX_MAX_STR_LABLE_LEN 32
|
||||
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
|
||||
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
|
||||
#define GOODIX_DRIVER_VERSION "v1.1.21"
|
||||
#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_MAX_STR_LABLE_LEN 32
|
||||
|
||||
#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 TS_DEFAULT_FIRMWARE "goodix_firmware.bin"
|
||||
#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin"
|
||||
|
||||
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),
|
||||
|
|
@ -52,7 +66,9 @@ enum IC_TYPE_ID {
|
|||
IC_TYPE_NORMANDY,
|
||||
IC_TYPE_NANJING,
|
||||
IC_TYPE_YELLOWSTONE,
|
||||
IC_TYPE_BERLIN,
|
||||
IC_TYPE_BERLIN_A,
|
||||
IC_TYPE_BERLIN_B,
|
||||
IC_TYPE_BERLIN_D
|
||||
};
|
||||
|
||||
enum GOODIX_IC_CONFIG_TYPE {
|
||||
|
|
@ -180,6 +196,18 @@ struct goodix_ic_info {
|
|||
};
|
||||
#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
|
||||
|
|
@ -193,7 +221,6 @@ struct goodix_module {
|
|||
bool initilized;
|
||||
struct mutex mutex;
|
||||
struct workqueue_struct *wq;
|
||||
struct completion core_comp;
|
||||
struct goodix_ts_core *core_data;
|
||||
};
|
||||
|
||||
|
|
@ -214,6 +241,8 @@ struct goodix_ts_board_data {
|
|||
char iovdd_name[GOODIX_MAX_STR_LABLE_LEN];
|
||||
int reset_gpio;
|
||||
int irq_gpio;
|
||||
int avdd_gpio;
|
||||
int iovdd_gpio;
|
||||
unsigned int irq_flags;
|
||||
|
||||
unsigned int swap_axis;
|
||||
|
|
@ -223,8 +252,8 @@ struct goodix_ts_board_data {
|
|||
unsigned int panel_max_p; /*pressure*/
|
||||
|
||||
bool pen_enable;
|
||||
const char *fw_name;
|
||||
const char *cfg_bin_name;
|
||||
char fw_name[GOODIX_MAX_STR_LABLE_LEN];
|
||||
char cfg_bin_name[GOODIX_MAX_STR_LABLE_LEN];
|
||||
};
|
||||
|
||||
enum goodix_fw_update_mode {
|
||||
|
|
@ -324,6 +353,7 @@ struct goodix_pen_data {
|
|||
* @event_data: event data
|
||||
*/
|
||||
struct goodix_ts_event {
|
||||
int retry;
|
||||
enum ts_event_type event_type;
|
||||
u8 request_code; /* represent the request type */
|
||||
u8 gesture_type;
|
||||
|
|
@ -339,6 +369,7 @@ enum goodix_ic_bus_type {
|
|||
|
||||
struct goodix_bus_interface {
|
||||
int bus_type;
|
||||
int ic_type;
|
||||
struct device *dev;
|
||||
int (*read)(struct device *dev, unsigned int addr,
|
||||
unsigned char *data, unsigned int len);
|
||||
|
|
@ -366,6 +397,7 @@ struct goodix_ts_hw_ops {
|
|||
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); /* clean sync flag */
|
||||
int (*get_capacitance_data)(struct goodix_ts_core *cd, struct ts_rawdata_info *info);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -375,6 +407,7 @@ struct goodix_ts_hw_ops {
|
|||
* off esd protection
|
||||
*/
|
||||
struct goodix_ts_esd {
|
||||
bool irq_status;
|
||||
atomic_t esd_on;
|
||||
struct delayed_work esd_work;
|
||||
struct notifier_block esd_notifier;
|
||||
|
|
@ -403,7 +436,7 @@ struct goodix_ts_core {
|
|||
struct goodix_ts_hw_ops *hw_ops;
|
||||
struct input_dev *input_dev;
|
||||
struct input_dev *pen_dev;
|
||||
/* TODO counld we remove this from core data? */
|
||||
/* TODO counld we remove this from core data? */
|
||||
struct goodix_ts_event ts_event;
|
||||
|
||||
/* every pointer of this array represent a kind of config */
|
||||
|
|
@ -417,6 +450,8 @@ struct goodix_ts_core {
|
|||
|
||||
atomic_t irq_enabled;
|
||||
atomic_t suspended;
|
||||
/* 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;
|
||||
|
|
@ -436,9 +471,9 @@ enum goodix_ext_priority {
|
|||
EXTMOD_PRIO_DEFAULT,
|
||||
};
|
||||
|
||||
#define EVT_HANDLED 0
|
||||
#define EVT_HANDLED 0
|
||||
#define EVT_CONTINUE 0
|
||||
#define EVT_CANCEL 1
|
||||
#define EVT_CANCEL 1
|
||||
#define EVT_CANCEL_IRQEVT 1
|
||||
#define EVT_CANCEL_SUSPEND 1
|
||||
#define EVT_CANCEL_RESUME 1
|
||||
|
|
@ -511,16 +546,11 @@ struct goodix_ext_attribute {
|
|||
static struct goodix_ext_attribute ext_attr_##_name = \
|
||||
__EXTMOD_ATTR(_name, _mode, _show, _store);
|
||||
|
||||
|
||||
//#define CONFIG_GOODIX_DEBUG
|
||||
/* 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)
|
||||
#ifdef CONFIG_GOODIX_DEBUG
|
||||
#define ts_debug(fmt, arg...) pr_info("[GTP-DBG][%s:%d] "fmt"\n", __func__, __LINE__, ##arg)
|
||||
#else
|
||||
#define ts_debug(fmt, arg...) do {} while (0)
|
||||
#endif
|
||||
#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
|
||||
|
|
@ -554,24 +584,35 @@ int goodix_unregister_ext_module(struct goodix_ext_module *module);
|
|||
/* remove all registered ext module
|
||||
* return 0 on success, otherwise return < 0
|
||||
*/
|
||||
int goodix_unregister_all_module(void);
|
||||
int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v);
|
||||
void goodix_debugfs_printf(const char *fmt, ...);
|
||||
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_bus_init(void);
|
||||
void goodix_bus_exit(void);
|
||||
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 *data);
|
||||
int goodix_gesture_enable(int enable);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
|
@ -48,6 +48,30 @@ struct gesture_module {
|
|||
};
|
||||
|
||||
static struct gesture_module *gsx_gesture; /*allocated in gesture init module*/
|
||||
static bool module_initialized;
|
||||
|
||||
|
||||
int goodix_gesture_enable(int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!module_initialized)
|
||||
return 0;
|
||||
|
||||
if (enable) {
|
||||
if (atomic_read(&gsx_gesture->registered))
|
||||
ts_info("gesture module has been already registered");
|
||||
else
|
||||
ret = goodix_register_ext_module_no_wait(&gsx_gesture->module);
|
||||
} else {
|
||||
if (!atomic_read(&gsx_gesture->registered))
|
||||
ts_info("gesture module has been already unregistered");
|
||||
else
|
||||
ret = goodix_unregister_ext_module(&gsx_gesture->module);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsx_gesture_type_show - show valid gesture type
|
||||
|
|
@ -125,10 +149,10 @@ static ssize_t gsx_gesture_enable_store(struct goodix_ext_module *module,
|
|||
return ret;
|
||||
|
||||
if (val) {
|
||||
ret = goodix_register_ext_module_no_wait(&gsx_gesture->module);
|
||||
ret = goodix_gesture_enable(1);
|
||||
return ret ? ret : count;
|
||||
} else {
|
||||
ret = goodix_unregister_ext_module(&gsx_gesture->module);
|
||||
ret = goodix_gesture_enable(0);
|
||||
return ret ? ret : count;
|
||||
}
|
||||
}
|
||||
|
|
@ -157,46 +181,33 @@ const struct goodix_ext_attribute gesture_attrs[] = {
|
|||
static int gsx_gesture_init(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
|
||||
if (!cd || !cd->hw_ops->gesture) {
|
||||
ts_err("gesture unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_read(&gsx_gesture->registered))
|
||||
return 0;
|
||||
|
||||
ts_info("gesture switch: ON");
|
||||
ts_debug("enable all gesture type");
|
||||
/* set all bit to 1 to enable all gesture wakeup */
|
||||
memset(gsx_gesture->gesture_type, 0xff, GSX_GESTURE_TYPE_LEN);
|
||||
module->priv_data = cd;
|
||||
|
||||
ret = kobject_init_and_add(&module->kobj, goodix_get_default_ktype(),
|
||||
&cd->pdev->dev.kobj, "gesture");
|
||||
if (ret) {
|
||||
ts_err("failed create gesture sysfs node!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++)
|
||||
ret = sysfs_create_file(&module->kobj, &gesture_attrs[i].attr);
|
||||
if (ret) {
|
||||
ts_err("failed create gst sysfs files");
|
||||
while (--i >= 0)
|
||||
sysfs_remove_file(&module->kobj, &gesture_attrs[i].attr);
|
||||
|
||||
kobject_put(&module->kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
atomic_set(&gsx_gesture->registered, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsx_gesture_exit(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
if (!cd || !cd->hw_ops->gesture) {
|
||||
ts_err("gesture unsupported");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ts_info("gesture switch: OFF");
|
||||
ts_debug("disable all gesture type");
|
||||
memset(gsx_gesture->gesture_type, 0x00, GSX_GESTURE_TYPE_LEN);
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -248,9 +259,10 @@ static int gsx_gesture_ist(struct goodix_ts_core *cd,
|
|||
|
||||
re_send_ges_cmd:
|
||||
if (hw_ops->gesture(cd, 0))
|
||||
ts_info("warning: failed re_send gesture cmd\n");
|
||||
ts_info("warning: failed re_send gesture cmd");
|
||||
gesture_ist_exit:
|
||||
hw_ops->after_event_handler(cd);
|
||||
if (!cd->tools_ctrl_sync)
|
||||
hw_ops->after_event_handler(cd);
|
||||
return EVT_CANCEL_IRQEVT;
|
||||
}
|
||||
|
||||
|
|
@ -268,29 +280,49 @@ static int gsx_gesture_before_suspend(struct goodix_ts_core *cd,
|
|||
int ret;
|
||||
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
|
||||
|
||||
atomic_set(&cd->suspended, 1);
|
||||
ret = hw_ops->gesture(cd, 0);
|
||||
if (ret)
|
||||
ts_err("failed enter gesture mode");
|
||||
else
|
||||
ts_info("enter gesture mode");
|
||||
|
||||
hw_ops->irq_enable(cd, true);
|
||||
enable_irq_wake(cd->irq);
|
||||
|
||||
return EVT_CANCEL_SUSPEND;
|
||||
}
|
||||
|
||||
static int gsx_gesture_before_resume(struct goodix_ts_core *cd,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
|
||||
|
||||
hw_ops->irq_enable(cd, false);
|
||||
disable_irq_wake(cd->irq);
|
||||
hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
|
||||
|
||||
return EVT_CANCEL_RESUME;
|
||||
}
|
||||
|
||||
static struct goodix_ext_module_funcs gsx_gesture_funcs = {
|
||||
.irq_event = gsx_gesture_ist,
|
||||
.init = gsx_gesture_init,
|
||||
.exit = gsx_gesture_exit,
|
||||
.before_suspend = gsx_gesture_before_suspend
|
||||
.before_suspend = gsx_gesture_before_suspend,
|
||||
.before_resume = gsx_gesture_before_resume,
|
||||
};
|
||||
|
||||
static int __init goodix_gsx_gesture_init(void)
|
||||
int gesture_module_init(void)
|
||||
{
|
||||
ts_info("gesture module init");
|
||||
int ret;
|
||||
int i;
|
||||
struct kobject *def_kobj = goodix_get_default_kobj();
|
||||
struct kobj_type *def_kobj_type = goodix_get_default_ktype();
|
||||
|
||||
gsx_gesture = kzalloc(sizeof(struct gesture_module), GFP_KERNEL);
|
||||
if (!gsx_gesture)
|
||||
return -ENOMEM;
|
||||
|
||||
gsx_gesture->module.funcs = &gsx_gesture_funcs;
|
||||
gsx_gesture->module.priority = EXTMOD_PRIO_GESTURE;
|
||||
gsx_gesture->module.name = "Goodix_gsx_gesture";
|
||||
|
|
@ -298,32 +330,55 @@ static int __init goodix_gsx_gesture_init(void)
|
|||
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
rwlock_init(&gsx_gesture->rwlock);
|
||||
goodix_register_ext_module(&(gsx_gesture->module));
|
||||
|
||||
/* gesture sysfs init */
|
||||
ret = kobject_init_and_add(&gsx_gesture->module.kobj,
|
||||
def_kobj_type, def_kobj, "gesture");
|
||||
if (ret) {
|
||||
ts_err("failed create gesture sysfs node!");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++)
|
||||
ret = sysfs_create_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
if (ret) {
|
||||
ts_err("failed create gst sysfs files");
|
||||
while (--i >= 0)
|
||||
sysfs_remove_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
|
||||
kobject_put(&gsx_gesture->module.kobj);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
module_initialized = true;
|
||||
ts_info("gesture module init success");
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
ts_err("gesture module init failed!");
|
||||
kfree(gsx_gesture);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit goodix_gsx_gesture_exit(void)
|
||||
void gesture_module_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
ts_info("gesture module exit");
|
||||
if (atomic_read(&gsx_gesture->registered)) {
|
||||
goodix_unregister_ext_module(&gsx_gesture->module);
|
||||
atomic_set(&gsx_gesture->registered, 0);
|
||||
if (!module_initialized)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
|
||||
sysfs_remove_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
goodix_gesture_enable(0);
|
||||
|
||||
kobject_put(&gsx_gesture->module.kobj);
|
||||
}
|
||||
/* deinit sysfs */
|
||||
for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
|
||||
sysfs_remove_file(&gsx_gesture->module.kobj,
|
||||
&gesture_attrs[i].attr);
|
||||
|
||||
kobject_put(&gsx_gesture->module.kobj);
|
||||
kfree(gsx_gesture);
|
||||
}
|
||||
|
||||
late_initcall(goodix_gsx_gesture_init);
|
||||
module_exit(goodix_gsx_gesture_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Goodix Touchscreen Gesture Module");
|
||||
MODULE_AUTHOR("Goodix, Inc.");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
module_initialized = false;
|
||||
}
|
||||
2736
drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_inspect.c
Normal file
2736
drivers/input/touchscreen/goodix_berlin_mmi/goodix_ts_inspect.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -45,30 +45,13 @@ static const u16 goodix_tools_ver = ((GOODIX_TOOLS_VER_MAJOR << 8) +
|
|||
#define GTP_READ_CONFIG (_IOW(GOODIX_TS_IOC_MAGIC, 7, u8) & NEGLECT_SIZE_MASK)
|
||||
#define GTP_ESD_ENABLE _IO(GOODIX_TS_IOC_MAGIC, 8)
|
||||
#define GTP_TOOLS_VER (_IOR(GOODIX_TS_IOC_MAGIC, 9, u8) & NEGLECT_SIZE_MASK)
|
||||
#define GTP_TOOLS_CTRL_SYNC (_IOW(GOODIX_TS_IOC_MAGIC, 10, u8) & NEGLECT_SIZE_MASK)
|
||||
|
||||
#define GOODIX_TS_IOC_MAXNR 10
|
||||
#define MAX_BUF_LENGTH (16*1024)
|
||||
#define IRQ_FALG (0x01 << 2)
|
||||
|
||||
#define I2C_MSG_HEAD_LEN 20
|
||||
|
||||
/*
|
||||
* struct goodix_tools_data - goodix tools data message used in sync read
|
||||
* @data: The buffer into which data is written
|
||||
* @reg_addr: Slave device register start address to start read data
|
||||
* @length: Number of data bytes in @data being read from slave device
|
||||
* @filled: When buffer @data be filled will set this flag with 1, outhrwise 0
|
||||
* @list_head:Eonnet every goodix_tools_data struct into a list
|
||||
*/
|
||||
|
||||
struct goodix_tools_data {
|
||||
u32 reg_addr;
|
||||
u32 length;
|
||||
u8 *data;
|
||||
bool filled;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct goodix_tools_dev - goodix tools device struct
|
||||
* @ts_core: The core data struct of ts driver
|
||||
|
|
@ -188,64 +171,6 @@ err_out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* read data from i2c synchronous,
|
||||
* return data length when success, otherwise return < 0
|
||||
*/
|
||||
static int sync_read(struct goodix_tools_dev *dev, void __user *arg)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
|
||||
struct goodix_tools_data tools_data;
|
||||
|
||||
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
|
||||
if (ret) {
|
||||
ts_err("Copy data from user failed");
|
||||
return -EFAULT;
|
||||
}
|
||||
tools_data.reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
|
||||
+ (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
|
||||
tools_data.length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
|
||||
+ (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
|
||||
tools_data.filled = 0;
|
||||
if (tools_data.length > MAX_BUF_LENGTH) {
|
||||
ts_err("buffer too long:%d > %d",
|
||||
tools_data.length, MAX_BUF_LENGTH);
|
||||
return -EINVAL;
|
||||
}
|
||||
tools_data.data = kzalloc(tools_data.length, GFP_KERNEL);
|
||||
if (!tools_data.data) {
|
||||
ts_err("Alloc memory failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
list_add_tail(&tools_data.list, &dev->head);
|
||||
mutex_unlock(&dev->mutex);
|
||||
/* wait queue will timeout after 1 seconds */
|
||||
wait_event_interruptible_timeout(dev->wq, tools_data.filled == 1, HZ * 3);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
list_del(&tools_data.list);
|
||||
mutex_unlock(&dev->mutex);
|
||||
if (!tools_data.filled) {
|
||||
ret = -EAGAIN;
|
||||
ts_err("Wait queue timeout");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = copy_to_user((u8 *)arg + I2C_MSG_HEAD_LEN,
|
||||
tools_data.data, tools_data.length);
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
ts_err("Copy_to_user failed");
|
||||
goto out;
|
||||
}
|
||||
ret = tools_data.length;
|
||||
out:
|
||||
kfree(tools_data.data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* write data to i2c asynchronous,
|
||||
* success return bytes write, else return <= 0
|
||||
*/
|
||||
|
|
@ -351,11 +276,6 @@ static long goodix_tools_ioctl(struct file *filp, unsigned int cmd,
|
|||
ts_err("Bad magic num:%c", _IOC_TYPE(cmd));
|
||||
return -ENOTTY;
|
||||
}
|
||||
if (_IOC_NR(cmd) > GOODIX_TS_IOC_MAXNR) {
|
||||
ts_err("Bad cmd num:%d > %d",
|
||||
_IOC_NR(cmd), GOODIX_TS_IOC_MAXNR);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
switch (cmd & NEGLECT_SIZE_MASK) {
|
||||
case GTP_IRQ_ENABLE:
|
||||
|
|
@ -425,14 +345,7 @@ static long goodix_tools_ioctl(struct file *filp, unsigned int cmd,
|
|||
ts_err("Async data read failed");
|
||||
break;
|
||||
case GTP_SYNC_READ:
|
||||
if (filp->f_flags & O_NONBLOCK) {
|
||||
ts_err("Goodix tools now worked in sync_bus mode");
|
||||
ret = -EAGAIN;
|
||||
goto err_out;
|
||||
}
|
||||
ret = sync_read(dev, (void __user *)arg);
|
||||
if (ret < 0)
|
||||
ts_err("Sync data read failed");
|
||||
ts_info("unsupport sync read");
|
||||
break;
|
||||
case GTP_ASYNC_WRITE:
|
||||
ret = async_write(dev, (void __user *)arg);
|
||||
|
|
@ -445,6 +358,10 @@ static long goodix_tools_ioctl(struct file *filp, unsigned int cmd,
|
|||
if (ret)
|
||||
ts_err("failed copy driver version info to user");
|
||||
break;
|
||||
case GTP_TOOLS_CTRL_SYNC:
|
||||
ts_core->tools_ctrl_sync = !!arg;
|
||||
ts_info("set tools ctrl sync %d", ts_core->tools_ctrl_sync);
|
||||
break;
|
||||
default:
|
||||
ts_info("Invalid cmd");
|
||||
ret = -ENOTTY;
|
||||
|
|
@ -489,41 +406,13 @@ static int goodix_tools_release(struct inode *inode, struct file *filp)
|
|||
{
|
||||
int ret = 0;
|
||||
/* when the last close this dev node unregister the module */
|
||||
goodix_tools_dev->ts_core->tools_ctrl_sync = false;
|
||||
atomic_set(&goodix_tools_dev->in_use, 0);
|
||||
goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
|
||||
ret = goodix_unregister_ext_module(&goodix_tools_dev->module);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* goodix_tools_module_irq - goodix tools Irq handle
|
||||
* This functions is excuted when interrupt happended
|
||||
*
|
||||
* @core_data: pointer to touch core data
|
||||
* @module: pointer to goodix_ext_module struct
|
||||
* return: EVT_CONTINUE let other module handle this irq
|
||||
*/
|
||||
static int goodix_tools_module_irq(struct goodix_ts_core *core_data,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
struct goodix_tools_dev *dev = module->priv_data;
|
||||
const struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
|
||||
struct goodix_tools_data *tools_data, *next;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
if (!list_empty(&dev->head)) {
|
||||
list_for_each_entry_safe(tools_data, next, &dev->head, list) {
|
||||
if (!hw_ops->read(core_data, tools_data->reg_addr,
|
||||
tools_data->data, tools_data->length)) {
|
||||
tools_data->filled = 1;
|
||||
}
|
||||
}
|
||||
wake_up(&dev->wq);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
return EVT_CONTINUE;
|
||||
}
|
||||
|
||||
static int goodix_tools_module_init(struct goodix_ts_core *core_data,
|
||||
struct goodix_ext_module *module)
|
||||
{
|
||||
|
|
@ -566,7 +455,6 @@ static struct miscdevice goodix_tools_miscdev = {
|
|||
};
|
||||
|
||||
static struct goodix_ext_module_funcs goodix_tools_module_funcs = {
|
||||
.irq_event = goodix_tools_module_irq,
|
||||
.init = goodix_tools_module_init,
|
||||
.exit = goodix_tools_module_exit,
|
||||
};
|
||||
|
|
@ -576,7 +464,7 @@ static struct goodix_ext_module_funcs goodix_tools_module_funcs = {
|
|||
*
|
||||
* return: 0 success, else failed
|
||||
*/
|
||||
static int __init goodix_tools_init(void)
|
||||
int goodix_tools_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -601,20 +489,15 @@ static int __init goodix_tools_init(void)
|
|||
ret = misc_register(&goodix_tools_miscdev);
|
||||
if (ret)
|
||||
ts_err("Debug tools miscdev register failed");
|
||||
else
|
||||
ts_info("Debug tools miscdev register success");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit goodix_tools_exit(void)
|
||||
void goodix_tools_exit(void)
|
||||
{
|
||||
misc_deregister(&goodix_tools_miscdev);
|
||||
kfree(goodix_tools_dev);
|
||||
ts_info("Goodix tools miscdev exit");
|
||||
ts_info("Debug tools miscdev exit");
|
||||
}
|
||||
|
||||
late_initcall(goodix_tools_init);
|
||||
module_exit(goodix_tools_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Goodix tools Module");
|
||||
MODULE_AUTHOR("Goodix, Inc.");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
#include "goodix_ts_core.h"
|
||||
|
||||
bool debug_log_flag = false;
|
||||
|
||||
/*****************************************************************************
|
||||
* goodix_append_checksum
|
||||
* @summary
|
||||
|
|
@ -119,3 +121,59 @@ u32 goodix_get_file_config_id(u8 *ic_config)
|
|||
return 0;
|
||||
return le32_to_cpup((__le32 *)&ic_config[CONFIG_ID_OFFSET]);
|
||||
}
|
||||
|
||||
/* matrix transpose */
|
||||
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data)
|
||||
{
|
||||
s16 *temp_buf = NULL;
|
||||
int size = tx * rx;
|
||||
int i;
|
||||
int j;
|
||||
int col;
|
||||
|
||||
temp_buf = kcalloc(size, sizeof(s16), GFP_KERNEL);
|
||||
if (!temp_buf) {
|
||||
ts_err("malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0, col = 0; i < size; i++) {
|
||||
temp_buf[i] = data[j++ * rx + col];
|
||||
if (j == tx) {
|
||||
j = 0;
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(data, temp_buf, size * sizeof(s16));
|
||||
kfree(temp_buf);
|
||||
}
|
||||
|
||||
/* get ic type */
|
||||
int goodix_get_ic_type(struct device_node *node)
|
||||
{
|
||||
const char *name_tmp;
|
||||
int ret;
|
||||
|
||||
ret = of_property_read_string(node, "compatible", &name_tmp);
|
||||
if (ret < 0) {
|
||||
ts_err("get compatible failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (strstr(name_tmp, "9897")) {
|
||||
ts_info("ic type is BerlinA");
|
||||
ret = IC_TYPE_BERLIN_A;
|
||||
} else if (strstr(name_tmp, "9966") || strstr(name_tmp, "7986")) {
|
||||
ts_info("ic type is BerlinB");
|
||||
ret = IC_TYPE_BERLIN_B;
|
||||
} else if (strstr(name_tmp, "9916")) {
|
||||
ts_info("ic type is BerlinD");
|
||||
ret = IC_TYPE_BERLIN_D;
|
||||
} else {
|
||||
ts_info("can't find valid ic_type");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
Loading…
Reference in a new issue