dlkm: chipone_tddi_fhd: add initial chipone fhd tddi driver

chipone_tddi_fhd_mmi:
Add initial fhd tddi touch driver. This driver is for icnl9922 and
later fhd driver.

Change-Id: I2cce6e8d624e56fbaae963c4da47ad0c063f7e65
Reviewed-on: https://gerrit.mot.com/2209608
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Yeqing Wang <wangyq13@motorola.com>
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Reviewed-by: Jun Weng <wengjun1@motorola.com>
Submit-Approved: panyq6 <panyq6@motorola.com>
This commit is contained in:
wingte49 2022-03-08 10:43:35 +08:00 • committed by bijiaming01
commit a0a0b42641
28 changed files with 17707 additions and 0 deletions

View file

@ -0,0 +1,17 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
ifeq ($(DLKM_INSTALL_TO_VENDOR_OUT),true)
CHIPONE_MMI_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/modules/
else
CHIPONE_MMI_MODULE_PATH := $(KERNEL_MODULES_OUT)
endif
ifeq ($(CHIPONE_ESD),true)
KERNEL_CFLAGS += CONFIG_CHIPONE_ESD=y
endif
include $(CLEAR_VARS)
LOCAL_MODULE := chipone_tddi_fhd_mmi.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(CHIPONE_MMI_MODULE_PATH)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -0,0 +1,26 @@
# 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/chipone_tddi_fhd_mmi
ifneq ($(filter m y,$(CONFIG_CHIPONE_ESD)),)
EXTRA_CFLAGS += -DCONFIG_CTS_ESD_PROTECTION
endif
#EXTRA_CFLAGS += -DCONFIG_CTS_I2C_HOST
obj-m := chipone_tddi_fhd_mmi.o
chipone_tddi_fhd_mmi-objs += cts_i2c_driver.o
chipone_tddi_fhd_mmi-objs += cts_core.o
chipone_tddi_fhd_mmi-objs += cts_platform.o
chipone_tddi_fhd_mmi-objs += cts_sfctrlv2.o
chipone_tddi_fhd_mmi-objs += cts_spi_flash.o
chipone_tddi_fhd_mmi-objs += cts_firmware.o
chipone_tddi_fhd_mmi-objs += cts_tool.o
chipone_tddi_fhd_mmi-objs += cts_sysfs.o
chipone_tddi_fhd_mmi-objs += cts_test.o
chipone_tddi_fhd_mmi-objs += cts_charger_detect.o
chipone_tddi_fhd_mmi-objs += cts_hostcomm.o
chipone_tddi_fhd_mmi-objs += cts_tcs.o

View file

@ -0,0 +1,22 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
obj-$(CONFIG_TOUCHSCREEN_CHIPONE) += chipone-tddi.o
chipone-tddi-objs := cts_i2c_driver.o
chipone-tddi-objs += cts_core.o cts_sfctrlv2.o cts_spi_flash.o cts_firmware.o cts_test.o
chipone-tddi-objs += cts_charger_detect.o
chipone-tddi-objs += cts_hostcomm.o
chipone-tddi-objs += cts_tcs.o
chipone-tddi-objs += cts_platform.o
chipone-tddi-objs += cts_tool.o
chipone-tddi-objs += cts_sysfs.o

View file

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
static u8 icnl9911s_driver_builtin_firmware[] = {
};
static u8 icnl9911c_driver_builtin_firmware[] = {
};
const static struct cts_firmware cts_driver_builtin_firmwares[] = {
{
.name = "OEM-Project", /* MUST set non-NULL */
.hwid = CTS_DEV_HWID_ICNL9911S,
.fwid = CTS_DEV_FWID_ICNL9911S,
.data = icnl9911s_driver_builtin_firmware,
.size = ARRAY_SIZE(icnl9911s_driver_builtin_firmware),
},
{
.name = "OEM-Project", /* MUST set non-NULL */
.hwid = CTS_DEV_HWID_ICNL9911C,
.fwid = CTS_DEV_FWID_ICNL9911C,
.data = icnl9911c_driver_builtin_firmware,
.size = ARRAY_SIZE(icnl9911c_driver_builtin_firmware),
},
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_CHARGER_DETECT_H
#define CTS_CHARGER_DETECT_H
#include "cts_config.h"
struct chipone_ts_data;
#ifdef CONFIG_CTS_CHARGER_DETECT
extern int cts_charger_detect_init(struct chipone_ts_data *cts_data);
extern int cts_charger_detect_deinit(struct chipone_ts_data *cts_data);
extern int cts_start_charger_detect(struct chipone_ts_data *cts_data);
extern int cts_stop_charger_detect(struct chipone_ts_data *cts_data);
extern int cts_is_charger_attached(struct chipone_ts_data *cts_data,
bool *attached);
#else /* CONFIG_CTS_CHARGER_DETECT */
static inline int cts_charger_detect_init(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_charger_detect_deinit(struct chipone_ts_data *cts_data)
{
return -ENOTSUPP;
}
static inline int cts_start_charger_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_stop_charger_detect(struct chipone_ts_data *cts_data)
{
return -ENODEV;
}
static inline int cts_is_charger_attached(struct chipone_ts_data *cts_data,
bool *attached)
{
return -ENODEV;
}
#endif /* CONFIG_CTS_CHARGER_DETECT */
#endif /* CTS_CHARGER_DETECT_H */

View file

@ -0,0 +1,143 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_CONFIG_H
#define CTS_CONFIG_H
/** Driver version */
#define CFG_CTS_DRIVER_MAJOR_VERSION 3
#define CFG_CTS_DRIVER_MINOR_VERSION 0
#define CFG_CTS_DRIVER_PATCH_VERSION 0
#define CFG_CTS_DRIVER_VERSION "v3.0.9"
/** Whether reset pin is used */
#define CFG_CTS_HAS_RESET_PIN
/* #define CONFIG_CTS_I2C_HOST */
#ifndef CONFIG_CTS_I2C_HOST
#ifndef CFG_CTS_HAS_RESET_PIN
#define CFG_CTS_HAS_RESET_PIN
#endif
#define CFG_CTS_SPI_SPEED_KHZ 6000
#endif
#define CFG_CTS_FORCE_UP
#define CONFIG_GENERIC_HARDIRQS
//#define CFG_CTS_FW_LOG_REDIRECT
/** Whether force download firmware to chip */
/* #define CFG_CTS_FIRMWARE_FORCE_UPDATE */
/** Use build in firmware or firmware file in fs*/
/* #define CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
#define CFG_CTS_FIRMWARE_IN_FS
#ifdef CFG_CTS_FIRMWARE_IN_FS
/* Add FW custom process. */
/* #define CFG_CTS_FW_UPDATE_SYS */
/* Load config fw bin as default. */
/* #define CFG_CTS_FW_UPDATE_FILE_LOAD */
#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD
#define CFG_CTS_FW_FILE_NAME_MAX_LEN 128
#define CFG_CTS_FW_FILE_PATH "/vendor/firmware/"
#define CFG_CTS_FW_FILE_NAME_VENDOR "chipone"
#endif /*CFG_CTS_FW_UPDATE_FILE_LOAD */
#define CFG_CTS_FIRMWARE_FILENAME_9911 "ICNL9911.bin"
#define CFG_CTS_FIRMWARE_FILENAME_9916 "ICNL9916.bin"
#define CFG_CTS_FIRMWARE_FILENAME_9922 "ICNL9922.bin"
#define CFG_CTS_FIRMWARE_FILEPATH_9911 "/vendor/firmware/ICNL9911.bin"
#define CFG_CTS_FIRMWARE_FILEPATH_9916 "/vendor/firmware/ICNL9916.bin"
#define CFG_CTS_FIRMWARE_FILEPATH_9922 "/vendor/firmware/ICNL9922.bin"
#endif /* CFG_CTS_FIRMWARE_IN_FS */
/* IC type support */
#define CFG_CTS_CHIP_NAME "ICNL9911S"
#ifdef CONFIG_PROC_FS
/* Proc FS for backward compatibility for APK tool com.ICN85xx */
#define CONFIG_CTS_LEGACY_TOOL
#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_SYSFS
/* Sys FS for gesture report, debug feature etc. */
#define CONFIG_CTS_SYSFS
#endif /* CONFIG_SYSFS */
#define CFG_CTS_MAX_TOUCH_NUM (10) // 5
/* Virtual key support */
/* #define CONFIG_CTS_VIRTUALKEY */
#ifdef CONFIG_CTS_VIRTUALKEY
#define CFG_CTS_MAX_VKEY_NUM (4)
#define CFG_CTS_NUM_VKEY (3)
#define CFG_CTS_VKEY_KEYCODES {KEY_BACK, KEY_HOME, KEY_MENU}
#endif /* CONFIG_CTS_VIRTUALKEY */
/* Gesture wakeup */
/* #define CFG_CTS_GESTURE */
#ifdef CFG_CTS_GESTURE
#define GESTURE_UP 0x11
#define GESTURE_C 0x12
#define GESTURE_O 0x13
#define GESTURE_M 0x14
#define GESTURE_W 0x15
#define GESTURE_E 0x16
#define GESTURE_S 0x17
#define GESTURE_Z 0x1d
#define GESTURE_V 0x1e
#define GESTURE_D_TAP 0x50
#define GESTURE_DOWN 0x22
#define GESTURE_LEFT 0x23
#define GESTURE_RIGHT 0x24
#define CFG_CTS_NUM_GESTURE (13u)
#define CFG_CTS_GESTURE_REPORT_KEY
#define CFG_CTS_GESTURE_KEYMAP \
({
{GESTURE_C, KEY_C,},
{GESTURE_W, KEY_W,},
{GESTURE_V, KEY_V,},
{GESTURE_D_TAP, KEY_F1,},
{GESTURE_Z, KEY_Z,},
{GESTURE_M, KEY_M,},
{GESTURE_O, KEY_O,},
{GESTURE_E, KEY_E,},
{GESTURE_S, KEY_S,},
{GESTURE_UP, KEY_UP,},
{GESTURE_DOWN, KEY_DOWN,},
{GESTURE_LEFT, KEY_LEFT,},
{GESTURE_RIGHT, KEY_RIGHT,},
})
#define CFG_CTS_GESTURE_REPORT_TRACE 0
#endif /* CFG_CTS_GESTURE */
/* #define CONFIG_CTS_GLOVE */
#define CONFIG_CTS_CHARGER_DETECT
/* ESD protection */
/* #define CONFIG_CTS_ESD_PROTECTION */
#ifdef CONFIG_CTS_ESD_PROTECTION
#define CFG_CTS_ESD_PROTECTION_CHECK_PERIOD (2 * HZ)
#define CFG_CTS_ESD_FAILED_CONFIRM_CNT 3
#endif /* CONFIG_CTS_ESD_PROTECTION */
/* Use slot protocol (protocol B), comment it if use protocol A. */
#define CONFIG_CTS_SLOTPROTOCOL
#ifdef CONFIG_CTS_LEGACY_TOOL
#define CFG_CTS_TOOL_PROC_FILENAME "icn85xx_tool"
#endif /* CONFIG_CTS_LEGACY_TOOL */
#define CFG_CTS_UPDATE_CRCCHECK
/****************************************************************************
* Platform configurations
****************************************************************************/
#include "cts_plat_qcom_config.h"
#endif /* CTS_CONFIG_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,890 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_CORE_H
#define CTS_CORE_H
#include "cts_config.h"
enum cts_dev_hw_reg {
CTS_DEV_HW_REG_HARDWARE_ID = 0x30000u,
CTS_DEV_HW_REG_CLOCK_GATING = 0x30004u,
CTS_DEV_HW_REG_RESET_CONFIG = 0x30008u,
CTS_DEV_HW_REG_BOOT_MODE = 0x30010u,
CTS_DEV_HW_REG_CURRENT_MODE = 0x30011u,
};
enum cts_dev_boot_mode {
CTS_DEV_BOOT_MODE_IDLE = 0,
CTS_DEV_BOOT_MODE_FLASH = 1,
CTS_DEV_BOOT_MODE_I2C_PRG_9911C = 2,
CTS_DEV_BOOT_MODE_TCH_PRG_9916 = 2,
CTS_DEV_BOOT_MODE_SRAM = 3,
CTS_DEV_BOOT_MODE_DDI_PRG = 4,
CTS_DEV_BOOT_MODE_SPI_PRG_9911C = 5,
CTS_DEV_BOOT_MODE_MASK = 7,
};
/** I2C addresses(7bits), transfer size and bitrate */
#define CTS_DEV_NORMAL_MODE_I2CADDR (0x48)
#define CTS_DEV_PROGRAM_MODE_I2CADDR (0x30)
#define CTS_DEV_NORMAL_MODE_ADDR_WIDTH (2)
#define CTS_DEV_PROGRAM_MODE_ADDR_WIDTH (3)
#define CTS_DEV_NORMAL_MODE_SPIADDR (0xF0)
#define CTS_DEV_PROGRAM_MODE_SPIADDR (0x60)
/** Chipone firmware register addresses under normal mode */
enum cts_device_fw_reg {
CTS_DEVICE_FW_REG_WORK_MODE = 0x0000,
CTS_DEVICE_FW_REG_SYS_BUSY = 0x0001,
CTS_DEVICE_FW_REG_DATA_READY = 0x0002,
CTS_DEVICE_FW_REG_CMD = 0x0004,
CTS_DEVICE_FW_REG_POWER_MODE = 0x0005,
CTS_DEVICE_FW_REG_FW_LIB_MAIN_VERSION = 0x0009,
CTS_DEVICE_FW_REG_CHIP_TYPE = 0x000A,
CTS_DEVICE_FW_REG_VERSION = 0x000C,
CTS_DEVICE_FW_REG_DDI_VERSION = 0x0010,
CTS_DEVICE_FW_REG_GET_WORK_MODE = 0x003F,
CTS_DEVICE_FW_REG_FW_LIB_SUB_VERSION = 0x0047,
CTS_DEVICE_FW_REG_COMPENSATE_CAP_READY = 0x004E,
CTS_DEVICE_FW_REG_TOUCH_INFO = 0x1000,
CTS_DEVICE_FW_REG_RAW_DATA = 0x2000,
CTS_DEVICE_FW_REG_DIFF_DATA = 0x3000,
CTS_DEVICE_FW_REG_GESTURE_INFO = 0x7000,
CTS_DEVICE_FW_REG_PANEL_PARAM = 0x8000,
CTS_DEVICE_FW_REG_NUM_TX = 0x8007,
CTS_DEVICE_FW_REG_NUM_RX = 0x8008,
CTS_DEVICE_FW_REG_INT_KEEP_TIME = 0x8047, /* Unit us */
CTS_DEVICE_FW_REG_RAWDATA_TARGET = 0x8049,
CTS_DEVICE_FW_REG_X_RESOLUTION = 0x8090,
CTS_DEVICE_FW_REG_Y_RESOLUTION = 0x8092,
CTS_DEVICE_FW_REG_SWAP_AXES = 0x8094,
CTS_DEVICE_FW_REG_GLOVE_MODE = 0x8095,
CTS_DEVICE_FW_REG_TEST_WITH_DISPLAY_ON = 0x80A3,
CTS_DEVICE_FW_REG_INT_MODE = 0x80D8,
CTS_DEVICE_FW_REG_EARJACK_DETECT_SUPP = 0x8113,
CTS_DEVICE_FW_REG_AUTO_COMPENSATE_EN = 0x8114,
CTS_DEVICE_FW_REG_ESD_PROTECTION = 0x8156, /* RW */
CTS_DEVICE_FW_REG_FLAG_BITS = 0x8158,
CTS_DEVICE_FW_REG_COMPENSATE_CAP = 0xA000,
CTS_DEVICE_FW_REG_DEBUG_INTF = 0xF000,
};
/** Hardware IDs, read from hardware id register */
enum cts_dev_hwid {
CTS_DEV_HWID_ICNL9911 = 0x990100u,
CTS_DEV_HWID_ICNL9911S = 0x990110u,
CTS_DEV_HWID_ICNL9911C = 0x991110u,
CTS_DEV_HWID_ICNL9916 = 0x990160u,
CTS_DEV_HWID_ICNL9922 = 0x990220u,
CTS_DEV_HWID_ANY = 0,
CTS_DEV_HWID_INVALID = 0xFFFFFFFFu,
};
/* Firmware IDs, read from firmware register @ref CTS_DEV_FW_REG_CHIP_TYPE
* under normal mode
*/
enum cts_dev_fwid {
CTS_DEV_FWID_ICNL9911 = 0x9911u,
CTS_DEV_FWID_ICNL9911S = 0x9964u,
CTS_DEV_FWID_ICNL9911C = 0x9954u,
CTS_DEV_FWID_ICNL9916 = 0x9916u,
CTS_DEV_FWID_ICNL9922 = 0x9922u,
CTS_DEV_FWID_ANY = 0u,
CTS_DEV_FWID_INVALID = 0xFFFFu
};
/** Commands written to firmware register @ref CTS_DEVICE_FW_REG_CMD under normal mode */
enum cts_firmware_cmd {
CTS_CMD_RESET = 1,
CTS_CMD_SUSPEND = 2,
CTS_CMD_ENTER_WRITE_PARA_TO_FLASH_MODE = 3,
CTS_CMD_WRITE_PARA_TO_FLASH = 4,
CTS_CMD_WRTITE_INT_HIGH = 5,
CTS_CMD_WRTITE_INT_LOW = 6,
CTS_CMD_RELASE_INT_TEST = 7,
CTS_CMD_RECOVERY_TX_VOL = 0x10,
CTS_CMD_DEC_TX_VOL_1 = 0x11,
CTS_CMD_DEC_TX_VOL_2 = 0x12,
CTS_CMD_DEC_TX_VOL_3 = 0x13,
CTS_CMD_DEC_TX_VOL_4 = 0x14,
CTS_CMD_DEC_TX_VOL_5 = 0x15,
CTS_CMD_DEC_TX_VOL_6 = 0x16,
CTS_CMD_ENABLE_READ_RAWDATA = 0x20,
CTS_CMD_DISABLE_READ_RAWDATA = 0x21,
CTS_CMD_SUSPEND_WITH_GESTURE = 0x40,
CTS_CMD_QUIT_GESTURE_MONITOR = 0x41,
CTS_CMD_CHARGER_ATTACHED = 0x55,
CTS_CMD_EARJACK_ATTACHED = 0x57,
CTS_CMD_EARJACK_DETACHED = 0x58,
CTS_CMD_CHARGER_DETACHED = 0x66,
CTS_CMD_ENABLE_FW_LOG_REDIRECT = 0x86,
CTS_CMD_DISABLE_FW_LOG_REDIRECT = 0x87,
CTS_CMD_ENABLE_READ_CNEG = 0x88,
CTS_CMD_DISABLE_READ_CNEG = 0x89,
CTS_CMD_FW_LOG_SHOW_FINISH = 0xE0,
};
#pragma pack(1)
/** Touch message read back from chip */
struct cts_device_touch_msg {
u8 id;
__le16 x;
__le16 y;
u8 pressure;
u8 event;
#define CTS_DEVICE_TOUCH_EVENT_NONE (0)
#define CTS_DEVICE_TOUCH_EVENT_DOWN (1)
#define CTS_DEVICE_TOUCH_EVENT_MOVE (2)
#define CTS_DEVICE_TOUCH_EVENT_STAY (3)
#define CTS_DEVICE_TOUCH_EVENT_UP (4)
};
/** Touch information read back from chip */
struct cts_device_touch_info {
u8 vkey_state;
u8 num_msg;
struct cts_device_touch_msg msgs[CFG_CTS_MAX_TOUCH_NUM];
};
/** Gesture trace point read back from chip */
struct cts_device_gesture_point {
__le16 x;
__le16 y;
u8 pressure;
u8 event;
};
/** Gesture information read back from chip */
struct cts_device_gesture_info {
u8 gesture_id;
#define CTS_GESTURE_UP (0x11)
#define CTS_GESTURE_C (0x12)
#define CTS_GESTURE_O (0x13)
#define CTS_GESTURE_M (0x14)
#define CTS_GESTURE_W (0x15)
#define CTS_GESTURE_E (0x16)
#define CTS_GESTURE_S (0x17)
#define CTS_GESTURE_B (0x18)
#define CTS_GESTURE_T (0x19)
#define CTS_GESTURE_H (0x1A)
#define CTS_GESTURE_F (0x1B)
#define CTS_GESTURE_X (0x1C)
#define CTS_GESTURE_Z (0x1D)
#define CTS_GESTURE_V (0x1E)
#define CTS_GESTURE_D_TAP (0x50)
u8 num_points;
#define CTS_CHIP_MAX_GESTURE_TRACE_POINT (64u)
struct cts_device_gesture_point points[CTS_CHIP_MAX_GESTURE_TRACE_POINT];
};
#pragma pack()
struct cts_device;
enum cts_crc_type {
CTS_CRC16 = 1,
CTS_CRC32 = 2,
};
/** Chip hardware data, will never change */
struct cts_device_hwdata {
const char *name;
u32 hwid;
u16 fwid;
u8 num_row;
u8 num_col;
u32 sram_size;
/* Address width under program mode */
u8 program_addr_width;
const struct cts_sfctrl *sfctrl;
int (*enable_access_ddi_reg)(struct cts_device *cts_dev, bool enable);
};
enum int_data_type {
INT_DATA_TYPE_NONE = 0,
INT_DATA_TYPE_RAWDATA = BIT(0),
INT_DATA_TYPE_MANUAL_DIFF = BIT(1),
INT_DATA_TYPE_REAL_DIFF = BIT(2),
INT_DATA_TYPE_NOISE_DIFF = BIT(3),
INT_DATA_TYPE_BASEDATA = BIT(4),
INT_DATA_TYPE_CNEGDATA = BIT(5),
INT_DATA_TYPE_MASK = 0x3F,
};
enum int_data_method {
INT_DATA_METHOD_NONE,
INT_DATA_METHOD_HOST,
INT_DATA_METHOD_POLLING,
};
/** Chip firmware data */
struct cts_device_fwdata {
u16 version;
u16 res_x;
u16 res_y;
u8 rows;
u8 cols;
bool flip_x;
bool flip_y;
bool swap_axes;
u8 ddi_version;
u8 int_mode;
u8 esd_method;
u16 lib_version;
u16 int_keep_time;
u16 rawdata_target;
bool has_int_data;
u8 int_data_method;
u16 int_data_types;
size_t int_data_size;
};
/** Chip runtime data */
struct cts_device_rtdata {
u8 slave_addr;
int addr_width;
bool program_mode;
bool has_flash;
bool suspended;
bool updating;
bool testing;
bool gesture_wakeup_enabled;
bool charger_exist;
bool fw_log_redirect_enabled;
bool glove_mode_enabled;
struct cts_device_touch_info touch_info;
u8 *int_data;
};
struct cts_dev_ops {
int (*get_fw_ver)(const struct cts_device *cts_dev, u16 *fwver);
int (*get_lib_ver)(const struct cts_device *cts_dev, u16 *libver);
int (*get_ddi_ver)(const struct cts_device *cts_dev, u8 *ddiver);
int (*get_res_x)(const struct cts_device *cts_dev, u16 *res_x);
int (*get_res_y)(const struct cts_device *cts_dev, u16 *res_y);
int (*get_rows)(const struct cts_device *cts_dev, u8 *rows);
int (*get_cols)(const struct cts_device *cts_dev, u8 *cols);
int (*get_flip_x)(const struct cts_device *cts_dev, bool *flip_x);
int (*get_flip_y)(const struct cts_device *cts_dev, bool *flip_y);
int (*get_swap_axes)(const struct cts_device *cts_dev,
bool *swap_axes);
int (*get_int_mode)(const struct cts_device *cts_dev, u8 *int_mode);
int (*get_int_keep_time)(const struct cts_device *cts_dev,
u16 *int_keep_time);
int (*get_esd_method)(const struct cts_device *cts_dev,
u8 *esd_method);
int (*get_touchinfo)(const struct cts_device *cts_dev,
struct cts_device_touch_info *touch_info);
int (*get_esd_protection)(const struct cts_device *cts_dev,
u8 *esd_protection);
int (*get_data_ready_flag)(const struct cts_device *cts_dev,
u8 *ready);
int (*clr_data_ready_flag)(const struct cts_device *cts_dev);
int (*enable_get_rawdata)(const struct cts_device *cts_dev);
int (*is_enabled_get_rawdata)(const struct cts_device *cts_dev,
u8 *enabled);
int (*disable_get_rawdata)(const struct cts_device *cts_dev);
int (*enable_get_cneg)(const struct cts_device *cts_dev);
int (*disable_get_cneg)(const struct cts_device *cts_dev);
int (*is_cneg_ready)(const struct cts_device *cts_dev, u8 *ready);
int (*quit_guesture_mode)(const struct cts_device *cts_dev);
int (*get_rawdata)(const struct cts_device *cts_dev, u8 *buf);
int (*get_diffdata)(const struct cts_device *cts_dev, u8 *buf);
int (*get_basedata)(const struct cts_device *cts_dev, u8 *buf);
int (*get_cneg)(const struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*read_hw_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int (*write_hw_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int (*read_ddi_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int (*write_ddi_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int (*read_fw_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int (*write_fw_reg)(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int (*read_reg)(const struct cts_device *cts_dev, uint16_t cmd,
u8 *rbuf, size_t rlen);
int (*write_reg)(const struct cts_device *cts_dev, uint16_t cmd,
u8 *wbuf, size_t wlen);
int (*get_fw_id)(const struct cts_device *cts_dev, u16 *fwid);
int (*get_workmode)(const struct cts_device *cts_dev, u8 *workmode);
int (*set_workmode)(const struct cts_device *cts_dev, u8 workmode);
int (*set_openshort_mode)(const struct cts_device *cts_dev, u8 mode);
int (*set_tx_vol)(const struct cts_device *cts_dev, u8 txvol);
int (*set_short_test_type)(const struct cts_device *cts_dev,
u8 short_type);
int (*set_openshort_enable)(const struct cts_device *cts_dev,
u8 enable);
int (*is_openshort_enabled)(const struct cts_device *cts_dev,
u8 *enabled);
int (*set_esd_enable)(const struct cts_device *cts_dev, u8 enable);
int (*set_cneg_enable)(const struct cts_device *cts_dev, u8 enable);
int (*set_mnt_enable)(const struct cts_device *cts_dev, u8 enable);
int (*is_display_on)(const struct cts_device *cts_dev,
u8 *display_on);
int (*set_display_on)(const struct cts_device *cts_dev, u8 display_on);
int (*is_cneg_enabled)(const struct cts_device *cts_dev, u8 *enabled);
int (*is_mnt_enabled)(const struct cts_device *cts_dev, u8 *enabled);
int (*set_pwr_mode)(const struct cts_device *cts_dev, u8 pwr_mode);
int (*read_sram_normal_mode)(const struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry,
int delay);
int (*init_int_data)(struct cts_device *cts_dev);
int (*deinit_int_data)(struct cts_device *cts_dev);
int (*get_has_int_data)(const struct cts_device *cts_dev,
bool *has_int_data);
int (*get_int_data_method)(const struct cts_device *cts_dev,
u8 *int_data_method);
int (*set_int_data_method)(const struct cts_device *cts_dev,
u8 int_data_method);
int (*get_int_data_types)(const struct cts_device *cts_dev,
u16 *int_data_types);
int (*set_int_data_types)(const struct cts_device *cts_dev,
u16 int_data_types);
int (*calc_int_data_size)(struct cts_device *cts_dev);
int (*polling_data)(const struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*polling_test_data)(const struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_rawdata)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_manual_diff)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_real_diff)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_noise_diff)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_basedata)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*top_get_cnegdata)(struct cts_device *cts_dev, u8 *buf,
size_t size);
int (*reset_device)(const struct cts_device *cts_dev);
};
struct cts_device {
struct cts_platform_data *pdata;
const struct cts_device_hwdata *hwdata;
struct cts_device_fwdata fwdata;
struct cts_device_rtdata rtdata;
const struct cts_flash *flash;
bool enabled;
#ifdef CFG_CTS_FW_UPDATE_FILE_LOAD
char config_fw_name[CFG_CTS_FW_FILE_NAME_MAX_LEN + 1];
#endif /* CFG_CTS_FW_UPDATE_FILE_LOAD */
struct cts_dev_ops *ops;
u8 *tx;
u8 *rx;
};
struct cts_platform_data;
struct chipone_ts_data {
#ifdef CONFIG_CTS_I2C_HOST
struct i2c_client *i2c_client;
#else
struct spi_device *spi_client;
#endif /* CONFIG_CTS_I2C_HOST */
struct device *device;
struct cts_device cts_dev;
struct cts_platform_data *pdata;
struct workqueue_struct *workqueue;
struct delayed_work fw_upgrade_work;
struct work_struct ts_resume_work;
#ifdef CONFIG_CTS_CHARGER_DETECT
void *charger_detect_data;
#endif /* CONFIG_CTS_CHARGER_DETECT */
#ifdef CONFIG_CTS_ESD_PROTECTION
struct workqueue_struct *esd_workqueue;
struct delayed_work esd_work;
bool esd_enabled;
int esd_check_fail_cnt;
#endif /* CONFIG_CTS_ESD_PROTECTION */
#ifdef CONFIG_CTS_LEGACY_TOOL
struct proc_dir_entry *procfs_entry;
#endif /* CONFIG_CTS_LEGACY_TOOL */
bool force_reflash;
};
static inline u32 get_unaligned_le24(const void *p)
{
const u8 *puc = (const u8 *)p;
return (puc[0] | (puc[1] << 8) | (puc[2] << 16));
}
static inline u32 get_unaligned_be24(const void *p)
{
const u8 *puc = (const u8 *)p;
return (puc[2] | (puc[1] << 8) | (puc[0] << 16));
}
static inline void put_unaligned_be24(u32 v, void *p)
{
u8 *puc = (u8 *) p;
puc[0] = (v >> 16) & 0xFF;
puc[1] = (v >> 8) & 0xFF;
puc[2] = (v >> 0) & 0xFF;
}
#define wrap(max, x) ((max) - 1 - (x))
extern void cts_lock_device(const struct cts_device *cts_dev);
extern void cts_unlock_device(const struct cts_device *cts_dev);
extern int cts_dev_readb(const struct cts_device *cts_dev,
u32 addr, u8 *b, int retry, int delay);
extern int cts_dev_writeb(const struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
extern int cts_sram_writeb_retry(const struct cts_device *cts_dev,
u32 addr, u8 b, int retry, int delay);
extern int cts_sram_writew_retry(const struct cts_device *cts_dev,
u32 addr, u16 w, int retry, int delay);
extern int cts_sram_writel_retry(const struct cts_device *cts_dev,
u32 addr, u32 l, int retry, int delay);
extern int cts_sram_writesb_retry(const struct cts_device *cts_dev,
u32 addr, const void *src, size_t len,
int retry, int delay);
extern int cts_sram_writesb_check_crc_retry(const struct cts_device *cts_dev,
u32 addr, const void *src,
size_t len, u32 crc, int retry);
extern int cts_sram_readb_retry(const struct cts_device *cts_dev,
u32 addr, u8 *b, int retry, int delay);
extern int cts_sram_readw_retry(const struct cts_device *cts_dev,
u32 addr, u16 *w, int retry, int delay);
extern int cts_sram_readl_retry(const struct cts_device *cts_dev,
u32 addr, u32 *l, int retry, int delay);
extern int cts_sram_readsb_retry(const struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry,
int delay);
extern int cts_fw_reg_writeb_retry(const struct cts_device *cts_dev,
u32 reg_addr, u8 b, int retry, int delay);
extern int cts_fw_reg_writew_retry(const struct cts_device *cts_dev,
u32 reg_addr, u16 w, int retry, int delay);
extern int cts_fw_reg_writel_retry(const struct cts_device *cts_dev,
u32 reg_addr, u32 l, int retry, int delay);
extern int cts_fw_reg_writesb_retry(const struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len,
int retry, int delay);
extern int cts_fw_reg_readb_retry(const struct cts_device *cts_dev,
u32 reg_addr, u8 *b, int retry, int delay);
extern int cts_fw_reg_readw_retry(const struct cts_device *cts_dev,
u32 reg_addr, u16 *w, int retry, int delay);
extern int cts_fw_reg_readl_retry(const struct cts_device *cts_dev,
u32 reg_addr, u32 *l, int retry, int delay);
extern int cts_fw_reg_readsb_retry(const struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len,
int retry, int delay);
extern int cts_fw_reg_readsb_retry_delay_idle(const struct cts_device *cts_dev,
u32 reg_addr, void *dst,
size_t len, int retry, int delay,
int idle);
extern int cts_hw_reg_writeb_retry(const struct cts_device *cts_dev,
u32 reg_addr, u8 b, int retry, int delay);
extern int cts_hw_reg_writew_retry(const struct cts_device *cts_dev,
u32 reg_addr, u16 w, int retry, int delay);
extern int cts_hw_reg_writel_retry(const struct cts_device *cts_dev,
u32 reg_addr, u32 l, int retry, int delay);
extern int cts_hw_reg_writesb_retry(const struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len,
int retry, int delay);
extern int cts_hw_reg_readb_retry(const struct cts_device *cts_dev,
u32 reg_addr, u8 *b, int retry, int delay);
extern int cts_hw_reg_readw_retry(const struct cts_device *cts_dev,
u32 reg_addr, u16 *w, int retry, int delay);
extern int cts_hw_reg_readl_retry(const struct cts_device *cts_dev,
u32 reg_addr, u32 *l, int retry, int delay);
extern int cts_hw_reg_readsb_retry(const struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len,
int retry, int delay);
static inline int cts_hw_reg_readb(const struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writeb(const struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writew(const struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_writeb(const struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_fw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_fw_reg_writew(const struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_fw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_writel(const struct cts_device *cts_dev,
u32 reg_addr, u32 l)
{
return cts_fw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_fw_reg_writesb(const struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len)
{
return cts_fw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0);
}
static inline int cts_fw_reg_readb(const struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_fw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_fw_reg_readw(const struct cts_device *cts_dev,
u32 reg_addr, u16 *w)
{
return cts_fw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_fw_reg_readl(const struct cts_device *cts_dev,
u32 reg_addr, u32 *l)
{
return cts_fw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_fw_reg_readsb(const struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len)
{
return cts_fw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0);
}
static inline int cts_fw_reg_readsb_delay_idle(const struct cts_device *cts_dev,
u32 reg_addr, void *dst,
size_t len, int idle)
{
return cts_fw_reg_readsb_retry_delay_idle(cts_dev, reg_addr, dst, len,
1, 0, idle);
}
static inline int cts_hw_reg_writeb_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u8 b)
{
return cts_hw_reg_writeb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_writew_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u16 w)
{
return cts_hw_reg_writew_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_hw_reg_writel_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u32 l)
{
return cts_hw_reg_writel_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_hw_reg_writesb(const struct cts_device *cts_dev,
u32 reg_addr, const void *src, size_t len)
{
return cts_hw_reg_writesb_retry(cts_dev, reg_addr, src, len, 1, 0);
}
static inline int cts_hw_reg_readb_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u8 *b)
{
return cts_hw_reg_readb_retry(cts_dev, reg_addr, b, 1, 0);
}
static inline int cts_hw_reg_readw_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u16 *w)
{
return cts_hw_reg_readw_retry(cts_dev, reg_addr, w, 1, 0);
}
static inline int cts_hw_reg_readl_relaxed(const struct cts_device *cts_dev,
u32 reg_addr, u32 *l)
{
return cts_hw_reg_readl_retry(cts_dev, reg_addr, l, 1, 0);
}
static inline int cts_hw_reg_readsb(const struct cts_device *cts_dev,
u32 reg_addr, void *dst, size_t len)
{
return cts_hw_reg_readsb_retry(cts_dev, reg_addr, dst, len, 1, 0);
}
static inline int cts_sram_writeb(const struct cts_device *cts_dev,
u32 addr, u8 b)
{
return cts_sram_writeb_retry(cts_dev, addr, b, 1, 0);
}
static inline int cts_sram_writew(const struct cts_device *cts_dev,
u32 addr, u16 w)
{
return cts_sram_writew_retry(cts_dev, addr, w, 1, 0);
}
static inline int cts_sram_writel(const struct cts_device *cts_dev,
u32 addr, u32 l)
{
return cts_sram_writel_retry(cts_dev, addr, l, 1, 0);
}
static inline int cts_sram_writesb(const struct cts_device *cts_dev, u32 addr,
const void *src, size_t len)
{
return cts_sram_writesb_retry(cts_dev, addr, src, len, 1, 0);
}
static inline int cts_sram_readb(const struct cts_device *cts_dev,
u32 addr, u8 *b)
{
return cts_sram_readb_retry(cts_dev, addr, b, 1, 0);
}
static inline int cts_sram_readw(const struct cts_device *cts_dev,
u32 addr, u16 *w)
{
return cts_sram_readw_retry(cts_dev, addr, w, 1, 0);
}
static inline int cts_sram_readl(const struct cts_device *cts_dev,
u32 addr, u32 *l)
{
return cts_sram_readl_retry(cts_dev, addr, l, 1, 0);
}
static inline int cts_sram_readsb(const struct cts_device *cts_dev,
u32 addr, void *dst, size_t len)
{
return cts_sram_readsb_retry(cts_dev, addr, dst, len, 1, 0);
}
#ifdef CONFIG_CTS_I2C_HOST
static inline void cts_set_program_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_I2CADDR;
cts_dev->rtdata.program_mode = true;
cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH;
}
static inline void cts_set_normal_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_I2CADDR;
cts_dev->rtdata.program_mode = false;
cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH;
}
#else
static inline void cts_set_program_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_PROGRAM_MODE_SPIADDR;
cts_dev->rtdata.program_mode = true;
cts_dev->rtdata.addr_width = CTS_DEV_PROGRAM_MODE_ADDR_WIDTH;
}
static inline void cts_set_normal_addr(struct cts_device *cts_dev)
{
cts_dev->rtdata.slave_addr = CTS_DEV_NORMAL_MODE_SPIADDR;
cts_dev->rtdata.program_mode = false;
cts_dev->rtdata.addr_width = CTS_DEV_NORMAL_MODE_ADDR_WIDTH;
}
#endif
extern int cts_irq_handler(struct cts_device *cts_dev);
extern void cts_firmware_upgrade_work(struct work_struct *work);
extern bool cts_is_device_suspended(const struct cts_device *cts_dev);
extern int cts_suspend_device(struct cts_device *cts_dev);
extern int cts_resume_device(struct cts_device *cts_dev);
extern bool cts_is_device_program_mode(const struct cts_device *cts_dev);
extern int cts_enter_program_mode(struct cts_device *cts_dev);
extern int cts_enter_normal_mode(struct cts_device *cts_dev);
extern int cts_probe_device(struct cts_device *cts_dev);
extern int cts_set_work_mode(const struct cts_device *cts_dev, u8 mode);
extern int cts_get_work_mode(const struct cts_device *cts_dev, u8 *mode);
extern int cts_get_firmware_version(const struct cts_device *cts_dev,
u16 *version);
extern int cts_get_ddi_version(const struct cts_device *cts_dev, u8 *version);
extern int cts_get_lib_version(const struct cts_device *cts_dev,
u16 *lib_version);
extern int cts_get_data_ready_flag(const struct cts_device *cts_dev, u8 *flag);
extern int cts_clr_data_ready_flag(const struct cts_device *cts_dev);
extern int cts_send_command(const struct cts_device *cts_dev, u8 cmd);
extern int cts_get_panel_param(const struct cts_device *cts_dev,
void *param, size_t size);
extern int cts_set_panel_param(const struct cts_device *cts_dev,
const void *param, size_t size);
extern int cts_get_x_resolution(const struct cts_device *cts_dev,
u16 *resolution);
extern int cts_get_y_resolution(const struct cts_device *cts_dev,
u16 *resolution);
extern int cts_get_num_rows(const struct cts_device *cts_dev, u8 *num_rows);
extern int cts_get_num_cols(const struct cts_device *cts_dev, u8 *num_cols);
extern int cts_enable_get_rawdata(const struct cts_device *cts_dev);
extern int cts_disable_get_rawdata(const struct cts_device *cts_dev);
extern int cts_polling_data(const struct cts_device *cts_dev, void *buf,
size_t size);
extern int cts_polling_test_data(const struct cts_device *cts_dev, void *buf,
size_t size);
extern int cts_get_rawdata(const struct cts_device *cts_dev, void *buf);
extern int cts_get_diffdata(const struct cts_device *cts_dev, void *buf);
extern int cts_get_basedata(const struct cts_device *cts_dev, void *buf);
extern int cts_get_compensate_cap(struct cts_device *cts_dev, u8 *cap);
extern int cts_get_fwid(struct cts_device *cts_dev, u16 *fwid);
extern int cts_get_hwid(struct cts_device *cts_dev, u32 *hwid);
extern int cts_read_sram_normal_mode(const struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry,
int delay);
#ifdef CFG_CTS_GESTURE
extern void cts_enable_gesture_wakeup(struct cts_device *cts_dev);
extern void cts_disable_gesture_wakeup(struct cts_device *cts_dev);
extern bool cts_is_gesture_wakeup_enabled(const struct cts_device *cts_dev);
extern int cts_get_gesture_info(const struct cts_device *cts_dev,
void *gesture_info, bool trace_point);
#endif /* CFG_CTS_GESTURE */
extern int cts_set_int_data_types(struct cts_device *cts_dev, u16 types);
extern int cts_set_int_data_method(struct cts_device *cts_dev, u8 method);
#ifdef CONFIG_CTS_ESD_PROTECTION
extern void cts_init_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_enable_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_disable_esd_protection(struct chipone_ts_data *cts_data);
extern void cts_deinit_esd_protection(struct chipone_ts_data *cts_data);
#else /* CONFIG_CTS_ESD_PROTECTION */
static inline void cts_init_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_enable_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_disable_esd_protection(struct chipone_ts_data *cts_data)
{
}
static inline void cts_deinit_esd_protection(struct chipone_ts_data *cts_data)
{
}
#endif /* CONFIG_CTS_ESD_PROTECTION */
#ifdef CONFIG_CTS_GLOVE
extern int cts_enter_glove_mode(struct cts_device *cts_dev);
extern int cts_exit_glove_mode(struct cts_device *cts_dev);
int cts_is_glove_enabled(const struct cts_device *cts_dev);
#else
static inline int cts_enter_glove_mode(struct cts_device *cts_dev)
{
return 0;
}
static inline int cts_exit_glove_mode(struct cts_device *cts_dev)
{
return 0;
}
static inline int cts_is_glove_enabled(const struct cts_device *cts_dev)
{
return 0;
}
#endif
#ifdef CONFIG_CTS_CHARGER_DETECT
extern bool cts_is_charger_exist(struct cts_device *cts_dev);
extern int cts_set_dev_charger_attached(struct cts_device *cts_dev,
bool attached);
#else /* CONFIG_CTS_CHARGER_DETECT */
static inline bool cts_is_charger_exist(struct cts_device *cts_dev)
{
return false;
}
static inline int cts_set_dev_charger_attached(struct cts_device *cts_dev,
bool attached)
{
return 0;
}
#endif /* CONFIG_CTS_CHARGER_DETECT */
#ifdef CONFIG_CTS_LEGACY_TOOL
extern int cts_tool_init(struct chipone_ts_data *cts_data);
extern void cts_tool_deinit(struct chipone_ts_data *data);
#else /* CONFIG_CTS_LEGACY_TOOL */
static inline int cts_tool_init(struct chipone_ts_data *cts_data)
{
return 0;
}
static inline void cts_tool_deinit(struct chipone_ts_data *data)
{
}
#endif /* CONFIG_CTS_LEGACY_TOOL */
extern bool cts_is_device_enabled(const struct cts_device *cts_dev);
extern int cts_start_device(struct cts_device *cts_dev);
extern int cts_stop_device(struct cts_device *cts_dev);
#ifdef CFG_CTS_FW_LOG_REDIRECT
extern int cts_enable_fw_log_redirect(struct cts_device *cts_dev);
extern int cts_disable_fw_log_redirect(struct cts_device *cts_dev);
extern bool cts_is_fw_log_redirect(struct cts_device *cts_dev);
extern int cts_fw_log_show_finish(struct cts_device *cts_dev);
#endif
#ifdef CFG_CTS_UPDATE_CRCCHECK
extern int cts_sram_writesb_boot_crc_retry(const struct cts_device *cts_dev,
size_t len, u32 crc, int retry);
#endif
extern const char *cts_dev_boot_mode2str(u8 boot_mode);
extern bool cts_is_fwid_valid(u16 fwid);
extern void cts_deinit_rtdata(struct cts_device *cts_dev);
extern int cts_reset_device(struct cts_device *cts_dev);
#endif /* CTS_CORE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_FIRMWARE_H
#define CTS_FIRMWARE_H
#include "cts_config.h"
#include <linux/firmware.h>
struct cts_firmware {
const char *name; /* MUST set to non-NULL if driver builtin firmware */
u32 hwid;
u16 fwid;
u8 *data;
size_t size;
const struct firmware *fw;
};
#define FIRMWARE_VERSION_OFFSET 0x100
#define FIRMWARE_VERSION(firmware) \
get_unaligned_le16((firmware)->data + FIRMWARE_VERSION_OFFSET)
struct cts_device;
extern const struct cts_firmware *cts_request_firmware(const struct cts_device
*cts_dev, u32 hwid,
u16 fwid,
u16 device_fw_ver);
extern void cts_release_firmware(const struct cts_firmware *firmware);
#ifdef CFG_CTS_DRIVER_BUILTIN_FIRMWARE
extern int cts_get_num_driver_builtin_firmware(void);
extern const struct cts_firmware
*cts_request_driver_builtin_firmware_by_name(const char *name);
extern const struct cts_firmware
*cts_request_driver_builtin_firmware_by_index(u32 index);
#else /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
static inline int cts_get_num_driver_builtin_firmware(void)
{
return 0;
}
static inline const struct cts_firmware
*cts_request_driver_builtin_firmware_by_name(const char *name)
{
return NULL;
}
static inline const struct cts_firmware
*cts_request_driver_builtin_firmware_by_index(u32 index)
{
return NULL;
}
#endif /* CFG_CTS_DRIVER_BUILTIN_FIRMWARE */
extern bool cts_is_firmware_updating(const struct cts_device *cts_dev);
extern int cts_update_firmware(struct cts_device *cts_dev,
const struct cts_firmware *firmware,
bool to_flash);
#ifdef CFG_CTS_FIRMWARE_IN_FS
extern const struct cts_firmware *cts_request_firmware_from_fs(const struct
cts_device
*cts_dev,
const char
*filepath);
extern int cts_update_firmware_from_file(struct cts_device *cts_dev,
const char *filepath, bool to_flash);
#endif /* CFG_CTS_FIRMWARE_IN_FS */
extern u16 cts_crc16(const u8 *data, size_t len);
extern u32 cts_crc32(const u8 *data, size_t len);
#endif /* CTS_FIRMWARE_H */

View file

@ -0,0 +1,533 @@
// SPDX-License-Identifier: GPL-2.0
#include "cts_config.h"
#include "cts_firmware.h"
#include "cts_platform.h"
#include "cts_hostcomm.h"
extern bool set_short_test_type(const struct cts_device *cts_dev, u8 type);
extern int disable_fw_monitor_mode(const struct cts_device *cts_dev);
extern int disable_fw_auto_compensate(const struct cts_device *cts_dev);
extern int disable_fw_esd_protection(const struct cts_device *cts_dev);
extern int set_fw_work_mode(const struct cts_device *cts_dev, u8 mode);
extern int set_display_state(const struct cts_device *cts_dev, bool active);
int cts_hostcomm_get_fw_ver(const struct cts_device *cts_dev, u16 *fwver)
{
return cts_get_firmware_version(cts_dev, fwver);
}
int cts_hostcomm_get_lib_ver(const struct cts_device *cts_dev, u16 *libver)
{
return cts_get_lib_version(cts_dev, libver);
}
int cts_hostcomm_get_ddi_ver(const struct cts_device *cts_dev, u8 *ddiver)
{
return cts_get_ddi_version(cts_dev, ddiver);
}
int cts_hostcomm_get_res_x(const struct cts_device *cts_dev, u16 *res_x)
{
return cts_get_x_resolution(cts_dev, res_x);
}
int cts_hostcomm_get_res_y(const struct cts_device *cts_dev, u16 *res_y)
{
return cts_get_y_resolution(cts_dev, res_y);
}
int cts_hostcomm_get_rows(const struct cts_device *cts_dev, u8 *rows)
{
return cts_get_num_rows(cts_dev, rows);
}
int cts_hostcomm_get_cols(const struct cts_device *cts_dev, u8 *cols)
{
return cts_get_num_cols(cts_dev, cols);
}
int cts_hostcomm_get_flip_x(const struct cts_device *cts_dev, bool *flip_x)
{
u8 val;
int ret;
ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FLAG_BITS, &val);
if (ret < 0)
return ret;
*flip_x = !!(val & BIT(2));
return 0;
}
int cts_hostcomm_get_flip_y(const struct cts_device *cts_dev, bool *flip_y)
{
u8 val;
int ret;
ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_FLAG_BITS, &val);
if (ret < 0)
return ret;
*flip_y = !!(val & BIT(3));
return 0;
}
int cts_hostcomm_get_swap_axes(const struct cts_device *cts_dev,
bool *swap_axes)
{
u8 val;
int ret;
ret = cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_SWAP_AXES, &val);
if (ret < 0)
return ret;
*swap_axes = !!val;
return 0;
}
int cts_hostcomm_get_int_mode(const struct cts_device *cts_dev, u8 *int_mode)
{
return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_INT_MODE, int_mode);
}
int cts_hostcomm_get_int_keep_time(const struct cts_device *cts_dev,
u16 *int_keep_time)
{
return cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_INT_KEEP_TIME,
int_keep_time);
}
int cts_hostcomm_get_esd_method(const struct cts_device *cts_dev,
u8 *esd_method)
{
return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_ESD_PROTECTION,
esd_method);
}
int cts_hostcomm_get_esd_protection(const struct cts_device *cts_dev,
u8 *esd_protection)
{
return cts_fw_reg_readb(cts_dev, 0x8000 + 342, esd_protection);
}
int cts_hostcomm_get_data_ready_flag(const struct cts_device *cts_dev,
u8 *ready)
{
return cts_get_data_ready_flag(cts_dev, ready);
}
int cts_hostcomm_clr_data_ready_flag(const struct cts_device *cts_dev)
{
return cts_clr_data_ready_flag(cts_dev);
}
int cts_hostcomm_enable_get_rawdata(const struct cts_device *cts_dev)
{
return cts_enable_get_rawdata(cts_dev);
}
int cts_hostcomm_disable_get_rawdata(const struct cts_device *cts_dev)
{
return cts_disable_get_rawdata(cts_dev);
}
int cts_hostcomm_enable_get_cneg(const struct cts_device *cts_dev)
{
return cts_send_command(cts_dev, CTS_CMD_ENABLE_READ_CNEG);
}
int cts_hostcomm_disable_get_cneg(const struct cts_device *cts_dev)
{
return cts_send_command(cts_dev, CTS_CMD_DISABLE_READ_CNEG);
}
int cts_hostcomm_is_cneg_ready(const struct cts_device *cts_dev, u8 *ready)
{
return cts_fw_reg_readb(cts_dev,
CTS_DEVICE_FW_REG_COMPENSATE_CAP_READY, ready);
}
int cts_hostcomm_quit_guesture_mode(const struct cts_device *cts_dev)
{
//TODO:
return 0;
}
int cts_hostcomm_get_rawdata(const struct cts_device *cts_dev, u8 *buf)
{
return cts_fw_reg_readsb_delay_idle(cts_dev,
CTS_DEVICE_FW_REG_RAW_DATA,
buf,
cts_dev->fwdata.rows *
cts_dev->fwdata.cols * 2, 500);
}
int cts_hostcomm_get_diffdata(const struct cts_device *cts_dev, u8 *buf)
{
return cts_fw_reg_readsb_delay_idle(cts_dev,
CTS_DEVICE_FW_REG_DIFF_DATA,
buf,
(cts_dev->fwdata.rows + 2) *
(cts_dev->fwdata.cols + 2) * 2,
500);
}
int cts_hostcomm_get_basedata(const struct cts_device *cts_dev, u8 *buf)
{
//TODO:
return 0;
}
int cts_hostcomm_get_cneg(const struct cts_device *cts_dev, u8 *buf,
size_t size)
{
return cts_fw_reg_readsb_delay_idle(cts_dev,
CTS_DEVICE_FW_REG_COMPENSATE_CAP,
buf,
cts_dev->hwdata->num_row *
cts_dev->hwdata->num_col, 500);
}
int cts_hostcomm_read_hw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
return cts_hw_reg_readsb_retry(cts_dev, addr, regbuf, size, 3, 100);
}
int cts_hostcomm_write_hw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
return cts_hw_reg_writesb_retry(cts_dev, addr, regbuf, size, 3, 100);
}
int cts_hostcomm_read_ddi_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
int ret = -1;
cts_err("%s: BUG! Should not be here!", __func__);
return ret;
}
int cts_hostcomm_write_ddi_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
int ret = -1;
cts_err("%s: BUG! Should not be here!", __func__);
return ret;
}
int cts_hostcomm_read_reg(const struct cts_device *cts_dev, uint16_t cmd,
u8 *rbuf, size_t rlen)
{
int ret = -1;
cts_err("%s: BUG! Should not be here!", __func__);
return ret;
}
int cts_hostcomm_write_reg(const struct cts_device *cts_dev, uint16_t cmd,
u8 *wbuf, size_t wlen)
{
int ret = -1;
cts_err("%s: BUG! Should not be here!", __func__);
return ret;
}
int cts_hostcomm_read_fw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
return cts_fw_reg_readsb(cts_dev, addr, regbuf, size);
}
int cts_hostcomm_write_fw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size)
{
return cts_fw_reg_writesb(cts_dev, addr, regbuf, size);
}
int cts_hostcomm_get_touchinfo(const struct cts_device *cts_dev,
struct cts_device_touch_info *touch_info)
{
memset(touch_info, 0, sizeof(*touch_info));
return cts_fw_reg_readsb(cts_dev, CTS_DEVICE_FW_REG_TOUCH_INFO,
touch_info, sizeof(*touch_info));
}
int cts_hostcomm_get_fw_id(const struct cts_device *cts_dev, u16 *fwid)
{
u16 tmp = 0xffff;
int ret;
ret = cts_fw_reg_readw(cts_dev, CTS_DEVICE_FW_REG_CHIP_TYPE, &tmp);
tmp = be16_to_cpu(tmp);
*fwid = tmp;
cts_info("%s:%04X", __func__, tmp);
return ret;
}
int cts_hostcomm_get_workmode(const struct cts_device *cts_dev, u8 *workmode)
{
return cts_fw_reg_readb(cts_dev, CTS_DEVICE_FW_REG_GET_WORK_MODE,
workmode);
}
int cts_hostcomm_set_workmode(const struct cts_device *cts_dev, u8 workmode)
{
return set_fw_work_mode(cts_dev, workmode);
}
int cts_hostcomm_set_openshort_mode(const struct cts_device *cts_dev, u8 type)
{
int i, ret;
cts_info("Set test type %d", type);
for (i = 0; i < 5; i++) {
u8 type_readback;
ret = cts_fw_reg_writeb(cts_dev, 0x34, type);
if (ret) {
cts_err("Write test type register to failed %d", ret);
continue;
}
ret = cts_fw_reg_readb(cts_dev, 0x34, &type_readback);
if (ret) {
cts_err("Read test type register failed %d", ret);
continue;
}
if (type != type_readback) {
cts_err("Set test type %u != readback %u", type,
type_readback);
ret = -EFAULT;
continue;
}
}
return ret;
}
int cts_hostcomm_set_tx_vol(const struct cts_device *cts_dev, u8 txvol)
{
return cts_send_command(cts_dev, CTS_CMD_RECOVERY_TX_VOL);
}
int cts_hostcomm_is_enabled_get_rawdata(const struct cts_device *cts_dev,
u8 *enabled)
{
return cts_fw_reg_readb(cts_dev, 0x12, enabled);
}
int cts_hostcomm_set_short_test_type(const struct cts_device *cts_dev,
u8 short_type)
{
return set_short_test_type(cts_dev, short_type);
}
int cts_hostcomm_is_openshort_enabled(const struct cts_device *cts_dev,
u8 *enabled)
{
int ret = -1;
cts_err("BUG! Should not be here!");
return ret;
}
int cts_hostcomm_set_openshort_enable(const struct cts_device *cts_dev,
u8 enable)
{
int ret = -1;
cts_err("BUG! Should not be here!");
return ret;
}
int cts_hostcomm_set_esd_enable(const struct cts_device *cts_dev, u8 enable)
{
int ret = -1;
if (!enable)
return disable_fw_esd_protection(cts_dev);
return ret;
}
int cts_hostcomm_is_cneg_enabled(const struct cts_device *cts_dev, u8 *enabled)
{
return cts_fw_reg_readb(cts_dev, 0x8000 + 276, enabled);
}
int cts_hostcomm_is_mnt_enabled(const struct cts_device *cts_dev, u8 *enabled)
{
return cts_fw_reg_readb(cts_dev, 0x8000 + 344, enabled);
}
int cts_hostcomm_set_cneg_enable(const struct cts_device *cts_dev, u8 enable)
{
int ret = -1;
if (!enable)
return disable_fw_auto_compensate(cts_dev);
return ret;
}
int cts_hostcomm_set_mnt_enable(const struct cts_device *cts_dev, u8 enable)
{
int ret = -1;
if (!enable)
return disable_fw_monitor_mode(cts_dev);
return ret;
}
int cts_hostcomm_is_display_on(const struct cts_device *cts_dev,
u8 *display_on)
{
return cts_fw_reg_readb(cts_dev, 0x8000 + 163, display_on);
}
int cts_hostcomm_set_pwr_mode(const struct cts_device *cts_dev, u8 pwr_mode)
{
//TODO:
return 0;
}
int cts_hostcomm_set_display_on(const struct cts_device *cts_dev, u8 display_on)
{
return set_display_state(cts_dev, false);
}
int cts_hostcomm_top_get_rawdata(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
//TODO: moved from sysfs:rawdata_show
//TODO:
return 0;
}
int cts_hostcomm_top_get_manual_diff(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
//TODO:
return 0;
}
int cts_hostcomm_top_get_real_diff(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
//TODO:
return 0;
}
int cts_hostcomm_top_get_noise_diff(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
//TODO:
return 0;
}
int cts_hostcomm_top_get_basedata(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
//TODO:
return 0;
}
int cts_hostcomm_top_get_cnegdata(struct cts_device *cts_dev, u8 *buf,
size_t size)
{
return cts_get_compensate_cap(cts_dev, buf);
}
int cts_hostcomm_reset_device(const struct cts_device *cts_dev)
{
return cts_plat_reset_device(cts_dev->pdata);
}
struct cts_dev_ops hostcomm_ops = {
.get_fw_ver = cts_hostcomm_get_fw_ver,
.get_lib_ver = cts_hostcomm_get_lib_ver,
.get_ddi_ver = cts_hostcomm_get_ddi_ver,
.get_res_x = cts_hostcomm_get_res_x,
.get_res_y = cts_hostcomm_get_res_y,
.get_rows = cts_hostcomm_get_rows,
.get_cols = cts_hostcomm_get_cols,
.get_flip_x = cts_hostcomm_get_flip_x,
.get_flip_y = cts_hostcomm_get_flip_y,
.get_swap_axes = cts_hostcomm_get_swap_axes,
.get_int_mode = cts_hostcomm_get_int_mode,
.get_int_keep_time = cts_hostcomm_get_int_keep_time,
.get_esd_method = cts_hostcomm_get_esd_method,
.get_touchinfo = cts_hostcomm_get_touchinfo,
.get_esd_protection = cts_hostcomm_get_esd_protection,
.get_data_ready_flag = cts_hostcomm_get_data_ready_flag,
.clr_data_ready_flag = cts_hostcomm_clr_data_ready_flag,
.enable_get_rawdata = cts_hostcomm_enable_get_rawdata,
.is_enabled_get_rawdata = cts_hostcomm_is_enabled_get_rawdata,
.disable_get_rawdata = cts_hostcomm_disable_get_rawdata,
.enable_get_cneg = cts_hostcomm_enable_get_cneg,
.disable_get_cneg = cts_hostcomm_disable_get_cneg,
.is_cneg_ready = cts_hostcomm_is_cneg_ready,
.quit_guesture_mode = cts_hostcomm_quit_guesture_mode,
.get_rawdata = cts_hostcomm_get_rawdata,
.get_diffdata = cts_hostcomm_get_diffdata,
.get_basedata = cts_hostcomm_get_basedata,
.get_cneg = cts_hostcomm_get_cneg,
.read_hw_reg = cts_hostcomm_read_hw_reg,
.write_hw_reg = cts_hostcomm_write_hw_reg,
.read_ddi_reg = cts_hostcomm_read_ddi_reg,
.write_ddi_reg = cts_hostcomm_write_ddi_reg,
.read_fw_reg = cts_hostcomm_read_fw_reg,
.write_fw_reg = cts_hostcomm_write_fw_reg,
.read_reg = cts_hostcomm_read_reg,
.write_reg = cts_hostcomm_write_reg,
.get_fw_id = cts_hostcomm_get_fw_id,
.get_workmode = cts_hostcomm_get_workmode,
.set_workmode = cts_hostcomm_set_workmode,
.set_openshort_mode = cts_hostcomm_set_openshort_mode,
.set_tx_vol = cts_hostcomm_set_tx_vol,
.set_short_test_type = cts_hostcomm_set_short_test_type,
.set_openshort_enable = cts_hostcomm_set_openshort_enable,
.is_openshort_enabled = cts_hostcomm_is_openshort_enabled,
.set_esd_enable = cts_hostcomm_set_esd_enable,
.set_cneg_enable = cts_hostcomm_set_cneg_enable,
.set_mnt_enable = cts_hostcomm_set_mnt_enable,
.is_display_on = cts_hostcomm_is_display_on,
.set_display_on = cts_hostcomm_set_display_on,
.is_cneg_enabled = cts_hostcomm_is_cneg_enabled,
.is_mnt_enabled = cts_hostcomm_is_mnt_enabled,
.set_pwr_mode = cts_hostcomm_set_pwr_mode,
.read_sram_normal_mode = cts_read_sram_normal_mode,
.init_int_data = NULL, //TODO
.deinit_int_data = NULL, //TODO
.get_has_int_data = NULL,
.get_int_data_types = NULL,
.set_int_data_types = NULL,
.get_int_data_method = NULL,
.set_int_data_method = NULL,
.calc_int_data_size = NULL,
.polling_data = NULL,
.polling_test_data = NULL,
.top_get_rawdata = cts_hostcomm_top_get_rawdata,
.top_get_manual_diff = cts_hostcomm_top_get_manual_diff,
.top_get_real_diff = cts_hostcomm_top_get_real_diff,
.top_get_noise_diff = cts_hostcomm_top_get_noise_diff,
.top_get_basedata = cts_hostcomm_top_get_basedata,
.top_get_cnegdata = cts_hostcomm_top_get_cnegdata,
.reset_device = cts_hostcomm_reset_device,
};
//TODO:
//fwdata->rawdata_target;

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_HOSTCOMM_H
#define CTS_HOSTCOMM_H
#include "cts_config.h"
#include "cts_core.h"
extern struct cts_dev_ops hostcomm_ops;
#endif /* CTS_HOSTCOMM_H */

View file

@ -0,0 +1,960 @@
// SPDX-License-Identifier: GPL-2.0
#define LOG_TAG "I2CDrv"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sysfs.h"
#include "cts_charger_detect.h"
static void cts_resume_work_func(struct work_struct *work);
#ifdef CFG_CTS_DRM_NOTIFIER
#include <drm/drm_panel.h>
static struct drm_panel *active_panel;
static int check_dt(struct device_node *np);
#endif
bool cts_show_debug_log;
#ifdef CTS_MTK_GET_PANEL
static char *active_panel_name;
#endif
module_param_named(debug_log, cts_show_debug_log, bool, 0660);
MODULE_PARM_DESC(debug_log, "Show debug log control");
static int cts_suspend(struct chipone_ts_data *cts_data)
{
int ret;
cts_info("Suspend");
cts_lock_device(&cts_data->cts_dev);
ret = cts_suspend_device(&cts_data->cts_dev);
cts_unlock_device(&cts_data->cts_dev);
if (ret)
cts_err("Suspend device failed %d", ret);
ret = cts_stop_device(&cts_data->cts_dev);
if (ret) {
cts_err("Stop device failed %d", ret);
return ret;
}
#ifdef CFG_CTS_GESTURE
/* Enable IRQ wake if gesture wakeup enabled */
if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) {
ret = cts_plat_enable_irq_wake(cts_data->pdata);
if (ret) {
cts_err("Enable IRQ wake failed %d", ret);
return ret;
}
ret = cts_plat_enable_irq(cts_data->pdata);
if (ret) {
cts_err("Enable IRQ failed %d", ret);
return ret;
}
}
#endif /* CFG_CTS_GESTURE */
/** - To avoid waking up while not sleeping,
*delay 20ms to ensure reliability
*/
msleep(20);
return 0;
}
static int cts_resume(struct chipone_ts_data *cts_data)
{
int ret;
cts_info("Resume");
#ifdef CFG_CTS_GESTURE
if (cts_is_gesture_wakeup_enabled(&cts_data->cts_dev)) {
ret = cts_plat_disable_irq_wake(cts_data->pdata);
if (ret)
cts_warn("Disable IRQ wake failed %d", ret);
ret = cts_plat_disable_irq(cts_data->pdata);
if (ret < 0)
cts_err("Disable IRQ failed %d", ret);
}
#endif /* CFG_CTS_GESTURE */
cts_lock_device(&cts_data->cts_dev);
ret = cts_resume_device(&cts_data->cts_dev);
cts_unlock_device(&cts_data->cts_dev);
if (ret) {
cts_warn("Resume device failed %d", ret);
return ret;
}
ret = cts_start_device(&cts_data->cts_dev);
if (ret) {
cts_err("Start device failed %d", ret);
return ret;
}
return 0;
}
static void cts_resume_work_func(struct work_struct *work)
{
struct chipone_ts_data *cts_data =
container_of(work, struct chipone_ts_data, ts_resume_work);
cts_info("%s", __func__);
cts_resume(cts_data);
}
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
#ifdef CFG_CTS_DRM_NOTIFIER
static int fb_notifier_callback(struct notifier_block *nb,
unsigned long action, void *data)
{
volatile int blank;
const struct cts_platform_data *pdata =
container_of(nb, struct cts_platform_data, fb_notifier);
struct chipone_ts_data *cts_data =
container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev);
struct drm_panel_notifier *evdata = data;
cts_info("FB notifier callback");
if (!evdata || !cts_data)
return 0;
blank = *(int *)evdata->data;
cts_info("action=%lu, blank=%d\n", action, blank);
if (action == DRM_PANEL_EARLY_EVENT_BLANK) {
if (blank == DRM_PANEL_BLANK_POWERDOWN)
cts_suspend(cts_data);
} else if (evdata->data) {
blank = *(int *)evdata->data;
if (action == DRM_PANEL_EVENT_BLANK) {
if (blank == DRM_PANEL_BLANK_UNBLANK)
/* cts_resume(cts_data); */
queue_work(cts_data->workqueue,
&cts_data->ts_resume_work);
}
}
return 0;
}
#else
static int fb_notifier_callback(struct notifier_block *nb,
unsigned long action, void *data)
{
volatile int blank;
const struct cts_platform_data *pdata =
container_of(nb, struct cts_platform_data, fb_notifier);
struct chipone_ts_data *cts_data =
container_of(pdata->cts_dev, struct chipone_ts_data, cts_dev);
struct fb_event *evdata = data;
cts_info("FB notifier callback");
if (evdata && evdata->data) {
if (action == FB_EVENT_BLANK) {
blank = *(int *)evdata->data;
if (blank == FB_BLANK_UNBLANK) {
/* cts_resume(cts_data); */
queue_work(cts_data->workqueue,
&cts_data->ts_resume_work);
return NOTIFY_OK;
}
} else if (action == FB_EARLY_EVENT_BLANK) {
blank = *(int *)evdata->data;
if (blank == FB_BLANK_POWERDOWN) {
cts_suspend(cts_data);
return NOTIFY_OK;
}
}
}
return NOTIFY_DONE;
}
#endif
static int cts_init_pm_fb_notifier(struct chipone_ts_data *cts_data)
{
cts_info("Init FB notifier");
cts_data->pdata->fb_notifier.notifier_call = fb_notifier_callback;
#ifdef CFG_CTS_DRM_NOTIFIER
{
int ret = -ENODEV;
if (active_panel) {
ret =
drm_panel_notifier_register(active_panel,
&cts_data->pdata->fb_notifier);
if (ret)
cts_err
("register drm_notifier failed. ret=%d\n",
ret);
}
return ret;
}
#else
return fb_register_client(&cts_data->pdata->fb_notifier);
#endif
}
static int cts_deinit_pm_fb_notifier(struct chipone_ts_data *cts_data)
{
cts_info("Deinit FB notifier");
#ifdef CFG_CTS_DRM_NOTIFIER
{
int ret = 0;
if (active_panel) {
ret =
drm_panel_notifier_unregister(active_panel,
&cts_data->pdata->fb_notifier);
if (ret)
cts_err
("Error occurred while unregistering drm_notifier.\n");
}
return ret;
}
#else
return fb_unregister_client(&cts_data->pdata->fb_notifier);
#endif
}
#endif /* CONFIG_CTS_PM_FB_NOTIFIER */
#ifdef CFG_CTS_DRM_NOTIFIER
static int check_dt(struct device_node *np)
{
int i;
int count;
struct device_node *node;
struct drm_panel *panel;
count = of_count_phandle_with_args(np, "panel", NULL);
if (count <= 0)
return 0;
for (i = 0; i < count; i++) {
node = of_parse_phandle(np, "panel", i);
panel = of_drm_find_panel(node);
of_node_put(node);
if (!IS_ERR(panel)) {
cts_info("check active_panel");
active_panel = panel;
return 0;
}
}
if (node)
pr_err("%s: %s not actived\n", __func__, node->name);
return -ENODEV;
}
static int check_default_tp(struct device_node *dt, const char *prop)
{
const char *active_tp;
const char *compatible;
char *start;
int ret;
ret = of_property_read_string(dt->parent, prop, &active_tp);
if (ret) {
cts_err(" %s:fail to read %s %d\n", __func__, prop, ret);
return -ENODEV;
}
ret = of_property_read_string(dt, "compatible", &compatible);
if (ret < 0) {
cts_err(" %s:fail to read %s %d\n", __func__, "compatible",
ret);
return -ENODEV;
}
start = strnstr(active_tp, compatible, strlen(active_tp));
if (start == NULL) {
cts_err(" %s:no match compatible, %s, %s\n",
__func__, compatible, active_tp);
ret = -ENODEV;
}
return ret;
}
#endif
#ifdef CTS_MTK_GET_PANEL
char panel_name[50] = { 0 };
static int cts_get_panel(void)
{
int ret = -1;
cts_info("enter");
if (saved_command_line) {
char *sub;
char key_prefix[] = "mipi_mot_vid_";
char ic_prefix[] = "icnl";
cts_info("saved_command_line is %s", saved_command_line);
sub = strstr(saved_command_line, key_prefix);
if (sub) {
char *d;
int n, len, len_max = 50;
d = strstr(sub, " ");
if (d)
n = strlen(sub) - strlen(d);
else
n = strlen(sub);
if (n > len_max)
len = len_max;
else
len = n;
strncpy(panel_name, sub, len);
active_panel_name = panel_name;
if (strstr(active_panel_name, ic_prefix))
cts_info("active_panel_name=%s",
active_panel_name);
else {
cts_info("Not chipone panel!");
return ret;
}
} else {
cts_info("chipone active panel not found!");
return ret;
}
} else {
cts_info("saved_command_line null!");
return ret;
}
return 0;
}
#endif
#ifdef CONFIG_CTS_I2C_HOST
static int cts_driver_probe(struct i2c_client *client,
const struct i2c_device_id *id)
#else
static int cts_driver_probe(struct spi_device *client)
#endif
{
struct chipone_ts_data *cts_data = NULL;
int ret = 0;
#ifdef CTS_MTK_GET_PANEL
ret = cts_get_panel();
if (ret) {
cts_info("MTK get chipone panel error");
return ret;
}
#endif
#ifdef CFG_CTS_DRM_NOTIFIER
{
struct device_node *dp = client->dev.of_node;
if (check_dt(dp)) {
if (!check_default_tp(dp, "qcom,i2c-touch-active"))
ret = -EPROBE_DEFER;
else
ret = -ENODEV;
cts_err("%s: %s not actived\n", __func__, dp->name);
return ret;
}
}
#endif
#ifdef CONFIG_CTS_I2C_HOST
cts_info("Probe i2c client: name='%s' addr=0x%02x flags=0x%02x irq=%d",
client->name, client->addr, client->flags, client->irq);
#if !defined(CONFIG_MTK_PLATFORM)
if (client->addr != CTS_DEV_NORMAL_MODE_I2CADDR) {
cts_err("Probe i2c addr 0x%02x != driver config addr 0x%02x",
client->addr, CTS_DEV_NORMAL_MODE_I2CADDR);
return -ENODEV;
};
#endif
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
cts_err("Check functionality failed");
return -ENODEV;
}
#endif
cts_data =
(struct chipone_ts_data *)kzalloc(sizeof(*cts_data), GFP_KERNEL);
if (cts_data == NULL) {
cts_err("Allocate chipone_ts_data failed");
return -ENOMEM;
}
cts_data->pdata = (struct cts_platform_data *)
kzalloc(sizeof(struct cts_platform_data), GFP_KERNEL);
if (cts_data->pdata == NULL) {
cts_err("Allocate cts_platform_data failed");
ret = -ENOMEM;
goto err_free_cts_data;
}
#ifdef CONFIG_CTS_I2C_HOST
i2c_set_clientdata(client, cts_data);
cts_data->i2c_client = client;
cts_data->device = &client->dev;
#else
spi_set_drvdata(client, cts_data);
cts_data->spi_client = client;
cts_data->device = &client->dev;
#endif
cts_init_platform_data(cts_data->pdata, client);
cts_data->cts_dev.pdata = cts_data->pdata;
cts_data->pdata->cts_dev = &cts_data->cts_dev;
cts_data->workqueue =
create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-workqueue");
if (cts_data->workqueue == NULL) {
cts_err("Create workqueue failed");
ret = -ENOMEM;
goto err_deinit_platform_data;
}
#ifdef CONFIG_CTS_ESD_PROTECTION
cts_data->esd_workqueue =
create_singlethread_workqueue(CFG_CTS_DEVICE_NAME "-esd_workqueue");
if (cts_data->esd_workqueue == NULL) {
cts_err("Create esd workqueue failed");
ret = -ENOMEM;
goto err_destroy_workqueue;
}
#endif
ret = cts_plat_request_resource(cts_data->pdata);
if (ret < 0) {
cts_err("Request resource failed %d", ret);
goto err_destroy_esd_workqueue;
}
ret = cts_reset_device(&cts_data->cts_dev);
if (ret < 0) {
cts_err("Reset device failed %d", ret);
goto err_free_resource;
}
ret = cts_probe_device(&cts_data->cts_dev);
if (ret) {
cts_err("Probe device failed %d", ret);
goto err_free_resource;
}
ret = cts_plat_init_touch_device(cts_data->pdata);
if (ret < 0) {
cts_err("Init touch device failed %d", ret);
goto err_free_resource;
}
ret = cts_plat_init_vkey_device(cts_data->pdata);
if (ret < 0) {
cts_err("Init vkey device failed %d", ret);
goto err_deinit_touch_device;
}
ret = cts_plat_init_gesture(cts_data->pdata);
if (ret < 0) {
cts_err("Init gesture failed %d", ret);
goto err_deinit_vkey_device;
}
cts_init_esd_protection(cts_data);
ret = cts_tool_init(cts_data);
if (ret < 0)
cts_warn("Init tool node failed %d", ret);
ret = cts_sysfs_add_device(&client->dev);
if (ret < 0)
cts_warn("Add sysfs entry for device failed %d", ret);
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
ret = cts_init_pm_fb_notifier(cts_data);
if (ret) {
cts_err("Init FB notifier failed %d", ret);
goto err_deinit_sysfs;
}
#endif /* CONFIG_CTS_PM_FB_NOTIFIER */
ret = cts_plat_request_irq(cts_data->pdata);
if (ret < 0) {
cts_err("Request IRQ failed %d", ret);
goto err_register_fb;
}
#ifdef CONFIG_CTS_CHARGE_DETECT
ret = cts_charger_detect_init(cts_data);
if (ret)
cts_err("Init charger detect failed %d", ret);
/* Ignore this error */
#endif
/* Init firmware upgrade work and schedule */
INIT_DELAYED_WORK(&cts_data->fw_upgrade_work,
cts_firmware_upgrade_work);
queue_delayed_work(cts_data->workqueue, &cts_data->fw_upgrade_work,
msecs_to_jiffies(15 * 1000));
INIT_WORK(&cts_data->ts_resume_work, cts_resume_work_func);
return 0;
err_register_fb:
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
cts_deinit_pm_fb_notifier(cts_data);
err_deinit_sysfs:
#endif /* CONFIG_CTS_PM_FB_NOTIFIER */
cts_sysfs_remove_device(&client->dev);
#ifdef CONFIG_CTS_LEGACY_TOOL
cts_tool_deinit(cts_data);
#endif /* CONFIG_CTS_LEGACY_TOOL */
#ifdef CONFIG_CTS_ESD_PROTECTION
cts_deinit_esd_protection(cts_data);
#endif /* CONFIG_CTS_ESD_PROTECTION */
#ifdef CFG_CTS_GESTURE
cts_plat_deinit_gesture(cts_data->pdata);
#endif /* CFG_CTS_GESTURE */
err_deinit_vkey_device:
#ifdef CONFIG_CTS_VIRTUALKEY
cts_plat_deinit_vkey_device(cts_data->pdata);
#endif /* CONFIG_CTS_VIRTUALKEY */
err_deinit_touch_device:
cts_plat_deinit_touch_device(cts_data->pdata);
err_free_resource:
cts_plat_free_resource(cts_data->pdata);
err_destroy_esd_workqueue:
#ifdef CONFIG_CTS_ESD_PROTECTION
destroy_workqueue(cts_data->esd_workqueue);
err_destroy_workqueue:
#endif
destroy_workqueue(cts_data->workqueue);
err_deinit_platform_data:
cts_deinit_platform_data(cts_data->pdata);
kfree(cts_data->pdata);
err_free_cts_data:
kfree(cts_data);
cts_err("Probe failed %d", ret);
return ret;
}
#ifdef CONFIG_CTS_I2C_HOST
static int cts_driver_remove(struct i2c_client *client)
#else
static int cts_driver_remove(struct spi_device *client)
#endif
{
struct chipone_ts_data *cts_data;
int ret = 0;
cts_info("Remove");
#ifdef CONFIG_CTS_I2C_HOST
cts_data = (struct chipone_ts_data *)i2c_get_clientdata(client);
#else
cts_data = (struct chipone_ts_data *)spi_get_drvdata(client);
#endif
if (cts_data) {
ret = cts_stop_device(&cts_data->cts_dev);
if (ret)
cts_warn("Stop device failed %d", ret);
#ifdef CONFIG_CTS_CHARGE_DETECT
cts_charger_detect_deinit(cts_data);
#endif
cts_plat_free_irq(cts_data->pdata);
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
cts_deinit_pm_fb_notifier(cts_data);
#endif /* CONFIG_CTS_PM_FB_NOTIFIER */
cts_tool_deinit(cts_data);
cts_sysfs_remove_device(&client->dev);
cts_deinit_esd_protection(cts_data);
cts_plat_deinit_touch_device(cts_data->pdata);
cts_plat_deinit_vkey_device(cts_data->pdata);
cts_plat_deinit_gesture(cts_data->pdata);
cts_plat_free_resource(cts_data->pdata);
#ifdef CONFIG_CTS_ESD_PROTECTION
if (cts_data->esd_workqueue)
destroy_workqueue(cts_data->esd_workqueue);
#endif
if (cts_data->workqueue)
destroy_workqueue(cts_data->workqueue);
cts_deinit_platform_data(cts_data->pdata);
cts_deinit_rtdata(&cts_data->cts_dev);
if (cts_data->pdata)
kfree(cts_data->pdata);
kfree(cts_data);
} else {
cts_warn
("Chipone i2c driver remove while NULL chipone_ts_data");
return -EINVAL;
}
return ret;
}
#ifdef CONFIG_CTS_PM_LEGACY
static int cts_i2c_driver_suspend(struct device *dev, pm_message_t state)
{
cts_info("Suspend by legacy power management");
return cts_suspend(dev_get_drvdata(dev));
}
static int cts_i2c_driver_resume(struct device *dev)
{
cts_info("Resume by legacy power management");
return cts_resume(dev_get_drvdata(dev));
}
#endif /* CONFIG_CTS_PM_LEGACY */
#ifdef CONFIG_CTS_PM_GENERIC
static int cts_i2c_driver_pm_suspend(struct device *dev)
{
cts_info("Suspend by bus power management");
return cts_suspend(dev_get_drvdata(dev));
}
static int cts_i2c_driver_pm_resume(struct device *dev)
{
cts_info("Resume by bus power management");
return cts_resume(dev_get_drvdata(dev));
}
/* bus control the suspend/resume procedure */
static const struct dev_pm_ops cts_i2c_driver_pm_ops = {
.suspend = cts_i2c_driver_pm_suspend,
.resume = cts_i2c_driver_pm_resume,
};
#endif /* CONFIG_CTS_PM_GENERIC */
#ifdef CONFIG_CTS_SYSFS
static ssize_t reset_pin_show(struct device_driver *driver, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_HAS_RESET_PIN: %c\n",
#ifdef CFG_CTS_HAS_RESET_PIN
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(reset_pin, S_IRUGO, reset_pin_show, NULL);
#else
static DRIVER_ATTR_RO(reset_pin);
#endif
static ssize_t swap_xy_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_SWAP_XY: %c\n",
#ifdef CFG_CTS_SWAP_XY
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(swap_xy, S_IRUGO, swap_xy_show, NULL);
#else
static DRIVER_ATTR_RO(swap_xy);
#endif
static ssize_t wrap_x_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_WRAP_X: %c\n",
#ifdef CFG_CTS_WRAP_X
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(wrap_x, S_IRUGO, wrap_x_show, NULL);
#else
static DRIVER_ATTR_RO(wrap_x);
#endif
static ssize_t wrap_y_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_WRAP_Y: %c\n",
#ifdef CFG_CTS_WRAP_Y
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(wrap_y, S_IRUGO, wrap_y_show, NULL);
#else
static DRIVER_ATTR_RO(wrap_y);
#endif
static ssize_t force_update_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_HAS_RESET_PIN: %c\n",
#ifdef CFG_CTS_FIRMWARE_FORCE_UPDATE
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(force_update, S_IRUGO, force_update_show, NULL);
#else
static DRIVER_ATTR_RO(force_update);
#endif
static ssize_t max_touch_num_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_TOUCH_NUM: %d\n",
CFG_CTS_MAX_TOUCH_NUM);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(max_touch_num, S_IRUGO, max_touch_num_show, NULL);
#else
static DRIVER_ATTR_RO(max_touch_num);
#endif
static ssize_t vkey_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_VIRTUALKEY: %c\n",
#ifdef CONFIG_CTS_VIRTUALKEY
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(vkey, S_IRUGO, vkey_show, NULL);
#else
static DRIVER_ATTR_RO(vkey);
#endif
static ssize_t gesture_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CFG_CTS_GESTURE: %c\n",
#ifdef CFG_CTS_GESTURE
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(gesture, S_IRUGO, gesture_show, NULL);
#else
static DRIVER_ATTR_RO(gesture);
#endif
static ssize_t esd_protection_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_ESD_PROTECTION: %c\n",
#ifdef CONFIG_CTS_ESD_PROTECTION
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(esd_protection, S_IRUGO, esd_protection_show, NULL);
#else
static DRIVER_ATTR_RO(esd_protection);
#endif
static ssize_t slot_protocol_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "CONFIG_CTS_SLOTPROTOCOL: %c\n",
#ifdef CONFIG_CTS_SLOTPROTOCOL
'Y'
#else
'N'
#endif
);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(slot_protocol, S_IRUGO, slot_protocol_show, NULL);
#else
static DRIVER_ATTR_RO(slot_protocol);
#endif
static ssize_t max_xfer_size_show(struct device_driver *dev, char *buf)
{
#ifdef CONFIG_CTS_I2C_HOST
return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_I2C_XFER_SIZE: %d\n",
CFG_CTS_MAX_I2C_XFER_SIZE);
#else
return snprintf(buf, PAGE_SIZE, "CFG_CTS_MAX_SPI_XFER_SIZE: %d\n",
CFG_CTS_MAX_SPI_XFER_SIZE);
#endif
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(max_xfer_size, S_IRUGO, max_xfer_size_show, NULL);
#else
static DRIVER_ATTR_RO(max_xfer_size);
#endif
static ssize_t driver_info_show(struct device_driver *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "Driver version: %s\n",
CFG_CTS_DRIVER_VERSION);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0)
static DRIVER_ATTR(driver_info, S_IRUGO, driver_info_show, NULL);
#else
static DRIVER_ATTR_RO(driver_info);
#endif
static struct attribute *cts_i2c_driver_config_attrs[] = {
&driver_attr_reset_pin.attr,
&driver_attr_swap_xy.attr,
&driver_attr_wrap_x.attr,
&driver_attr_wrap_y.attr,
&driver_attr_force_update.attr,
&driver_attr_max_touch_num.attr,
&driver_attr_vkey.attr,
&driver_attr_gesture.attr,
&driver_attr_esd_protection.attr,
&driver_attr_slot_protocol.attr,
&driver_attr_max_xfer_size.attr,
&driver_attr_driver_info.attr,
NULL
};
static const struct attribute_group cts_i2c_driver_config_group = {
.name = "config",
.attrs = cts_i2c_driver_config_attrs,
};
static const struct attribute_group *cts_i2c_driver_config_groups[] = {
&cts_i2c_driver_config_group,
NULL,
};
#endif /* CONFIG_CTS_SYSFS */
#ifdef CONFIG_CTS_OF
static const struct of_device_id cts_i2c_of_match_table[] = {
{.compatible = CFG_CTS_OF_DEVICE_ID_NAME, },
{ },
};
MODULE_DEVICE_TABLE(of, cts_i2c_of_match_table);
#endif /* CONFIG_CTS_OF */
#ifdef CONFIG_CTS_I2C_HOST
static const struct i2c_device_id cts_device_id_table[] = {
{ CFG_CTS_DEVICE_NAME, 0 },
{ }
};
#else
static const struct spi_device_id cts_device_id_table[] = {
{ CFG_CTS_DEVICE_NAME, 0 },
{ }
};
#endif
#ifdef CONFIG_CTS_I2C_HOST
static struct i2c_driver cts_i2c_driver = {
#else
static struct spi_driver cts_spi_driver = {
#endif
.probe = cts_driver_probe,
.remove = cts_driver_remove,
.driver = {
.name = CFG_CTS_DRIVER_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_CTS_OF
.of_match_table = of_match_ptr(cts_i2c_of_match_table),
#endif /* CONFIG_CTS_OF */
#ifdef CONFIG_CTS_SYSFS
.groups = cts_i2c_driver_config_groups,
#endif /* CONFIG_CTS_SYSFS */
#ifdef CONFIG_CTS_PM_LEGACY
.suspend = cts_i2c_driver_suspend,
.resume = cts_i2c_driver_resume,
#endif /* CONFIG_CTS_PM_LEGACY */
#ifdef CONFIG_CTS_PM_GENERIC
.pm = &cts_i2c_driver_pm_ops,
#endif /* CONFIG_CTS_PM_GENERIC */
},
.id_table = cts_device_id_table,
};
static int __init cts_driver_init(void)
{
cts_info("Init");
#ifdef CONFIG_CTS_I2C_HOST
return i2c_add_driver(&cts_i2c_driver);
#else
pr_err("%s spi", __func__);
return spi_register_driver(&cts_spi_driver);
#endif
}
static void __exit cts_driver_exit(void)
{
cts_info("Exit");
#ifdef CONFIG_CTS_I2C_HOST
i2c_del_driver(&cts_i2c_driver);
#else
spi_unregister_driver(&cts_spi_driver);
#endif
}
module_init(cts_driver_init);
module_exit(cts_driver_exit);
#if KERNEL_VERSION(5, 4, 0) <= LINUX_VERSION_CODE
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
#endif
MODULE_DESCRIPTION("Chipone TDDI touchscreen Driver for QualComm platform");
MODULE_VERSION(CFG_CTS_DRIVER_VERSION);
MODULE_AUTHOR("Miao Defang <dfmiao@chiponeic.com>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_PLAT_QCOM_CONFIG_H
#define CTS_PLAT_QCOM_CONFIG_H
#define CONFIG_CTS_PM_FB_NOTIFIER
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
/*
* #ifdef CONFIG_DRM
* #define CFG_CTS_DRM_NOTIFIER
* #endif
*/
#ifdef CONFIG_DRM
#define CFG_CTS_DRM_NOTIFIER
#endif /*CONFIG_DRM_MSM */
#else /*CONFIG_CTS_PM_FB_NOTIFIER */
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_SUSPEND)
/* #define CONFIG_CTS_PM_GENERIC */
#endif /* CONFIG_PM_SLEEP */
#if !defined(CONFIG_CTS_PM_GENERIC)
#define CONFIG_CTS_PM_LEGACY
#endif /*CONFIG_CTS_PM_GENERIC */
#endif /*CONFIG_CTS_PM_FB_NOTIFIER */
#define CFG_CTS_MAX_I2C_XFER_SIZE (48u)
#define CFG_CTS_MAX_SPI_XFER_SIZE (8192u)
#define CTS_FW_LOG_REDIRECT_SIGN 0x60
#define CTS_FW_LOG_BUF_LEN 128
/**
* #define CFG_CTS_SWAP_XY
* #define CFG_CTS_WRAP_X
* #define CFG_CTS_WRAP_Y
*/
#define CFG_CTS_DEVICE_NAME "chipone-tddi"
#define CFG_CTS_DRIVER_NAME "chipone-tddi"
#if CFG_CTS_MAX_I2C_XFER_SIZE < 8
#error "I2C transfer size should large than 8"
#endif
#ifdef CONFIG_OF
#define CONFIG_CTS_OF
#endif
#ifdef CONFIG_CTS_OF
#define CFG_CTS_OF_DEVICE_ID_NAME "chipone-tddi"
#define CFG_CTS_OF_INT_GPIO_NAME "chipone,irq-gpio"
#define CFG_CTS_OF_RST_GPIO_NAME "chipone,rst-gpio"
#ifdef CFG_CTS_MANUAL_CS
#define CFG_CTS_OF_CS_GPIO_NAME "chipone,cs-gpio"
#endif
#define CFG_CTS_OF_X_RESOLUTION_NAME "chipone,x-res"
#define CFG_CTS_OF_Y_RESOLUTION_NAME "chipone,y-res"
#ifdef CFG_CTS_FW_UPDATE_SYS
#define CFG_CTS_OF_PANEL_SUPPLIER "chipone,panel-supplier"
#endif
#endif /* CONFIG_CTS_OF */
#endif /* CTS_PLAT_QCOM_CONFIG_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,262 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_PLATFORM_H
#define CTS_PLATFORM_H
#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/unaligned/access_ok.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/spinlock.h>
#include <linux/rtmutex.h>
#include <linux/byteorder/generic.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
#include <linux/string.h>
#include <linux/suspend.h>
/* #include <linux/wakelock.h> */
#include <linux/firmware.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#endif /* CONFIG_OF */
#include <linux/fb.h>
#include <linux/notifier.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include "cts_config.h"
#include "cts_core.h"
extern bool cts_show_debug_log;
#ifndef LOG_TAG
#define LOG_TAG ""
#endif /* LOG_TAG */
#define cts_err(fmt, ...) \
printk("<E>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_warn(fmt, ...) \
printk("<W>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_info(fmt, ...) \
printk("<I>CTS-" LOG_TAG " " fmt"\n", ##__VA_ARGS__)
#define cts_dbg(fmt, ...) \
do { \
if (cts_show_debug_log) \
printk("<D>CTS-" LOG_TAG " "fmt"\n", ##__VA_ARGS__); \
} while (0)
struct cts_device;
struct cts_device_touch_msg;
struct cts_device_gesture_info;
struct cts_platform_data {
int irq;
int int_gpio;
#ifdef CFG_CTS_HAS_RESET_PIN
int rst_gpio;
#endif /* CFG_CTS_HAS_RESET_PIN */
#ifdef CFG_CTS_MANUAL_CS
int cs_gpio;
#endif
u32 res_x;
u32 res_y;
#ifdef CONFIG_CTS_VIRTUALKEY
u8 vkey_num;
u8 vkey_state;
u8 vkey_keycodes[CFG_CTS_MAX_VKEY_NUM];
#endif /* CONFIG_CTS_VIRTUALKEY */
#ifdef CFG_CTS_FW_UPDATE_SYS
const char *panel_supplier;
#endif
u32 build_id;
u32 config_id;
struct cts_device *cts_dev;
struct input_dev *ts_input_dev;
#ifndef CONFIG_GENERIC_HARDIRQS
struct work_struct ts_irq_work;
#endif /* CONFIG_GENERIC_HARDIRQS */
struct spinlock irq_lock;
bool irq_is_disable;
#ifdef CFG_CTS_GESTURE
u8 gesture_num;
u8 gesture_keymap[CFG_CTS_NUM_GESTURE][2];
bool irq_wake_enabled;
#endif /* CFG_CTS_GESTURE */
#ifdef CONFIG_CTS_PM_FB_NOTIFIER
struct notifier_block fb_notifier;
#endif /* CONFIG_CTS_PM_FB_NOTIFIER */
#ifdef CFG_CTS_FORCE_UP
struct delayed_work touch_event_timeout_work;
#endif
#ifdef CFG_CTS_FW_LOG_REDIRECT
u8 fw_log_buf[CTS_FW_LOG_BUF_LEN];
#endif
#ifdef CONFIG_CTS_I2C_HOST
struct i2c_client *i2c_client;
u8 i2c_fifo_buf[CFG_CTS_MAX_I2C_XFER_SIZE];
#else
struct spi_device *spi_client;
u8 spi_cache_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u8 spi_rx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u8 spi_tx_buf[ALIGN(CFG_CTS_MAX_SPI_XFER_SIZE + 10, 4)];
u32 spi_speed;
#endif /* CONFIG_CTS_I2C_HOST */
};
#ifdef CONFIG_CTS_I2C_HOST
extern size_t cts_plat_get_max_i2c_xfer_size(struct cts_platform_data *pdata);
extern u8 *cts_plat_get_i2c_xfer_buf(struct cts_platform_data *pdata,
size_t xfer_size);
extern int cts_plat_i2c_write(struct cts_platform_data *pdata, u8 i2c_addr,
const void *src, size_t len, int retry,
int delay);
extern int cts_plat_i2c_read(struct cts_platform_data *pdata, u8 i2c_addr,
const u8 *wbuf, size_t wlen, void *rbuf,
size_t rlen, int retry, int delay);
extern int cts_plat_is_i2c_online(struct cts_platform_data *pdata, u8 i2c_addr);
#else /* CONFIG_CTS_I2C_HOST */
extern size_t cts_plat_get_max_spi_xfer_size(struct cts_platform_data *pdata);
extern u8 *cts_plat_get_spi_xfer_buf(struct cts_platform_data *pdata,
size_t xfer_size);
extern int cts_plat_spi_write(struct cts_platform_data *pdata, u8 i2c_addr,
const void *src, size_t len, int retry,
int delay);
extern int cts_plat_spi_read(struct cts_platform_data *pdata, u8 i2c_addr,
const u8 *wbuf, size_t wlen, void *rbuf,
size_t rlen, int retry, int delay);
extern int cts_plat_spi_read_delay_idle(struct cts_platform_data *pdata,
u8 dev_addr, const u8 *wbuf,
size_t wlen, void *rbuf, size_t rlen,
int retry, int delay, int idle);
extern int cts_spi_send_recv(struct cts_platform_data *pdata, size_t len,
u8 *tx_buffer, u8 *rx_buffer);
#endif /* CONFIG_CTS_I2C_HOST */
#ifdef CONFIG_CTS_I2C_HOST
extern int cts_init_platform_data(struct cts_platform_data *pdata,
struct i2c_client *i2c_client);
#else
extern int cts_plat_is_normal_mode(struct cts_platform_data *pdata);
extern int cts_init_platform_data(struct cts_platform_data *pdata,
struct spi_device *spi);
#endif
extern int cts_deinit_platform_data(struct cts_platform_data *pdata);
extern int cts_plat_request_resource(struct cts_platform_data *pdata);
extern void cts_plat_free_resource(struct cts_platform_data *pdata);
extern int cts_plat_request_irq(struct cts_platform_data *pdata);
extern void cts_plat_free_irq(struct cts_platform_data *pdata);
extern int cts_plat_enable_irq(struct cts_platform_data *pdata);
extern int cts_plat_disable_irq(struct cts_platform_data *pdata);
#ifdef CFG_CTS_HAS_RESET_PIN
extern int cts_plat_reset_device(struct cts_platform_data *pdata);
#else /* CFG_CTS_HAS_RESET_PIN */
static inline int cts_plat_reset_device(struct cts_platform_data *pdata)
{
return 0;
}
#endif /* CFG_CTS_HAS_RESET_PIN */
extern int cts_plat_init_touch_device(struct cts_platform_data *pdata);
extern void cts_plat_deinit_touch_device(struct cts_platform_data *pdata);
extern int cts_plat_process_touch_msg(struct cts_platform_data *pdata,
struct cts_device_touch_msg *msgs,
int num);
extern int cts_plat_release_all_touch(struct cts_platform_data *pdata);
#ifdef CONFIG_CTS_VIRTUALKEY
extern int cts_plat_init_vkey_device(struct cts_platform_data *pdata);
extern void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata);
extern int cts_plat_process_vkey(struct cts_platform_data *pdata,
u8 vkey_state);
extern int cts_plat_release_all_vkey(struct cts_platform_data *pdata);
#else /* CONFIG_CTS_VIRTUALKEY */
static inline int cts_plat_init_vkey_device(struct cts_platform_data *pdata)
{
return 0;
}
static inline void cts_plat_deinit_vkey_device(struct cts_platform_data *pdata)
{
}
static inline int cts_plat_process_vkey(struct cts_platform_data *pdata,
u8 vkey_state)
{
return 0;
}
static inline int cts_plat_release_all_vkey(struct cts_platform_data *pdata)
{
return 0;
}
#endif /* CONFIG_CTS_VIRTUALKEY */
#ifdef CFG_CTS_GESTURE
extern int cts_plat_enable_irq_wake(struct cts_platform_data *pdata);
extern int cts_plat_disable_irq_wake(struct cts_platform_data *pdata);
extern int cts_plat_init_gesture(struct cts_platform_data *pdata);
extern void cts_plat_deinit_gesture(struct cts_platform_data *pdata);
extern int cts_plat_process_gesture_info(struct cts_platform_data *pdata,
struct cts_device_gesture_info
*gesture_info);
#else /* CFG_CTS_GESTURE */
static inline int cts_plat_init_gesture(struct cts_platform_data *pdata)
{
return 0;
}
static inline void cts_plat_deinit_gesture(struct cts_platform_data *pdata)
{
}
#endif /* CFG_CTS_GESTURE */
#ifdef CFG_CTS_FW_LOG_REDIRECT
extern size_t cts_plat_get_max_fw_log_size(struct cts_platform_data *pdata);
extern u8 *cts_plat_get_fw_log_buf(struct cts_platform_data *pdata,
size_t size);
#endif
extern int cts_plat_set_reset(struct cts_platform_data *pdata, int val);
extern int cts_plat_get_int_pin(struct cts_platform_data *pdata);
#ifdef CFG_CTS_MANUAL_CS
extern int cts_plat_set_cs(struct cts_platform_data *pdata, int val);
#endif
#endif /* CTS_PLATFORM_H */

View file

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_SFCTRL_H
#define CTS_SFCTRL_H
#include "cts_core.h"
#include "cts_spi_flash.h"
struct cts_device;
struct cts_sfctrl_ops {
int (*rdid)(const struct cts_device *cts_dev, u32 *id);
int (*se)(const struct cts_device *cts_dev, u32 sector_addr);
int (*be)(const struct cts_device *cts_dev, u32 sector_addr);
int (*read)(const struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t len);
int (*read_to_sram)(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t len);
int (*program)(const struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t len);
int (*program_from_sram)(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t len);
int (*calc_sram_crc)(const struct cts_device *cts_dev,
u32 sram_addr, size_t len, u32 *crc);
int (*calc_flash_crc)(const struct cts_device *cts_dev,
u32 flash_addr, size_t len, u32 *crc);
};
struct cts_sfctrl {
u32 reg_base;
u32 xchg_sram_base;
size_t xchg_sram_size;
const struct cts_sfctrl_ops *ops;
};
extern const struct cts_sfctrl_ops cts_sfctrlv2_ops;
#endif /* CTS_SFCTRL_H */

View file

@ -0,0 +1,354 @@
// SPDX-License-Identifier: GPL-2.0
#define LOG_TAG "SFCtrl"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sfctrl.h"
#define rSFCTRLv2_CMD_SEL (0x0000)
#define rSFCTRLv2_FLASH_ADDR (0x0004)
#define rSFCTRLv2_SRAM_ADDR (0x0008)
#define rSFCTRLv2_DATA_LENGTH (0x000C)
#define rSFCTRLv2_START_DEXC (0x0010)
#define rSFCTRLv2_RELEASE_FLASH (0x0014)
#define rSFCTRLv2_HW_STATE (0x0018)
#define rSFCTRLv2_CRC_RESULT (0x001C)
#define rSFCTRLv2_SRAM_CRC_START (0x0020)
#define rSFCTRLv2_FLASH_CRC_START (0x0022)
#define rSFCTRLv2_SF_BUSY (0x0024)
/** Constants for register @ref rSFCTRLv2_CMD_SEL */
enum sfctrlv2_cmd {
SFCTRLv2_CMD_FAST_READ = 0x01u,
SFCTRLv2_CMD_SE = 0x02u,
SFCTRLv2_CMD_BE = 0x03u,
SFCTRLv2_CMD_PP = 0x04u,
SFCTRLv2_CMD_RDSR = 0x05u,
SFCTRLv2_CMD_RDID = 0x06u
};
/** SPI flash controller v2 operation flags. */
enum sfctrlv2_opflags {
SFCTRLv2_OPFLAG_READ = BIT(0),
SFCTRLv2_OPFLAG_SET_FLASH_ADDR = BIT(1),
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG = BIT(2),
SFCTRLv2_OPFLAG_SET_DATA_LENGTH = BIT(3),
SFCTRLv2_OPFLAG_WAIT_WIP_CLR = BIT(4),
};
#define SFCTRLv2_CMD_RDID_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG)
#define SFCTRLv2_CMD_RDSR_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG)
#define SFCTRLv2_CMD_SE_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_BE_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_PP_FLAGS \
(SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \
SFCTRLv2_OPFLAG_SET_DATA_LENGTH | \
SFCTRLv2_OPFLAG_WAIT_WIP_CLR)
#define SFCTRLv2_CMD_FAST_READ_FLAGS \
(SFCTRLv2_OPFLAG_READ | \
SFCTRLv2_OPFLAG_SET_FLASH_ADDR | \
SFCTRLv2_OPFLAG_SRAM_DATA_XCHG | \
SFCTRLv2_OPFLAG_SET_DATA_LENGTH)
#define sfctrl_reg_addr(cts_dev, offset) \
((cts_dev)->hwdata->sfctrl->reg_base + offset)
#define DEFINE_SFCTRL_REG_ACCESS_FUNC(access_type, data_type) \
static inline int sfctrl_reg_ ## access_type(const struct cts_device *cts_dev, \
u32 reg, data_type data) { \
return cts_hw_reg_ ## access_type(cts_dev, sfctrl_reg_addr(cts_dev, reg), data); \
}
DEFINE_SFCTRL_REG_ACCESS_FUNC(writeb_relaxed, u8)
DEFINE_SFCTRL_REG_ACCESS_FUNC(writew_relaxed, u16)
DEFINE_SFCTRL_REG_ACCESS_FUNC(writel_relaxed, u32)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readb_relaxed, u8 *)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readw_relaxed, u16 *)
DEFINE_SFCTRL_REG_ACCESS_FUNC(readl_relaxed, u32 *)
#define sfctrl_write_reg_check_ret(access_type, reg, val) \
do { \
int ret; \
cts_dbg("Write " #reg " to 0x%x", val); \
ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \
if (ret) { \
cts_err("Write " #reg " failed %d", ret); \
return ret; \
} \
} while (0)
#define sfctrl_read_reg_check_ret(access_type, reg, val) \
do { \
int ret; \
cts_dbg("Read " #reg ""); \
ret = sfctrl_reg_ ## access_type(cts_dev, reg, val); \
if (ret) { \
cts_err("Read " #reg " failed %d", ret); \
return ret; \
} \
} while (0)
static int wait_sfctrl_xfer_comp(const struct cts_device *cts_dev)
{
int retries = 0;
u8 status;
do {
sfctrl_read_reg_check_ret(readb_relaxed, rSFCTRLv2_SF_BUSY,
&status);
if (status == 0)
return 0;
mdelay(20);
} while (status && retries++ < 50);
return -ETIMEDOUT;
}
static int sfctrlv2_rdsr(const struct cts_device *cts_dev, u8 *status)
{
#define RDSR_XCHG_SRAM_ADDR (cts_dev->hwdata->sram_size - 1)
int ret;
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL,
SFCTRLv2_CMD_RDSR);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR,
RDSR_XCHG_SRAM_ADDR);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
ret = cts_sram_readb(cts_dev, RDSR_XCHG_SRAM_ADDR, status);
if (ret) {
cts_err("Read exchange sram failed %d", ret);
return ret;
}
#undef RDSR_XCHG_SRAM_ADDR
return 0;
}
static int wait_flash_wip_clear(const struct cts_device *cts_dev)
{
#define FLASH_SR_WIP BIT(0) /*!< Write in progress */
int ret, retries = 0;
u8 status;
do {
ret = sfctrlv2_rdsr(cts_dev, &status);
if (ret) {
cts_err("Read flash status register failed %d", ret);
return ret;
}
if (status & FLASH_SR_WIP)
mdelay(1);
else
return 0;
} while (status & FLASH_SR_WIP && retries++ < 1000);
return -ETIMEDOUT;
#undef FLASH_SR_WIP
}
static int sfctrlv2_transfer(const struct cts_device *cts_dev,
u8 cmd, void *data, u32 flash_addr, u32 sram_addr,
size_t size, u32 flags)
{
int ret;
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_CMD_SEL, cmd);
if (flags & SFCTRLv2_OPFLAG_SRAM_DATA_XCHG) {
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR,
sram_addr);
/** - Write data to exchange SRAM if operation is write and
* data != NULL(data not in SRAM)
*/
if ((!(flags & SFCTRLv2_OPFLAG_READ)) && data) {
ret = cts_sram_writesb(cts_dev, sram_addr, data, size);
if (ret) {
cts_err
("Write data to exchange sram 0x%06x size %zu failed %d",
sram_addr, size, ret);
return ret;
}
}
}
if (flags & SFCTRLv2_OPFLAG_SET_FLASH_ADDR) {
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR,
flash_addr);
}
if (flags & SFCTRLv2_OPFLAG_SET_DATA_LENGTH) {
sfctrl_write_reg_check_ret(writel_relaxed,
rSFCTRLv2_DATA_LENGTH, (u32) size);
}
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_START_DEXC, 1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
ret = wait_flash_wip_clear(cts_dev);
if (flags & SFCTRLv2_OPFLAG_WAIT_WIP_CLR && ret != 0) {
cts_err("Wait WIP clear failed %d", ret);
return ret;
}
if ((flags & SFCTRLv2_OPFLAG_READ) && data) {
ret = cts_sram_readsb(cts_dev, sram_addr, data, size);
if (ret) {
cts_err
("Read data from exchange sram 0x%06x size %zu failed %d",
sram_addr, size, ret);
return ret;
}
}
return 0;
}
static int sfctrlv2_rdid(const struct cts_device *cts_dev, u32 *id)
{
int ret;
u8 buf[4];
ret = sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_RDID, buf,
0, cts_dev->hwdata->sfctrl->xchg_sram_base, 3,
SFCTRLv2_CMD_RDID_FLAGS);
*id = ret ? 0 : get_unaligned_be24(buf);
return ret;
}
static int sfctrlv2_se(const struct cts_device *cts_dev, u32 sector_addr)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_SE, NULL,
sector_addr, 0, 0, SFCTRLv2_CMD_SE_FLAGS);
}
static int sfctrlv2_be(const struct cts_device *cts_dev, u32 block_addr)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_BE, NULL,
block_addr, 0, 0, SFCTRLv2_CMD_BE_FLAGS);
}
static int sfctrlv2_pp(const struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, (void *)src,
flash_addr,
cts_dev->hwdata->sfctrl->xchg_sram_base, size,
SFCTRLv2_CMD_PP_FLAGS);
}
static int sfctrlv2_program_flash_from_sram(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t len)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_PP, NULL,
flash_addr, sram_addr, len,
SFCTRLv2_CMD_PP_FLAGS);
}
static int sfctrlv2_read(const struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, dst,
flash_addr,
cts_dev->hwdata->sfctrl->xchg_sram_base, size,
SFCTRLv2_CMD_FAST_READ_FLAGS);
}
static int sfctrlv2_read_flash_to_sram(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t size)
{
return sfctrlv2_transfer(cts_dev, SFCTRLv2_CMD_FAST_READ, NULL,
flash_addr, sram_addr, size,
SFCTRLv2_CMD_FAST_READ_FLAGS);
}
int sfctrlv2_calc_sram_crc(const struct cts_device *cts_dev,
u32 sram_addr, size_t size, u32 *crc)
{
int ret;
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_SRAM_ADDR,
sram_addr);
mdelay(1);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH,
(u32) size);
mdelay(1);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_SRAM_CRC_START, 1);
mdelay(10);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc);
return 0;
}
int sfctrlv2_calc_flash_crc(const struct cts_device *cts_dev,
u32 flash_addr, size_t size, u32 *crc)
{
int ret;
cts_info("Calc crc from flash 0x%06x size %zu", flash_addr, size);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_FLASH_ADDR,
flash_addr);
sfctrl_write_reg_check_ret(writel_relaxed, rSFCTRLv2_DATA_LENGTH,
(u32) size);
sfctrl_write_reg_check_ret(writeb_relaxed, rSFCTRLv2_FLASH_CRC_START,
1);
ret = wait_sfctrl_xfer_comp(cts_dev);
if (ret != 0) {
cts_err("Wait sfctrl ready failed %d", ret);
return ret;
}
sfctrl_read_reg_check_ret(readl_relaxed, rSFCTRLv2_CRC_RESULT, crc);
return 0;
}
const struct cts_sfctrl_ops cts_sfctrlv2_ops = {
.rdid = sfctrlv2_rdid,
.se = sfctrlv2_se,
.be = sfctrlv2_be,
.read = sfctrlv2_read,
.read_to_sram = sfctrlv2_read_flash_to_sram,
.program = sfctrlv2_pp,
.program_from_sram = sfctrlv2_program_flash_from_sram,
.calc_sram_crc = sfctrlv2_calc_sram_crc,
.calc_flash_crc = sfctrlv2_calc_flash_crc,
};

View file

@ -0,0 +1,532 @@
// SPDX-License-Identifier: GPL-2.0
#define LOG_TAG "Flash"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_sfctrl.h"
#include "cts_spi_flash.h"
/* NOTE: double check command sets and memory organization when you add
* more flash chips. This current list focusses on newer chips, which
* have been converging on command sets which including JEDEC ID.
*/
static int probe_flash(struct cts_device *cts_dev)
{
/* for no-flash project */
return -ENODEV;
}
/** Make sure sector addr is sector aligned && < flash total size */
static int erase_sector_retry(const struct cts_device *cts_dev,
u32 sector_addr, int retry)
{
int ret, retries;
cts_info(" Erase sector 0x%06x", sector_addr);
retries = 0;
do {
retries++;
ret = cts_dev->hwdata->sfctrl->ops->se(cts_dev, sector_addr);
if (ret) {
cts_err("Erase sector 0x%06x failed %d retries %d",
sector_addr, ret, retries);
continue;
}
} while (retries < retry);
return ret;
}
/** Make sure sector addr is sector aligned && < flash total size */
static inline int erase_sector(const struct cts_device *cts_dev,
u32 sector_addr)
{
return erase_sector_retry(cts_dev, sector_addr,
CTS_FLASH_ERASE_DEFAULT_RETRY);
}
/** Make sure block addr is block aligned && < flash total size */
static int erase_block_retry(const struct cts_device *cts_dev,
u32 block_addr, int retry)
{
int ret, retries;
cts_info(" Erase block 0x%06x", block_addr);
retries = 0;
do {
retries++;
ret = cts_dev->hwdata->sfctrl->ops->be(cts_dev, block_addr);
if (ret) {
cts_err("Erase block 0x%06x failed %d retries %d",
block_addr, ret, retries);
continue;
}
} while (retries < retry);
return ret;
}
/** Make sure block addr is block aligned && < flash total size */
static inline int erase_block(const struct cts_device *cts_dev, u32 block_addr)
{
return erase_block_retry(cts_dev, block_addr,
CTS_FLASH_ERASE_DEFAULT_RETRY);
}
int cts_prepare_flash_operation(struct cts_device *cts_dev)
{
int ret;
u8 diva = 0;
bool program_mode = cts_is_device_program_mode(cts_dev);
bool enabled = cts_is_device_enabled(cts_dev);
cts_info("Prepare for flash operation");
if (enabled) {
ret = cts_stop_device(cts_dev);
if (ret) {
cts_err("Stop device failed %d", ret);
return ret;
}
}
if (!program_mode) {
ret = cts_enter_program_mode(cts_dev);
if (ret) {
cts_err("Enter program mode failed %d", ret);
goto err_start_device;
}
}
ret = cts_hw_reg_readb_retry(cts_dev, 0x30033, &diva, 5, 0);
if (ret)
cts_warn("Read DIVA failed %d", ret);
else
cts_dbg("Device DIVA = %d", diva);
if (ret == 0 && diva == 0x0C)
cts_info("DIVA is ready already");
else {
int retries;
/* Set HCLK to 10MHz */
ret = cts_hw_reg_writeb_retry(cts_dev, 0x30033, 0x0C, 5, 0);
if (ret) {
cts_err("Write DIVA failed %d", ret);
goto err_enter_normal_mode;
}
/* Reset SFCTL */
ret = cts_hw_reg_writeb_retry(cts_dev, 0x30008, 0xFB, 5, 0);
if (ret) {
cts_err("Reset sfctl failed %d", ret);
goto err_enter_normal_mode;
}
retries = 0;
do {
u8 state;
ret =
cts_hw_reg_readb_relaxed(cts_dev, 0x3401B, &state);
if (ret == 0 && (state & 0x40) != 0)
goto init_flash;
mdelay(2);
} while (++retries < 1000);
cts_warn("Wait SFCTRL ready failed %d", ret);
}
init_flash:
if (cts_dev->flash == NULL) {
cts_info("Flash is not initialized, try to probe...");
ret = probe_flash(cts_dev);
if (ret != 0) {
cts_dev->rtdata.has_flash = false;
cts_warn("Probe flash failed %d", ret);
return 0;
}
}
cts_dev->rtdata.has_flash = true;
return 0;
err_enter_normal_mode:
if (!program_mode) {
int r = cts_enter_normal_mode(cts_dev);
if (r)
cts_err("Enter normal mode failed %d", r);
}
err_start_device:
if (enabled) {
int r = cts_start_device(cts_dev);
if (r)
cts_err("Start device failed %d", r);
}
return ret;
}
int cts_post_flash_operation(struct cts_device *cts_dev)
{
cts_info("Post flash operation");
return cts_hw_reg_writeb_retry(cts_dev, 0x30033, 4, 5, 0);
}
int cts_read_flash_retry(const struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size, int retry)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Read from 0x%06x size %zu", flash_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL || sfctrl->ops->read == NULL) {
cts_err("Read not supported");
return -ENOTSUPP;
}
if (flash_addr > flash->total_size) {
cts_err("Read from 0x%06x > flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Read actually from 0x%06x size %zu", flash_addr, size);
while (size) {
size_t l;
l = min(sfctrl->xchg_sram_size, size);
ret = sfctrl->ops->read(cts_dev, flash_addr, dst, l);
if (ret < 0) {
cts_err("Read from 0x%06x size %zu failed %d",
flash_addr, size, ret);
return ret;
}
dst += l;
size -= l;
flash_addr += l;
}
return 0;
}
int cts_read_flash_to_sram_retry(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t size,
int retry)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret, retries;
cts_info("Read from 0x%06x to sram 0x%06x size %zu",
flash_addr, sram_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL || sfctrl->ops->read_to_sram == NULL) {
cts_err("Read to sram not supported");
return -ENOTSUPP;
}
if (flash_addr > flash->total_size) {
cts_err("Read to sram from 0x%06x > flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Read to sram actually from 0x%06x size %zu", flash_addr,
size);
retries = 0;
do {
retries++;
ret =
sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr,
size);
if (ret) {
cts_err
("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d",
flash_addr, sram_addr, size, ret, retries);
continue;
}
} while (retries < retry);
return ret;
}
int cts_read_flash_to_sram_check_crc_retry(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t size, u32 crc, int retry)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret, retries;
cts_info("Read from 0x%06x to sram 0x%06x size %zu with crc check",
flash_addr, sram_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL ||
sfctrl->ops->read_to_sram == NULL ||
sfctrl->ops->calc_sram_crc == NULL) {
cts_err("Read to sram check crc not supported");
return -ENOTSUPP;
}
if (flash_addr > flash->total_size) {
cts_err("Read to sram from 0x%06x > flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Read to sram actually from 0x%06x size %zu with crc check",
flash_addr, size);
retries = 0;
do {
u32 crc_sram;
retries++;
ret =
sfctrl->ops->read_to_sram(cts_dev, flash_addr, sram_addr,
size);
if (ret) {
cts_err
("Read from 0x%06x to sram 0x%06x size %zu failed %d retries %d",
flash_addr, sram_addr, size, ret, retries);
continue;
}
ret =
sfctrl->ops->calc_sram_crc(cts_dev, sram_addr, size,
&crc_sram);
if (ret) {
cts_err
("Get crc for read from 0x%06x to sram 0x%06x size %zu "
"failed %d retries %d", flash_addr, sram_addr,
size, ret, retries);
continue;
}
if (crc == crc_sram)
return 0;
cts_err
("Check crc for read from 0x%06x to sram 0x%06x size %zu "
"mismatch %x != %x, retries %d", flash_addr, sram_addr,
size, crc, crc_sram, retries);
ret = -EFAULT;
} while (retries < retry);
return ret;
}
int cts_program_flash(const struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Program to 0x%06x size %zu", flash_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL || sfctrl->ops->program == NULL) {
cts_err("Program not supported");
return -ENOTSUPP;
}
if (flash_addr >= flash->total_size) {
cts_err("Program from 0x%06x >= flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Program actually to 0x%06x size %zu", flash_addr, size);
while (size) {
size_t l, offset;
l = min(flash->page_size, size);
offset = flash_addr & (flash->page_size - 1);
if (offset)
l = min(flash->page_size - offset, l);
ret = sfctrl->ops->program(cts_dev, flash_addr, src, l);
if (ret) {
cts_err("Program to 0x%06x size %zu failed %d",
flash_addr, l, ret);
return ret;
}
src += l;
size -= l;
flash_addr += l;
}
return 0;
}
int cts_program_flash_from_sram(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Program to 0x%06x from sram 0x%06x size %zu",
flash_addr, sram_addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL ||
sfctrl->ops == NULL || sfctrl->ops->program_from_sram == NULL) {
cts_err("Program from sram not supported");
return -ENOTSUPP;
}
if (flash_addr >= flash->total_size) {
cts_err("Program from 0x%06x >= flash size 0x%06zx",
flash_addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - flash_addr);
cts_info("Program actually to 0x%06x from sram 0x%06x size %zu",
flash_addr, sram_addr, size);
while (size) {
size_t l, offset;
l = min(flash->page_size, size);
offset = flash_addr & (flash->page_size - 1);
if (offset)
l = min(flash->page_size - offset, l);
ret =
sfctrl->ops->program_from_sram(cts_dev, flash_addr,
sram_addr, l);
if (ret) {
cts_err
("Program to 0x%06x from sram 0x%06x size %zu failed %d",
flash_addr, sram_addr, l, ret);
return ret;
}
size -= l;
flash_addr += l;
sram_addr += l;
}
return 0;
}
int cts_erase_flash(const struct cts_device *cts_dev, u32 addr, size_t size)
{
const struct cts_sfctrl *sfctrl;
const struct cts_flash *flash;
int ret;
cts_info("Erase from 0x%06x size %zu", addr, size);
sfctrl = cts_dev->hwdata->sfctrl;
flash = cts_dev->flash;
if (flash == NULL ||
sfctrl == NULL || sfctrl->ops == NULL ||
sfctrl->ops->se == NULL || sfctrl->ops->be == NULL ||
flash == NULL) {
cts_err("Oops");
return -EINVAL;
}
/* Addr and size MUST sector aligned */
addr = rounddown(addr, flash->sector_size);
size = roundup(size, flash->sector_size);
if (addr > flash->total_size) {
cts_err("Erase from 0x%06x > flash size 0x%06zx",
addr, flash->total_size);
return -EINVAL;
}
size = min(size, flash->total_size - addr);
cts_info("Erase actually from 0x%06x size %zu", addr, size);
if (flash->block_size) {
while (addr != ALIGN(addr, flash->block_size) &&
size >= flash->sector_size) {
ret = erase_sector(cts_dev, addr);
if (ret) {
cts_err
("Erase sector 0x%06x size 0x%04zx failed %d",
addr, flash->sector_size, ret);
return ret;
}
addr += flash->sector_size;
size -= flash->sector_size;
}
while (size >= flash->block_size) {
ret = erase_block(cts_dev, addr);
if (ret) {
cts_err
("Erase block 0x%06x size 0x%04zx failed %d",
addr, flash->block_size, ret);
return ret;
}
addr += flash->block_size;
size -= flash->block_size;
}
}
while (size >= flash->sector_size) {
ret = erase_sector(cts_dev, addr);
if (ret) {
cts_err("Erase sector 0x%06x size 0x%04zx failed %d",
addr, flash->sector_size, ret);
return ret;
}
addr += flash->sector_size;
size -= flash->sector_size;
}
return 0;
}

View file

@ -0,0 +1,73 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_SPI_FLASH_H
#define CTS_SPI_FLASH_H
struct cts_flash {
const char *name;
u32 jedec_id; /* Device ID by command 0x9F */
size_t page_size; /* Page size by command 0x02 */
size_t sector_size; /* Sector size by command 0x20 */
/* Block size by command 0x52,
* if 0 means block erase NOT supported
*/
size_t block_size;
size_t total_size;
};
#define CTS_FLASH_READ_DEFAULT_RETRY (3)
#define CTS_FLASH_ERASE_DEFAULT_RETRY (3)
struct cts_device;
extern int cts_prepare_flash_operation(struct cts_device *cts_dev);
extern int cts_post_flash_operation(struct cts_device *cts_dev);
extern int cts_read_flash_retry(const struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size,
int retry);
static inline int cts_read_flash(const struct cts_device *cts_dev,
u32 flash_addr, void *dst, size_t size)
{
return cts_read_flash_retry(cts_dev, flash_addr, dst, size,
CTS_FLASH_READ_DEFAULT_RETRY);
}
extern int cts_read_flash_to_sram_retry(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t size, int retry);
static inline int cts_read_flash_to_sram(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t size)
{
return cts_read_flash_to_sram_retry(cts_dev,
flash_addr, sram_addr, size,
CTS_FLASH_READ_DEFAULT_RETRY);
}
extern int cts_read_flash_to_sram_check_crc_retry(const struct cts_device
*cts_dev, u32 flash_addr,
u32 sram_addr, size_t size,
u32 crc, int retry);
static inline int cts_read_flash_to_sram_check_crc(const struct cts_device
*cts_dev, u32 flash_addr,
u32 sram_addr, size_t size,
u32 crc)
{
return cts_read_flash_to_sram_check_crc_retry(cts_dev,
flash_addr, sram_addr,
size, crc,
CTS_FLASH_READ_DEFAULT_RETRY);
}
extern int cts_erase_flash(const struct cts_device *cts_dev, u32 addr,
size_t size);
extern int cts_program_flash(const struct cts_device *cts_dev,
u32 flash_addr, const void *src, size_t size);
extern int cts_program_flash_from_sram(const struct cts_device *cts_dev,
u32 flash_addr, u32 sram_addr,
size_t size);
#endif /* CTS_SPI_FLASH_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_SYSFS_H
#define CTS_SYSFS_H
#include "cts_config.h"
struct device;
extern u16 speed;
#ifdef CONFIG_CTS_SYSFS
extern int cts_sysfs_add_device(struct device *dev);
extern void cts_sysfs_remove_device(struct device *dev);
#else /* CONFIG_CTS_SYSFS */
static inline int cts_sysfs_add_device(struct device *dev)
{
return -ENOTSUPP;
}
static inline void cts_sysfs_remove_device(struct device *dev)
{
}
#endif /* CONFIG_CTS_SYSFS */
#endif /* CTS_SYSFS_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,228 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _CTS_TCS_H_
#define _CTS_TCS_H_
#include "cts_config.h"
#define TCS_RD_ADDR 0xF1
#define TCS_WR_ADDR 0xF0
#define INT_DATA_MAX_SIZ 8192
#pragma pack(1)
typedef struct {
u8 addr;
u16 cmd;
u16 datlen;
u16 crc16;
} tcs_tx_head;
typedef struct {
u8 ecode;
u16 cmd;
u16 crc16;
} tcs_rx_tail;
typedef struct {
u8 baseFlag;
u8 classID;
u8 cmdID;
u8 isRead;
u8 isWrite;
u8 isData;
} TcsCmdValue_t;
#pragma pack(0)
int cts_tcs_get_fw_ver(const struct cts_device *cts_dev, u16 *fwver);
int cts_tcs_get_lib_ver(const struct cts_device *cts_dev, u16 *libver);
int cts_tcs_get_ddi_ver(const struct cts_device *cts_dev, u8 *ddiver);
int cts_tcs_get_res_x(const struct cts_device *cts_dev, u16 *res_x);
int cts_tcs_get_res_y(const struct cts_device *cts_dev, u16 *res_y);
int cts_tcs_get_rows(const struct cts_device *cts_dev, u8 *rows);
int cts_tcs_get_cols(const struct cts_device *cts_dev, u8 *cols);
int cts_tcs_get_flip_x(const struct cts_device *cts_dev, bool *flip_x);
int cts_tcs_get_flip_y(const struct cts_device *cts_dev, bool *flip_y);
int cts_tcs_get_swap_axes(const struct cts_device *cts_dev, bool *swap_axes);
int cts_tcs_get_int_mode(const struct cts_device *cts_dev, u8 *int_mode);
int cts_tcs_get_int_keep_time(const struct cts_device *cts_dev,
u16 *int_keep_time);
int cts_tcs_get_esd_method(const struct cts_device *cts_dev, u8 *esd_method);
int cts_tcs_get_touchinfo(const struct cts_device *cts_dev,
struct cts_device_touch_info *touch_info);
int cts_tcs_get_esd_protection(const struct cts_device *cts_dev,
u8 *esd_protection);
int cts_tcs_get_data_ready_flag(const struct cts_device *cts_dev, u8 *ready);
int cts_tcs_clr_data_ready_flag(const struct cts_device *cts_dev);
int cts_tcs_enable_get_rawdata(const struct cts_device *cts_dev);
int cts_tcs_is_enabled_get_rawdata(const struct cts_device *cts_dev,
u8 *enabled);
int cts_tcs_disable_get_rawdata(const struct cts_device *cts_dev);
int cts_tcs_enable_get_cneg(const struct cts_device *cts_dev);
int cts_tcs_disable_get_cneg(const struct cts_device *cts_dev);
int cts_tcs_is_cneg_ready(const struct cts_device *cts_dev, u8 *ready);
int cts_tcs_quit_guesture_mode(const struct cts_device *cts_dev);
int cts_tcs_get_rawdata(const struct cts_device *cts_dev, u8 *buf);
int cts_tcs_get_diffdata(const struct cts_device *cts_dev, u8 *buf);
int cts_tcs_get_basedata(const struct cts_device *cts_dev, u8 *buf);
int cts_tcs_get_cneg(const struct cts_device *cts_dev, u8 *buf, size_t size);
int cts_tcs_read_hw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_write_hw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_read_ddi_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int cts_tcs_write_ddi_reg(const struct cts_device *cts_dev, u32 addr,
u8 *regbuf, size_t size);
int cts_tcs_read_fw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_write_fw_reg(const struct cts_device *cts_dev, u32 addr,
u8 *buf, size_t size);
int cts_tcs_read_reg(const struct cts_device *cts_dev, uint16_t cmd,
u8 *rbuf, size_t rlen);
int cts_tcs_write_reg(const struct cts_device *cts_dev, uint16_t cmd,
u8 *wbuf, size_t wlen);
int cts_tcs_get_fw_id(const struct cts_device *cts_dev, u16 *fwid);
int cts_tcs_get_workmode(const struct cts_device *cts_dev, u8 *workmode);
int cts_tcs_set_workmode(const struct cts_device *cts_dev, u8 workmode);
int cts_tcs_set_openshort_mode(const struct cts_device *cts_dev, u8 mode);
int cts_tcs_set_tx_vol(const struct cts_device *cts_dev, u8 txvol);
int cts_tcs_set_short_test_type(const struct cts_device *cts_dev,
u8 short_type);
int cts_tcs_set_openshort_enable(const struct cts_device *cts_dev, u8 enable);
int cts_tcs_is_openshort_enabled(const struct cts_device *cts_dev,
u8 *enabled);
int cts_tcs_set_esd_enable(const struct cts_device *cts_dev, u8 enable);
int cts_tcs_set_cneg_enable(const struct cts_device *cts_dev, u8 enable);
int cts_tcs_set_mnt_enable(const struct cts_device *cts_dev, u8 enable);
int cts_tcs_is_display_on(const struct cts_device *cts_dev, u8 *display_on);
int cts_tcs_set_display_on(const struct cts_device *cts_dev, u8 display_on);
int cts_tcs_is_cneg_enabled(const struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_is_mnt_enabled(const struct cts_device *cts_dev, u8 *enabled);
int cts_tcs_set_pwr_mode(const struct cts_device *cts_dev, u8 pwr_mode);
int cts_tcs_read_sram_normal_mode(const struct cts_device *cts_dev,
u32 addr, void *dst, size_t len, int retry,
int delay);
enum TcsCmdIndex {
TP_STD_CMD_INFO_CHIP_FW_ID_RO,
TP_STD_CMD_INFO_FW_VER_RO,
TP_STD_CMD_INFO_TOUCH_XY_INFO_RO,
TP_STD_CMD_TP_DATA_OFFSET_AND_TYPE_CFG_RW,
TP_STD_CMD_TP_DATA_READ_START_RO,
TP_STD_CMD_TP_DATA_COORDINATES_RO,
TP_STD_CMD_TP_DATA_RAW_RO,
TP_STD_CMD_TP_DATA_DIFF_RO,
TP_STD_CMD_TP_DATA_BASE_RO,
TP_STD_CMD_TP_DATA_CNEG_RO,
TP_STD_CMD_TP_DATA_WR_REG_RAM_SEQUENCE_WO,
TP_STD_CMD_TP_DATA_WR_REG_RAM_BATCH_WO,
TP_STD_CMD_TP_DATA_WR_DDI_REG_SEQUENCE_WO,
TP_STD_CMD_GET_DATA_BY_POLLING_RO,
TP_STD_CMD_SYS_STS_READ_RO,
TP_STD_CMD_SYS_STS_WORK_MODE_RW,
TP_STD_CMD_SYS_STS_DAT_RDY_FLAG_RW,
TP_STD_CMD_SYS_STS_PWR_STATE_RW,
TP_STD_CMD_SYS_STS_DDI_CODE_VER_RO,
TP_STD_CMD_SYS_STS_DAT_TRANS_IN_NORMAL_RW,
TP_STD_CMD_SYS_STS_VSTIM_LVL_RW,
TP_STD_CMD_SYS_STS_CNEG_RDY_FLAG_RW,
TP_STD_CMD_SYS_STS_RESET_WO,
TP_STD_CMD_SYS_STS_CNEG_RD_EN_RW,
TP_STD_CMD_SYS_STS_INT_MODE_RW,
TP_STD_CMD_SYS_STS_INT_KEEP_TIME_RW,
TP_STD_CMD_SYS_STS_CURRENT_WORKMODE_RO,
TP_STD_CMD_SYS_STS_DATA_CAPTURE_SUPPORT_RO,
TP_STD_CMD_SYS_STS_DATA_CAPTURE_EN_RW,
TP_STD_CMD_SYS_STS_DATA_CAPTURE_FUNC_MAP_RW,
TP_STD_CMD_MNT_EN_RW,
TP_STD_CMD_MNT_FORCE_EXIT_MNT_WO,
TP_STD_CMD_DDI_ESD_EN_RW,
TP_STD_CMD_DDI_ESD_OPTIONS_RW,
TP_STD_CMD_CNEG_EN_RW,
TP_STD_CMD_COORD_FLIP_X_EN_RW,
TP_STD_CMD_COORD_FLIP_Y_EN_RW,
TP_STD_CMD_COORD_SWAP_AXES_EN_RW,
TP_STD_CMD_OPENSHORT_EN_RW,
TP_STD_CMD_OPENSHORT_MODE_SEL_RW,
TP_STD_CMD_OPENSHORT_SHORT_SEL_RW,
TP_STD_CMD_OPENSHORT_SHORT_DISP_ON_EN_RW,
};
#ifdef _CTS_TCS_C_
static TcsCmdValue_t TcsCmdValue[] = {
/*---------------------------------------------------
*baseFlage, classID, cmdID, isRead, isWrite, isData
*---------------------------------------------------
*/
{ 0, 0, 3, 1, 0, 0 }, /* TP_STD_CMD_INFO_CHIP_FW_ID_RO */
{ 0, 0, 5, 1, 0, 0 }, /* TP_STD_CMD_INFO_FW_VER_RO */
{ 0, 0, 7, 1, 0, 0 }, /* TP_STD_CMD_INFO_TOUCH_XY_INFO_RO */
{ 0, 1, 1, 1, 1, 0 }, /* TP_STD_CMD_TP_DATA_OFFSET_AND_TYPE_CFG_RW */
{ 0, 1, 2, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_READ_START_RO */
{ 0, 1, 3, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_COORDINATES_RO */
{ 0, 1, 4, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_RAW_RO */
{ 0, 1, 5, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_DIFF_RO */
{ 0, 1, 6, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_BASE_RO */
{ 0, 1, 10, 1, 0, 1 }, /* TP_STD_CMD_TP_DATA_CNEG_RO */
{ 0, 1, 20, 0, 1, 1 }, /* TP_STD_CMD_TP_DATA_WR_REG_RAM_SEQUENCE_WO */
{ 0, 1, 21, 0, 1, 1 }, /* TP_STD_CMD_TP_DATA_WR_REG_RAM_BATCH_WO */
{ 0, 1, 22, 0, 1, 1 }, /* TP_STD_CMD_TP_DATA_WR_DDI_REG_SEQUENCE_WO */
{ 0, 1, 35, 1, 0, 0 }, /* TP_STD_CMD_GET_DATA_BY_POLLING_RO */
{ 0, 2, 0, 1, 0, 1 }, /* TP_STD_CMD_SYS_STS_READ_RO *//*CHECK!!*/
{ 0, 2, 1, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_WORK_MODE_RW */
{ 0, 2, 3, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_DAT_RDY_FLAG_RW */
{ 0, 2, 4, 1, 1, 1 }, /* TP_STD_CMD_SYS_STS_PWR_STATE_RW */
{ 0, 2, 6, 1, 0, 0 }, /* TP_STD_CMD_SYS_STS_DDI_CODE_VER_RO */
{ 0, 2, 7, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_DAT_TRANS_IN_NORMAL_RW */
{ 0, 2, 8, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_VSTIM_LVL_RW */
{ 0, 2, 17, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_CNEG_RDY_FLAG_RW */
{ 0, 2, 22, 0, 1, 0 }, /* TP_STD_CMD_SYS_STS_RESET_WO */
{ 0, 2, 25, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_CNEG_RD_EN_RW */
{ 0, 2, 35, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_INT_MODE_RW */
{ 0, 2, 36, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_INT_KEEP_TIME_RW */
{ 0, 2, 51, 1, 0, 0 }, /* TP_STD_CMD_SYS_STS_CURRENT_WORKMODE_RO */
{ 0, 2, 63, 1, 0, 0 }, /* TP_STD_CMD_SYS_STS_DATA_CAPTURE_SUPPORT_RO */
{ 0, 2, 64, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_DATA_CAPTURE_EN_RW */
{ 0, 2, 65, 1, 1, 0 }, /* TP_STD_CMD_SYS_STS_DATA_CAPTURE_FUNC_MAP_RW */
{ 0, 4, 1, 1, 1, 0 }, /* TP_STD_CMD_MNT_EN_RW */
{ 0, 4, 3, 0, 1, 0 }, /* TP_STD_CMD_MNT_FORCE_EXIT_MNT_WO */
{ 0, 5, 1, 1, 1, 0 }, /* TP_STD_CMD_DDI_ESD_EN_RW */
{ 0, 5, 2, 1, 1, 0 }, /* TP_STD_CMD_DDI_ESD_OPTIONS_RW */
{ 0, 6, 1, 1, 1, 0 }, /* TP_STD_CMD_CNEG_EN_RW */
{ 0, 7, 2, 1, 1, 0 }, /* TP_STD_CMD_COORD_FLIP_X_EN_RW */
{ 0, 7, 3, 1, 1, 0 }, /* TP_STD_CMD_COORD_FLIP_Y_EN_RW */
{ 0, 7, 4, 1, 1, 0 }, /* TP_STD_CMD_COORD_SWAP_AXES_EN_RW */
{ 0, 11, 1, 1, 1, 0 }, /* TP_STD_CMD_OPENSHORT_EN_RW */
{ 0, 11, 2, 1, 1, 0 }, /* TP_STD_CMD_OPENSHORT_MODE_SEL_RW */
{ 0, 11, 3, 1, 1, 0 }, /* TP_STD_CMD_OPENSHORT_SHORT_SEL_RW */
{ 0, 11, 4, 1, 1, 0 }, /* TP_STD_CMD_OPENSHORT_SHORT_DISP_ON_EN_RW */
};
#endif /* _CTS_TCS_C_ */
extern struct cts_dev_ops tcs_ops;
#endif /* _CTS_TCS_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef CTS_TEST_H
#define CTS_TEST_H
struct cts_device;
extern int cts_short_test(struct cts_device *cts_dev, u16 threshold);
extern int cts_open_test(struct cts_device *cts_dev, u16 threshold);
extern int cts_reset_test(struct cts_device *cts_dev);
extern int cts_compensate_cap_test(struct cts_device *cts_dev, u8 min_thres,
u8 max_thres);
extern int cts_rawdata_test(struct cts_device *cts_dev, u16 min_thres,
u16 max_thres);
extern int cts_noise_test(struct cts_device *cts_dev, u32 frames, u16 max);
extern int cts_test_int_pin(struct cts_device *cts_dev);
#endif /* CTS_TEST_H */

View file

@ -0,0 +1,803 @@
// SPDX-License-Identifier: GPL-2.0
#define LOG_TAG "Tool"
#include "cts_config.h"
#include "cts_platform.h"
#include "cts_core.h"
#include "cts_firmware.h"
#include "cts_test.h"
#ifdef CONFIG_CTS_LEGACY_TOOL
#pragma pack(1)
/** Tool command structure */
struct cts_tool_cmd {
u8 cmd;
u8 flag;
u8 circle;
u8 times;
u8 retry;
u32 data_len;
u8 addr_len;
u8 addr[4];
u8 tcs[2];
u8 data[PAGE_SIZE];
};
#pragma pack()
#define CTS_TOOL_CMD_HEADER_LENGTH (16)
enum cts_tool_cmd_code {
CTS_TOOL_CMD_GET_PANEL_PARAM = 0,
CTS_TOOL_CMD_GET_DOWNLOAD_STATUS = 2,
CTS_TOOL_CMD_GET_RAW_DATA = 4,
CTS_TOOL_CMD_GET_DIFF_DATA = 6,
CTS_TOOL_CMD_READ_HOSTCOMM = 12,
CTS_TOOL_CMD_READ_ADC_STATUS = 14,
CTS_TOOL_CMD_READ_GESTURE_INFO = 16,
CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE = 18,
CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE = 20,
CTS_TOOL_CMD_READ_ICTYPE = 22,
CTS_TOOL_CMD_I2C_DIRECT_READ = 24,
CTS_TOOL_CMD_GET_DRIVER_INFO = 26,
CTS_TOOL_CMD_TCS_READ_HW_CMD = 28,
CTS_TOOL_CMD_TCS_READ_DDI_CMD = 30,
CTS_TOOL_CMD_TCS_READ_FW_CMD = 32,
CTS_TOOL_CMD_GET_BASE_DATA = 34,
CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM = 1,
CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME = 3,
CTS_TOOL_CMD_DOWNLOAD_FIRMWARE = 5,
CTS_TOOL_CMD_WRITE_HOSTCOMM = 11,
CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE = 15,
CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE = 17,
CTS_TOOL_CMD_I2C_DIRECT_WRITE = 19,
CTS_TOOL_CMD_TCS_WRITE_HW_CMD = 21,
CTS_TOOL_CMD_TCS_WRITE_DDI_CMD = 23,
CTS_TOOL_CMD_TCS_WRITE_FW_CMD = 25,
CTS_TOOL_CMD_TCS_ENABLE_GET_RAWDATA_CMD = 27,
CTS_TOOL_CMD_TCS_DISABLE_GET_RAWDATA_CMD = 29,
};
struct cts_test_rawdata_ioctl_data {
int frames;
int min;
int max;
};
struct cts_test_noise_ioctl_data {
int frames;
int max;
};
struct cts_test_open_ioctl_data {
int min;
int max;
};
struct cts_test_short_ioctl_data {
int min;
int max;
bool display_on;
bool disable_gas;
};
struct cts_test_comp_cap_ioctl_data {
int min;
int max;
};
#define CTS_TOOL_IOCTL_GET_DRIVER_VERSION _IOR('C', 0x00, unsigned int)
#define CTS_TOOL_IOCTL_GET_DEVICE_TYPE _IOR('C', 0x01, unsigned int)
#define CTS_TOOL_IOCTL_GET_FW_VERSION _IOR('C', 0x02, unsigned short)
#define CTS_TOOL_IOCTL_TEST_RESET_PIN _IO('C', 0x11)
#define CTS_TOOL_IOCTL_TEST_INT_PIN _IO('C', 0x12)
#define CTS_TOOL_IOCTL_TEST_DEVICE_TYPE _IOW('C', 0x13, unsigned int)
#define CTS_TOOL_IOCTL_TEST_FW_VERSION _IOW('C', 0x14, unsigned short)
#define CTS_TOOL_IOCTL_TEST_RAWDATA \
_IOW('C', 0x15, struct cts_test_rawdata_ioctl_data *)
#define CTS_TOOL_IOCTL_TEST_NOISE \
_IOW('C', 0x16, struct cts_test_noise_ioctl_data *)
#define CTS_TOOL_IOCTL_TEST_OPEN \
_IOW('C', 0x17, struct cts_test_open_ioctl_data *)
#define CTS_TOOL_IOCTL_TEST_SHORT \
_IOW('C', 0x18, struct cts_test_short_ioctl_data *)
#define CTS_TOOL_IOCTL_TEST_COMP_CAP \
_IOW('C', 0x19, struct cts_test_comp_cap_ioctl_data *)
#define CTS_DRIVER_VERSION_CODE ((CFG_CTS_DRIVER_MAJOR_VERSION << 16) | \
(CFG_CTS_DRIVER_MINOR_VERSION << 8) | \
(CFG_CTS_DRIVER_PATCH_VERSION << 0))
static struct cts_tool_cmd cts_tool_cmd;
static char cts_tool_firmware_filepath[PATH_MAX];
/* If CFG_CTS_MAX_I2C_XFER_SIZE < 58(PC tool length), this is neccessary */
#ifdef CONFIG_CTS_I2C_HOST
/*static u32 cts_tool_direct_access_addr = 0;*/
#endif /* CONFIG_CTS_I2C_HOST */
static int cts_tool_open(struct inode *inode, struct file *file)
{
file->private_data = PDE_DATA(inode);
return 0;
}
static ssize_t cts_tool_read(struct file *file,
char __user *buffer, size_t count, loff_t *ppos)
{
#define RAWDATA_BUFFER_SIZE(cts_dev) \
(cts_dev->hwdata->num_row * cts_dev->hwdata->num_col * 2)
struct chipone_ts_data *cts_data;
struct cts_tool_cmd *cmd;
struct cts_device *cts_dev;
int ret = 0;
cts_data = (struct chipone_ts_data *)file->private_data;
if (cts_data == NULL) {
cts_err("Read with private_data = NULL");
return -EIO;
}
cmd = &cts_tool_cmd;
cts_dev = &cts_data->cts_dev;
cts_lock_device(cts_dev);
cts_info("read: flag:%d, addr:0x%06x, tcm:0x%04x, datalen:%d",
cmd->cmd, get_unaligned_le32(cmd->addr),
get_unaligned_le16(cmd->tcs), cmd->data_len);
switch (cmd->cmd) {
case CTS_TOOL_CMD_TCS_READ_HW_CMD:
cts_dev->ops->read_hw_reg(cts_dev,
get_unaligned_le32(cmd->addr),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_TCS_READ_DDI_CMD:
cts_dev->ops->read_ddi_reg(cts_dev,
get_unaligned_le32(cmd->addr),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_TCS_READ_FW_CMD:
cts_dev->ops->read_reg(cts_dev, get_unaligned_le16(cmd->tcs),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_GET_PANEL_PARAM:
cts_info("Get panel param len: %u", cmd->data_len);
ret = cts_get_panel_param(cts_dev, cmd->data, cmd->data_len);
if (ret) {
cts_err("Get panel param len: %u failed %d",
cmd->data_len, ret);
}
break;
case CTS_TOOL_CMD_GET_DOWNLOAD_STATUS:
cmd->data[0] = 100;
cts_info("Get update status = %hhu", cmd->data[0]);
break;
case CTS_TOOL_CMD_GET_RAW_DATA:
case CTS_TOOL_CMD_GET_DIFF_DATA:
case CTS_TOOL_CMD_GET_BASE_DATA:
cts_info("Get %s data row: %u col: %u len: %u",
cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA ? "raw" : "diff",
cmd->addr[1], cmd->addr[0], cmd->data_len);
if (cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA) {
// ret = cts_get_rawdata(cts_dev, cmd->data);
ret =
cts_dev->ops->top_get_rawdata(cts_dev,
(u8 *) cmd->data,
RAWDATA_BUFFER_SIZE
(cts_dev));
} else if (cmd->cmd == CTS_TOOL_CMD_GET_DIFF_DATA) {
// ret = cts_get_diffdata(cts_dev, cmd->data);
ret =
cts_dev->ops->top_get_manual_diff(cts_dev,
(u8 *) cmd->data,
RAWDATA_BUFFER_SIZE
(cts_dev));
} else if (cmd->cmd == CTS_TOOL_CMD_GET_BASE_DATA) {
// ret = cts_get_basedata(cts_dev, cmd->data);
ret =
cts_dev->ops->top_get_basedata(cts_dev,
(u8 *) cmd->data,
RAWDATA_BUFFER_SIZE
(cts_dev));
}
if (ret) {
cts_err("Get %s data failed %d",
cmd->cmd == CTS_TOOL_CMD_GET_RAW_DATA ? "raw" :
cmd->cmd ==
CTS_TOOL_CMD_GET_DIFF_DATA ? "diff" : "base",
ret);
}
break;
case CTS_TOOL_CMD_READ_HOSTCOMM:
ret = cts_fw_reg_readb(cts_dev, get_unaligned_le16(cmd->addr),
cmd->data);
if (ret) {
cts_err("Read firmware reg addr 0x%04x failed %d",
get_unaligned_le16(cmd->addr), ret);
} else {
cts_dbg("Read firmware reg addr 0x%04x, val=0x%02x",
get_unaligned_le16(cmd->addr), cmd->data[0]);
}
break;
#ifdef CFG_CTS_GESTURE
case CTS_TOOL_CMD_READ_GESTURE_INFO:
ret = cts_get_gesture_info(cts_dev, cmd->data, true);
if (ret)
cts_err("Get gesture info failed %d", ret);
break;
#endif /* CFG_CTS_GESTURE */
case CTS_TOOL_CMD_READ_HOSTCOMM_MULTIBYTE:
cmd->data_len = min((size_t)cmd->data_len, sizeof(cmd->data));
ret = cts_fw_reg_readsb(cts_dev, get_unaligned_le16(cmd->addr),
cmd->data, cmd->data_len);
if (ret) {
cts_err
("Read firmware reg addr 0x%04x len %u failed %d",
get_unaligned_le16(cmd->addr), cmd->data_len, ret);
} else {
cts_dbg("Read firmware reg addr 0x%04x len %u",
get_unaligned_le16(cmd->addr), cmd->data_len);
}
break;
case CTS_TOOL_CMD_READ_PROGRAM_MODE_MULTIBYTE:
cts_dbg("Read under program mode addr 0x%06x len %u",
(cmd->flag << 16) | get_unaligned_le16(cmd->addr),
cmd->data_len);
ret = cts_enter_program_mode(cts_dev);
if (ret) {
cts_err("Enter program mode failed %d", ret);
break;
}
ret = cts_sram_readsb(&cts_data->cts_dev,
get_unaligned_le16(cmd->addr), cmd->data,
cmd->data_len);
if (ret) {
cts_err("Read under program mode I2C xfer failed %d",
ret);
}
ret = cts_enter_normal_mode(cts_dev);
if (ret) {
cts_err("Enter normal mode failed %d", ret);
break;
}
break;
case CTS_TOOL_CMD_READ_ICTYPE:
cts_info("Get IC type");
if (cts_dev->hwdata) {
switch (cts_dev->hwdata->hwid) {
case CTS_DEV_HWID_ICNL9911:
cmd->data[0] = 0x91;
break;
case CTS_DEV_HWID_ICNL9911S:
cmd->data[0] = 0x91;
break;
case CTS_DEV_HWID_ICNL9911C:
cmd->data[0] = 0x91;
break;
default:
cmd->data[0] = 0x00;
break;
}
} else {
cmd->data[0] = 0x10;
}
break;
#ifdef CONFIG_CTS_I2C_HOST
case CTS_TOOL_CMD_I2C_DIRECT_READ:
{
u32 addr_width;
char *wr_buff = NULL;
u8 addr_buff[4];
size_t left_size, max_xfer_size;
u8 *data;
if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) {
cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR;
addr_width = 2;
} else {
addr_width =
cts_dev->hwdata->program_addr_width;
}
cts_dbg
("Direct read from i2c_addr 0x%02x addr 0x%06x size %u",
cmd->addr[0], cts_tool_direct_access_addr,
cmd->data_len);
left_size = cmd->data_len;
max_xfer_size =
cts_plat_get_max_i2c_xfer_size(cts_dev->pdata);
data = cmd->data;
while (left_size) {
size_t xfer_size =
min(left_size, max_xfer_size);
ret =
cts_plat_i2c_read(cts_data->pdata,
cmd->addr[0], wr_buff,
addr_width, data,
xfer_size, 1, 0);
if (ret) {
cts_err
("Direct read i2c_addr 0x%02x addr 0x%06x "
"len %zu failed %d", cmd->addr[0],
cts_tool_direct_access_addr,
xfer_size, ret);
break;
}
left_size -= xfer_size;
if (left_size) {
data += xfer_size;
cts_tool_direct_access_addr +=
xfer_size;
if (addr_width == 2) {
put_unaligned_be16
(cts_tool_direct_access_addr,
addr_buff);
} else if (addr_width == 3) {
put_unaligned_be24
(cts_tool_direct_access_addr,
addr_buff);
}
wr_buff = addr_buff;
}
}
}
break;
#endif
case CTS_TOOL_CMD_GET_DRIVER_INFO:
break;
default:
cts_warn("Read unknown command %u", cmd->cmd);
ret = -EINVAL;
break;
}
cts_unlock_device(cts_dev);
if (ret == 0) {
if (cmd->cmd == CTS_TOOL_CMD_I2C_DIRECT_READ) {
ret = copy_to_user(buffer + CTS_TOOL_CMD_HEADER_LENGTH,
cmd->data, cmd->data_len);
} else {
ret = copy_to_user(buffer, cmd->data, cmd->data_len);
}
if (ret) {
cts_err("Copy data to user buffer failed %d", ret);
return 0;
}
return cmd->data_len;
}
return 0;
}
static ssize_t cts_tool_write(struct file *file,
const char __user *buffer, size_t count,
loff_t *ppos)
{
struct chipone_ts_data *cts_data;
struct cts_device *cts_dev;
struct cts_tool_cmd *cmd;
int ret = 0;
if (count < CTS_TOOL_CMD_HEADER_LENGTH || count > PAGE_SIZE) {
cts_err("Write len %zu invalid", count);
return -EFAULT;
}
cts_data = (struct chipone_ts_data *)file->private_data;
if (cts_data == NULL) {
cts_err("Write with private_data = NULL");
return -EIO;
}
cmd = &cts_tool_cmd;
ret = copy_from_user(cmd, buffer, CTS_TOOL_CMD_HEADER_LENGTH);
cts_info
("write: flag:%d, addr:0x%06x, tcmd:0x%04x data:0x%02x, datalen:%d",
cmd->cmd, get_unaligned_le32(cmd->addr),
get_unaligned_le16(cmd->tcs), cmd->data[0], cmd->data_len);
if (ret) {
cts_err("Copy command header from user buffer failed %d", ret);
return -EIO;
} else
ret = CTS_TOOL_CMD_HEADER_LENGTH;
if (cmd->data_len > PAGE_SIZE) {
cts_err("Write with invalid count %d", cmd->data_len);
return -EIO;
}
if (cmd->cmd & BIT(0)) {
if (cmd->data_len) {
ret =
copy_from_user(cmd->data,
buffer + CTS_TOOL_CMD_HEADER_LENGTH,
cmd->data_len);
if (ret) {
cts_err
("Copy command payload from user buffer len %u failed %d",
cmd->data_len, ret);
return -EIO;
}
}
} else {
/* Prepare for read command */
cts_dbg("Write read command(%d) header, prepare read size: %d",
cmd->cmd, cmd->data_len);
return CTS_TOOL_CMD_HEADER_LENGTH + cmd->data_len;
}
cts_dev = &cts_data->cts_dev;
cts_lock_device(cts_dev);
switch (cmd->cmd) {
case CTS_TOOL_CMD_TCS_WRITE_HW_CMD:
cts_dev->ops->write_hw_reg(cts_dev,
get_unaligned_le32(cmd->addr),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_TCS_WRITE_DDI_CMD:
cts_dev->ops->write_ddi_reg(cts_dev,
get_unaligned_le32(cmd->addr),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_TCS_WRITE_FW_CMD:
cts_dev->ops->write_reg(cts_dev, get_unaligned_le16(cmd->tcs),
cmd->data, cmd->data_len);
break;
case CTS_TOOL_CMD_TCS_ENABLE_GET_RAWDATA_CMD:
cts_info("Enable touch data");
ret = cts_dev->ops->enable_get_rawdata(cts_dev);
if (ret)
cts_err("Enable get touch data failed");
break;
case CTS_TOOL_CMD_TCS_DISABLE_GET_RAWDATA_CMD:
cts_info("Disable touch data");
ret = cts_dev->ops->disable_get_rawdata(cts_dev);
if (ret)
cts_err("Disable get touch data failed");
break;
case CTS_TOOL_CMD_UPDATE_PANEL_PARAM_IN_SRAM:
cts_info("Write panel param len %u data\n", cmd->data_len);
ret = cts_fw_reg_writesb(cts_dev, CTS_DEVICE_FW_REG_PANEL_PARAM,
cmd->data, cmd->data_len);
if (ret) {
cts_err("Write panel param failed %d", ret);
break;
}
ret = cts_send_command(cts_dev, CTS_CMD_RESET);
ret = cts_set_work_mode(cts_dev, 1);
mdelay(100);
ret = cts_set_work_mode(cts_dev, 0);
mdelay(100);
break;
case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE_WITH_FILENAME:
cts_info("Write firmware path: '%.*s'",
cmd->data_len, cmd->data);
memcpy(cts_tool_firmware_filepath, cmd->data, cmd->data_len);
cts_tool_firmware_filepath[cmd->data_len] = '\0';
break;
case CTS_TOOL_CMD_DOWNLOAD_FIRMWARE:
cts_info("Start download firmware path: '%s'",
cts_tool_firmware_filepath);
ret = cts_stop_device(cts_dev);
if (ret) {
cts_err("Stop device failed %d", ret);
break;
}
/**
*TODO: Use async mode such as thread, otherwise,
*host can not get update status.
*/
ret = cts_update_firmware_from_file(cts_dev,
cts_tool_firmware_filepath,
true);
if (ret)
cts_err("Updata firmware failed %d", ret);
ret = cts_start_device(cts_dev);
if (ret) {
cts_err("Start device failed %d", ret);
break;
}
break;
case CTS_TOOL_CMD_WRITE_HOSTCOMM:
cts_dbg("Write firmware reg addr: 0x%04x val=0x%02x",
get_unaligned_le16(cmd->addr), cmd->data[0]);
ret = cts_fw_reg_writeb(cts_dev, get_unaligned_le16(cmd->addr),
cmd->data[0]);
if (ret) {
cts_err
("Write firmware reg addr: 0x%04x val=0x%02x failed %d",
get_unaligned_le16(cmd->addr), cmd->data[0], ret);
}
break;
case CTS_TOOL_CMD_WRITE_HOSTCOMM_MULTIBYTE:
cts_dbg("Write firmare reg addr: 0x%04x len %u",
get_unaligned_le16(cmd->addr), cmd->data_len);
ret = cts_fw_reg_writesb(cts_dev, get_unaligned_le16(cmd->addr),
cmd->data, cmd->data_len);
if (ret) {
cts_err
("Write firmare reg addr: 0x%04x len %u failed %d",
get_unaligned_le16(cmd->addr), cmd->data_len, ret);
}
break;
case CTS_TOOL_CMD_WRITE_PROGRAM_MODE_MULTIBYTE:
cts_dbg("Write to addr 0x%06x size %u under program mode",
(cmd->flag << 16) | (cmd->addr[1] << 8) | cmd->addr[0],
cmd->data_len);
ret = cts_enter_program_mode(cts_dev);
if (ret) {
cts_err("Enter program mode failed %d", ret);
break;
}
ret = cts_sram_writesb(cts_dev,
(cmd->flag << 16) | (cmd->addr[1] << 8) |
cmd->addr[0], cmd->data, cmd->data_len);
if (ret)
cts_err("Write program mode multibyte failed %d", ret);
ret = cts_enter_normal_mode(cts_dev);
if (ret) {
cts_err("Enter normal mode failed %d", ret);
break;
}
break;
#ifdef CONFIG_CTS_I2C_HOST
case CTS_TOOL_CMD_I2C_DIRECT_WRITE:
{
u32 addr_width;
size_t left_payload_size; /* Payload exclude address field */
size_t max_xfer_size;
char *payload;
if (cmd->addr[0] != CTS_DEV_PROGRAM_MODE_I2CADDR) {
cmd->addr[0] = CTS_DEV_NORMAL_MODE_I2CADDR;
addr_width = 2;
cts_tool_direct_access_addr =
get_unaligned_be16(cmd->data);
} else {
addr_width =
cts_dev->hwdata->program_addr_width;
cts_tool_direct_access_addr =
get_unaligned_be24(cmd->data);
}
if (cmd->data_len < addr_width) {
cts_err
("Direct write too short %d < address width %d",
cmd->data_len, addr_width);
ret = -EINVAL;
break;
}
cts_dbg
("Direct write to i2c_addr 0x%02x addr 0x%06x size %u",
cmd->addr[0], cts_tool_direct_access_addr,
cmd->data_len);
left_payload_size = cmd->data_len - addr_width;
max_xfer_size =
cts_plat_get_max_i2c_xfer_size(cts_dev->pdata);
payload = cmd->data + addr_width;
do {
size_t xfer_payload_size =
min(left_payload_size,
max_xfer_size - addr_width);
size_t xfer_len =
xfer_payload_size + addr_width;
ret = cts_plat_i2c_write(cts_data->pdata,
cmd->addr[0],
payload - addr_width,
xfer_len, 1, 0);
if (ret) {
cts_err
("Direct write i2c_addr 0x%02x addr 0x%06x len %zu failed %d",
cmd->addr[0],
cts_tool_direct_access_addr,
xfer_len, ret);
break;
}
left_payload_size -= xfer_payload_size;
if (left_payload_size) {
payload += xfer_payload_size;
cts_tool_direct_access_addr +=
xfer_payload_size;
if (addr_width == 2) {
put_unaligned_be16
(cts_tool_direct_access_addr,
payload - addr_width);
} else if (addr_width == 3) {
put_unaligned_be24
(cts_tool_direct_access_addr,
payload - addr_width);
}
}
} while (left_payload_size);
}
break;
#endif
default:
cts_warn("Write unknown command %u", cmd->cmd);
ret = -EINVAL;
break;
}
cts_unlock_device(cts_dev);
return ret ? 0 : cmd->data_len + CTS_TOOL_CMD_HEADER_LENGTH;
}
static long cts_tool_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct chipone_ts_data *cts_data;
struct cts_device *cts_dev;
cts_info("ioctl, cmd=0x%04x, arg=0x%02lx", cmd, arg);
cts_data = file->private_data;
if (cts_data == NULL) {
cts_err("IOCTL with private data = NULL");
return -EFAULT;
}
cts_dev = &cts_data->cts_dev;
switch (cmd) {
case CTS_TOOL_IOCTL_GET_DRIVER_VERSION:
return put_user(CTS_DRIVER_VERSION_CODE,
(unsigned int __user *)arg);
case CTS_TOOL_IOCTL_GET_DEVICE_TYPE:
return put_user(cts_dev->hwdata->hwid,
(unsigned int __user *)arg);
case CTS_TOOL_IOCTL_GET_FW_VERSION:
return put_user(cts_dev->fwdata.version,
(unsigned short __user *)arg);
case CTS_TOOL_IOCTL_TEST_RESET_PIN:
return cts_reset_test(cts_dev);
case CTS_TOOL_IOCTL_TEST_INT_PIN:
return cts_test_int_pin(cts_dev);
case CTS_TOOL_IOCTL_TEST_DEVICE_TYPE:
if (cts_dev->hwdata->hwid == (u32) arg)
return 0;
return -EINVAL;
case CTS_TOOL_IOCTL_TEST_FW_VERSION:
if (cts_dev->fwdata.version == (u16) arg)
return 0;
return -EINVAL;
case CTS_TOOL_IOCTL_TEST_RAWDATA:{
struct cts_test_rawdata_ioctl_data param;
if (copy_from_user(&param,
(struct cts_test_rawdata_ioctl_data
__user *)arg, sizeof(param)))
return -EFAULT;
return cts_rawdata_test(cts_dev, param.min, param.max);
}
case CTS_TOOL_IOCTL_TEST_NOISE:{
struct cts_test_noise_ioctl_data param;
if (copy_from_user(&param,
(struct
cts_test_noise_ioctl_data__user *)
arg, sizeof(param)))
return -EFAULT;
return cts_noise_test(cts_dev, param.frames, param.max);
}
case CTS_TOOL_IOCTL_TEST_OPEN:{
struct cts_test_open_ioctl_data param;
if (copy_from_user(&param,
(struct cts_test_open_ioctl_data
__user *)arg, sizeof(param)))
return -EFAULT;
return cts_open_test(cts_dev, param.max);
}
case CTS_TOOL_IOCTL_TEST_SHORT:{
struct cts_test_short_ioctl_data param;
if (copy_from_user
(&param,
(struct cts_test_short_ioctl_data __user *)arg,
sizeof(param)))
return -EFAULT;
return cts_short_test(cts_dev, param.max);
}
case CTS_TOOL_IOCTL_TEST_COMP_CAP:{
struct cts_test_comp_cap_ioctl_data param;
if (copy_from_user
(&param,
(struct cts_test_comp_cap_ioctl_data __user *)arg,
sizeof(param)))
return -EFAULT;
return cts_compensate_cap_test(cts_dev, param.min,
param.max);
}
default:
break;
}
return -ENOTSUPP;
}
static struct file_operations cts_tool_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.open = cts_tool_open,
.read = cts_tool_read,
.write = cts_tool_write,
.unlocked_ioctl = cts_tool_ioctl,
};
int cts_tool_init(struct chipone_ts_data *cts_data)
{
cts_info("Init");
cts_data->procfs_entry = proc_create_data(CFG_CTS_TOOL_PROC_FILENAME,
0600, NULL, &cts_tool_fops,
cts_data);
if (cts_data->procfs_entry == NULL) {
cts_err("Create proc entry failed");
return -EFAULT;
}
return 0;
}
void cts_tool_deinit(struct chipone_ts_data *data)
{
cts_info("Deinit");
if (data->procfs_entry)
remove_proc_entry(CFG_CTS_TOOL_PROC_FILENAME, NULL);
}
#endif /* CONFIG_CTS_LEGACY_TOOL */