Add 'qcom/opensource/touch-drivers/' from commit '0abb70a15bd5d3469505bb0249d49266a4a5595e'

git-subtree-dir: qcom/opensource/touch-drivers
git-subtree-mainline: 51ff30338b
git-subtree-split: 0abb70a15b
Change-Id:
repo: https://git.codelinaro.org/clo/la/platform/vendor/opensource/touch-drivers
tag: LA.VENDOR.14.3.0.r1-17300-lanai.QSSI15.0
This commit is contained in:
David Wronek
2024-10-06 16:45:39 +02:00
164 changed files with 156774 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
cc_library_headers {
name: "qti_glink_touch_kernel_headers",
export_include_dirs: [
"glink_interface_ts",
],
vendor_available: true,
}

View File

@@ -0,0 +1,403 @@
# Android makefile for display kernel modules
TOUCH_DLKM_ENABLE := true
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
ifeq ($(TARGET_KERNEL_DLKM_TOUCH_OVERRIDE), false)
TOUCH_DLKM_ENABLE := false
endif
endif
ifeq ($(TOUCH_DLKM_ENABLE), true)
TOUCH_SELECT := CONFIG_MSM_TOUCH=m
BOARD_OPENSOURCE_DIR ?= vendor/qcom/opensource
BOARD_COMMON_DIR ?= device/qcom/common
LOCAL_PATH := $(call my-dir)
ifeq ($(TARGET_BOARD_PLATFORM), pineapple)
LOCAL_MODULE_DDK_BUILD := true
endif
ifeq ($(TARGET_BOARD_PLATFORM), blair)
LOCAL_MODULE_DDK_BUILD := true
endif
ifeq ($(TARGET_BOARD_PLATFORM), pitti)
LOCAL_MODULE_DDK_BUILD := true
endif
ifeq ($(TARGET_BOARD_PLATFORM), monaco)
LOCAL_MODULE_DDK_BUILD := true
endif
ifeq ($(TARGET_BOARD_PLATFORM), volcano)
LOCAL_MODULE_DDK_BUILD := true
endif
include $(CLEAR_VARS)
# This makefile is only for DLKM
ifneq ($(findstring vendor,$(LOCAL_PATH)),)
ifneq ($(findstring opensource,$(LOCAL_PATH)),)
TOUCH_BLD_DIR := $(shell pwd)/$(BOARD_OPENSOURCE_DIR)/touch-drivers
endif # opensource
DLKM_DIR := $(TOP)/$(BOARD_COMMON_DIR)/dlkm
LOCAL_ADDITIONAL_DEPENDENCIES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
# Build
###########################################################
# This is set once per LOCAL_PATH, not per (kernel) module
KBUILD_OPTIONS := TOUCH_ROOT=$(TOUCH_BLD_DIR)
KBUILD_OPTIONS += MODNAME=touch_dlkm
KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
KBUILD_OPTIONS += $(TOUCH_SELECT)
###########################################################
ifeq ($(TARGET_BOARD_PLATFORM), monaco)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := pt_ts.ko
LOCAL_MODULE_KBUILD_NAME := pt_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := pt_i2c.ko
LOCAL_MODULE_KBUILD_NAME := pt_i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := pt_device_access.ko
LOCAL_MODULE_KBUILD_NAME := pt_device_access.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := glink_comm.ko
LOCAL_MODULE_KBUILD_NAME := glink_comm.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := raydium_ts.ko
LOCAL_MODULE_KBUILD_NAME := raydium_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), kona)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := focaltech_fts.ko
LOCAL_MODULE_KBUILD_NAME := focaltech_fts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), pineapple)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := nt36xxx-i2c.ko
LOCAL_MODULE_KBUILD_NAME := nt36xxx-i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := atmel_mxt_ts.ko
LOCAL_MODULE_KBUILD_NAME := atmel_mxt_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), kalama)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := nt36xxx-i2c.ko
LOCAL_MODULE_KBUILD_NAME := nt36xxx-i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := atmel_mxt_ts.ko
LOCAL_MODULE_KBUILD_NAME := atmel_mxt_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), blair)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := focaltech_fts.ko
LOCAL_MODULE_KBUILD_NAME := focaltech_fts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := nt36xxx-i2c.ko
LOCAL_MODULE_KBUILD_NAME := nt36xxx-i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := synaptics_tcm_ts.ko
LOCAL_MODULE_KBUILD_NAME := synaptics_tcm_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), crow)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), bengal)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := synaptics_tcm_ts.ko
LOCAL_MODULE_KBUILD_NAME := synaptics_tcm_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := nt36xxx-i2c.ko
LOCAL_MODULE_KBUILD_NAME := nt36xxx-i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := focaltech_fts.ko
LOCAL_MODULE_KBUILD_NAME := focaltech_fts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), trinket)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := synaptics_tcm_ts.ko
LOCAL_MODULE_KBUILD_NAME := synaptics_tcm_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), pitti)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := focaltech_fts.ko
LOCAL_MODULE_KBUILD_NAME := focaltech_fts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else ifeq ($(TARGET_BOARD_PLATFORM), volcano)
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := focaltech_fts.ko
LOCAL_MODULE_KBUILD_NAME := focaltech_fts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
else
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := nt36xxx-i2c.ko
LOCAL_MODULE_KBUILD_NAME := nt36xxx-i2c.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := goodix_ts.ko
LOCAL_MODULE_KBUILD_NAME := goodix_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := atmel_mxt_ts.ko
LOCAL_MODULE_KBUILD_NAME := atmel_mxt_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
###########################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
LOCAL_MODULE := synaptics_tcm_ts.ko
LOCAL_MODULE_KBUILD_NAME := synaptics_tcm_ts.ko
LOCAL_MODULE_TAGS := optional
#LOCAL_MODULE_DEBUG_ENABLE := true
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/Build_external_kernelmodule.mk
###########################################################
endif #kona
endif # DLKM check
endif

View File

@@ -0,0 +1,82 @@
load("//build/kernel/kleaf:kernel.bzl", "ddk_headers")
package(
default_visibility = [
"//visibility:public"],
)
ddk_headers(
name = "goodix_ts_headers",
hdrs = glob([
"goodix_berlin_driver/*.h",
"qts/*.h"
]
)
)
ddk_headers(
name = "nt36xxx_headers",
hdrs = glob([
"nt36xxx/*.h"
]
)
)
ddk_headers(
name = "focaltech_headers",
hdrs = glob([
"focaltech_touch/*.h"
]
)
)
ddk_headers(
name = "synaptics_tcm_headers",
hdrs = glob([
"synaptics_tcm/*.h"
]
)
)
ddk_headers(
name = "config_headers",
hdrs = glob([
"config/*.h"
]
),
includes = ["config"]
)
ddk_headers(
name = "glink_interface_ts_headers",
hdrs = glob([
"glink_interface_ts/*.h"
]
),
includes = ["glink_interface_ts"]
)
ddk_headers(
name = "pt_headers",
hdrs = glob([
"pt/*.h"
]
)
)
ddk_headers(
name = "raydium_headers",
hdrs = glob([
"raydium/*.h",
"raydium/chip_raydium/*.h"
]
)
)
ddk_headers(
name = "touch_drivers_headers",
hdrs = [":goodix_ts_headers", ":nt36xxx_headers", ":focaltech_headers", ":synaptics_tcm_headers", ":glink_interface_ts_headers", ":pt_headers", ":raydium_headers", ":config_headers"]
)
load(":target.bzl", "define_touch_target")
define_touch_target()

View File

@@ -0,0 +1,247 @@
KDIR := $(TOP)/kernel_platform/common
ifeq ($(CONFIG_ARCH_WAIPIO), y)
include $(TOUCH_ROOT)/config/gki_waipiotouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_waipiotouchconf.h
endif
ifeq ($(CONFIG_ARCH_KALAMA), y)
include $(TOUCH_ROOT)/config/gki_kalamatouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_kalamatouchconf.h
endif
ifeq ($(CONFIG_ARCH_KHAJE), y)
include $(TOUCH_ROOT)/config/gki_khajetouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_khajetouchconf.h
endif
ifeq ($(CONFIG_ARCH_PINEAPPLE), y)
include $(TOUCH_ROOT)/config/gki_pineappletouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_pineappletouchconf.h
endif
ifeq ($(CONFIG_ARCH_MONACO), y)
include $(TOUCH_ROOT)/config/gki_monacotouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_monacotouchconf.h
endif
ifeq ($(CONFIG_ARCH_KONA), y)
include $(TOUCH_ROOT)/config/gki_konatouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_konatouchconf.h
endif
ifeq ($(CONFIG_ARCH_BLAIR), y)
include $(TOUCH_ROOT)/config/gki_blairtouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_blairtouchconf.h
endif
ifeq ($(CONFIG_ARCH_CROW), y)
include $(TOUCH_ROOT)/config/gki_crowtouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_crowtouchconf.h
endif
ifeq ($(CONFIG_ARCH_TRINKET), y)
include $(TOUCH_ROOT)/config/gki_trinkettouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_trinkettouchconf.h
endif
ifeq ($(CONFIG_ARCH_BENGAL), y)
include $(TOUCH_ROOT)/config/gki_bengaltouch.conf
LINUX_INC += -include $(TOUCH_ROOT)/config/gki_bengaltouchconf.h
endif
LINUX_INC += -Iinclude/linux \
-Iinclude/linux/drm \
-Iinclude/linux/gunyah \
-Iinclude/linux/input
CDEFINES += -DANI_LITTLE_BYTE_ENDIAN \
-DANI_LITTLE_BIT_ENDIAN \
-DDOT11F_LITTLE_ENDIAN_HOST \
-DANI_COMPILER_TYPE_GCC \
-DANI_OS_TYPE_ANDROID=6 \
-DPTT_SOCK_SVC_ENABLE \
-Wall\
-Werror\
-D__linux__
KBUILD_CPPFLAGS += $(CDEFINES)
ccflags-y += $(LINUX_INC)
ifeq ($(call cc-option-yn, -Wmaybe-uninitialized),y)
EXTRA_CFLAGS += -Wmaybe-uninitialized
endif
ifeq ($(call cc-option-yn, -Wheader-guard),y)
EXTRA_CFLAGS += -Wheader-guard
endif
######### CONFIG_MSM_TOUCH ########
ifeq ($(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX), y)
LINUX_INC += -include $(TOUCH_ROOT)/synaptics_dsx/synaptics_dsx.h
LINUX_INC += -include $(TOUCH_ROOT)/synaptics_dsx/synaptics_dsx_core.h
synaptics_dsx-y := \
./synaptics_dsx/synaptics_dsx_core.o \
./synaptics_dsx/synaptics_dsx_i2c.o
obj-$(CONFIG_MSM_TOUCH) += synaptics_dsx.o
endif
ifeq ($(CONFIG_TOUCH_FOCALTECH), y)
LINUX_INC += -include $(TOUCH_ROOT)/focaltech_touch/focaltech_common.h
LINUX_INC += -include $(TOUCH_ROOT)/focaltech_touch/focaltech_config.h
LINUX_INC += -include $(TOUCH_ROOT)/focaltech_touch/focaltech_core.h
LINUX_INC += -include $(TOUCH_ROOT)/focaltech_touch/focaltech_flash.h
focaltech_fts-y := \
./focaltech_touch/focaltech_core.o \
./focaltech_touch/focaltech_ex_fun.o \
./focaltech_touch/focaltech_ex_mode.o \
./focaltech_touch/focaltech_gesture.o \
./focaltech_touch/focaltech_esdcheck.o \
./focaltech_touch/focaltech_point_report_check.o \
./focaltech_touch/focaltech_i2c.o \
./focaltech_touch/focaltech_flash.o \
./focaltech_touch/focaltech_flash/focaltech_upgrade_ft3518.o
obj-$(CONFIG_MSM_TOUCH) += focaltech_fts.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_NT36XXX_I2C), y)
LINUX_INC += -include $(TOUCH_ROOT)/nt36xxx/nt36xxx.h
LINUX_INC += -include $(TOUCH_ROOT)/nt36xxx/nt36xxx_mem_map.h
LINUX_INC += -include $(TOUCH_ROOT)/nt36xxx/nt36xxx_mp_ctrlram.h
nt36xxx-i2c-y := \
./nt36xxx/nt36xxx.o \
./nt36xxx/nt36xxx_fw_update.o \
./nt36xxx/nt36xxx_ext_proc.o \
./nt36xxx/nt36xxx_mp_ctrlram.o
obj-$(CONFIG_MSM_TOUCH) += nt36xxx-i2c.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_GOODIX_BRL), y)
LINUX_INC += -include $(TOUCH_ROOT)/goodix_berlin_driver/goodix_ts_core.h
LINUX_INC += -include $(TOUCH_ROOT)/qts/qts_core.h
LINUX_INC += -include $(TOUCH_ROOT)/qts/qts_core_common.h
goodix_ts-y := \
./goodix_berlin_driver/goodix_ts_core.o \
./goodix_berlin_driver/goodix_brl_hw.o \
./goodix_berlin_driver/goodix_cfg_bin.o \
./goodix_berlin_driver/goodix_ts_utils.o \
./goodix_berlin_driver/goodix_brl_fwupdate.o \
./goodix_berlin_driver/goodix_ts_tools.o \
./goodix_berlin_driver/goodix_ts_gesture.o \
./goodix_berlin_driver/goodix_ts_inspect.o \
./goodix_berlin_driver/goodix_brl_spi.o \
./goodix_berlin_driver/goodix_brl_i2c.o \
./qts/qts_core.o
obj-$(CONFIG_MSM_TOUCH) += goodix_ts.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_ATMEL_MXT), y)
atmel_mxt_ts-y := \
./atmel_mxt/atmel_mxt_ts.o
obj-$(CONFIG_MSM_TOUCH) += atmel_mxt_ts.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_DUMMY), y)
dummy_ts-y := ./dummy_touch/dummy_touch.o
obj-$(CONFIG_MSM_TOUCH) += dummy_ts.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_MSM_GLINK), y)
LINUXINCLUDE += -I$(TOUCH_ROOT)/glink_interface_ts
glink_comm-y := ./glink_interface_ts/glink_interface.o
obj-$(CONFIG_MSM_TOUCH) += glink_comm.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_SYNAPTICS_TCM), y)
synaptics_tcm_ts-y := \
./synaptics_tcm/synaptics_tcm_core.o \
./synaptics_tcm/synaptics_tcm_i2c.o \
./synaptics_tcm/synaptics_tcm_touch.o
obj-$(CONFIG_MSM_TOUCH) += synaptics_tcm_ts.o
endif
ifneq ($(CONFIG_ARCH_PINEAPPLE), y)
ifeq ($(CONFIG_TOUCHSCREEN_PARADE), y)
LINUX_INC += -include $(TOUCH_ROOT)/pt/pt_regs.h
LINUX_INC += -include $(TOUCH_ROOT)/pt/pt_core.h
LINUX_INC += -include $(TOUCH_ROOT)/pt/pt_platform.h
pt_ts-y := \
./pt/pt_core.o \
./pt/pt_mt_common.o \
./pt/pt_platform.o \
./pt/pt_devtree.o \
./pt/pt_btn.o \
./pt/pt_mtb.o \
./pt/pt_proximity.o
obj-$(CONFIG_MSM_TOUCH) += pt_ts.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_I2C), y)
LINUX_INC += -include $(TOUCH_ROOT)/pt/pt_regs.h
pt_i2c-y := \
./pt/pt_i2c.o
obj-$(CONFIG_MSM_TOUCH) += pt_i2c.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS), y)
LINUX_INC += -include $(TOUCH_ROOT)/pt/pt_regs.h
pt_device_access-y := \
./pt/pt_device_access.o
obj-$(CONFIG_MSM_TOUCH) += pt_device_access.o
endif
ifeq ($(CONFIG_TOUCHSCREEN_RM_TS), y)
LINUX_INC += -include $(TOUCH_ROOT)/raydium/Config.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/drv_interface.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/rad_fw_image_30.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/raydium_driver.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/raydium_selftest.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/tpselftest_30.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/chip_raydium/f303_ic_control.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/chip_raydium/f303_ic_reg.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/chip_raydium/f303_ic_test.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/chip_raydium/ic_drv_global.h
LINUX_INC += -include $(TOUCH_ROOT)/raydium/chip_raydium/ic_drv_interface.h
raydium_ts-y := \
./raydium/drv_interface.o \
./raydium/raydium_driver.o \
./raydium/raydium_fw_update.o \
./raydium/raydium_selftest.o \
./raydium/raydium_sysfs.o \
./raydium/chip_raydium/f303_ic_control.o \
./raydium/chip_raydium/f303_ic_test.o \
./raydium/chip_raydium/ic_drv_global.o \
./raydium/chip_raydium/ic_drv_interface.o
obj-$(CONFIG_MSM_TOUCH) += raydium_ts.o
endif
endif # pineapple
CDEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"

View File

@@ -0,0 +1,16 @@
KBUILD_OPTIONS+= TOUCH_ROOT=$(KERNEL_SRC)/$(M)
KBUILD_OPTIONS += MODNAME?=touch_dlkm
all:
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
%:
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
clean:
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
rm -rf .tmp_versions

View File

@@ -0,0 +1,24 @@
TOUCH_ROOT=$(ROOTDIR)vendor/qcom/opensource/touch-drivers
KBUILD_OPTIONS := TOUCH_ROOT=$(TOUCH_ROOT) CONFIG_MSM_TOUCH=m
ifeq ($(TARGET_SUPPORT),genericarmv8)
KBUILD_OPTIONS += CONFIG_ARCH_WAIPIO=y
endif
ifeq ($(TARGET_SUPPORT),genericarmv8)
KBUILD_OPTIONS += CONFIG_ARCH_PINEAPPLE=y
endif
all:
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
%:
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
clean:
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
rm -rf .tmp_versions

View File

@@ -0,0 +1,191 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
*/
/*
*
* Raydium TouchScreen driver.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
* Qualcomm Innovation Center, Inc. chooses to use it under GPLv2
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* BSD LICENSE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. or Linaro Ltd. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* Parade TouchScreen driver.
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* Synaptics DSX touchscreen driver
*
* Copyright (C) 2012-2016 Synaptics Incorporated. All rights reserved.
*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
* Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
* EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
* AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
* IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
* WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
* AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
* NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
* TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
* DOLLARS.
*/
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 - 2018 Novatek, Inc.
*
* $Revision: 47247 $
* $Date: 2019-07-10 10:41:36 +0800 (Wed, 10 Jul 2019) $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* FTS Capacitive touch screen controller (FingerTipS)
*
* Copyright (C) 2016-2019, STMicroelectronics Limited.
* Authors: AMG(Analog Mems Group) <marco.cali@st.com>
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Atmel maXTouch Touchscreen driver
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Copyright (C) 2011-2014 Atmel Corporation
* Copyright (C) 2012 Google, Inc.
* Copyright (C) 2016 Zodiac Inflight Innovations
*
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y
export CONFIG_TOUCH_FOCALTECH=y
export CONFIG_TOUCHSCREEN_FTS_DIRECTORY="focaltech_touch"

View File

@@ -0,0 +1,11 @@
/*
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH 1
#define CONFIG_TOUCH_FOCALTECH 1
#define CONFIG_TOUCHSCREEN_FTS_DIRECTORY "focaltech_touch"

View File

@@ -0,0 +1,10 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCH_FOCALTECH=y
export CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y
export CONFIG_TOUCHSCREEN_GOODIX_BRL=y
export CONFIG_TOUCHSCREEN_FTS_DIRECTORY="focaltech_touch"
export CONFIG_FTS_TRUSTED_TOUCH=n

View File

@@ -0,0 +1,13 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#define CONFIG_TOUCH_FOCALTECH 1
#define CONFIG_TOUCHSCREEN_NT36XXX_I2C 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH 1
#define CONFIG_TOUCHSCREEN_GOODIX_BRL 1
#define CONFIG_TOUCHSCREEN_FTS_DIRECTORY "focaltech_touch"

View File

@@ -0,0 +1,2 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCHSCREEN_GOODIX_BRL=y

View File

@@ -0,0 +1,6 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#define CONFIG_TOUCHSCREEN_GOODIX_BRL 1

View File

@@ -0,0 +1,5 @@
export CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
export CONFIG_TOUCHSCREEN_GOODIX_BRL=y
export CONFIG_TOUCHSCREEN_ATMEL_MXT=y
export CONFIG_TOUCHSCREEN_DUMMY=y
export CONFIG_MSM_TOUCH=m

View File

@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define CONFIG_TOUCHSCREEN_NT36XXX_I2C 1
#define CONFIG_TOUCHSCREEN_GOODIX_BRL 1
#define CONFIG_TOUCHSCREEN_ATMEL_MXT 1

View File

@@ -0,0 +1,6 @@
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y
export CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
export CONFIG_MSM_TOUCH=m

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH 1
#define CONFIG_TOUCHSCREEN_NT36XXX_I2C 1

View File

@@ -0,0 +1,4 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCH_FOCALTECH=y
export CONFIG_TOUCHSCREEN_FTS_DIRECTORY="focaltech_touch"
export CONFIG_FTS_TRUSTED_TOUCH=n

View File

@@ -0,0 +1,7 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#define CONFIG_TOUCH_FOCALTECH 1
#define CONFIG_TOUCHSCREEN_FTS_DIRECTORY "focaltech_touch"

View File

@@ -0,0 +1,7 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCHSCREEN_PARADE=y
export CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT=y
export CONFIG_TOUCHSCREEN_PARADE_I2C=y
export CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS=y
export CONFIG_TOUCHSCREEN_RM_TS=y
export CONFIG_TOUCHSCREEN_MSM_GLINK=y

View File

@@ -0,0 +1,8 @@
#define CONFIG_TOUCHSCREEN_PARADE 1
#define CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT 1
#define CONFIG_TOUCHSCREEN_PARADE_I2C 1
#define CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS 1
#define CONFIG_TOUCHSCREEN_PARADE_BUTTON 1
#define CONFIG_TOUCHSCREEN_PARADE_PROXIMITY 1
#define CONFIG_TOUCHSCREEN_RM_TS 1
#define CONFIG_TOUCHSCREEN_MSM_GLINK 1

View File

@@ -0,0 +1,5 @@
export CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
export CONFIG_TOUCHSCREEN_GOODIX_BRL=y
export CONFIG_TOUCHSCREEN_ATMEL_MXT=y
export CONFIG_TOUCHSCREEN_DUMMY=y
export CONFIG_MSM_TOUCH=m

View File

@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define CONFIG_TOUCHSCREEN_NT36XXX_I2C 1
#define CONFIG_TOUCHSCREEN_GOODIX_BRL 1
#define CONFIG_TOUCHSCREEN_ATMEL_MXT 1

View File

@@ -0,0 +1,5 @@
export CONFIG_MSM_TOUCH=m
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y

View File

@@ -0,0 +1,9 @@
/*
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
* SPDX-License-Identifier: GPL-2.0-only
*/
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH 1

View File

@@ -0,0 +1,6 @@
export CONFIG_TOUCH_FOCALTECH=y
export CONFIG_TOUCHSCREEN_FTS_DIRECTORY="focaltech_touch"
export CONFIG_FTS_TRUSTED_TOUCH=y
export CONFIG_TOUCHSCREEN_SYNAPTICS_DSX=y
export CONFIG_TOUCHSCREEN_NT36XXX_I2C=y
export CONFIG_TOUCH_BUILD=m

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#define CONFIG_TOUCH_FOCALTECH 1
#define CONFIG_TOUCHSCREEN_FTS_DIRECTORY "focaltech_touch"
#define CONFIG_FTS_TRUSTED_TOUCH 1
#define CONFIG_TOUCHSCREEN_SYNAPTICS_DSX 1
#define CONFIG_TOUCHSCREEN_NT36XXX_I2C 1

View File

@@ -0,0 +1,87 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
MODULE_DESCRIPTION("QTI dummy touchscreen driver");
MODULE_LICENSE("GPL v2");
#define DEVICE_COMPATIBLE "qti,dummy_ts"
#define DRIVER_NAME "qti_dummy_ts"
static int dummy_touch_probe(struct platform_device *device)
{
struct input_dev *touch_dev = NULL;
int rc;
touch_dev = input_allocate_device();
if (!touch_dev) {
pr_err("%s: input device allocate failed\n", __func__);
return -ENOMEM;
}
touch_dev->name = "qti_dummy_ts";
touch_dev->id.bustype = BUS_VIRTUAL;
touch_dev->evbit[0] = BIT_MASK(EV_KEY);
touch_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
touch_dev->dev.parent = NULL;
rc = input_register_device(touch_dev);
if (rc) {
pr_err("%s: touch device register failed, rc = %d\n", __func__, rc);
input_free_device(touch_dev);
return rc;
}
pr_info("qti_dummy_ts device registered\n");
platform_set_drvdata(device, (void *)touch_dev);
return 0;
}
static int dummy_touch_remove(struct platform_device *device)
{
struct input_dev *touch_dev = NULL;
touch_dev = (struct input_dev *)platform_get_drvdata(device);
if (touch_dev)
input_free_device(touch_dev);
return 0;
}
static const struct of_device_id dummy_touch_id[] = {
{.compatible = DEVICE_COMPATIBLE},
{}
};
static struct platform_driver dummy_touch_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = dummy_touch_id,
},
.probe = dummy_touch_probe,
.remove = dummy_touch_remove,
};
static int __init dummy_touch_init(void)
{
platform_driver_register(&dummy_touch_driver);
return 0;
}
static void __exit dummy_touch_exit(void)
{
platform_driver_unregister(&dummy_touch_driver);
}
late_initcall(dummy_touch_init);
module_exit(dummy_touch_exit);

View File

@@ -0,0 +1,167 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_common.h
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-16
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
#ifndef __LINUX_FOCALTECH_COMMON_H__
#define __LINUX_FOCALTECH_COMMON_H__
#include "focaltech_config.h"
/*****************************************************************************
* Macro definitions using #define
*****************************************************************************/
#define FTS_DRIVER_VERSION "Focaltech V3.2 20200422"
#define BYTE_OFF_0(x) (u8)((x) & 0xFF)
#define BYTE_OFF_8(x) (u8)(((x) >> 8) & 0xFF)
#define BYTE_OFF_16(x) (u8)(((x) >> 16) & 0xFF)
#define BYTE_OFF_24(x) (u8)(((x) >> 24) & 0xFF)
#define FLAGBIT(x) (0x00000001 << (x))
#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) & (0xFFFFFFFF << (x)))
#define FLAG_ICSERIALS_LEN 8
#define FLAG_HID_BIT 10
#define FLAG_IDC_BIT 11
#define IC_SERIALS(type) ((type) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define FTS_CHIP_IDC(type) (((type) & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
#define FTS_HID_SUPPORTTED(type) (((type) & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT))
#define FILE_NAME_LENGTH 128
#define ENABLE 1
#define DISABLE 0
#define VALID 1
#define INVALID 0
#define FTS_CMD_START1 0x55
#define FTS_CMD_START2 0xAA
#define FTS_CMD_START_DELAY 12
#define FTS_CMD_READ_ID 0x90
#define FTS_CMD_READ_ID_LEN 4
#define FTS_CMD_READ_ID_LEN_INCELL 1
#define FTS_CMD_READ_FW_CONF 0xA8
/*register address*/
#define FTS_REG_INT_CNT 0x8F
#define FTS_REG_FLOW_WORK_CNT 0x91
#define FTS_REG_WORKMODE 0x00
#define FTS_REG_WORKMODE_FACTORY_VALUE 0x40
#define FTS_REG_WORKMODE_WORK_VALUE 0x00
#define FTS_REG_ESDCHECK_DISABLE 0x8D
#define FTS_REG_CHIP_ID 0xA3
#define FTS_REG_CHIP_ID2 0x9F
#define FTS_REG_POWER_MODE 0xA5
#define FTS_REG_POWER_MODE_SLEEP 0x03
#define FTS_REG_FW_VER 0xA6
#define FTS_REG_VENDOR_ID 0xA8
#define FTS_REG_LCD_BUSY_NUM 0xAB
#define FTS_REG_FACE_DEC_MODE_EN 0xB0
#define FTS_REG_FACTORY_MODE_DETACH_FLAG 0xB4
#define FTS_REG_FACE_DEC_MODE_STATUS 0x01
#define FTS_REG_IDE_PARA_VER_ID 0xB5
#define FTS_REG_IDE_PARA_STATUS 0xB6
#define FTS_REG_GLOVE_MODE_EN 0xC0
#define FTS_REG_COVER_MODE_EN 0xC1
#define FTS_REG_REPORT_RATE 0x88
#define FTS_REG_CHARGER_MODE_EN 0x8B
#define FTS_REG_GESTURE_EN 0xD0
#define FTS_REG_GESTURE_OUTPUT_ADDRESS 0xD3
#define FTS_REG_MODULE_ID 0xE3
#define FTS_REG_LIC_VER 0xE4
#define FTS_REG_ESD_SATURATE 0xED
#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1')
#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0')
#define kfree_safe(pbuf) do {\
if (pbuf) {\
kfree(pbuf);\
pbuf = NULL;\
}\
} while(0)
/*****************************************************************************
* Alternative mode (When something goes wrong,
* the modules may be able to solve the problem.)
*****************************************************************************/
/*
* point report check
* default: disable
*/
#define FTS_POINT_REPORT_CHECK_EN 0
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
struct ft_chip_t {
u64 type;
u8 chip_idh;
u8 chip_idl;
u8 rom_idh;
u8 rom_idl;
u8 pb_idh;
u8 pb_idl;
u8 bl_idh;
u8 bl_idl;
};
struct ts_ic_info {
bool is_incell;
bool hid_supported;
struct ft_chip_t ids;
};
/*****************************************************************************
* DEBUG function define here
*****************************************************************************/
#if FTS_DEBUG_EN
#define FTS_DEBUG(fmt, args...) do { \
printk("[FTS_TS]%s:"fmt"\n", __func__, ##args); \
} while (0)
#define FTS_FUNC_ENTER() do { \
printk("[FTS_TS]%s: Enter\n", __func__); \
} while (0)
#define FTS_FUNC_EXIT() do { \
printk("[FTS_TS]%s: Exit(%d)\n", __func__, __LINE__); \
} while (0)
#else /* #if FTS_DEBUG_EN*/
#define FTS_DEBUG(fmt, args...)
#define FTS_FUNC_ENTER()
#define FTS_FUNC_EXIT()
#endif
#define FTS_INFO(fmt, args...) do { \
printk(KERN_INFO "[FTS_TS/I]%s:"fmt"\n", __func__, ##args); \
} while (0)
#define FTS_ERROR(fmt, args...) do { \
printk(KERN_ERR "[FTS_TS/E]%s:"fmt"\n", __func__, ##args); \
} while (0)
#endif /* __LINUX_FOCALTECH_COMMON_H__ */

View File

@@ -0,0 +1,278 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, FocalTech Systems, Ltd., all rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/************************************************************************
*
* File Name: focaltech_config.h
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract: global configurations
*
* Version: v1.0
*
************************************************************************/
#ifndef _LINUX_FOCLATECH_CONFIG_H_
#define _LINUX_FOCLATECH_CONFIG_H_
/**************************************************/
/****** G: A, I: B, S: C, U: D ******************/
/****** chip type defines, do not modify *********/
#define _FT8716 0x87160805
#define _FT8736 0x87360806
#define _FT8006M 0x80060807
#define _FT8607 0x86070809
#define _FT8006U 0x8006D80B
#define _FT8006S 0x8006A80B
#define _FT8613 0x8613080C
#define _FT8719 0x8719080D
#define _FT8739 0x8739080E
#define _FT8615 0x8615080F
#define _FT8201 0x82010810
#define _FT8006P 0x86220811
#define _FT7251 0x72510812
#define _FT7252 0x72520813
#define _FT8613S 0x8613C814
#define _FT8756 0x87560815
#define _FT8302 0x83020816
#define _FT8009 0x80090817
#define _FT8656 0x86560818
#define _FT8006S_AA 0x86320819
#define _FT7250 0x7250081A
#define _FT7120 0x7120081B
#define _FT8720 0x8720081C
#define _FT8726 0x8726081C
#define _FT8016 0x8016081D
#define _FT5416 0x54160402
#define _FT5426 0x54260402
#define _FT5435 0x54350402
#define _FT5436 0x54360402
#define _FT5526 0x55260402
#define _FT5526I 0x5526B402
#define _FT5446 0x54460402
#define _FT5346 0x53460402
#define _FT5446I 0x5446B402
#define _FT5346I 0x5346B402
#define _FT7661 0x76610402
#define _FT7511 0x75110402
#define _FT7421 0x74210402
#define _FT7681 0x76810402
#define _FT3C47U 0x3C47D402
#define _FT3417 0x34170402
#define _FT3517 0x35170402
#define _FT3327 0x33270402
#define _FT3427 0x34270402
#define _FT7311 0x73110402
#define _FT5526_V00 0x5526C402
#define _FT5626 0x56260401
#define _FT5726 0x57260401
#define _FT5826B 0x5826B401
#define _FT5826S 0x5826C401
#define _FT7811 0x78110401
#define _FT3D47 0x3D470401
#define _FT3617 0x36170401
#define _FT3717 0x37170401
#define _FT3817B 0x3817B401
#define _FT3517U 0x3517D401
#define _FT6236U 0x6236D003
#define _FT6336G 0x6336A003
#define _FT6336U 0x6336D003
#define _FT6436U 0x6436D003
#define _FT6436T 0x6436E003
#define _FT3267 0x32670004
#define _FT3367 0x33670004
#define _FT3327DQQ_XXX 0x3327D482
#define _FT5446DQS_XXX 0x5446D482
#define _FT3427_003 0x3427D482
#define _FT3427G_003 0x3427A482
#define _FT5446_003 0x5446D482
#define _FT5446_Q03 0x5446C482
#define _FT5446_P03 0x5446A481
#define _FT5426_003 0x5426D482
#define _FT5526_003 0x5526D482
#define _FT3518 0x35180481
#define _FT3518U 0x3518D481
#define _FT3558 0x35580481
#define _FT3528 0x35280481
#define _FT5536 0x55360481
#define _FT5536L 0x5536E481
#define _FT3418 0x34180481
#define _FT5446U 0x5446D083
#define _FT5456U 0x5456D083
#define _FT3417U 0x3417D083
#define _FT5426U 0x5426D083
#define _FT3428 0x34280083
#define _FT3437U 0x3437D083
#define _FT7302 0x73020084
#define _FT7202 0x72020084
#define _FT3308 0x33080084
#define _FT6446 0x64460084
#define _FT6346U 0x6346D085
#define _FT6346G 0x6346A085
#define _FT3067 0x30670085
#define _FT3068 0x30680085
#define _FT3168 0x31680085
#define _FT3268 0x32680085
#define _FT6146 0x61460085
#define _FT5726_003 0x5726D486
#define _FT5726_V03 0x5726C486
#define _FT3618 0x36180487
#define _FT5646 0x56460487
#define _FT3A58 0x3A580487
#define _FT3B58 0x3B580487
#define _FT3D58 0x3D580487
#define _FT5936 0x59360487
#define _FT5A36 0x5A360487
#define _FT5B36 0x5B360487
#define _FT5D36 0x5D360487
#define _FT5946 0x59460487
#define _FT5A46 0x5A460487
#define _FT5B46 0x5B460487
#define _FT5D46 0x5D460487
#define _FT3658U 0x3658D488
/******************* Enables *********************/
/*********** 1 to enable, 0 to disable ***********/
/*
* show debug log info
* enable it for debug, disable it for release
*/
#define FTS_DEBUG_EN 0
/*
* Linux MultiTouch Protocol
* 1: Protocol B(default), 0: Protocol A
*/
#define FTS_MT_PROTOCOL_B_EN 1
/*
* Report Pressure in multitouch
* 1:enable(default),0:disable
*/
#define FTS_REPORT_PRESSURE_EN 1
/*
* Gesture function enable
* default: disable
*/
#define FTS_GESTURE_EN 0
/*
* ESD check & protection
* default: disable
*/
#define FTS_ESDCHECK_EN 0
/*
* Production test enable
* 1: enable, 0:disable(default)
*/
#define FTS_TEST_EN 0
/*
* Pinctrl enable
* default: disable
*/
#define FTS_PINCTRL_EN 1
/*
* Customer power enable
* enable it when customer need control TP power
* default: disable
*/
#define FTS_POWER_SOURCE_CUST_EN 1
/****************************************************/
/********************** Upgrade ****************************/
/*
* auto upgrade
*/
#define FTS_AUTO_UPGRADE_EN 1
/*
* auto upgrade for lcd cfg
*/
#define FTS_AUTO_LIC_UPGRADE_EN 0
/*
* Numbers of modules support
*/
#define FTS_GET_MODULE_NUM 2
/*
* module_id: mean vendor_id generally, also maybe gpio or lcm_id...
* If means vendor_id, the FTS_MODULE_ID = PANEL_ID << 8 + VENDOR_ID
* FTS_GET_MODULE_NUM == 0/1, no check module id, you may ignore them
* FTS_GET_MODULE_NUM >= 2, compatible with FTS_MODULE2_ID
* FTS_GET_MODULE_NUM >= 3, compatible with FTS_MODULE3_ID
*/
#define FTS_MODULE_ID 0x0000
#define FTS_MODULE2_ID 0xd566
#define FTS_MODULE3_ID 0x0000
/*
* Need set the following when get firmware via firmware_request()
* For example: if module'vendor is tianma,
* #define FTS_MODULE_NAME "tianma"
* then file_name will be "focaltech_ts_fw_tianma"
* You should rename fw to "focaltech_ts_fw_tianma", and push it into
* etc/firmware or by customers
*/
#define FTS_MODULE_NAME "gvo"
#define FTS_MODULE2_NAME "jdi"
#define FTS_MODULE3_NAME ""
/*
* FW.i file for auto upgrade, you must replace it with your own
* define your own fw_file, the sample one to be replaced is invalid
* NOTE: if FTS_GET_MODULE_NUM > 1, it's the fw corresponding with FTS_VENDOR_ID
*/
#define FTS_UPGRADE_FW_FILE "include/firmware/fw_sample.i"
/*
* if FTS_GET_MODULE_NUM >= 2, fw corrsponding with FTS_VENDOR_ID2
* define your own fw_file, the sample one is invalid
*/
#define FTS_UPGRADE_FW2_FILE "include/firmware/fw_sample.i"
/*
* if FTS_GET_MODULE_NUM >= 3, fw corrsponding with FTS_VENDOR_ID3
* define your own fw_file, the sample one is invalid
*/
#define FTS_UPGRADE_FW3_FILE "include/firmware/fw_sample.i"
/*********************************************************/
#endif /* _LINUX_FOCLATECH_CONFIG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,391 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_core.h
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
#ifndef __LINUX_FOCALTECH_CORE_H__
#define __LINUX_FOCALTECH_CORE_H__
/*****************************************************************************
* Included header files
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <asm/uaccess.h>
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/dma-mapping.h>
#if defined(CONFIG_FTS_TRUSTED_TOUCH)
#include <linux/gunyah/gh_irq_lend.h>
#include <linux/gunyah/gh_mem_notifier.h>
#endif
#include "focaltech_common.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */
#define FTS_MAX_KEYS 4
#define FTS_KEY_DIM 10
#define FTS_ONE_TCH_LEN 6
#define FTS_TOUCH_DATA_LEN (FTS_MAX_POINTS_SUPPORT * FTS_ONE_TCH_LEN + 3)
#define FTS_GESTURE_POINTS_MAX 6
#define FTS_GESTURE_DATA_LEN (FTS_GESTURE_POINTS_MAX * 4 + 4)
#define FTS_MAX_ID 0x0A
#define FTS_TOUCH_X_H_POS 3
#define FTS_TOUCH_X_L_POS 4
#define FTS_TOUCH_Y_H_POS 5
#define FTS_TOUCH_Y_L_POS 6
#define FTS_TOUCH_PRE_POS 7
#define FTS_TOUCH_AREA_POS 8
#define FTS_TOUCH_POINT_NUM 2
#define FTS_TOUCH_EVENT_POS 3
#define FTS_TOUCH_ID_POS 5
#define FTS_COORDS_ARR_SIZE 4
#define FTS_X_MIN_DISPLAY_DEFAULT 0
#define FTS_Y_MIN_DISPLAY_DEFAULT 0
#define FTS_X_MAX_DISPLAY_DEFAULT 720
#define FTS_Y_MAX_DISPLAY_DEFAULT 1280
#define FTS_TOUCH_DOWN 0
#define FTS_TOUCH_UP 1
#define FTS_TOUCH_CONTACT 2
#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag))
#define EVENT_UP(flag) (FTS_TOUCH_UP == flag)
#define EVENT_NO_DOWN(data) (!data->point_num)
#define FTX_MAX_COMPATIBLE_TYPE 4
#define FTX_MAX_COMMMAND_LENGTH 16
/*****************************************************************************
* Alternative mode (When something goes wrong, the modules may be able to solve the problem.)
*****************************************************************************/
/*
* For commnication error in PM(deep sleep) state
*/
#define FTS_PATCH_COMERR_PM 0
#define FTS_TIMEOUT_COMERR_PM 700
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct ftxxxx_proc {
struct proc_dir_entry *proc_entry;
u8 opmode;
u8 cmd_len;
u8 cmd[FTX_MAX_COMMMAND_LENGTH];
};
struct fts_ts_platform_data {
u32 type;
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
u32 reset_gpio_flags;
bool have_key;
u32 key_number;
u32 keys[FTS_MAX_KEYS];
u32 key_y_coords[FTS_MAX_KEYS];
u32 key_x_coords[FTS_MAX_KEYS];
u32 x_max;
u32 y_max;
u32 x_min;
u32 y_min;
u32 max_touch_number;
};
struct ts_event {
int x; /*x coordinate */
int y; /*y coordinate */
int p; /* pressure */
int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
int id; /*touch ID */
int area;
};
enum trusted_touch_mode_config {
TRUSTED_TOUCH_VM_MODE,
TRUSTED_TOUCH_MODE_NONE
};
enum trusted_touch_pvm_states {
TRUSTED_TOUCH_PVM_INIT,
PVM_I2C_RESOURCE_ACQUIRED,
PVM_INTERRUPT_DISABLED,
PVM_IOMEM_LENT,
PVM_IOMEM_LENT_NOTIFIED,
PVM_IRQ_LENT,
PVM_IRQ_LENT_NOTIFIED,
PVM_IOMEM_RELEASE_NOTIFIED,
PVM_IRQ_RELEASE_NOTIFIED,
PVM_ALL_RESOURCES_RELEASE_NOTIFIED,
PVM_IRQ_RECLAIMED,
PVM_IOMEM_RECLAIMED,
PVM_INTERRUPT_ENABLED,
PVM_I2C_RESOURCE_RELEASED,
TRUSTED_TOUCH_PVM_STATE_MAX
};
enum trusted_touch_tvm_states {
TRUSTED_TOUCH_TVM_INIT,
TVM_IOMEM_LENT_NOTIFIED,
TVM_IRQ_LENT_NOTIFIED,
TVM_ALL_RESOURCES_LENT_NOTIFIED,
TVM_IOMEM_ACCEPTED,
TVM_I2C_SESSION_ACQUIRED,
TVM_IRQ_ACCEPTED,
TVM_INTERRUPT_ENABLED,
TVM_INTERRUPT_DISABLED,
TVM_IRQ_RELEASED,
TVM_I2C_SESSION_RELEASED,
TVM_IOMEM_RELEASED,
TRUSTED_TOUCH_TVM_STATE_MAX
};
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#define TRUSTED_TOUCH_MEM_LABEL 0x7
#define TOUCH_RESET_GPIO_BASE 0xF114000
#define TOUCH_RESET_GPIO_SIZE 0x1000
#define TOUCH_RESET_GPIO_OFFSET 0x4
#define TOUCH_INTR_GPIO_BASE 0xF115000
#define TOUCH_INTR_GPIO_SIZE 0x1000
#define TOUCH_INTR_GPIO_OFFSET 0x8
#define TRUSTED_TOUCH_EVENT_LEND_FAILURE -1
#define TRUSTED_TOUCH_EVENT_LEND_NOTIFICATION_FAILURE -2
#define TRUSTED_TOUCH_EVENT_ACCEPT_FAILURE -3
#define TRUSTED_TOUCH_EVENT_FUNCTIONAL_FAILURE -4
#define TRUSTED_TOUCH_EVENT_RELEASE_FAILURE -5
#define TRUSTED_TOUCH_EVENT_RECLAIM_FAILURE -6
#define TRUSTED_TOUCH_EVENT_I2C_FAILURE -7
#define TRUSTED_TOUCH_EVENT_NOTIFICATIONS_PENDING 5
struct trusted_touch_vm_info {
enum gh_irq_label irq_label;
enum gh_mem_notifier_tag mem_tag;
enum gh_vm_names vm_name;
const char *trusted_touch_type;
u32 hw_irq;
gh_memparcel_handle_t vm_mem_handle;
u32 *iomem_bases;
u32 *iomem_sizes;
u32 iomem_list_size;
void *mem_cookie;
atomic_t vm_state;
};
#endif
struct fts_ts_data {
struct i2c_client *client;
struct spi_device *spi;
struct device *dev;
struct input_dev *input_dev;
struct fts_ts_platform_data *pdata;
struct ts_ic_info ic_info;
struct workqueue_struct *ts_workqueue;
struct work_struct fwupg_work;
struct delayed_work esdcheck_work;
struct delayed_work prc_work;
struct work_struct resume_work;
struct work_struct suspend_work;
struct ftxxxx_proc proc;
spinlock_t irq_lock;
struct mutex report_mutex;
struct mutex bus_lock;
struct mutex transition_lock;
int irq;
int log_level;
int fw_is_running; /* confirm fw is running when using spi:default 0 */
int dummy_byte;
#if defined(CONFIG_PM) && FTS_PATCH_COMERR_PM
struct completion pm_completion;
bool pm_suspend;
#endif
bool suspended;
bool fw_loading;
bool irq_disabled;
bool power_disabled;
bool glove_mode;
bool cover_mode;
bool charger_mode;
bool gesture_mode; /* gesture enable or disable, default: disable */
int report_rate;
/* multi-touch */
struct ts_event *events;
u8 *bus_tx_buf;
u8 *bus_rx_buf;
int bus_type;
u8 *point_buf;
void *notifier_cookie;
int pnt_buf_size;
int touchs;
int key_state;
int touch_point;
int point_num;
struct regulator *vdd;
struct regulator *vcc_i2c;
#if FTS_PINCTRL_EN
struct pinctrl *pinctrl;
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_suspend;
struct pinctrl_state *pins_release;
#endif
#if defined(CONFIG_FB) || defined(CONFIG_DRM)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
#ifdef CONFIG_FTS_TRUSTED_TOUCH
struct trusted_touch_vm_info *vm_info;
struct mutex fts_clk_io_ctrl_mutex;
const char *touch_environment;
struct completion trusted_touch_powerdown;
struct clk *core_clk;
struct clk *iface_clk;
atomic_t trusted_touch_initialized;
atomic_t trusted_touch_enabled;
atomic_t trusted_touch_transition;
atomic_t trusted_touch_event;
atomic_t trusted_touch_abort_status;
atomic_t trusted_touch_mode;
#endif
atomic_t delayed_vm_probe_pending;
};
enum _FTS_BUS_TYPE {
BUS_TYPE_NONE,
BUS_TYPE_I2C,
BUS_TYPE_SPI,
BUS_TYPE_SPI_V2,
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_ts_data *fts_data;
/* communication interface */
int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen);
int fts_read_reg(u8 addr, u8 *value);
int fts_write(u8 *writebuf, u32 writelen);
int fts_write_reg(u8 addr, u8 value);
void fts_hid2std(void);
int fts_bus_init(struct fts_ts_data *ts_data);
int fts_bus_exit(struct fts_ts_data *ts_data);
/* Gesture functions */
int fts_gesture_init(struct fts_ts_data *ts_data);
int fts_gesture_exit(struct fts_ts_data *ts_data);
void fts_gesture_recovery(struct fts_ts_data *ts_data);
int fts_gesture_readdata(struct fts_ts_data *ts_data, u8 *data);
int fts_gesture_suspend(struct fts_ts_data *ts_data);
int fts_gesture_resume(struct fts_ts_data *ts_data);
/* Apk and functions */
int fts_create_apk_debug_channel(struct fts_ts_data *);
void fts_release_apk_debug_channel(struct fts_ts_data *);
/* ADB functions */
int fts_create_sysfs(struct fts_ts_data *ts_data);
int fts_remove_sysfs(struct fts_ts_data *ts_data);
/* ESD */
#if FTS_ESDCHECK_EN
int fts_esdcheck_init(struct fts_ts_data *ts_data);
int fts_esdcheck_exit(struct fts_ts_data *ts_data);
int fts_esdcheck_switch(bool enable);
int fts_esdcheck_proc_busy(bool proc_debug);
int fts_esdcheck_set_intr(bool intr);
int fts_esdcheck_suspend(void);
int fts_esdcheck_resume(void);
#endif
/* Production test */
#if FTS_TEST_EN
int fts_test_init(struct fts_ts_data *ts_data);
int fts_test_exit(struct fts_ts_data *ts_data);
#endif
/* Point Report Check*/
#if FTS_POINT_REPORT_CHECK_EN
int fts_point_report_check_init(struct fts_ts_data *ts_data);
int fts_point_report_check_exit(struct fts_ts_data *ts_data);
void fts_prc_queue_work(struct fts_ts_data *ts_data);
#endif
/* FW upgrade */
int fts_fwupg_init(struct fts_ts_data *ts_data);
int fts_fwupg_exit(struct fts_ts_data *ts_data);
int fts_enter_test_environment(bool test_state);
/* Other */
int fts_reset_proc(int hdelayms);
int fts_wait_tp_to_valid(void);
void fts_release_all_finger(void);
void fts_tp_state_recovery(struct fts_ts_data *ts_data);
int fts_ex_mode_init(struct fts_ts_data *ts_data);
int fts_ex_mode_exit(struct fts_ts_data *ts_data);
int fts_ex_mode_recovery(struct fts_ts_data *ts_data);
void fts_irq_disable(void);
void fts_irq_enable(void);
int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *ts_data, int value);
int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *ts_data, int value);
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#ifdef CONFIG_ARCH_QTI_VM
void fts_ts_trusted_touch_tvm_i2c_failure_report(struct fts_ts_data *fts_data);
#endif
#endif
#endif /* __LINUX_FOCALTECH_CORE_H__ */

View File

@@ -0,0 +1,465 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, FocalTech Systems, Ltd., all rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_esdcheck.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-03
*
* Abstract: ESD check function
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By luougojin 2016-08-03
* v1.1: By luougojin 2017-02-15
* 1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_ESDCHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define ESDCHECK_WAIT_TIME 1000 /* ms */
#define LCD_ESD_PATCH 0
#define ESDCHECK_INTRCNT_MAX 2
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_esdcheck_st {
u8 mode : 1; /* 1- need check esd 0- no esd check */
u8 suspend : 1;
u8 proc_debug : 1; /* apk or adb use */
u8 intr : 1; /* 1- Interrupt trigger */
u8 unused : 4;
u8 intr_cnt;
u8 flow_work_hold_cnt; /* Flow Work Cnt(reg0x91) keep a same value for x times. >=5 times is ESD, need reset */
u8 flow_work_cnt_last; /* Save Flow Work Cnt(reg0x91) value */
u32 hardware_reset_cnt;
u32 nack_cnt;
u32 dataerror_cnt;
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_esdcheck_st fts_esdcheck_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
#if LCD_ESD_PATCH
int lcd_need_reset;
static int tp_need_recovery; /* LCD reset cause Tp reset */
int idc_esdcheck_lcderror(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 val = 0;
FTS_DEBUG("check LCD ESD");
if ( (tp_need_recovery == 1) && (lcd_need_reset == 0) ) {
tp_need_recovery = 0;
/* LCD reset, need recover TP state */
fts_release_all_finger();
fts_tp_state_recovery(ts_data);
}
ret = fts_read_reg(FTS_REG_ESD_SATURATE, &val);
if ( ret < 0) {
FTS_ERROR("read reg0xED fail,ret:%d", ret);
return -EIO;
}
if (val == 0xAA) {
/*
* 1. Set flag lcd_need_reset = 1;
* 2. LCD driver need reset(recovery) LCD and set lcd_need_reset to 0
* 3. recover TP state
*/
FTS_INFO("LCD ESD, need execute LCD reset");
lcd_need_reset = 1;
tp_need_recovery = 1;
}
return 0;
}
#endif
static int fts_esdcheck_tp_reset(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
fts_esdcheck_data.flow_work_hold_cnt = 0;
fts_esdcheck_data.hardware_reset_cnt++;
fts_reset_proc(200);
fts_release_all_finger();
fts_tp_state_recovery(ts_data);
FTS_FUNC_EXIT();
return 0;
}
static bool get_chip_id(struct fts_ts_data *ts_data)
{
int ret = 0;
int i = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
u8 chip_id = ts_data->ic_info.ids.chip_idh;
for (i = 0; i < 3; i++) {
reg_addr = FTS_REG_CHIP_ID;
ret = fts_read(&reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("read chip id fail,ret:%d", ret);
fts_esdcheck_data.nack_cnt++;
} else {
if (reg_value == chip_id) {
break;
} else {
FTS_DEBUG("read chip_id:%x,retry:%d", reg_value, i);
fts_esdcheck_data.dataerror_cnt++;
}
}
msleep(10);
}
/* if can't get correct data in 3 times, then need hardware reset */
if (i >= 3) {
FTS_ERROR("read chip id 3 times fail, need execute TP reset");
return true;
}
return false;
}
/*****************************************************************************
* Name: get_flow_cnt
* Brief: Read flow cnt(0x91)
* Input:
* Output:
* Return: 1(true) - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
* 0(false) - Reg 0x91(flow cnt) normal
*****************************************************************************/
static bool get_flow_cnt(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
reg_addr = FTS_REG_FLOW_WORK_CNT;
ret = fts_read(&reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("read reg0x91 fail,ret:%d", ret);
fts_esdcheck_data.nack_cnt++;
} else {
if ( reg_value == fts_esdcheck_data.flow_work_cnt_last ) {
FTS_DEBUG("reg0x91,val:%x,last:%x", reg_value,
fts_esdcheck_data.flow_work_cnt_last);
fts_esdcheck_data.flow_work_hold_cnt++;
} else {
fts_esdcheck_data.flow_work_hold_cnt = 0;
}
fts_esdcheck_data.flow_work_cnt_last = reg_value;
}
/* Flow Work Cnt keep a value for 5 times, need execute TP reset */
if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
FTS_DEBUG("reg0x91 keep a value for 5 times, need execute TP reset");
return true;
}
return false;
}
static int esdcheck_algorithm(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
bool hardware_reset = 0;
/* 1. esdcheck is interrupt, then return */
if (fts_esdcheck_data.intr == 1) {
fts_esdcheck_data.intr_cnt++;
if (fts_esdcheck_data.intr_cnt > ESDCHECK_INTRCNT_MAX)
fts_esdcheck_data.intr = 0;
else
return 0;
}
/* 2. check power state, if suspend, no need check esd */
if (fts_esdcheck_data.suspend == 1) {
FTS_DEBUG("In suspend, not check esd");
/* because in suspend state, adb can be used, when upgrade FW, will
* active ESD check(active = 1); But in suspend, then will don't
* queue_delayed_work, when resume, don't check ESD again
*/
return 0;
}
/* 3. check fts_esdcheck_data.proc_debug state, if 1-proc busy, no need check esd*/
if (fts_esdcheck_data.proc_debug == 1) {
FTS_INFO("In apk/adb command mode, not check esd");
return 0;
}
/* 4. In factory mode, can't check esd */
reg_addr = FTS_REG_WORKMODE;
ret = fts_read_reg(reg_addr, &reg_value);
if ( ret < 0 ) {
fts_esdcheck_data.nack_cnt++;
} else if ( (reg_value & 0x70) != FTS_REG_WORKMODE_WORK_VALUE) {
FTS_DEBUG("not in work mode(%x), no check esd", reg_value);
return 0;
}
/* 5. IDC esd check lcd default:close */
#if LCD_ESD_PATCH
idc_esdcheck_lcderror(ts_data);
#endif
/* 6. Get Chip ID */
hardware_reset = get_chip_id(ts_data);
/* 7. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */
if (!hardware_reset) {
hardware_reset = get_flow_cnt(ts_data);
}
/* 8. If need hardware reset, then handle it here */
if (hardware_reset == 1) {
FTS_DEBUG("NoACK=%d, Error Data=%d, Hardware Reset=%d",
fts_esdcheck_data.nack_cnt,
fts_esdcheck_data.dataerror_cnt,
fts_esdcheck_data.hardware_reset_cnt);
fts_esdcheck_tp_reset(ts_data);
}
return 0;
}
static void esdcheck_func(struct work_struct *work)
{
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, esdcheck_work.work);
if (ENABLE == fts_esdcheck_data.mode) {
esdcheck_algorithm(ts_data);
queue_delayed_work(ts_data->ts_workqueue,
&ts_data->esdcheck_work,
msecs_to_jiffies(ESDCHECK_WAIT_TIME));
}
}
int fts_esdcheck_set_intr(bool intr)
{
/* interrupt don't add debug message */
fts_esdcheck_data.intr = intr;
fts_esdcheck_data.intr_cnt = (u8)intr;
return 0;
}
static int fts_esdcheck_get_status(void)
{
/* interrupt don't add debug message */
return fts_esdcheck_data.mode;
}
/*****************************************************************************
* Name: fts_esdcheck_proc_busy
* Brief: When APK or ADB command access TP via driver, then need set proc_debug,
* then will not check ESD.
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_proc_busy(bool proc_debug)
{
fts_esdcheck_data.proc_debug = proc_debug;
return 0;
}
/*****************************************************************************
* Name: fts_esdcheck_switch
* Brief: FTS esd check function switch.
* Input: enable: 1 - Enable esd check
* 0 - Disable esd check
* Output:
* Return:
*****************************************************************************/
int fts_esdcheck_switch(bool enable)
{
struct fts_ts_data *ts_data = fts_data;
FTS_FUNC_ENTER();
if (fts_esdcheck_data.mode == ENABLE) {
if (enable) {
FTS_DEBUG("ESD check start");
fts_esdcheck_data.flow_work_hold_cnt = 0;
fts_esdcheck_data.flow_work_cnt_last = 0;
fts_esdcheck_data.intr = 0;
fts_esdcheck_data.intr_cnt = 0;
queue_delayed_work(ts_data->ts_workqueue,
&ts_data->esdcheck_work,
msecs_to_jiffies(ESDCHECK_WAIT_TIME));
} else {
FTS_DEBUG("ESD check stop");
cancel_delayed_work_sync(&ts_data->esdcheck_work);
}
}
FTS_FUNC_EXIT();
return 0;
}
int fts_esdcheck_suspend(void)
{
FTS_FUNC_ENTER();
fts_esdcheck_switch(DISABLE);
fts_esdcheck_data.suspend = 1;
fts_esdcheck_data.intr = 0;
fts_esdcheck_data.intr_cnt = 0;
FTS_FUNC_EXIT();
return 0;
}
int fts_esdcheck_resume( void )
{
FTS_FUNC_ENTER();
fts_esdcheck_switch(ENABLE);
fts_esdcheck_data.suspend = 0;
fts_esdcheck_data.intr = 0;
fts_esdcheck_data.intr_cnt = 0;
FTS_FUNC_EXIT();
return 0;
}
static ssize_t fts_esdcheck_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_DEBUG("enable esdcheck");
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_switch(ENABLE);
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_DEBUG("disable esdcheck");
fts_esdcheck_switch(DISABLE);
fts_esdcheck_data.mode = DISABLE;
}
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_esdcheck_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n", \
fts_esdcheck_get_status() ? "On" : "Off");
mutex_unlock(&input_dev->mutex);
return count;
}
/* sysfs esd node
* read example: cat fts_esd_mode ---read esd mode
* write example:echo 01 > fts_esd_mode ---make esdcheck enable
*
*/
static DEVICE_ATTR (fts_esd_mode, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
static struct attribute *fts_esd_mode_attrs[] = {
&dev_attr_fts_esd_mode.attr,
NULL,
};
static struct attribute_group fts_esd_group = {
.attrs = fts_esd_mode_attrs,
};
int fts_create_esd_sysfs(struct device *dev)
{
int ret = 0;
ret = sysfs_create_group(&dev->kobj, &fts_esd_group);
if ( ret != 0) {
FTS_ERROR("fts_create_esd_sysfs(sysfs) create fail");
sysfs_remove_group(&dev->kobj, &fts_esd_group);
return ret;
}
return 0;
}
int fts_esdcheck_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->esdcheck_work, esdcheck_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run esd check func!");
return -EINVAL;
}
memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_data.intr = 0;
fts_esdcheck_data.intr_cnt = 0;
fts_esdcheck_switch(ENABLE);
fts_create_esd_sysfs(ts_data->dev);
FTS_FUNC_EXIT();
return 0;
}
int fts_esdcheck_exit(struct fts_ts_data *ts_data)
{
sysfs_remove_group(&ts_data->dev->kobj, &fts_esd_group);
return 0;
}
#endif /* FTS_ESDCHECK_EN */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,359 @@
/*
*
* FocalTech ftxxxx TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_ex_mode.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-31
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* 2.Private constant and macro definitions using #define
*****************************************************************************/
/*****************************************************************************
* 3.Private enumerations, structures and unions using typedef
*****************************************************************************/
enum _ex_mode {
MODE_GLOVE = 0,
MODE_COVER,
MODE_CHARGER,
REPORT_RATE,
};
/*****************************************************************************
* 4.Static variables
*****************************************************************************/
/*****************************************************************************
* 5.Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* 6.Static function prototypes
*******************************************************************************/
static int fts_ex_mode_switch(enum _ex_mode mode, u8 value)
{
int ret = 0;
switch (mode) {
case MODE_GLOVE:
ret = fts_write_reg(FTS_REG_GLOVE_MODE_EN, value > 0 ? 1 : 0);
if (ret < 0)
FTS_ERROR("MODE_GLOVE switch to %d fail", value);
break;
case MODE_COVER:
ret = fts_write_reg(FTS_REG_COVER_MODE_EN, value > 0 ? 1 : 0);
if (ret < 0)
FTS_ERROR("MODE_COVER switch to %d fail", value);
break;
case MODE_CHARGER:
ret = fts_write_reg(FTS_REG_CHARGER_MODE_EN, value > 0 ? 1 : 0);
if (ret < 0)
FTS_ERROR("MODE_CHARGER switch to %d fail", value);
break;
case REPORT_RATE:
ret = fts_write_reg(FTS_REG_REPORT_RATE, value);
if (ret < 0)
FTS_ERROR("REPORT_RATE switch to %d fail", value);
break;
default:
FTS_ERROR("mode(%d) unsupport", mode);
ret = -EINVAL;
break;
}
return ret;
}
static ssize_t fts_glove_mode_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct fts_ts_data *ts_data = fts_data;
struct input_dev *input_dev = ts_data->input_dev;
mutex_lock(&input_dev->mutex);
fts_read_reg(FTS_REG_GLOVE_MODE_EN, &val);
count = scnprintf(buf + count, PAGE_SIZE, "Glove Mode:%s\n",
ts_data->glove_mode ? "On" : "Off");
count += scnprintf(buf + count, PAGE_SIZE - count,
"Glove Reg(0xC0):%d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_glove_mode_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
struct fts_ts_data *ts_data = fts_data;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!ts_data->glove_mode) {
FTS_DEBUG("enter glove mode");
ret = fts_ex_mode_switch(MODE_GLOVE, ENABLE);
if (ret >= 0) {
ts_data->glove_mode = ENABLE;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (ts_data->glove_mode) {
FTS_DEBUG("exit glove mode");
ret = fts_ex_mode_switch(MODE_GLOVE, DISABLE);
if (ret >= 0) {
ts_data->glove_mode = DISABLE;
}
}
}
FTS_DEBUG("glove mode:%d", ts_data->glove_mode);
return count;
}
static ssize_t fts_cover_mode_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct fts_ts_data *ts_data = fts_data;
struct input_dev *input_dev = ts_data->input_dev;
mutex_lock(&input_dev->mutex);
fts_read_reg(FTS_REG_COVER_MODE_EN, &val);
count = scnprintf(buf + count, PAGE_SIZE, "Cover Mode:%s\n",
ts_data->cover_mode ? "On" : "Off");
count += scnprintf(buf + count, PAGE_SIZE - count,
"Cover Reg(0xC1):%d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_cover_mode_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
struct fts_ts_data *ts_data = fts_data;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!ts_data->cover_mode) {
FTS_DEBUG("enter cover mode");
ret = fts_ex_mode_switch(MODE_COVER, ENABLE);
if (ret >= 0) {
ts_data->cover_mode = ENABLE;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (ts_data->cover_mode) {
FTS_DEBUG("exit cover mode");
ret = fts_ex_mode_switch(MODE_COVER, DISABLE);
if (ret >= 0) {
ts_data->cover_mode = DISABLE;
}
}
}
FTS_DEBUG("cover mode:%d", ts_data->cover_mode);
return count;
}
static ssize_t fts_charger_mode_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct fts_ts_data *ts_data = fts_data;
struct input_dev *input_dev = ts_data->input_dev;
mutex_lock(&input_dev->mutex);
fts_read_reg(FTS_REG_CHARGER_MODE_EN, &val);
count = scnprintf(buf + count, PAGE_SIZE, "Charger Mode:%s\n",
ts_data->charger_mode ? "On" : "Off");
count += scnprintf(buf + count, PAGE_SIZE - count,
"Charger Reg(0x8B):%d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_charger_mode_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
struct fts_ts_data *ts_data = fts_data;
if (FTS_SYSFS_ECHO_ON(buf)) {
if (!ts_data->charger_mode) {
FTS_DEBUG("enter charger mode");
ret = fts_ex_mode_switch(MODE_CHARGER, ENABLE);
if (ret >= 0) {
ts_data->charger_mode = ENABLE;
}
}
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
if (ts_data->charger_mode) {
FTS_DEBUG("exit charger mode");
ret = fts_ex_mode_switch(MODE_CHARGER, DISABLE);
if (ret >= 0) {
ts_data->charger_mode = DISABLE;
}
}
}
FTS_DEBUG("charger mode:%d", ts_data->glove_mode);
return count;
}
static ssize_t fts_report_rate_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct fts_ts_data *ts_data = fts_data;
struct input_dev *input_dev = ts_data->input_dev;
mutex_lock(&input_dev->mutex);
fts_read_reg(FTS_REG_REPORT_RATE, &val);
count = scnprintf(buf + count, PAGE_SIZE,
"Report Rate:%d\n", ts_data->report_rate);
count += scnprintf(buf + count, PAGE_SIZE - count,
"Report Rate Reg(0x88):%d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_report_rate_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
struct fts_ts_data *ts_data = fts_data;
int rate;
ret = kstrtoint(buf, 16, &rate);
if (ret)
return ret;
if (rate != ts_data->report_rate) {
ret = fts_ex_mode_switch(REPORT_RATE, (u8)rate);
if (ret >= 0)
ts_data->report_rate = rate;
}
FTS_DEBUG("report rate:%d", ts_data->report_rate);
return count;
}
/* read and write charger mode
* read example: cat fts_glove_mode ---read glove mode
* write example:echo 1 > fts_glove_mode ---write glove mode to 01
*/
static DEVICE_ATTR(fts_glove_mode, S_IRUGO | S_IWUSR,
fts_glove_mode_show, fts_glove_mode_store);
static DEVICE_ATTR(fts_cover_mode, S_IRUGO | S_IWUSR,
fts_cover_mode_show, fts_cover_mode_store);
static DEVICE_ATTR(fts_charger_mode, S_IRUGO | S_IWUSR,
fts_charger_mode_show, fts_charger_mode_store);
static DEVICE_ATTR_RW(fts_report_rate);
static struct attribute *fts_touch_mode_attrs[] = {
&dev_attr_fts_glove_mode.attr,
&dev_attr_fts_cover_mode.attr,
&dev_attr_fts_charger_mode.attr,
&dev_attr_fts_report_rate.attr,
NULL,
};
static struct attribute_group fts_touch_mode_group = {
.attrs = fts_touch_mode_attrs,
};
int fts_ex_mode_recovery(struct fts_ts_data *ts_data)
{
if (ts_data->glove_mode) {
fts_ex_mode_switch(MODE_GLOVE, ENABLE);
}
if (ts_data->cover_mode) {
fts_ex_mode_switch(MODE_COVER, ENABLE);
}
if (ts_data->charger_mode) {
fts_ex_mode_switch(MODE_CHARGER, ENABLE);
}
if (ts_data->report_rate > 0)
fts_ex_mode_switch(REPORT_RATE, ts_data->report_rate);
return 0;
}
int fts_ex_mode_init(struct fts_ts_data *ts_data)
{
int ret = 0;
ts_data->glove_mode = DISABLE;
ts_data->cover_mode = DISABLE;
ts_data->charger_mode = DISABLE;
ts_data->report_rate = 0;
ret = sysfs_create_group(&ts_data->dev->kobj, &fts_touch_mode_group);
if (ret < 0) {
FTS_ERROR("create sysfs(ex_mode) fail");
sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
return ret;
} else {
FTS_DEBUG("create sysfs(ex_mode) succeedfully");
}
return 0;
}
int fts_ex_mode_exit(struct fts_ts_data *ts_data)
{
sysfs_remove_group(&ts_data->dev->kobj, &fts_touch_mode_group);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,216 @@
/************************************************************************
* Copyright (C) 2012-2019, Focaltech Systems (R)<29><>All Rights Reserved.
*
* File Name: focaltech_flash.h
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-07
*
* Abstract:
*
************************************************************************/
#ifndef __LINUX_FOCALTECH_FLASH_H__
#define __LINUX_FOCALTECH_FLASH_H__
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_CMD_RESET 0x07
#define FTS_ROMBOOT_CMD_SET_PRAM_ADDR 0xAD
#define FTS_ROMBOOT_CMD_SET_PRAM_ADDR_LEN 4
#define FTS_ROMBOOT_CMD_WRITE 0xAE
#define FTS_ROMBOOT_CMD_START_APP 0x08
#define FTS_DELAY_PRAMBOOT_START 100
#define FTS_ROMBOOT_CMD_ECC 0xCC
#define FTS_PRAM_SADDR 0x000000
#define FTS_DRAM_SADDR 0xD00000
#define FTS_CMD_READ 0x03
#define FTS_CMD_READ_DELAY 1
#define FTS_CMD_READ_LEN 4
#define FTS_CMD_READ_LEN_SPI 6
#define FTS_CMD_FLASH_TYPE 0x05
#define FTS_CMD_FLASH_MODE 0x09
#define FLASH_MODE_WRITE_FLASH_VALUE 0x0A
#define FLASH_MODE_UPGRADE_VALUE 0x0B
#define FLASH_MODE_LIC_VALUE 0x0C
#define FLASH_MODE_PARAM_VALUE 0x0D
#define FTS_CMD_ERASE_APP 0x61
#define FTS_REASE_APP_DELAY 1350
#define FTS_ERASE_SECTOR_DELAY 60
#define FTS_RETRIES_REASE 50
#define FTS_RETRIES_DELAY_REASE 400
#define FTS_CMD_FLASH_STATUS 0x6A
#define FTS_CMD_FLASH_STATUS_LEN 2
#define FTS_CMD_FLASH_STATUS_NOP 0x0000
#define FTS_CMD_FLASH_STATUS_ECC_OK 0xF055
#define FTS_CMD_FLASH_STATUS_ERASE_OK 0xF0AA
#define FTS_CMD_FLASH_STATUS_WRITE_OK 0x1000
#define FTS_CMD_ECC_INIT 0x64
#define FTS_CMD_ECC_CAL 0x65
#define FTS_CMD_ECC_CAL_LEN 7
#define FTS_RETRIES_ECC_CAL 10
#define FTS_RETRIES_DELAY_ECC_CAL 50
#define FTS_CMD_ECC_READ 0x66
#define FTS_CMD_SET_WFLASH_ADDR 0xAB
#define FTS_CMD_SET_RFLASH_ADDR 0xAC
#define FTS_LEN_SET_ADDR 4
#define FTS_CMD_DATA_LEN 0xB0
#define FTS_CMD_APP_DATA_LEN_INCELL 0x7A
#define FTS_CMD_DATA_LEN_LEN 4
#define FTS_CMD_WRITE 0xBF
#define FTS_RETRIES_WRITE 100
#define FTS_RETRIES_DELAY_WRITE 1
#define FTS_CMD_WRITE_LEN 6
#define FTS_DELAY_READ_ID 20
#define FTS_DELAY_UPGRADE_RESET 80
#define PRAMBOOT_MIN_SIZE 0x120
#define PRAMBOOT_MAX_SIZE (64*1024)
#define FTS_FLASH_PACKET_LENGTH 32 /* max=128 */
#define FTS_MAX_LEN_ECC_CALC 0xFFFE /* must be even */
#define FTS_MIN_LEN 0x120
#define FTS_MAX_LEN_FILE (128 * 1024)
#define FTS_MAX_LEN_APP (64 * 1024)
#define FTS_MAX_LEN_SECTOR (4 * 1024)
#define FTS_CONIFG_VENDORID_OFF 0x04
#define FTS_CONIFG_MODULEID_OFF 0x1E
#define FTS_CONIFG_PROJECTID_OFF 0x20
#define FTS_APPINFO_OFF 0x100
#define FTS_APPINFO_APPLEN_OFF 0x00
#define FTS_APPINFO_APPLEN2_OFF 0x12
#define FTS_REG_UPGRADE 0xFC
#define FTS_REG_UPGRADE2 0xBC
#define FTS_UPGRADE_AA 0xAA
#define FTS_UPGRADE_55 0x55
#define FTS_DELAY_UPGRADE_AA 10
#define FTS_UPGRADE_LOOP 30
#define FTS_HEADER_LEN 32
#define FTS_FW_BIN_FILEPATH "/sdcard/"
#define FTS_FW_IDE_SIG "IDE_"
#define FTS_FW_IDE_SIG_LEN 4
#define MAX_MODULE_VENDOR_NAME_LEN 16
#define FTS_ROMBOOT_CMD_ECC_NEW_LEN 7
#define FTS_ECC_FINISH_TIMEOUT 100
#define FTS_ROMBOOT_CMD_ECC_FINISH 0xCE
#define FTS_ROMBOOT_CMD_ECC_FINISH_OK_A5 0xA5
#define FTS_ROMBOOT_CMD_ECC_FINISH_OK_00 0x00
#define FTS_ROMBOOT_CMD_ECC_READ 0xCD
#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3))
#define FTS_APP_INFO_OFFSET 0x100
enum FW_STATUS {
FTS_RUN_IN_ERROR,
FTS_RUN_IN_APP,
FTS_RUN_IN_ROM,
FTS_RUN_IN_PRAM,
FTS_RUN_IN_BOOTLOADER,
};
enum FW_FLASH_MODE {
FLASH_MODE_APP,
FLASH_MODE_LIC,
FLASH_MODE_PARAM,
FLASH_MODE_ALL,
};
enum ECC_CHECK_MODE {
ECC_CHECK_MODE_XOR,
ECC_CHECK_MODE_CRC16,
};
enum UPGRADE_SPEC {
UPGRADE_SPEC_V_1_0 = 0x0100,
};
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/* IC info */
struct upgrade_func {
u64 ctype[FTX_MAX_COMPATIBLE_TYPE];
u32 fwveroff;
u32 fwcfgoff;
u32 appoff;
u32 licoff;
u32 paramcfgoff;
u32 paramcfgveroff;
u32 paramcfg2off;
int pram_ecc_check_mode;
int fw_ecc_check_mode;
int upgspec_version;
bool new_return_value_from_ic;
bool appoff_handle_in_ic;
bool is_reset_register_BC;
bool read_boot_id_need_reset;
bool hid_supported;
bool pramboot_supported;
u8 *pramboot;
u32 pb_length;
int (*init)(u8 *, u32);
int (*write_pramboot_private)(void);
int (*upgrade)(u8 *, u32);
int (*get_hlic_ver)(u8 *);
int (*lic_upgrade)(u8 *, u32);
int (*param_upgrade)(u8 *, u32);
int (*force_upgrade)(u8 *, u32);
};
struct upgrade_setting_nf {
u8 rom_idh;
u8 rom_idl;
u16 reserved;
u32 app2_offset;
u32 ecclen_max;
u8 eccok_val;
u8 upgsts_boot;
u8 delay_init;
bool spi_pe;
bool half_length;
bool fd_check;
bool drwr_support;
};
struct upgrade_module {
int id;
char vendor_name[MAX_MODULE_VENDOR_NAME_LEN];
u8 *fw_file;
u32 fw_len;
};
struct fts_upgrade {
struct fts_ts_data *ts_data;
struct upgrade_module *module_info;
struct upgrade_func *func;
struct upgrade_setting_nf *setting_nf;
int module_id;
bool fw_from_request;
u8 *fw;
u32 fw_length;
u8 *lic;
u32 lic_length;
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct upgrade_func upgrade_func_ft5452;
extern struct upgrade_func upgrade_func_ft5652;
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
int fts_fwupg_reset_in_boot(void);
int fts_fwupg_enter_into_boot(void);
int fts_fwupg_erase(u32 delay);
int fts_fwupg_ecc_cal(u32 saddr, u32 len);
int fts_flash_write_buf(u32 saddr, u8 *buf, u32 len, u32 delay);
int fts_fwupg_upgrade(struct fts_upgrade *upg);
#endif

View File

@@ -0,0 +1,292 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_upgrade_ft5452.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-15
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "../focaltech_flash.h"
/************************************************************************
* Name: fts_ft5452_upgrade
* Brief:
* Input:
* Output:
* Return: return 0 if success, otherwise return error code
***********************************************************************/
static int fts_ft5452_upgrade(u8 *buf, u32 len)
{
int ret = 0;
u32 start_addr = 0;
u8 cmd[4] = { 0 };
int ecc_in_host = 0;
int ecc_in_tp = 0;
int i = 0;
u8 wbuf[7] = { 0 };
u8 reg_val[4] = {0};
if (NULL == buf) {
FTS_ERROR("fw buf is null");
return -EINVAL;
}
if ((len < FTS_MIN_LEN) || (len > (60 * 1024))) {
FTS_ERROR("fw buffer len(%x) fail", len);
return -EINVAL;
}
/* enter into upgrade environment */
ret = fts_fwupg_enter_into_boot();
if (ret < 0) {
FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
goto fw_reset;
}
cmd[0] = FTS_CMD_FLASH_MODE;
cmd[1] = FLASH_MODE_UPGRADE_VALUE;
ret = fts_write(cmd, 2);
if (ret < 0) {
FTS_ERROR("upgrade mode(09) cmd write fail");
goto fw_reset;
}
cmd[0] = FTS_CMD_DATA_LEN;
cmd[1] = BYTE_OFF_16(len);
cmd[2] = BYTE_OFF_8(len);
cmd[3] = BYTE_OFF_0(len);
ret = fts_write(cmd, FTS_CMD_DATA_LEN_LEN);
if (ret < 0) {
FTS_ERROR("data len cmd write fail");
goto fw_reset;
}
ret = fts_fwupg_erase(FTS_REASE_APP_DELAY);
if (ret < 0) {
FTS_ERROR("erase cmd write fail");
goto fw_reset;
}
/* write app */
start_addr = upgrade_func_ft5452.appoff;
ecc_in_host = fts_flash_write_buf(start_addr, buf, len, 1);
if (ecc_in_host < 0 ) {
FTS_ERROR("lcd initial code write fail");
goto fw_reset;
}
FTS_INFO( "**********read out checksum**********");
/* check sum init */
wbuf[0] = FTS_CMD_ECC_INIT;
ret = fts_write(wbuf, 1);
if (ret < 0) {
FTS_ERROR("ecc init cmd write fail");
return ret;
}
/* send commond to start checksum */
wbuf[0] = FTS_CMD_ECC_CAL;
wbuf[1] = BYTE_OFF_16(start_addr);
wbuf[2] = BYTE_OFF_8(start_addr);
wbuf[3] = BYTE_OFF_0(start_addr);
wbuf[4] = BYTE_OFF_16(len);
wbuf[5] = BYTE_OFF_8(len);
wbuf[6] = BYTE_OFF_0(len);
FTS_DEBUG("ecc calc startaddr:0x%04x, len:%d", start_addr, len);
ret = fts_write(wbuf, 7);
if (ret < 0) {
FTS_ERROR("ecc calc cmd write fail");
return ret;
}
msleep(len / 256);
/* read status if check sum is finished */
for (i = 0; i < FTS_RETRIES_ECC_CAL; i++) {
wbuf[0] = FTS_CMD_FLASH_STATUS;
reg_val[0] = reg_val[1] = 0x00;
fts_read(wbuf, 1, reg_val, 2);
FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!", reg_val[0], reg_val[1]);
if ((0xF0 == reg_val[0]) && (0x55 == reg_val[1])) {
break;
}
msleep(FTS_RETRIES_DELAY_ECC_CAL);
}
/* read out check sum */
wbuf[0] = FTS_CMD_ECC_READ;
ret = fts_read(wbuf, 1, reg_val, 1);
if (ret < 0) {
FTS_ERROR( "ecc read cmd write fail");
return ret;
}
ecc_in_tp = reg_val[0];
FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
if (ecc_in_tp != ecc_in_host) {
FTS_ERROR("ecc check fail");
goto fw_reset;
}
FTS_INFO("upgrade success, reset to normal boot");
ret = fts_fwupg_reset_in_boot();
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
msleep(200);
return 0;
fw_reset:
FTS_INFO("upgrade fail, reset to normal boot");
ret = fts_fwupg_reset_in_boot();
if (ret < 0) {
FTS_ERROR("reset to normal boot fail");
}
return -EIO;
}
struct upgrade_func upgrade_func_ft5452 = {
.ctype = {0x81},
.fwveroff = 0x010E,
.fwcfgoff = 0x1FFB0,
.appoff = 0x0000,
.pramboot_supported = false,
.hid_supported = true,
.upgrade = fts_ft5452_upgrade,
};
#define FTS_DELAY_ERASE_PAGE_2K 80
#define FTS_SIZE_PAGE_2K 2048
/************************************************************************
* Name: fts_ft5652_upgrade
* Brief:
* Input:
* Output:
* Return: return 0 if success, otherwise return error code
**********************************************************************/
static int fts_ft5652_upgrade(u8 *buf, u32 len)
{
int ret = 0;
u32 start_addr = 0;
u8 cmd[4] = { 0 };
u32 delay = 0;
int ecc_in_host = 0;
int ecc_in_tp = 0;
if ((buf == NULL) || (len < FTS_MIN_LEN)) {
FTS_ERROR("buffer/len(%x) is invalid", len);
return -EINVAL;
}
/* enter into upgrade environment */
ret = fts_fwupg_enter_into_boot();
if (ret < 0) {
FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
goto fw_reset;
}
cmd[0] = FTS_CMD_APP_DATA_LEN_INCELL;
cmd[1] = BYTE_OFF_16(len);
cmd[2] = BYTE_OFF_8(len);
cmd[3] = BYTE_OFF_0(len);
ret = fts_write(cmd, FTS_CMD_DATA_LEN_LEN);
if (ret < 0) {
FTS_ERROR("data len cmd write fail");
goto fw_reset;
}
cmd[0] = FTS_CMD_FLASH_MODE;
cmd[1] = FLASH_MODE_UPGRADE_VALUE;
ret = fts_write(cmd, 2);
if (ret < 0) {
FTS_ERROR("upgrade mode(09) cmd write fail");
goto fw_reset;
}
delay = FTS_DELAY_ERASE_PAGE_2K * (len / FTS_SIZE_PAGE_2K);
ret = fts_fwupg_erase(delay);
if (ret < 0) {
FTS_ERROR("erase cmd write fail");
goto fw_reset;
}
/* write app */
start_addr = upgrade_func_ft5652.appoff;
ecc_in_host = fts_flash_write_buf(start_addr, buf, len, 1);
if (ecc_in_host < 0) {
FTS_ERROR("flash write fail");
goto fw_reset;
}
/* ecc */
ecc_in_tp = fts_fwupg_ecc_cal(start_addr, len);
if (ecc_in_tp < 0) {
FTS_ERROR("ecc read fail");
goto fw_reset;
}
FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
if (ecc_in_tp != ecc_in_host) {
FTS_ERROR("ecc check fail");
goto fw_reset;
}
FTS_INFO("upgrade success, reset to normal boot");
ret = fts_fwupg_reset_in_boot();
if (ret < 0)
FTS_ERROR("reset to normal boot fail");
msleep(200);
return 0;
fw_reset:
FTS_INFO("upgrade fail, reset to normal boot");
ret = fts_fwupg_reset_in_boot();
if (ret < 0)
FTS_ERROR("reset to normal boot fail");
return -EIO;
}
struct upgrade_func upgrade_func_ft5652 = {
.ctype = {0x88},
.fwveroff = 0x010E,
.fwcfgoff = 0x1F80,
.appoff = 0x0000,
.upgspec_version = UPGRADE_SPEC_V_1_0,
.pramboot_supported = false,
.hid_supported = true,
.upgrade = fts_ft5652_upgrade,
};

View File

@@ -0,0 +1,477 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_gestrue.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/******************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define KEY_GESTURE_U KEY_U
#define KEY_GESTURE_UP KEY_UP
#define KEY_GESTURE_DOWN KEY_DOWN
#define KEY_GESTURE_LEFT KEY_LEFT
#define KEY_GESTURE_RIGHT KEY_RIGHT
#define KEY_GESTURE_O KEY_O
#define KEY_GESTURE_E KEY_E
#define KEY_GESTURE_M KEY_M
#define KEY_GESTURE_L KEY_L
#define KEY_GESTURE_W KEY_W
#define KEY_GESTURE_S KEY_S
#define KEY_GESTURE_V KEY_V
#define KEY_GESTURE_C KEY_C
#define KEY_GESTURE_Z KEY_Z
#define GESTURE_LEFT 0x20
#define GESTURE_RIGHT 0x21
#define GESTURE_UP 0x22
#define GESTURE_DOWN 0x23
#define GESTURE_DOUBLECLICK 0x24
#define GESTURE_O 0x30
#define GESTURE_W 0x31
#define GESTURE_M 0x32
#define GESTURE_E 0x33
#define GESTURE_L 0x44
#define GESTURE_S 0x46
#define GESTURE_V 0x54
#define GESTURE_Z 0x41
#define GESTURE_C 0x34
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*
* gesture_id - mean which gesture is recognised
* point_num - points number of this gesture
* coordinate_x - All gesture point x coordinate
* coordinate_y - All gesture point y coordinate
* mode - gesture enable/disable, need enable by host
* - 1:enable gesture function(default) 0:disable
* active - gesture work flag,
* always set 1 when suspend, set 0 when resume
*/
struct fts_gesture_st {
u8 gesture_id;
u8 point_num;
u16 coordinate_x[FTS_GESTURE_POINTS_MAX];
u16 coordinate_y[FTS_GESTURE_POINTS_MAX];
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_gesture_st fts_gesture_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
static ssize_t fts_gesture_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
u8 val = 0;
struct fts_ts_data *ts_data = fts_data;
mutex_lock(&ts_data->input_dev->mutex);
fts_read_reg(FTS_REG_GESTURE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Gesture Mode:%s\n",
ts_data->gesture_mode ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Reg(0xD0)=%d\n", val);
mutex_unlock(&ts_data->input_dev->mutex);
return count;
}
static ssize_t fts_gesture_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct fts_ts_data *ts_data = fts_data;
mutex_lock(&ts_data->input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_DEBUG("enable gesture");
ts_data->gesture_mode = ENABLE;
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_DEBUG("disable gesture");
ts_data->gesture_mode = DISABLE;
}
mutex_unlock(&ts_data->input_dev->mutex);
return count;
}
static ssize_t fts_gesture_buf_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
int count = 0;
int i = 0;
struct input_dev *input_dev = fts_data->input_dev;
struct fts_gesture_st *gesture = &fts_gesture_data;
mutex_lock(&input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "Gesture ID:%d\n", gesture->gesture_id);
count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum:%d\n",
gesture->point_num);
count += snprintf(buf + count, PAGE_SIZE, "Gesture Points Buffer:\n");
/* save point data,max:6 */
for (i = 0; i < FTS_GESTURE_POINTS_MAX; i++) {
count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i,
gesture->coordinate_x[i], gesture->coordinate_y[i]);
if ((i + 1) % 4 == 0)
count += snprintf(buf + count, PAGE_SIZE, "\n");
}
count += snprintf(buf + count, PAGE_SIZE, "\n");
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_gesture_buf_store(
struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
return -EPERM;
}
/* sysfs gesture node
* read example: cat fts_gesture_mode ---read gesture mode
* write example:echo 1 > fts_gesture_mode --- write gesture mode to 1
*
*/
static DEVICE_ATTR(fts_gesture_mode, S_IRUGO | S_IWUSR, fts_gesture_show,
fts_gesture_store);
/*
* read example: cat fts_gesture_buf --- read gesture buf
*/
static DEVICE_ATTR(fts_gesture_buf, S_IRUGO | S_IWUSR,
fts_gesture_buf_show, fts_gesture_buf_store);
static struct attribute *fts_gesture_mode_attrs[] = {
&dev_attr_fts_gesture_mode.attr,
&dev_attr_fts_gesture_buf.attr,
NULL,
};
static struct attribute_group fts_gesture_group = {
.attrs = fts_gesture_mode_attrs,
};
static int fts_create_gesture_sysfs(struct device *dev)
{
int ret = 0;
ret = sysfs_create_group(&dev->kobj, &fts_gesture_group);
if (ret) {
FTS_ERROR("gesture sys node create fail");
sysfs_remove_group(&dev->kobj, &fts_gesture_group);
return ret;
}
return 0;
}
static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
{
int gesture;
FTS_DEBUG("gesture_id:0x%x", gesture_id);
switch (gesture_id) {
case GESTURE_LEFT:
gesture = KEY_GESTURE_LEFT;
break;
case GESTURE_RIGHT:
gesture = KEY_GESTURE_RIGHT;
break;
case GESTURE_UP:
gesture = KEY_GESTURE_UP;
break;
case GESTURE_DOWN:
gesture = KEY_GESTURE_DOWN;
break;
case GESTURE_DOUBLECLICK:
gesture = KEY_POWER;
break;
case GESTURE_O:
gesture = KEY_GESTURE_O;
break;
case GESTURE_W:
gesture = KEY_GESTURE_W;
break;
case GESTURE_M:
gesture = KEY_GESTURE_M;
break;
case GESTURE_E:
gesture = KEY_GESTURE_E;
break;
case GESTURE_L:
gesture = KEY_GESTURE_L;
break;
case GESTURE_S:
gesture = KEY_GESTURE_S;
break;
case GESTURE_V:
gesture = KEY_GESTURE_V;
break;
case GESTURE_Z:
gesture = KEY_GESTURE_Z;
break;
case GESTURE_C:
gesture = KEY_GESTURE_C;
break;
default:
gesture = -1;
break;
}
/* report event key */
if (gesture != -1) {
FTS_DEBUG("Gesture Code=%d", gesture);
input_report_key(input_dev, gesture, 1);
input_sync(input_dev);
input_report_key(input_dev, gesture, 0);
input_sync(input_dev);
}
}
/*****************************************************************************
* Name: fts_gesture_readdata
* Brief: Read information about gesture: enable flag/gesture points..., if ges-
* ture enable, save gesture points' information, and report to OS.
* It will be called this function every intrrupt when FTS_GESTURE_EN = 1
*
* gesture data length: 1(enable) + 1(reserve) + 2(header) + 6 * 4
* Input: ts_data - global struct data
* data - gesture data buffer if non-flash, else NULL
* Output:
* Return: 0 - read gesture data successfully, the report data is gesture data
* 1 - tp not in suspend/gesture not enable in TP FW
* -Exx - error
*****************************************************************************/
int fts_gesture_readdata(struct fts_ts_data *ts_data, u8 *data)
{
int ret = 0;
int i = 0;
int index = 0;
u8 buf[FTS_GESTURE_DATA_LEN] = { 0 };
struct input_dev *input_dev = ts_data->input_dev;
struct fts_gesture_st *gesture = &fts_gesture_data;
if (!ts_data->suspended || !ts_data->gesture_mode) {
return 1;
}
ret = fts_read_reg(FTS_REG_GESTURE_EN, &buf[0]);
if ((ret < 0) || (buf[0] != ENABLE)) {
FTS_DEBUG("gesture not enable in fw, don't process gesture");
return 1;
}
buf[2] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
ret = fts_read(&buf[2], 1, &buf[2], FTS_GESTURE_DATA_LEN - 2);
if (ret < 0) {
FTS_ERROR("read gesture header data fail");
return ret;
}
/* init variable before read gesture point */
memset(gesture->coordinate_x, 0, FTS_GESTURE_POINTS_MAX * sizeof(u16));
memset(gesture->coordinate_y, 0, FTS_GESTURE_POINTS_MAX * sizeof(u16));
gesture->gesture_id = buf[2];
gesture->point_num = buf[3];
FTS_DEBUG("gesture_id=%d, point_num=%d",
gesture->gesture_id, gesture->point_num);
/* save point data,max:6 */
for (i = 0; i < FTS_GESTURE_POINTS_MAX; i++) {
index = 4 * i + 4;
gesture->coordinate_x[i] = (u16)(((buf[0 + index] & 0x0F) << 8)
+ buf[1 + index]);
gesture->coordinate_y[i] = (u16)(((buf[2 + index] & 0x0F) << 8)
+ buf[3 + index]);
}
/* report gesture to OS */
fts_gesture_report(input_dev, gesture->gesture_id);
return 0;
}
void fts_gesture_recovery(struct fts_ts_data *ts_data)
{
if (ts_data->gesture_mode && ts_data->suspended) {
FTS_DEBUG("gesture recovery...");
fts_write_reg(0xD1, 0xFF);
fts_write_reg(0xD2, 0xFF);
fts_write_reg(0xD5, 0xFF);
fts_write_reg(0xD6, 0xFF);
fts_write_reg(0xD7, 0xFF);
fts_write_reg(0xD8, 0xFF);
fts_write_reg(FTS_REG_GESTURE_EN, ENABLE);
}
}
int fts_gesture_suspend(struct fts_ts_data *ts_data)
{
int i = 0;
u8 state = 0xFF;
FTS_FUNC_ENTER();
if (enable_irq_wake(ts_data->irq)) {
FTS_DEBUG("enable_irq_wake(irq:%d) fail", ts_data->irq);
}
for (i = 0; i < 5; i++) {
fts_write_reg(0xD1, 0xFF);
fts_write_reg(0xD2, 0xFF);
fts_write_reg(0xD5, 0xFF);
fts_write_reg(0xD6, 0xFF);
fts_write_reg(0xD7, 0xFF);
fts_write_reg(0xD8, 0xFF);
fts_write_reg(FTS_REG_GESTURE_EN, ENABLE);
msleep(1);
fts_read_reg(FTS_REG_GESTURE_EN, &state);
if (state == ENABLE)
break;
}
if (i >= 5)
FTS_ERROR("make IC enter into gesture(suspend) fail,state:%x", state);
else
FTS_INFO("Enter into gesture(suspend) successfully");
FTS_FUNC_EXIT();
return 0;
}
int fts_gesture_resume(struct fts_ts_data *ts_data)
{
int i = 0;
u8 state = 0xFF;
FTS_FUNC_ENTER();
if (disable_irq_wake(ts_data->irq)) {
FTS_DEBUG("disable_irq_wake(irq:%d) fail", ts_data->irq);
}
for (i = 0; i < 5; i++) {
fts_write_reg(FTS_REG_GESTURE_EN, DISABLE);
msleep(1);
fts_read_reg(FTS_REG_GESTURE_EN, &state);
if (state == DISABLE)
break;
}
if (i >= 5)
FTS_ERROR("make IC exit gesture(resume) fail,state:%x", state);
else
FTS_INFO("resume from gesture successfully");
FTS_FUNC_EXIT();
return 0;
}
int fts_gesture_init(struct fts_ts_data *ts_data)
{
struct input_dev *input_dev = ts_data->input_dev;
FTS_FUNC_ENTER();
input_set_capability(input_dev, EV_KEY, KEY_POWER);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
__set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
__set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
__set_bit(KEY_GESTURE_UP, input_dev->keybit);
__set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
__set_bit(KEY_GESTURE_U, input_dev->keybit);
__set_bit(KEY_GESTURE_O, input_dev->keybit);
__set_bit(KEY_GESTURE_E, input_dev->keybit);
__set_bit(KEY_GESTURE_M, input_dev->keybit);
__set_bit(KEY_GESTURE_W, input_dev->keybit);
__set_bit(KEY_GESTURE_L, input_dev->keybit);
__set_bit(KEY_GESTURE_S, input_dev->keybit);
__set_bit(KEY_GESTURE_V, input_dev->keybit);
__set_bit(KEY_GESTURE_C, input_dev->keybit);
__set_bit(KEY_GESTURE_Z, input_dev->keybit);
fts_create_gesture_sysfs(ts_data->dev);
memset(&fts_gesture_data, 0, sizeof(struct fts_gesture_st));
ts_data->gesture_mode = FTS_GESTURE_EN;
FTS_FUNC_EXIT();
return 0;
}
int fts_gesture_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
sysfs_remove_group(&ts_data->dev->kobj, &fts_gesture_group);
FTS_FUNC_EXIT();
return 0;
}

View File

@@ -0,0 +1,548 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, FocalTech Systems, Ltd., all rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/************************************************************************
*
* File Name: focaltech_i2c.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-04
*
* Abstract: i2c communication with TP
*
* Version: v1.0
*
* Revision History:
*
************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#include <linux/pm_runtime.h>
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define I2C_RETRY_NUMBER 3
#define I2C_BUF_LENGTH 256
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_ts_data *ts_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
static int fts_i2c_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen)
{
int ret = 0;
int i = 0;
struct i2c_msg msg_list[2];
struct i2c_msg *msg = NULL;
int msg_num = 0;
/* must have data when read */
if (!ts_data || !ts_data->client || !data || !datalen
|| (datalen >= I2C_BUF_LENGTH) || (cmdlen >= I2C_BUF_LENGTH)) {
FTS_ERROR("fts_data/client/cmdlen(%d)/data/datalen(%d) is invalid",
cmdlen, datalen);
return -EINVAL;
}
mutex_lock(&ts_data->bus_lock);
memset(&msg_list[0], 0, sizeof(struct i2c_msg));
memset(&msg_list[1], 0, sizeof(struct i2c_msg));
memcpy(ts_data->bus_tx_buf, cmd, cmdlen);
msg_list[0].addr = ts_data->client->addr;
msg_list[0].flags = 0;
msg_list[0].len = cmdlen;
msg_list[0].buf = ts_data->bus_tx_buf;
msg_list[1].addr = ts_data->client->addr;
msg_list[1].flags = I2C_M_RD;
msg_list[1].len = datalen;
msg_list[1].buf = ts_data->bus_rx_buf;
if (cmd && cmdlen) {
msg = &msg_list[0];
msg_num = 2;
} else {
msg = &msg_list[1];
msg_num = 1;
}
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(ts_data->client->adapter, msg, msg_num);
if (ret < 0) {
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#ifdef CONFIG_ARCH_QTI_VM
if (atomic_read(&ts_data->trusted_touch_enabled) &&
ret == -ECONNRESET) {
pr_err("failed i2c read reacquiring session\n");
pm_runtime_put_sync(
ts_data->client->adapter->dev.parent);
pm_runtime_get_sync(
ts_data->client->adapter->dev.parent);
}
#endif
#endif
FTS_ERROR("i2c_transfer(read) fail,ret:%d", ret);
} else {
memcpy(data, ts_data->bus_rx_buf, datalen);
break;
}
}
if (ret < 0) {
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#ifdef CONFIG_ARCH_QTI_VM
pr_err("initiating abort due to i2c xfer failure\n");
fts_ts_trusted_touch_tvm_i2c_failure_report(ts_data);
#endif
#endif
}
mutex_unlock(&ts_data->bus_lock);
return ret;
}
static int fts_i2c_write(u8 *writebuf, u32 writelen)
{
int ret = 0;
int i = 0;
struct i2c_msg msgs;
if (!ts_data || !ts_data->client || !writebuf || !writelen
|| (writelen >= I2C_BUF_LENGTH)) {
FTS_ERROR("fts_data/client/data/datalen(%d) is invalid", writelen);
return -EINVAL;
}
mutex_lock(&ts_data->bus_lock);
memset(&msgs, 0, sizeof(struct i2c_msg));
memcpy(ts_data->bus_tx_buf, writebuf, writelen);
msgs.addr = ts_data->client->addr;
msgs.flags = 0;
msgs.len = writelen;
msgs.buf = ts_data->bus_tx_buf;
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(ts_data->client->adapter, &msgs, 1);
if (ret < 0) {
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#ifdef CONFIG_ARCH_QTI_VM
if (atomic_read(&ts_data->trusted_touch_enabled) &&
ret == -ECONNRESET){
pr_err("failed i2c write reacquiring session\n");
pm_runtime_put_sync(
ts_data->client->adapter->dev.parent);
pm_runtime_get_sync(
ts_data->client->adapter->dev.parent);
}
#endif
#endif
FTS_ERROR("i2c_transfer(write) fail,ret:%d", ret);
} else {
break;
}
}
if (ret < 0) {
#ifdef CONFIG_FTS_TRUSTED_TOUCH
#ifdef CONFIG_ARCH_QTI_VM
pr_err("initiating abort due to i2c xfer failure\n");
fts_ts_trusted_touch_tvm_i2c_failure_report(ts_data);
#endif
#endif
}
mutex_unlock(&ts_data->bus_lock);
return ret;
}
static int fts_i2c_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
ts_data->bus_tx_buf = kzalloc(I2C_BUF_LENGTH, GFP_KERNEL);
if (ts_data->bus_tx_buf == NULL) {
FTS_ERROR("failed to allocate memory for bus_tx_buf");
return -ENOMEM;
}
ts_data->bus_rx_buf = kzalloc(I2C_BUF_LENGTH, GFP_KERNEL);
if (ts_data->bus_rx_buf == NULL) {
FTS_ERROR("failed to allocate memory for bus_rx_buf");
return -ENOMEM;
}
FTS_FUNC_EXIT();
return 0;
}
static int fts_i2c_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data && ts_data->bus_tx_buf) {
kfree(ts_data->bus_tx_buf);
ts_data->bus_tx_buf = NULL;
}
if (ts_data && ts_data->bus_rx_buf) {
kfree(ts_data->bus_rx_buf);
ts_data->bus_rx_buf = NULL;
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Private constant and macro definitions using #define
****************************************************************************/
#define SPI_RETRY_NUMBER 3
#define CS_HIGH_DELAY 150 /* unit: us */
#define SPI_BUF_LENGTH 256
#define DATA_CRC_EN 0x20
#define WRITE_CMD 0x00
#define READ_CMD (0x80 | DATA_CRC_EN)
#define SPI_DUMMY_BYTE 3
#define SPI_HEADER_LENGTH 6 /*CRC*/
/*****************************************************************************
* functions body
****************************************************************************/
/* spi interface */
static int fts_spi_transfer(u8 *tx_buf, u8 *rx_buf, u32 len)
{
int ret = 0;
struct spi_device *spi = fts_data->spi;
struct spi_message msg;
struct spi_transfer xfer = {
.tx_buf = tx_buf,
.rx_buf = rx_buf,
.len = len,
};
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
ret = spi_sync(spi, &msg);
if (ret) {
FTS_ERROR("spi_sync fail,ret:%d", ret);
return ret;
}
return ret;
}
static void crckermit(u8 *data, u32 len, u16 *crc_out)
{
u32 i = 0;
u32 j = 0;
u16 crc = 0xFFFF;
for (i = 0; i < len; i++) {
crc ^= data[i];
for (j = 0; j < 8; j++) {
if (crc & 0x01)
crc = (crc >> 1) ^ 0x8408;
else
crc = (crc >> 1);
}
}
*crc_out = crc;
}
static int rdata_check(u8 *rdata, u32 rlen)
{
u16 crc_calc = 0;
u16 crc_read = 0;
crckermit(rdata, rlen - 2, &crc_calc);
crc_read = (u16)(rdata[rlen - 1] << 8) + rdata[rlen - 2];
if (crc_calc != crc_read)
return -EIO;
return 0;
}
static int fts_spi_write(u8 *writebuf, u32 writelen)
{
int ret = 0;
int i = 0;
struct fts_ts_data *ts_data = fts_data;
u8 *txbuf = NULL;
u8 *rxbuf = NULL;
u32 txlen = 0;
u32 txlen_need = writelen + SPI_HEADER_LENGTH + ts_data->dummy_byte;
u32 datalen = writelen - 1;
if (!writebuf || !writelen) {
FTS_ERROR("writebuf/len is invalid");
return -EINVAL;
}
mutex_lock(&ts_data->bus_lock);
if (txlen_need > SPI_BUF_LENGTH) {
txbuf = kzalloc(txlen_need, GFP_KERNEL);
if (txbuf == NULL) {
FTS_ERROR("txbuf malloc fail");
ret = -ENOMEM;
goto err_write;
}
rxbuf = kzalloc(txlen_need, GFP_KERNEL);
if (rxbuf == NULL) {
FTS_ERROR("rxbuf malloc fail");
ret = -ENOMEM;
goto err_write;
}
} else {
txbuf = ts_data->bus_tx_buf;
rxbuf = ts_data->bus_rx_buf;
memset(txbuf, 0x0, SPI_BUF_LENGTH);
memset(rxbuf, 0x0, SPI_BUF_LENGTH);
}
txbuf[txlen++] = writebuf[0];
txbuf[txlen++] = WRITE_CMD;
txbuf[txlen++] = (datalen >> 8) & 0xFF;
txbuf[txlen++] = datalen & 0xFF;
if (datalen > 0) {
txlen = txlen + SPI_DUMMY_BYTE;
memcpy(&txbuf[txlen], &writebuf[1], datalen);
txlen = txlen + datalen;
}
for (i = 0; i < SPI_RETRY_NUMBER; i++) {
ret = fts_spi_transfer(txbuf, rxbuf, txlen);
if ((ret == 0) && ((rxbuf[3] & 0xA0) == 0))
break;
FTS_DEBUG("data write(addr:%x),status:%x,retry:%d,ret:%d",
writebuf[0], rxbuf[3], i, ret);
ret = -EIO;
udelay(CS_HIGH_DELAY);
}
if (ret < 0) {
FTS_ERROR("data write(addr:%x) fail,status:%x,ret:%d",
writebuf[0], rxbuf[3], ret);
}
err_write:
if (txlen_need > SPI_BUF_LENGTH) {
kfree(txbuf);
kfree(rxbuf);
}
udelay(CS_HIGH_DELAY);
mutex_unlock(&ts_data->bus_lock);
return ret;
}
static int fts_spi_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen)
{
int ret = 0;
int i = 0;
u8 *txbuf = NULL;
u8 *rxbuf = NULL;
u32 txlen = 0;
u32 txlen_need = datalen + SPI_HEADER_LENGTH + ts_data->dummy_byte;
u8 ctrl = READ_CMD;
u32 dp = 0;
if (!cmd || !cmdlen || !data || !datalen) {
FTS_ERROR("cmd/cmdlen/data/datalen is invalid");
return -EINVAL;
}
mutex_lock(&ts_data->bus_lock);
if (txlen_need > SPI_BUF_LENGTH) {
txbuf = kzalloc(txlen_need, GFP_KERNEL);
if (txbuf == NULL) {
FTS_ERROR("txbuf malloc fail");
ret = -ENOMEM;
goto err_read;
}
rxbuf = kzalloc(txlen_need, GFP_KERNEL);
if (rxbuf == NULL) {
FTS_ERROR("rxbuf malloc fail");
ret = -ENOMEM;
goto err_read;
}
} else {
txbuf = ts_data->bus_tx_buf;
rxbuf = ts_data->bus_rx_buf;
memset(txbuf, 0x0, SPI_BUF_LENGTH);
memset(rxbuf, 0x0, SPI_BUF_LENGTH);
}
txbuf[txlen++] = cmd[0];
txbuf[txlen++] = ctrl;
txbuf[txlen++] = (datalen >> 8) & 0xFF;
txbuf[txlen++] = datalen & 0xFF;
dp = txlen + SPI_DUMMY_BYTE;
txlen = dp + datalen;
if (ctrl & DATA_CRC_EN)
txlen = txlen + 2;
for (i = 0; i < SPI_RETRY_NUMBER; i++) {
ret = fts_spi_transfer(txbuf, rxbuf, txlen);
if ((ret == 0) && ((rxbuf[3] & 0xA0) == 0)) {
memcpy(data, &rxbuf[dp], datalen);
/* crc check */
if (ctrl & DATA_CRC_EN) {
ret = rdata_check(&rxbuf[dp], txlen - dp);
if (ret < 0) {
FTS_DEBUG("data read(addr:%x) crc abnormal,retry:%d",
cmd[0], i);
udelay(CS_HIGH_DELAY);
continue;
}
}
break;
}
FTS_DEBUG("data read(addr:%x) status:%x,retry:%d,ret:%d",
cmd[0], rxbuf[3], i, ret);
ret = -EIO;
udelay(CS_HIGH_DELAY);
}
if (ret < 0) {
FTS_ERROR("data read(addr:%x) %s,status:%x,ret:%d", cmd[0],
(i >= SPI_RETRY_NUMBER) ? "crc abnormal" : "fail",
rxbuf[3], ret);
}
err_read:
if (txlen_need > SPI_BUF_LENGTH) {
kfree(txbuf);
kfree(rxbuf);
}
udelay(CS_HIGH_DELAY);
mutex_unlock(&ts_data->bus_lock);
return ret;
}
static int fts_spi_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
ts_data->bus_tx_buf = kzalloc(SPI_BUF_LENGTH, GFP_KERNEL);
if (ts_data->bus_tx_buf == NULL) {
FTS_ERROR("failed to allocate memory for bus_tx_buf");
return -ENOMEM;
}
ts_data->bus_rx_buf = kzalloc(SPI_BUF_LENGTH, GFP_KERNEL);
if (ts_data->bus_rx_buf == NULL) {
FTS_ERROR("failed to allocate memory for bus_rx_buf");
return -ENOMEM;
}
ts_data->dummy_byte = SPI_DUMMY_BYTE;
FTS_FUNC_EXIT();
return 0;
}
static int fts_spi_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data && ts_data->bus_tx_buf) {
kfree(ts_data->bus_tx_buf);
ts_data->bus_tx_buf = NULL;
}
if (ts_data && ts_data->bus_rx_buf) {
kfree(ts_data->bus_rx_buf);
ts_data->bus_rx_buf = NULL;
}
FTS_FUNC_EXIT();
return 0;
}
int fts_read(u8 *cmd, u32 cmdlen, u8 *data, u32 datalen)
{
int ret = 0;
if (ts_data->bus_type == BUS_TYPE_I2C)
ret = fts_i2c_read(cmd, cmdlen, data, datalen);
else
ret = fts_spi_read(cmd, cmdlen, data, datalen);
return ret;
}
int fts_write(u8 *writebuf, u32 writelen)
{
int ret = 0;
if (ts_data->bus_type == BUS_TYPE_I2C)
ret = fts_i2c_write(writebuf, writelen);
else
ret = fts_spi_write(writebuf, writelen);
return ret;
}
int fts_read_reg(u8 addr, u8 *value)
{
return fts_read(&addr, 1, value, 1);
}
int fts_write_reg(u8 addr, u8 value)
{
u8 buf[2] = { 0 };
buf[0] = addr;
buf[1] = value;
return fts_write(buf, sizeof(buf));
}
int fts_bus_init(struct fts_ts_data *_ts_data)
{
ts_data = _ts_data;
if (ts_data->bus_type == BUS_TYPE_I2C)
return fts_i2c_init(ts_data);
return fts_spi_init(ts_data);
}
int fts_bus_exit(struct fts_ts_data *ts_data)
{
if (ts_data->bus_type == BUS_TYPE_I2C)
return fts_i2c_exit(ts_data);
return fts_spi_exit(ts_data);
}

View File

@@ -0,0 +1,135 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2019, FocalTech Systems, Ltd., all rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*****************************************************************************
*
* File Name: focaltech_point_report_check.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-11-16
*
* Abstract: point report check function
*
* Version: v1.0
*
* Revision History:
*
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_POINT_REPORT_CHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define POINT_REPORT_CHECK_WAIT_TIME 200 /* unit:ms */
/*****************************************************************************
* functions body
*****************************************************************************/
/*****************************************************************************
* Name: fts_prc_func
* Brief: fts point report check work func, report whole up of points
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_prc_func(struct work_struct *work)
{
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, prc_work.work);
struct input_dev *input_dev = ts_data->input_dev;
#if FTS_MT_PROTOCOL_B_EN
u32 finger_count = 0;
u32 max_touches = fts_data->pdata->max_touch_number;
#endif
FTS_FUNC_ENTER();
mutex_lock(&ts_data->report_mutex);
#if FTS_MT_PROTOCOL_B_EN
for (finger_count = 0; finger_count < max_touches; finger_count++) {
input_mt_slot(input_dev, finger_count);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
}
#else
input_mt_sync(input_dev);
#endif
input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev);
mutex_unlock(&ts_data->report_mutex);
FTS_FUNC_EXIT();
}
/*****************************************************************************
* Name: fts_prc_queue_work
* Brief: fts point report check queue work, call it when interrupt comes
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_prc_queue_work(struct fts_ts_data *ts_data)
{
cancel_delayed_work_sync(&ts_data->prc_work);
queue_delayed_work(ts_data->ts_workqueue, &ts_data->prc_work,
msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
}
/*****************************************************************************
* Name: fts_point_report_check_init
* Brief:
* Input:
* Output:
* Return: < 0: Fail to create esd check queue
*****************************************************************************/
int fts_point_report_check_init(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->prc_work, fts_prc_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run point report check function");
return -EINVAL;
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_point_report_check_exit
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_point_report_check_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_POINT_REPORT_CHECK_EN */

View File

@@ -0,0 +1,126 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <glink_interface.h>
static struct glink_touch_dev *touch_pdev = NULL;
struct touch_channel_ops touch_ops;
void glink_touch_channel_init(void (*fn1)(bool), void (*fn2)(void *data, int len))
{
touch_ops.glink_channel_state = fn1;
touch_ops.rx_msg = fn2;
}
EXPORT_SYMBOL(glink_touch_channel_init);
int glink_touch_tx_msg(void *msg, size_t len)
{
int ret = 0;
if (touch_pdev == NULL || !touch_pdev->chnl_state) {
pr_err("pmsg_device is null, channel is closed\n");
return -ENETRESET;
}
touch_pdev->message = msg;
touch_pdev->message_length = len;
if (touch_pdev->message) {
ret = rpmsg_send(touch_pdev->channel,
touch_pdev->message, touch_pdev->message_length);
if (ret)
pr_err("rpmsg_send failed: %d\n", ret);
}
return ret;
}
EXPORT_SYMBOL(glink_touch_tx_msg);
static int glink_touch_probe(struct rpmsg_device *touch_rpdev)
{
int ret = 0;
void *msg = NULL;
if (!touch_rpdev) {
pr_err("rpmsg_device is null\n");
return -ENODEV;
}
pr_info("%s Start of glink_touch_probe\n", __func__);
touch_pdev = devm_kzalloc(&touch_rpdev->dev, sizeof(*touch_pdev), GFP_KERNEL);
if (!touch_pdev)
return -ENOMEM;
touch_pdev->channel = touch_rpdev->ept;
touch_pdev->dev = &touch_rpdev->dev;
if (touch_pdev->channel == NULL)
return -ENOMEM;
touch_pdev->chnl_state = true;
dev_set_drvdata(&touch_rpdev->dev, touch_pdev);
/* send a callback to slate-MSM touch driver*/
touch_ops.glink_channel_state(true);
if (touch_pdev->message == NULL)
ret = glink_touch_tx_msg(msg, 0);
pr_info("%s End of glink_touch_probe\n", __func__);
return 0;
}
static void glink_touch_remove(struct rpmsg_device *touch_rpdev)
{
touch_pdev->chnl_state = false;
touch_pdev->message = NULL;
dev_dbg(&touch_rpdev->dev, "rpmsg client driver is removed\n");
touch_ops.glink_channel_state(false);
dev_set_drvdata(&touch_rpdev->dev, NULL);
}
static int glink_touch_cb(struct rpmsg_device *touch_rpdev,
void *data, int len, void *priv, u32 src)
{
struct glink_touch_dev *touch_dev =
dev_get_drvdata(&touch_rpdev->dev);
if (!touch_dev)
return -ENODEV;
touch_ops.rx_msg(data, len);
return 0;
}
static const struct rpmsg_device_id glink_touch_driver_id_table[] = {
{ "touch-ctrl" },
{},
};
MODULE_DEVICE_TABLE(rpmsg, glink_touch_driver_id_table);
static const struct of_device_id glink_touch_driver_of_match[] = {
{ .compatible = "qcom,slatetouch-rpmsg" },
{},
};
static struct rpmsg_driver glink_touch_client = {
.id_table = glink_touch_driver_id_table,
.probe = glink_touch_probe,
.callback = glink_touch_cb,
.remove = glink_touch_remove,
.drv = {
.name = "glink_interface",
.of_match_table = glink_touch_driver_of_match,
},
};
module_rpmsg_driver(glink_touch_client);
MODULE_DESCRIPTION("Interface Driver for MSM TOUCH and RPMSG");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef GLINKINTERFACE_H
#define GLINKINTERFACE_H
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/rpmsg.h>
#define TOUCH_GLINK_INTENT_SIZE 0x0c
#define TOUCH_MSG_SIZE 0x08
#define TIMEOUT_MS 2000
struct glink_touch_priv {
void *handle;
struct mutex glink_mutex;
struct mutex touch_state_mutex;
void *lhndl;
char rx_buf[TOUCH_GLINK_INTENT_SIZE];
bool glink_touch_cmplt;
wait_queue_head_t link_state_wait;
bool msm_touch_rpmsg;
};
static void *glink_touch_drv;
enum touch_slate_cmds {
TOUCH_ENTER_PREPARE = 0x1100,
TOUCH_ENTER,
TOUCH_EXIT_PREPARE,
TOUCH_EXIT
};
struct glink_touch_dev {
struct rpmsg_endpoint *channel;
struct device *dev;
bool chnl_state;
void *message;
size_t message_length;
};
struct touch_channel_ops {
void (*glink_channel_state)(bool state);
void (*rx_msg)(void *data, int len);
};
void glink_touch_channel_init(void (*fn1)(bool), void (*fn2)(void *, int));
#if IS_ENABLED(CONFIG_MSM_SLATERSB_RPMSG)
int glink_touch_tx_msg(void *msg, size_t len);
#else
static inline int glink_touch_tx_msg(void *msg, size_t len)
{
return -EIO;
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,272 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/version.h>
#include "goodix_ts_core.h"
#define TS_DRIVER_NAME "gtx8_i2c"
#define I2C_MAX_TRANSFER_SIZE 256
#define GOODIX_BUS_RETRY_TIMES 2
#define GOODIX_REG_ADDR_SIZE 4
static struct platform_device *goodix_pdev;
struct goodix_bus_interface goodix_i2c_bus;
static int goodix_i2c_read(struct device *dev, unsigned int reg,
unsigned char *data, unsigned int len)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned int transfer_length = 0;
unsigned int pos = 0, address = reg;
unsigned char get_buf[128], addr_buf[GOODIX_REG_ADDR_SIZE];
int retry, r = 0;
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = !I2C_M_RD,
.buf = &addr_buf[0],
.len = GOODIX_REG_ADDR_SIZE,
}, {
.addr = client->addr,
.flags = I2C_M_RD,
}
};
if (likely(len < sizeof(get_buf))) {
/* code optimize, use stack memory */
msgs[1].buf = &get_buf[0];
} else {
msgs[1].buf = kzalloc(len, GFP_KERNEL);
if (msgs[1].buf == NULL)
return -ENOMEM;
}
while (pos != len) {
if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE))
transfer_length = I2C_MAX_TRANSFER_SIZE;
else
transfer_length = len - pos;
msgs[0].buf[0] = (address >> 24) & 0xFF;
msgs[0].buf[1] = (address >> 16) & 0xFF;
msgs[0].buf[2] = (address >> 8) & 0xFF;
msgs[0].buf[3] = address & 0xFF;
msgs[1].len = transfer_length;
for (retry = 0; retry < GOODIX_BUS_RETRY_TIMES; retry++) {
if (likely(i2c_transfer(client->adapter, msgs, 2) == 2)) {
memcpy(&data[pos], msgs[1].buf, transfer_length);
pos += transfer_length;
address += transfer_length;
break;
}
ts_info("I2c read retry[%d]:0x%x", retry + 1, reg);
usleep_range(2000, 2100);
}
if (unlikely(retry == GOODIX_BUS_RETRY_TIMES)) {
ts_err("I2c read failed,dev:%02x,reg:%04x,size:%u",
client->addr, reg, len);
r = -EAGAIN;
goto read_exit;
}
}
read_exit:
if (unlikely(len >= sizeof(get_buf)))
kfree(msgs[1].buf);
return r;
}
static int goodix_i2c_write(struct device *dev, unsigned int reg,
unsigned char *data, unsigned int len)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned int pos = 0, transfer_length = 0;
unsigned int address = reg;
unsigned char put_buf[128];
int retry, r = 0;
struct i2c_msg msg = {
.addr = client->addr,
.flags = !I2C_M_RD,
};
if (likely(len + GOODIX_REG_ADDR_SIZE < sizeof(put_buf))) {
/* code optimize,use stack memory*/
msg.buf = &put_buf[0];
} else {
msg.buf = kmalloc(len + GOODIX_REG_ADDR_SIZE, GFP_KERNEL);
if (msg.buf == NULL)
return -ENOMEM;
}
while (pos != len) {
if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE -
GOODIX_REG_ADDR_SIZE))
transfer_length = I2C_MAX_TRANSFER_SIZE -
GOODIX_REG_ADDR_SIZE;
else
transfer_length = len - pos;
msg.buf[0] = (address >> 24) & 0xFF;
msg.buf[1] = (address >> 16) & 0xFF;
msg.buf[2] = (address >> 8) & 0xFF;
msg.buf[3] = address & 0xFF;
msg.len = transfer_length + GOODIX_REG_ADDR_SIZE;
memcpy(&msg.buf[GOODIX_REG_ADDR_SIZE],
&data[pos], transfer_length);
for (retry = 0; retry < GOODIX_BUS_RETRY_TIMES; retry++) {
if (likely(i2c_transfer(client->adapter,
&msg, 1) == 1)) {
pos += transfer_length;
address += transfer_length;
break;
}
ts_debug("I2c write retry[%d]", retry + 1);
msleep(20);
}
if (unlikely(retry == GOODIX_BUS_RETRY_TIMES)) {
ts_err("I2c write failed,dev:%02x,reg:%04x,size:%u",
client->addr, reg, len);
r = -EAGAIN;
goto write_exit;
}
}
write_exit:
if (likely(len + GOODIX_REG_ADDR_SIZE >= sizeof(put_buf)))
kfree(msg.buf);
return r;
}
static void goodix_pdev_release(struct device *dev)
{
ts_info("goodix pdev released");
kfree(goodix_pdev);
}
static int goodix_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
int ret = 0;
ts_info("goodix i2c probe in");
#ifndef CONFIG_ARCH_QTI_VM
ret = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
if (!ret)
return -EIO;
#endif
/* get ic type */
ret = goodix_get_ic_type(client->dev.of_node);
if (ret < 0)
return ret;
goodix_i2c_bus.ic_type = ret;
goodix_i2c_bus.bus_type = GOODIX_BUS_TYPE_I2C;
goodix_i2c_bus.dev = &client->dev;
goodix_i2c_bus.read = goodix_i2c_read;
goodix_i2c_bus.write = goodix_i2c_write;
/* ts core device */
goodix_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
if (!goodix_pdev)
return -ENOMEM;
goodix_pdev->name = GOODIX_CORE_DRIVER_NAME;
goodix_pdev->id = 0;
goodix_pdev->num_resources = 0;
/*
* you can find this platform dev in
* /sys/devices/platform/goodix_ts.0
* goodix_pdev->dev.parent = &client->dev;
*/
goodix_pdev->dev.platform_data = &goodix_i2c_bus;
goodix_pdev->dev.release = goodix_pdev_release;
/* register platform device, then the goodix_ts_core
* module will probe the touch device.
*/
ret = platform_device_register(goodix_pdev);
if (ret) {
ts_err("failed register goodix platform device, %d", ret);
goto err_pdev;
}
ts_info("i2c probe out");
return ret;
err_pdev:
kfree(goodix_pdev);
goodix_pdev = NULL;
ts_info("i2c probe out, %d", ret);
return ret;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
static void goodix_i2c_remove(struct i2c_client *client)
{
platform_device_unregister(goodix_pdev);
}
#else
static int goodix_i2c_remove(struct i2c_client *client)
{
platform_device_unregister(goodix_pdev);
return 0;
}
#endif
#ifdef CONFIG_OF
static const struct of_device_id i2c_matchs[] = {
{.compatible = "goodix,gt9897",},
{.compatible = "goodix,gt9966",},
{.compatible = "goodix,gt9916",},
{},
};
MODULE_DEVICE_TABLE(of, i2c_matchs);
#endif
static const struct i2c_device_id i2c_id_table[] = {
{TS_DRIVER_NAME, 0},
{},
};
MODULE_DEVICE_TABLE(i2c, i2c_id_table);
static struct i2c_driver goodix_i2c_driver = {
.driver = {
.name = TS_DRIVER_NAME,
//.owner = THIS_MODULE,
.of_match_table = of_match_ptr(i2c_matchs),
},
.probe = goodix_i2c_probe,
.remove = goodix_i2c_remove,
.id_table = i2c_id_table,
};
int goodix_i2c_bus_init(void)
{
ts_info("Goodix i2c driver init");
return i2c_add_driver(&goodix_i2c_driver);
}
void goodix_i2c_bus_exit(void)
{
ts_info("Goodix i2c driver exit");
i2c_del_driver(&goodix_i2c_driver);
}

View File

@@ -0,0 +1,317 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/version.h>
#include "goodix_ts_core.h"
#define TS_DRIVER_NAME "gtx8_spi"
#define SPI_TRANS_PREFIX_LEN 1
#define REGISTER_WIDTH 4
#define SPI_READ_DUMMY_LEN 4
#define SPI_READ_PREFIX_LEN \
(SPI_TRANS_PREFIX_LEN + REGISTER_WIDTH + SPI_READ_DUMMY_LEN)
#define SPI_WRITE_PREFIX_LEN (SPI_TRANS_PREFIX_LEN + REGISTER_WIDTH)
#define SPI_WRITE_FLAG 0xF0
#define SPI_READ_FLAG 0xF1
static struct platform_device *goodix_pdev;
struct goodix_bus_interface goodix_spi_bus[MAX_SUPPORTED_TOUCH_PANELS];
/**
* goodix_spi_read_bra- read device register through spi bus
* @dev: pointer to device data
* @addr: register address
* @data: read buffer
* @len: bytes to read
* return: 0 - read ok, < 0 - spi transter error
*/
static int goodix_spi_read_bra(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
u8 *rx_buf = NULL;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
struct spi_message spi_msg;
int ret = 0;
rx_buf = kzalloc(SPI_READ_PREFIX_LEN + len, GFP_KERNEL);
tx_buf = kzalloc(SPI_READ_PREFIX_LEN + len, GFP_KERNEL);
if (!rx_buf || !tx_buf) {
ts_err("alloc tx/rx_buf failed, size:%d",
SPI_READ_PREFIX_LEN + len);
return -ENOMEM;
}
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
/*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/
tx_buf[0] = SPI_READ_FLAG;
tx_buf[1] = (addr >> 24) & 0xFF;
tx_buf[2] = (addr >> 16) & 0xFF;
tx_buf[3] = (addr >> 8) & 0xFF;
tx_buf[4] = addr & 0xFF;
tx_buf[5] = 0xFF;
tx_buf[6] = 0xFF;
tx_buf[7] = 0xFF;
tx_buf[8] = 0xFF;
xfers.tx_buf = tx_buf;
xfers.rx_buf = rx_buf;
xfers.len = SPI_READ_PREFIX_LEN + len;
xfers.cs_change = 0;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
if (ret < 0) {
ts_err("spi transfer error:%d", ret);
goto exit;
}
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN], len);
exit:
kfree(rx_buf);
kfree(tx_buf);
return ret;
}
static int goodix_spi_read(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
u8 *rx_buf = NULL;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
struct spi_message spi_msg;
int ret = 0;
rx_buf = kzalloc(SPI_READ_PREFIX_LEN - 1 + len, GFP_KERNEL);
tx_buf = kzalloc(SPI_READ_PREFIX_LEN - 1 + len, GFP_KERNEL);
if (!rx_buf || !tx_buf) {
ts_err("alloc tx/rx_buf failed, size:%d",
SPI_READ_PREFIX_LEN - 1 + len);
return -ENOMEM;
}
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
/*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/
tx_buf[0] = SPI_READ_FLAG;
tx_buf[1] = (addr >> 24) & 0xFF;
tx_buf[2] = (addr >> 16) & 0xFF;
tx_buf[3] = (addr >> 8) & 0xFF;
tx_buf[4] = addr & 0xFF;
tx_buf[5] = 0xFF;
tx_buf[6] = 0xFF;
tx_buf[7] = 0xFF;
xfers.tx_buf = tx_buf;
xfers.rx_buf = rx_buf;
xfers.len = SPI_READ_PREFIX_LEN - 1 + len;
xfers.cs_change = 0;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
if (ret < 0) {
ts_err("spi transfer error:%d", ret);
goto exit;
}
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN - 1], len);
exit:
kfree(rx_buf);
kfree(tx_buf);
return ret;
}
/**
* goodix_spi_write- write device register through spi bus
* @dev: pointer to device data
* @addr: register address
* @data: write buffer
* @len: bytes to write
* return: 0 - write ok; < 0 - spi transter error.
*/
static int goodix_spi_write(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
u8 *tx_buf = NULL;
struct spi_transfer xfers;
struct spi_message spi_msg;
int ret = 0;
tx_buf = kzalloc(SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL);
if (!tx_buf)
return -ENOMEM;
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
tx_buf[0] = SPI_WRITE_FLAG;
tx_buf[1] = (addr >> 24) & 0xFF;
tx_buf[2] = (addr >> 16) & 0xFF;
tx_buf[3] = (addr >> 8) & 0xFF;
tx_buf[4] = addr & 0xFF;
memcpy(&tx_buf[SPI_WRITE_PREFIX_LEN], data, len);
xfers.tx_buf = tx_buf;
xfers.len = SPI_WRITE_PREFIX_LEN + len;
xfers.cs_change = 0;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
if (ret < 0)
ts_err("spi transfer error:%d", ret);
kfree(tx_buf);
return ret;
}
static void goodix_pdev_release(struct device *dev)
{
ts_info("goodix pdev released");
kfree(goodix_pdev);
}
static int goodix_spi_probe(struct spi_device *spi)
{
int ret = 0, idx;
ts_info("goodix spi probe in");
/* init spi_device */
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
ret = spi_setup(spi);
if (ret) {
ts_err("failed set spi mode, %d", ret);
return ret;
}
/* get ic type */
ret = goodix_get_ic_type(spi->dev.of_node);
if (ret < 0)
return ret;
idx = goodix_get_touch_type(spi->dev.of_node);
if (idx < 0 || idx >= MAX_SUPPORTED_TOUCH_PANELS) {
ts_err("unsupported touch type idx:%d", idx);
return -ENODEV;
}
goodix_spi_bus[idx].ic_type = ret;
goodix_spi_bus[idx].bus_type = GOODIX_BUS_TYPE_SPI;
goodix_spi_bus[idx].dev = &spi->dev;
if (goodix_spi_bus[idx].ic_type == IC_TYPE_BERLIN_A)
goodix_spi_bus[idx].read = goodix_spi_read_bra;
else
goodix_spi_bus[idx].read = goodix_spi_read;
goodix_spi_bus[idx].write = goodix_spi_write;
/* ts core device */
goodix_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
if (!goodix_pdev)
return -ENOMEM;
if (idx)
goodix_pdev->name = GOODIX_CORE_DEVICE_2_NAME;
else
goodix_pdev->name = GOODIX_CORE_DEVICE_NAME;
goodix_pdev->id = 0;
goodix_pdev->num_resources = 0;
/*
* you can find this platform dev in
* /sys/devices/platfrom/goodix_ts.0
* goodix_pdev->dev.parent = &client->dev;
*/
goodix_pdev->dev.platform_data = &goodix_spi_bus[idx];
goodix_pdev->dev.release = goodix_pdev_release;
/*
* register platform device, then the goodix_ts_core
* module will probe the touch deivce.
*/
ret = platform_device_register(goodix_pdev);
if (ret) {
ts_err("failed register goodix platform device, %d", ret);
goto err_pdev;
}
ts_info("spi probe out");
return 0;
err_pdev:
kfree(goodix_pdev);
goodix_pdev = NULL;
ts_info("spi probe out, %d", ret);
return ret;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0))
static void goodix_spi_remove(struct spi_device *spi)
{
platform_device_unregister(goodix_pdev);
}
#else
static int goodix_spi_remove(struct spi_device *spi)
{
platform_device_unregister(goodix_pdev);
return 0;
}
#endif
#ifdef CONFIG_OF
static const struct of_device_id spi_matchs[] = {
{.compatible = "goodix,gt9897S",},
{.compatible = "goodix,gt9897T",},
{.compatible = "goodix,gt9966S",},
{.compatible = "goodix,gt9916S",},
{.compatible = "goodix,gt9916S2",},
{},
};
#endif
static const struct spi_device_id spi_id_table[] = {
{TS_DRIVER_NAME, 0},
{},
};
static struct spi_driver goodix_spi_driver = {
.driver = {
.name = TS_DRIVER_NAME,
//.owner = THIS_MODULE,
.of_match_table = spi_matchs,
},
.id_table = spi_id_table,
.probe = goodix_spi_probe,
.remove = goodix_spi_remove,
};
int goodix_spi_bus_init(void)
{
ts_info("Goodix spi driver init");
return spi_register_driver(&goodix_spi_driver);
}
void goodix_spi_bus_exit(void)
{
ts_info("Goodix spi driver exit");
spi_unregister_driver(&goodix_spi_driver);
}

View File

@@ -0,0 +1,343 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include "goodix_ts_core.h"
#define TS_BIN_VERSION_START_INDEX 5
#define TS_BIN_VERSION_LEN 4
#define TS_CFG_BIN_HEAD_RESERVED_LEN 6
#define TS_CFG_OFFSET_LEN 2
#define TS_IC_TYPE_NAME_MAX_LEN 15
#define TS_CFG_BIN_HEAD_LEN \
(sizeof(struct goodix_cfg_bin_head) + \
TS_CFG_BIN_HEAD_RESERVED_LEN)
#define TS_PKG_CONST_INFO_LEN \
(sizeof(struct goodix_cfg_pkg_const_info))
#define TS_PKG_REG_INFO_LEN \
(sizeof(struct goodix_cfg_pkg_reg_info))
#define TS_PKG_HEAD_LEN \
(TS_PKG_CONST_INFO_LEN + TS_PKG_REG_INFO_LEN)
/*cfg block definitin*/
#define TS_CFG_BLOCK_PID_LEN 8
#define TS_CFG_BLOCK_VID_LEN 8
#define TS_CFG_BLOCK_FW_MASK_LEN 9
#define TS_CFG_BLOCK_FW_PATCH_LEN 4
#define TS_CFG_BLOCK_RESERVED_LEN 9
#define TS_NORMAL_CFG 0x01
#define TS_HIGH_SENSE_CFG 0x03
#define TS_RQST_FW_RETRY_TIMES 2
#pragma pack(1)
struct goodix_cfg_pkg_reg {
u16 addr;
u8 reserved1;
u8 reserved2;
};
struct goodix_cfg_pkg_const_info {
u32 pkg_len;
u8 ic_type[TS_IC_TYPE_NAME_MAX_LEN];
u8 cfg_type;
u8 sensor_id;
u8 hw_pid[TS_CFG_BLOCK_PID_LEN];
u8 hw_vid[TS_CFG_BLOCK_VID_LEN];
u8 fw_mask[TS_CFG_BLOCK_FW_MASK_LEN];
u8 fw_patch[TS_CFG_BLOCK_FW_PATCH_LEN];
u16 x_res_offset;
u16 y_res_offset;
u16 trigger_offset;
};
struct goodix_cfg_pkg_reg_info {
struct goodix_cfg_pkg_reg cfg_send_flag;
struct goodix_cfg_pkg_reg version_base;
struct goodix_cfg_pkg_reg pid;
struct goodix_cfg_pkg_reg vid;
struct goodix_cfg_pkg_reg sensor_id;
struct goodix_cfg_pkg_reg fw_mask;
struct goodix_cfg_pkg_reg fw_status;
struct goodix_cfg_pkg_reg cfg_addr;
struct goodix_cfg_pkg_reg esd;
struct goodix_cfg_pkg_reg command;
struct goodix_cfg_pkg_reg coor;
struct goodix_cfg_pkg_reg gesture;
struct goodix_cfg_pkg_reg fw_request;
struct goodix_cfg_pkg_reg proximity;
u8 reserved[TS_CFG_BLOCK_RESERVED_LEN];
};
struct goodix_cfg_bin_head {
u32 bin_len;
u8 checksum;
u8 bin_version[TS_BIN_VERSION_LEN];
u8 pkg_num;
};
#pragma pack()
struct goodix_cfg_package {
struct goodix_cfg_pkg_const_info cnst_info;
struct goodix_cfg_pkg_reg_info reg_info;
const u8 *cfg;
u32 pkg_len;
};
struct goodix_cfg_bin {
unsigned char *bin_data;
unsigned int bin_data_len;
struct goodix_cfg_bin_head head;
struct goodix_cfg_package *cfg_pkgs;
};
static int goodix_read_cfg_bin(struct device *dev, const char *cfg_name,
struct goodix_cfg_bin *cfg_bin)
{
const struct firmware *firmware = NULL;
int ret;
int retry = GOODIX_RETRY_3;
ts_info("cfg_bin_name:%s", cfg_name);
while (retry--) {
ret = request_firmware(&firmware, cfg_name, dev);
if (!ret)
break;
ts_info("get cfg bin retry:[%d]", GOODIX_RETRY_3 - retry);
msleep(200);
}
if (retry < 0) {
ts_err("failed get cfg bin[%s] error:%d", cfg_name, ret);
return ret;
}
if (firmware->size <= 0) {
ts_err("request_firmware, cfg_bin length ERROR,len:%zu",
firmware->size);
ret = -EINVAL;
goto exit;
}
cfg_bin->bin_data_len = firmware->size;
/* allocate memory for cfg_bin->bin_data */
cfg_bin->bin_data = kzalloc(cfg_bin->bin_data_len, GFP_KERNEL);
if (!cfg_bin->bin_data) {
ret = -ENOMEM;
goto exit;
}
memcpy(cfg_bin->bin_data, firmware->data, cfg_bin->bin_data_len);
exit:
release_firmware(firmware);
return ret;
}
static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin)
{
u16 offset1, offset2;
u8 checksum;
int i;
/* copy cfg_bin head info */
if (cfg_bin->bin_data_len < sizeof(struct goodix_cfg_bin_head)) {
ts_err("Invalid cfg_bin size:%d", cfg_bin->bin_data_len);
return -EINVAL;
}
memcpy(&cfg_bin->head, cfg_bin->bin_data,
sizeof(struct goodix_cfg_bin_head));
cfg_bin->head.bin_len = le32_to_cpu(cfg_bin->head.bin_len);
/*check length*/
if (cfg_bin->bin_data_len != cfg_bin->head.bin_len) {
ts_err("cfg_bin len check failed,%d != %d",
cfg_bin->head.bin_len, cfg_bin->bin_data_len);
return -EINVAL;
}
/*check cfg_bin valid*/
checksum = 0;
for (i = TS_BIN_VERSION_START_INDEX; i < cfg_bin->bin_data_len; i++)
checksum += cfg_bin->bin_data[i];
if (checksum != cfg_bin->head.checksum) {
ts_err("cfg_bin checksum check filed 0x%02x != 0x%02x",
cfg_bin->head.checksum, checksum);
return -EINVAL;
}
/*allocate memory for cfg packages*/
cfg_bin->cfg_pkgs = kzalloc(sizeof(struct goodix_cfg_package) *
cfg_bin->head.pkg_num, GFP_KERNEL);
if (!cfg_bin->cfg_pkgs)
return -ENOMEM;
/*get cfg_pkg's info*/
for (i = 0; i < cfg_bin->head.pkg_num; i++) {
/*get cfg pkg length*/
if (i == cfg_bin->head.pkg_num - 1) {
offset1 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN] +
(cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN + 1] << 8);
cfg_bin->cfg_pkgs[i].pkg_len =
cfg_bin->bin_data_len - offset1;
} else {
offset1 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN] +
(cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN + 1] << 8);
offset2 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN + 2] +
(cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN +
i * TS_CFG_OFFSET_LEN + 3] << 8);
if (offset2 <= offset1) {
ts_err("offset error,pkg:%d, offset1:%d, offset2:%d",
i, offset1, offset2);
goto exit;
}
cfg_bin->cfg_pkgs[i].pkg_len = offset2 - offset1;
}
/*get cfg pkg head*/
memcpy(&cfg_bin->cfg_pkgs[i].cnst_info,
&cfg_bin->bin_data[offset1], TS_PKG_CONST_INFO_LEN);
memcpy(&cfg_bin->cfg_pkgs[i].reg_info,
&cfg_bin->bin_data[offset1 + TS_PKG_CONST_INFO_LEN],
TS_PKG_REG_INFO_LEN);
/*get configuration data*/
cfg_bin->cfg_pkgs[i].cfg =
&cfg_bin->bin_data[offset1 + TS_PKG_HEAD_LEN];
}
/*debug, print pkg information*/
ts_info("Driver bin info: ver %s, len %d, pkgs %d",
cfg_bin->head.bin_version,
cfg_bin->head.bin_len,
cfg_bin->head.pkg_num);
return 0;
exit:
kfree(cfg_bin->cfg_pkgs);
return -EINVAL;
}
static int goodix_get_reg_and_cfg(struct goodix_ts_core *cd, u8 sensor_id,
struct goodix_cfg_bin *cfg_bin)
{
int i;
u8 cfg_type;
u32 cfg_len;
struct goodix_cfg_package *cfg_pkg;
if (!cfg_bin->head.pkg_num || !cfg_bin->cfg_pkgs) {
ts_err("there is none cfg package, pkg_num:%d",
cfg_bin->head.pkg_num);
return -EINVAL;
}
/* find cfg packages with same sensor_id */
for (i = 0; i < cfg_bin->head.pkg_num; i++) {
cfg_pkg = &cfg_bin->cfg_pkgs[i];
if (sensor_id != cfg_pkg->cnst_info.sensor_id) {
ts_info("pkg:%d, sensor id contrast FAILED, bin %d != %d",
i, cfg_pkg->cnst_info.sensor_id, sensor_id);
continue;
}
cfg_type = cfg_pkg->cnst_info.cfg_type;
if (cfg_type >= GOODIX_MAX_CONFIG_GROUP) {
ts_err("usupported config type %d",
cfg_pkg->cnst_info.cfg_type);
goto err_out;
}
cfg_len = cfg_pkg->pkg_len - TS_PKG_CONST_INFO_LEN -
TS_PKG_REG_INFO_LEN;
if (cfg_len > GOODIX_CFG_MAX_SIZE) {
ts_err("config len exceed limit %d > %d",
cfg_len, GOODIX_CFG_MAX_SIZE);
goto err_out;
}
if (cd->ic_configs[cfg_type]) {
ts_err("found same type config twice for sensor id %d, skiped",
sensor_id);
continue;
}
cd->ic_configs[cfg_type] =
kzalloc(sizeof(struct goodix_ic_config),
GFP_KERNEL);
if (!cd->ic_configs[cfg_type])
goto err_out;
cd->ic_configs[cfg_type]->len = cfg_len;
memcpy(cd->ic_configs[cfg_type]->data, cfg_pkg->cfg, cfg_len);
ts_info("get config type %d, len %d, for sensor id %d",
cfg_type, cfg_len, sensor_id);
}
return 0;
err_out:
/* parse config enter error, release memory alloced */
for (i = 0; i < GOODIX_MAX_CONFIG_GROUP; i++) {
kfree(cd->ic_configs[i]);
cd->ic_configs[i] = NULL;
}
return -EINVAL;
}
static int goodix_get_config_data(struct goodix_ts_core *cd, u8 sensor_id)
{
struct goodix_cfg_bin cfg_bin = {0};
char *cfg_name = cd->board_data.cfg_bin_name;
int ret;
/*get cfg_bin from file system*/
ret = goodix_read_cfg_bin(&cd->pdev->dev, cfg_name, &cfg_bin);
if (ret) {
ts_err("failed get valid config bin data");
return ret;
}
/*parse cfg bin*/
ret = goodix_parse_cfg_bin(&cfg_bin);
if (ret) {
ts_err("failed parse cfg bin");
goto err_out;
}
/*get register address and configuration from cfg bin*/
ret = goodix_get_reg_and_cfg(cd, sensor_id, &cfg_bin);
if (!ret)
ts_info("success get reg and cfg info from cfg bin");
else
ts_err("failed get cfg and reg info, update fw then retry");
kfree(cfg_bin.cfg_pkgs);
err_out:
kfree(cfg_bin.bin_data);
return ret;
}
int goodix_get_config_proc(struct goodix_ts_core *cd)
{
return goodix_get_config_data(cd, cd->fw_version.sensor_id);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,707 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#ifndef _GOODIX_TS_CORE_H_
#define _GOODIX_TS_CORE_H_
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/vmalloc.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/of_irq.h>
#if IS_ENABLED(CONFIG_OF)
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#endif
#if IS_ENABLED(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include "../qts/qts_core_common.h"
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
#define GOODIX_CORE_DEVICE_NAME "goodix_ts"
#define GOODIX_CORE_DEVICE_2_NAME "goodix_ts2"
#define GOODIX_DRIVER_VERSION "v1.2.4"
#define GOODIX_MAX_TOUCH 10
#define GOODIX_PEN_MAX_PRESSURE 4096
#define GOODIX_MAX_PEN_KEY 2
#define GOODIX_PEN_MAX_TILT 90
#define GOODIX_CFG_MAX_SIZE 4096
#define GOODIX_FW_MAX_SIEZE (300 * 1024)
#define GOODIX_MAX_STR_LABLE_LEN 32
#define GOODIX_MAX_FRAMEDATA_LEN 1700
#define GOODIX_GESTURE_DATA_LEN 16
#define GOODIX_NORMAL_RESET_DELAY_MS 100
#define GOODIX_HOLD_CPU_RESET_DELAY_MS 5
#define GOODIX_RETRY_3 3
#define GOODIX_RETRY_5 5
#define GOODIX_RETRY_10 10
#define TS_DEFAULT_FIRMWARE "goodix_firmware.bin"
#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin"
enum GOODIX_GESTURE_TYP {
GESTURE_SINGLE_TAP = (1 << 0),
GESTURE_DOUBLE_TAP = (1 << 1),
GESTURE_FOD_PRESS = (1 << 2)
};
enum CORD_PROB_STA {
CORE_MODULE_UNPROBED = 0,
CORE_MODULE_PROB_SUCCESS = 1,
CORE_MODULE_PROB_FAILED = -1,
CORE_MODULE_REMOVED = -2,
};
enum GOODIX_ERR_CODE {
GOODIX_EBUS = (1<<0),
GOODIX_ECHECKSUM = (1<<1),
GOODIX_EVERSION = (1<<2),
GOODIX_ETIMEOUT = (1<<3),
GOODIX_EMEMCMP = (1<<4),
GOODIX_EOTHER = (1<<7)
};
enum IC_TYPE_ID {
IC_TYPE_NONE,
IC_TYPE_NORMANDY,
IC_TYPE_NANJING,
IC_TYPE_YELLOWSTONE,
IC_TYPE_BERLIN_A,
IC_TYPE_BERLIN_B,
IC_TYPE_BERLIN_D
};
enum GOODIX_IC_CONFIG_TYPE {
CONFIG_TYPE_TEST = 0,
CONFIG_TYPE_NORMAL = 1,
CONFIG_TYPE_HIGHSENSE = 2,
CONFIG_TYPE_CHARGER = 3,
CONFIG_TYPE_CHARGER_HS = 4,
CONFIG_TYPE_HOLSTER = 5,
CONFIG_TYPE_HOSTER_CH = 6,
CONFIG_TYPE_OTHER = 7,
/* keep this at the last */
GOODIX_MAX_CONFIG_GROUP = 8,
};
enum CHECKSUM_MODE {
CHECKSUM_MODE_U8_LE,
CHECKSUM_MODE_U16_LE,
};
enum DUAL_TOUCH_TYPE {
PRIMARY_TOUCH_IDX,
SECONDARY_TOUCH_IDX,
MAX_SUPPORTED_TOUCH_PANELS,
};
#define MAX_SCAN_FREQ_NUM 8
#define MAX_SCAN_RATE_NUM 8
#define MAX_FREQ_NUM_STYLUS 8
#define MAX_STYLUS_SCAN_FREQ_NUM 6
#pragma pack(1)
struct frame_head {
uint8_t sync;
uint16_t frame_index;
uint16_t cur_frame_len;
uint16_t next_frame_len;
uint32_t data_en; /* 0- 7 for pack_en; 8 - 31 for type en */
uint8_t touch_pack_index;
uint8_t stylus_pack_index;
uint8_t res;
uint16_t checksum;
};
struct goodix_fw_version {
u8 rom_pid[6]; /* rom PID */
u8 rom_vid[3]; /* Mask VID */
u8 rom_vid_reserved;
u8 patch_pid[8]; /* Patch PID */
u8 patch_vid[4]; /* Patch VID */
u8 patch_vid_reserved;
u8 sensor_id;
u8 reserved[2];
u16 checksum;
};
struct goodix_ic_info_version {
u8 info_customer_id;
u8 info_version_id;
u8 ic_die_id;
u8 ic_version_id;
u32 config_id;
u8 config_version;
u8 frame_data_customer_id;
u8 frame_data_version_id;
u8 touch_data_customer_id;
u8 touch_data_version_id;
u8 reserved[3];
};
struct goodix_ic_info_feature { /* feature info*/
u16 freqhop_feature;
u16 calibration_feature;
u16 gesture_feature;
u16 side_touch_feature;
u16 stylus_feature;
};
struct goodix_ic_info_param { /* param */
u8 drv_num;
u8 sen_num;
u8 button_num;
u8 force_num;
u8 active_scan_rate_num;
u16 active_scan_rate[MAX_SCAN_RATE_NUM];
u8 mutual_freq_num;
u16 mutual_freq[MAX_SCAN_FREQ_NUM];
u8 self_tx_freq_num;
u16 self_tx_freq[MAX_SCAN_FREQ_NUM];
u8 self_rx_freq_num;
u16 self_rx_freq[MAX_SCAN_FREQ_NUM];
u8 stylus_freq_num;
u16 stylus_freq[MAX_FREQ_NUM_STYLUS];
};
struct goodix_ic_info_misc { /* other data */
u32 cmd_addr;
u16 cmd_max_len;
u32 cmd_reply_addr;
u16 cmd_reply_len;
u32 fw_state_addr;
u16 fw_state_len;
u32 fw_buffer_addr;
u16 fw_buffer_max_len;
u32 frame_data_addr;
u16 frame_data_head_len;
u16 fw_attr_len;
u16 fw_log_len;
u8 pack_max_num;
u8 pack_compress_version;
u16 stylus_struct_len;
u16 mutual_struct_len;
u16 self_struct_len;
u16 noise_struct_len;
u32 touch_data_addr;
u16 touch_data_head_len;
u16 point_struct_len;
u16 reserved1;
u16 reserved2;
u32 mutual_rawdata_addr;
u32 mutual_diffdata_addr;
u32 mutual_refdata_addr;
u32 self_rawdata_addr;
u32 self_diffdata_addr;
u32 self_refdata_addr;
u32 iq_rawdata_addr;
u32 iq_refdata_addr;
u32 im_rawdata_addr;
u16 im_readata_len;
u32 noise_rawdata_addr;
u16 noise_rawdata_len;
u32 stylus_rawdata_addr;
u16 stylus_rawdata_len;
u32 noise_data_addr;
u32 esd_addr;
};
struct goodix_ic_info {
u16 length;
struct goodix_ic_info_version version;
struct goodix_ic_info_feature feature;
struct goodix_ic_info_param parm;
struct goodix_ic_info_misc misc;
};
#pragma pack()
/*
* struct ts_rawdata_info
*
*/
#define TS_RAWDATA_BUFF_MAX 7000
#define TS_RAWDATA_RESULT_MAX 100
struct ts_rawdata_info {
int used_size; //fill in rawdata size
s16 buff[TS_RAWDATA_BUFF_MAX];
char result[TS_RAWDATA_RESULT_MAX];
};
/*
* struct goodix_module - external modules container
* @head: external modules list
* @initilized: whether this struct is initilized
* @mutex: mutex lock
* @wq: workqueue to do register work
* @core_data: core_data pointer
*/
struct goodix_module {
struct list_head head;
bool initilized;
struct mutex mutex;
struct workqueue_struct *wq;
struct goodix_ts_core *core_data;
};
/*
* struct goodix_ts_board_data - board data
* @avdd_name: name of analoy regulator
* @iovdd_name: name of analoy regulator
* @reset_gpio: reset gpio number
* @irq_gpio: interrupt gpio number
* @irq_flag: irq trigger type
* @swap_axis: whether swaw x y axis
* @panel_max_x/y/w/p: resolution and size
* @invert_xy: invert x and y for inversely mounted IC
* @pannel_key_map: key map
* @fw_name: name of the firmware image
*/
struct goodix_ts_board_data {
char avdd_name[GOODIX_MAX_STR_LABLE_LEN];
char iovdd_name[GOODIX_MAX_STR_LABLE_LEN];
int reset_gpio;
int irq_gpio;
int avdd_gpio;
int iovdd_gpio;
unsigned int irq_flags;
unsigned int swap_axis;
unsigned int panel_max_x;
unsigned int panel_max_y;
unsigned int panel_max_w; /*major and minor*/
unsigned int panel_max_p; /*pressure*/
bool invert_xy;
bool pen_enable;
char fw_name[GOODIX_MAX_STR_LABLE_LEN];
char cfg_bin_name[GOODIX_MAX_STR_LABLE_LEN];
};
enum goodix_fw_update_mode {
UPDATE_MODE_DEFAULT = 0,
UPDATE_MODE_FORCE = (1 << 0), /* force update mode */
UPDATE_MODE_BLOCK = (1 << 1), /* update in block mode */
UPDATE_MODE_FLASH_CFG = (1 << 2), /* reflash config */
UPDATE_MODE_SRC_SYSFS = (1 << 4), /* firmware file from sysfs */
UPDATE_MODE_SRC_HEAD = (1 << 5), /* firmware file from head file */
UPDATE_MODE_SRC_REQUEST = (1 << 6), /* request firmware */
UPDATE_MODE_SRC_ARGS = (1 << 7), /* firmware data from function args */
};
#define MAX_CMD_DATA_LEN 10
#define MAX_CMD_BUF_LEN 16
#pragma pack(1)
struct goodix_ts_cmd {
union {
struct {
u8 state;
u8 ack;
u8 len;
u8 cmd;
u8 data[MAX_CMD_DATA_LEN];
};
u8 buf[MAX_CMD_BUF_LEN];
};
};
#pragma pack()
/* interrupt event type */
enum ts_event_type {
EVENT_INVALID = 0,
EVENT_TOUCH = (1 << 0), /* finger touch event */
EVENT_PEN = (1 << 1), /* pen event */
EVENT_REQUEST = (1 << 2),
EVENT_GESTURE = (1 << 3),
};
enum ts_request_type {
REQUEST_TYPE_CONFIG = 1,
REQUEST_TYPE_RESET = 3,
};
/* notifier event */
enum ts_notify_event {
NOTIFY_FWUPDATE_START,
NOTIFY_FWUPDATE_FAILED,
NOTIFY_FWUPDATE_SUCCESS,
NOTIFY_SUSPEND,
NOTIFY_RESUME,
NOTIFY_ESD_OFF,
NOTIFY_ESD_ON,
NOTIFY_CFG_BIN_FAILED,
NOTIFY_CFG_BIN_SUCCESS,
};
enum touch_point_status {
TS_NONE,
TS_RELEASE,
TS_TOUCH,
};
/* coordinate package */
struct goodix_ts_coords {
int status; /* NONE, RELEASE, TOUCH */
unsigned int x, y, w, p;
};
struct goodix_pen_coords {
int status; /* NONE, RELEASE, TOUCH */
int tool_type; /* BTN_TOOL_RUBBER BTN_TOOL_PEN */
unsigned int x, y, p;
signed char tilt_x;
signed char tilt_y;
};
/* touch event data */
struct goodix_touch_data {
int touch_num;
struct goodix_ts_coords coords[GOODIX_MAX_TOUCH];
};
struct goodix_ts_key {
int status;
int code;
};
struct goodix_pen_data {
struct goodix_pen_coords coords;
struct goodix_ts_key keys[GOODIX_MAX_PEN_KEY];
};
/*
* struct goodix_ts_event - touch event struct
* @event_type: touch event type, touch data or
* request event
* @event_data: event data
*/
struct goodix_ts_event {
enum ts_event_type event_type;
u8 request_code; /* represent the request type */
u8 gesture_type;
u8 gesture_data[GOODIX_GESTURE_DATA_LEN];
struct goodix_touch_data touch_data;
struct goodix_pen_data pen_data;
};
enum goodix_ic_bus_type {
GOODIX_BUS_TYPE_I2C,
GOODIX_BUS_TYPE_SPI,
GOODIX_BUS_TYPE_I3C,
};
struct goodix_bus_interface {
int bus_type;
int ic_type;
struct device *dev;
int (*read)(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len);
int (*write)(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len);
};
struct goodix_ts_hw_ops {
int (*power_on)(struct goodix_ts_core *cd, bool on);
int (*resume)(struct goodix_ts_core *cd);
int (*suspend)(struct goodix_ts_core *cd);
int (*gesture)(struct goodix_ts_core *cd, int gesture_type);
int (*reset)(struct goodix_ts_core *cd, int delay_ms);
int (*irq_enable)(struct goodix_ts_core *cd, bool enable);
int (*read)(struct goodix_ts_core *cd, unsigned int addr,
unsigned char *data, unsigned int len);
int (*write)(struct goodix_ts_core *cd, unsigned int addr,
unsigned char *data, unsigned int len);
int (*send_cmd)(struct goodix_ts_core *cd,
struct goodix_ts_cmd *cmd);
int (*send_config)(struct goodix_ts_core *cd,
u8 *config, int len);
int (*read_config)(struct goodix_ts_core *cd,
u8 *config_data, int size);
int (*read_version)(struct goodix_ts_core *cd,
struct goodix_fw_version *version);
int (*get_ic_info)(struct goodix_ts_core *cd,
struct goodix_ic_info *ic_info);
int (*esd_check)(struct goodix_ts_core *cd);
int (*event_handler)(struct goodix_ts_core *cd,
struct goodix_ts_event *ts_event);
int (*after_event_handler)(struct goodix_ts_core *cd);
int (*get_capacitance_data)(struct goodix_ts_core *cd,
struct ts_rawdata_info *info);
};
/*
* struct goodix_ts_esd - esd protector structure
* @esd_work: esd delayed work
* @esd_on: 1 - turn on esd protection, 0 - turn
* off esd protection
*/
struct goodix_ts_esd {
bool irq_status;
atomic_t esd_on;
struct delayed_work esd_work;
struct notifier_block esd_notifier;
struct goodix_ts_core *ts_core;
};
enum goodix_core_init_stage {
CORE_UNINIT,
CORE_INIT_FAIL,
CORE_INIT_STAGE1,
CORE_INIT_STAGE2
};
struct goodix_ic_config {
int len;
u8 data[GOODIX_CFG_MAX_SIZE];
};
struct goodix_ts_core {
int init_stage;
struct platform_device *pdev;
struct goodix_fw_version fw_version;
struct goodix_ic_info ic_info;
struct goodix_bus_interface *bus;
struct goodix_ts_board_data board_data;
struct goodix_ts_hw_ops *hw_ops;
struct input_dev *input_dev;
struct input_dev *pen_dev;
/* TODO counld we remove this from core data? */
struct goodix_ts_event ts_event;
/* every pointer of this array represent a kind of config */
struct goodix_ic_config *ic_configs[GOODIX_MAX_CONFIG_GROUP];
struct regulator *avdd;
struct regulator *iovdd;
unsigned char gesture_type;
int power_on;
int irq;
size_t irq_trig_cnt;
atomic_t irq_enabled;
atomic_t suspended;
/* when this flag is true, driver should not clean the sync flag */
bool tools_ctrl_sync;
struct notifier_block ts_notifier;
struct goodix_ts_esd ts_esd;
bool esd_initialized;
bool ready;
#if defined(CONFIG_DRM)
struct notifier_block fb_notifier;
void *notifier_cookie;
const char *touch_environment;
#elif defined(CONFIG_FB)
struct notifier_block fb_notifier;
#endif
#ifdef CONFIG_GOODIX_TRUSTED_TOUCH
struct trusted_touch_vm_info *vm_info;
struct mutex fts_clk_io_ctrl_mutex;
struct completion trusted_touch_powerdown;
struct clk *core_clk;
struct clk *iface_clk;
atomic_t trusted_touch_initialized;
atomic_t trusted_touch_enabled;
atomic_t trusted_touch_transition;
atomic_t trusted_touch_event;
atomic_t trusted_touch_abort_status;
atomic_t delayed_vm_probe_pending;
atomic_t trusted_touch_mode;
#endif
bool qts_en;
struct mutex tui_transition_lock;
};
/* external module structures */
enum goodix_ext_priority {
EXTMOD_PRIO_RESERVED = 0,
EXTMOD_PRIO_FWUPDATE,
EXTMOD_PRIO_GESTURE,
EXTMOD_PRIO_HOTKNOT,
EXTMOD_PRIO_DBGTOOL,
EXTMOD_PRIO_DEFAULT,
};
#define EVT_HANDLED 0
#define EVT_CONTINUE 0
#define EVT_CANCEL 1
#define EVT_CANCEL_IRQEVT 1
#define EVT_CANCEL_SUSPEND 1
#define EVT_CANCEL_RESUME 1
#define EVT_CANCEL_RESET 1
struct goodix_ext_module;
/* external module's operations callback */
struct goodix_ext_module_funcs {
int (*init)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*exit)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*before_reset)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*after_reset)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*before_suspend)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*after_suspend)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*before_resume)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*after_resume)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
int (*irq_event)(struct goodix_ts_core *core_data,
struct goodix_ext_module *module);
};
/*
* struct goodix_ext_module - external module struct
* @list: list used to link into modules manager
* @name: name of external module
* @priority: module priority vlaue, zero is invalid
* @funcs: operations callback
* @priv_data: private data region
* @kobj: kobject
* @work: used to queue one work to do registration
*/
struct goodix_ext_module {
struct list_head list;
char *name;
enum goodix_ext_priority priority;
const struct goodix_ext_module_funcs *funcs;
void *priv_data;
struct kobject kobj;
struct work_struct work;
};
/*
* struct goodix_ext_attribute - exteranl attribute struct
* @attr: attribute
* @show: show interface of external attribute
* @store: store interface of external attribute
*/
struct goodix_ext_attribute {
struct attribute attr;
ssize_t (*show)(struct goodix_ext_module *module, char *buf);
ssize_t (*store)(struct goodix_ext_module *module,
const char *buf, size_t len);
};
/* external attrs helper macro */
#define __EXTMOD_ATTR(_name, _mode, _show, _store) { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
.show = _show, \
.store = _store, \
}
/* external attrs helper macro, used to define external attrs */
#define DEFINE_EXTMOD_ATTR(_name, _mode, _show, _store) \
static struct goodix_ext_attribute ext_attr_##_name = \
__EXTMOD_ATTR(_name, _mode, _show, _store)
/* log macro */
extern bool debug_log_flag;
#define ts_info(fmt, arg...) \
pr_info("[GTP-INF][%s:%d] "fmt"\n", __func__, __LINE__, ##arg)
#define ts_err(fmt, arg...) \
pr_err("[GTP-ERR][%s:%d] "fmt"\n", __func__, __LINE__, ##arg)
#define ts_debug(fmt, arg...) \
{if (debug_log_flag) \
pr_info("[GTP-DBG][%s:%d] "fmt"\n", __func__, __LINE__, ##arg);}
/*
* get board data pointer
*/
static inline struct goodix_ts_board_data *board_data(
struct goodix_ts_core *core)
{
if (!core)
return NULL;
return &(core->board_data);
}
/**
* goodix_register_ext_module - interface for external module
* to register into touch core modules structure
*
* @module: pointer to external module to be register
* return: 0 ok, <0 failed
*/
int goodix_register_ext_module(struct goodix_ext_module *module);
/* register module no wait */
int goodix_register_ext_module_no_wait(struct goodix_ext_module *module);
/**
* goodix_unregister_ext_module - interface for external module
* to unregister external modules
*
* @module: pointer to external module
* return: 0 ok, <0 failed
*/
int goodix_unregister_ext_module(struct goodix_ext_module *module);
/* remove all registered ext module
* return 0 on success, otherwise return < 0
*/
int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v);
struct kobj_type *goodix_get_default_ktype(void);
struct kobject *goodix_get_default_kobj(void);
struct goodix_ts_hw_ops *goodix_get_hw_ops(void);
int goodix_get_config_proc(struct goodix_ts_core *cd);
int goodix_spi_bus_init(void);
void goodix_spi_bus_exit(void);
int goodix_i2c_bus_init(void);
void goodix_i2c_bus_exit(void);
u32 goodix_append_checksum(u8 *data, int len, int mode);
int checksum_cmp(const u8 *data, int size, int mode);
int is_risk_data(const u8 *data, int size);
u32 goodix_get_file_config_id(u8 *ic_config);
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data);
int goodix_fw_update_init(struct goodix_ts_core *core_data);
void goodix_fw_update_uninit(void);
int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode);
int goodix_get_ic_type(struct device_node *node);
int gesture_module_init(void);
void gesture_module_exit(void);
int inspect_module_init(void);
void inspect_module_exit(void);
int goodix_tools_init(void);
void goodix_tools_exit(void);
int goodix_get_touch_type(struct device_node *np);
/* goodix FB test */
/*
void goodix_fb_ext_ctrl(int suspend);
*/
#endif

View File

@@ -0,0 +1,446 @@
/*
* Goodix Gesture Module
*
* Copyright (C) 2019 - 2020 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/atomic.h>
#include <linux/input/mt.h>
#include "goodix_ts_core.h"
#define GOODIX_GESTURE_DOUBLE_TAP 0xCC
#define GOODIX_GESTURE_SINGLE_TAP 0x4C
#define GOODIX_GESTURE_FOD_DOWN 0x46
#define GOODIX_GESTURE_FOD_UP 0x55
/*
* struct gesture_module - gesture module data
* @registered: module register state
* @sysfs_node_created: sysfs node state
* @gesture_type: valid gesture type, each bit represent one gesture type
* @gesture_data: store latest gesture code get from irq event
* @gesture_ts_cmd: gesture command data
*/
struct gesture_module {
atomic_t registered;
struct goodix_ts_core *ts_core;
struct goodix_ext_module module;
};
static struct gesture_module *gsx_gesture; /*allocated in gesture init module*/
static bool module_initialized;
static ssize_t gsx_double_type_show(struct goodix_ext_module *module,
char *buf)
{
struct gesture_module *gsx = module->priv_data;
unsigned char type = gsx->ts_core->gesture_type;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
return scnprintf(buf, PAGE_SIZE, "%s\n",
(type & GESTURE_DOUBLE_TAP) ? "enable" : "disable");
}
static ssize_t gsx_double_type_store(struct goodix_ext_module *module,
const char *buf, size_t count)
{
struct gesture_module *gsx = module->priv_data;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
if (buf[0] == '1') {
ts_info("enable double tap");
gsx->ts_core->gesture_type |= GESTURE_DOUBLE_TAP;
} else if (buf[0] == '0') {
ts_info("disable double tap");
gsx->ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
static ssize_t gsx_single_type_show(struct goodix_ext_module *module,
char *buf)
{
struct gesture_module *gsx = module->priv_data;
unsigned char type = gsx->ts_core->gesture_type;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
return scnprintf(buf, PAGE_SIZE, "%s\n",
(type & GESTURE_SINGLE_TAP) ? "enable" : "disable");
}
static ssize_t gsx_single_type_store(struct goodix_ext_module *module,
const char *buf, size_t count)
{
struct gesture_module *gsx = module->priv_data;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
if (buf[0] == '1') {
ts_info("enable single tap");
gsx->ts_core->gesture_type |= GESTURE_SINGLE_TAP;
} else if (buf[0] == '0') {
ts_info("disable single tap");
gsx->ts_core->gesture_type &= ~GESTURE_SINGLE_TAP;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
static ssize_t gsx_fod_type_show(struct goodix_ext_module *module,
char *buf)
{
struct gesture_module *gsx = module->priv_data;
unsigned char type = gsx->ts_core->gesture_type;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
return scnprintf(buf, PAGE_SIZE, "%s\n",
(type & GESTURE_FOD_PRESS) ? "enable" : "disable");
}
static ssize_t gsx_fod_type_store(struct goodix_ext_module *module,
const char *buf, size_t count)
{
struct gesture_module *gsx = module->priv_data;
if (!gsx)
return -EIO;
if (atomic_read(&gsx->registered) == 0) {
ts_err("gesture module is not registered");
return 0;
}
if (buf[0] == '1') {
ts_info("enable fod");
gsx->ts_core->gesture_type |= GESTURE_FOD_PRESS;
} else if (buf[0] == '0') {
ts_info("disable fod");
gsx->ts_core->gesture_type &= ~GESTURE_FOD_PRESS;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
const struct goodix_ext_attribute gesture_attrs[] = {
__EXTMOD_ATTR(double_en, 0664,
gsx_double_type_show, gsx_double_type_store),
__EXTMOD_ATTR(single_en, 0664,
gsx_single_type_show, gsx_single_type_store),
__EXTMOD_ATTR(fod_en, 0664,
gsx_fod_type_show, gsx_fod_type_store),
};
static int gsx_gesture_init(struct goodix_ts_core *cd,
struct goodix_ext_module *module)
{
struct gesture_module *gsx = module->priv_data;
if (!cd || !cd->hw_ops->gesture) {
ts_err("gesture unsupported");
return -EINVAL;
}
gsx->ts_core = cd;
gsx->ts_core->gesture_type = 0;
atomic_set(&gsx->registered, 1);
return 0;
}
static int gsx_gesture_exit(struct goodix_ts_core *cd,
struct goodix_ext_module *module)
{
struct gesture_module *gsx = module->priv_data;
if (!cd || !cd->hw_ops->gesture) {
ts_err("gesture unsupported");
return -EINVAL;
}
atomic_set(&gsx->registered, 0);
return 0;
}
/**
* gsx_gesture_ist - Gesture Irq handle
* This functions is excuted when interrupt happended and
* ic in doze mode.
*
* @cd: pointer to touch core data
* @module: pointer to goodix_ext_module struct
* return: 0 goon execute, EVT_CANCEL_IRQEVT stop execute
*/
static int gsx_gesture_ist(struct goodix_ts_core *cd,
struct goodix_ext_module *module)
{
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
struct goodix_ts_event gs_event = {0};
int fodx, fody, overlay_area;
int ret;
if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0)
return EVT_CONTINUE;
ret = hw_ops->event_handler(cd, &gs_event);
if (ret) {
ts_err("failed get gesture data");
goto re_send_ges_cmd;
}
if (!(gs_event.event_type & EVENT_GESTURE)) {
ts_err("invalid event type: 0x%x",
cd->ts_event.event_type);
goto re_send_ges_cmd;
}
switch (gs_event.gesture_type) {
case GOODIX_GESTURE_SINGLE_TAP:
if (cd->gesture_type & GESTURE_SINGLE_TAP) {
ts_info("get SINGLE-TAP gesture");
input_report_key(cd->input_dev, KEY_WAKEUP, 1);
// input_report_key(cd->input_dev, KEY_GOTO, 1);
input_sync(cd->input_dev);
input_report_key(cd->input_dev, KEY_WAKEUP, 0);
// input_report_key(cd->input_dev, KEY_GOTO, 0);
input_sync(cd->input_dev);
} else {
ts_debug("not enable SINGLE-TAP");
}
break;
case GOODIX_GESTURE_DOUBLE_TAP:
if (cd->gesture_type & GESTURE_DOUBLE_TAP) {
ts_info("get DOUBLE-TAP gesture");
input_report_key(cd->input_dev, KEY_WAKEUP, 1);
input_sync(cd->input_dev);
input_report_key(cd->input_dev, KEY_WAKEUP, 0);
input_sync(cd->input_dev);
} else {
ts_debug("not enable DOUBLE-TAP");
}
break;
case GOODIX_GESTURE_FOD_DOWN:
if (cd->gesture_type & GESTURE_FOD_PRESS) {
ts_info("get FOD-DOWN gesture");
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
overlay_area = gs_event.gesture_data[4];
ts_debug("fodx:%d fody:%d overlay_area:%d", fodx, fody, overlay_area);
input_report_key(cd->input_dev, BTN_TOUCH, 1);
input_mt_slot(cd->input_dev, 0);
input_mt_report_slot_state(cd->input_dev, MT_TOOL_FINGER, 1);
input_report_abs(cd->input_dev, ABS_MT_POSITION_X, fodx);
input_report_abs(cd->input_dev, ABS_MT_POSITION_Y, fody);
input_report_abs(cd->input_dev, ABS_MT_WIDTH_MAJOR, overlay_area);
input_sync(cd->input_dev);
} else {
ts_debug("not enable FOD-DOWN");
}
break;
case GOODIX_GESTURE_FOD_UP:
if (cd->gesture_type & GESTURE_FOD_PRESS) {
ts_info("get FOD-UP gesture");
fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
fody = le16_to_cpup((__le16 *)(gs_event.gesture_data + 2));
overlay_area = gs_event.gesture_data[4];
input_report_key(cd->input_dev, BTN_TOUCH, 0);
input_mt_slot(cd->input_dev, 0);
input_mt_report_slot_state(cd->input_dev,
MT_TOOL_FINGER, 0);
input_sync(cd->input_dev);
} else {
ts_debug("not enable FOD-UP");
}
break;
default:
ts_err("not support gesture type[%02X]", gs_event.gesture_type);
break;
}
re_send_ges_cmd:
if (hw_ops->gesture(cd, 0))
ts_info("warning: failed re_send gesture cmd");
return EVT_CANCEL_IRQEVT;
}
/**
* gsx_gesture_before_suspend - execute gesture suspend routine
* This functions is excuted to set ic into doze mode
*
* @cd: pointer to touch core data
* @module: pointer to goodix_ext_module struct
* return: 0 goon execute, EVT_IRQCANCLED stop execute
*/
static int gsx_gesture_before_suspend(struct goodix_ts_core *cd,
struct goodix_ext_module *module)
{
int ret;
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
if (cd->gesture_type == 0)
return EVT_CONTINUE;
ret = hw_ops->gesture(cd, 0);
if (ret)
ts_err("failed enter gesture mode");
else
ts_info("enter gesture mode, type[0x%02X]", cd->gesture_type);
hw_ops->irq_enable(cd, true);
enable_irq_wake(cd->irq);
return EVT_CANCEL_SUSPEND;
}
static int gsx_gesture_before_resume(struct goodix_ts_core *cd,
struct goodix_ext_module *module)
{
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
if (cd->gesture_type == 0)
return EVT_CONTINUE;
disable_irq_wake(cd->irq);
hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
return EVT_CANCEL_RESUME;
}
static struct goodix_ext_module_funcs gsx_gesture_funcs = {
.irq_event = gsx_gesture_ist,
.init = gsx_gesture_init,
.exit = gsx_gesture_exit,
.before_suspend = gsx_gesture_before_suspend,
.before_resume = gsx_gesture_before_resume,
};
int gesture_module_init(void)
{
int ret;
int i;
struct kobject *def_kobj = goodix_get_default_kobj();
struct kobj_type *def_kobj_type = goodix_get_default_ktype();
gsx_gesture = kzalloc(sizeof(struct gesture_module), GFP_KERNEL);
if (!gsx_gesture)
return -ENOMEM;
gsx_gesture->module.funcs = &gsx_gesture_funcs;
gsx_gesture->module.priority = EXTMOD_PRIO_GESTURE;
gsx_gesture->module.name = "Goodix_gsx_gesture";
gsx_gesture->module.priv_data = gsx_gesture;
atomic_set(&gsx_gesture->registered, 0);
/* gesture sysfs init */
ret = kobject_init_and_add(&gsx_gesture->module.kobj,
def_kobj_type, def_kobj, "gesture");
if (ret) {
ts_err("failed create gesture sysfs node!");
goto err_out;
}
for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++)
ret = sysfs_create_file(&gsx_gesture->module.kobj,
&gesture_attrs[i].attr);
if (ret) {
ts_err("failed create gst sysfs files");
while (--i >= 0)
sysfs_remove_file(&gsx_gesture->module.kobj,
&gesture_attrs[i].attr);
kobject_put(&gsx_gesture->module.kobj);
goto err_out;
}
module_initialized = true;
goodix_register_ext_module_no_wait(&gsx_gesture->module);
ts_info("gesture module init success");
return 0;
err_out:
ts_err("gesture module init failed!");
kfree(gsx_gesture);
return ret;
}
void gesture_module_exit(void)
{
int i;
ts_info("gesture module exit");
if (!module_initialized)
return;
goodix_unregister_ext_module(&gsx_gesture->module);
/* deinit sysfs */
for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
sysfs_remove_file(&gsx_gesture->module.kobj,
&gesture_attrs[i].attr);
kobject_put(&gsx_gesture->module.kobj);
kfree(gsx_gesture);
module_initialized = false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,503 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
#include "goodix_ts_core.h"
#define GOODIX_TOOLS_NAME "gtp_tools"
#define GOODIX_TOOLS_VER_MAJOR 1
#define GOODIX_TOOLS_VER_MINOR 0
static const u16 goodix_tools_ver = ((GOODIX_TOOLS_VER_MAJOR << 8) +
(GOODIX_TOOLS_VER_MINOR));
#define GOODIX_TS_IOC_MAGIC 'G'
#define NEGLECT_SIZE_MASK (~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
#define GTP_IRQ_ENABLE _IO(GOODIX_TS_IOC_MAGIC, 0)
#define GTP_DEV_RESET _IO(GOODIX_TS_IOC_MAGIC, 1)
#define GTP_SEND_COMMAND (_IOW(GOODIX_TS_IOC_MAGIC, 2, u8) & NEGLECT_SIZE_MASK)
#define GTP_SEND_CONFIG (_IOW(GOODIX_TS_IOC_MAGIC, 3, u8) & NEGLECT_SIZE_MASK)
#define GTP_ASYNC_READ (_IOR(GOODIX_TS_IOC_MAGIC, 4, u8) & NEGLECT_SIZE_MASK)
#define GTP_SYNC_READ (_IOR(GOODIX_TS_IOC_MAGIC, 5, u8) & NEGLECT_SIZE_MASK)
#define GTP_ASYNC_WRITE (_IOW(GOODIX_TS_IOC_MAGIC, 6, u8) & NEGLECT_SIZE_MASK)
#define GTP_READ_CONFIG (_IOW(GOODIX_TS_IOC_MAGIC, 7, u8) & NEGLECT_SIZE_MASK)
#define GTP_ESD_ENABLE _IO(GOODIX_TS_IOC_MAGIC, 8)
#define GTP_TOOLS_VER (_IOR(GOODIX_TS_IOC_MAGIC, 9, u8) & NEGLECT_SIZE_MASK)
#define GTP_TOOLS_CTRL_SYNC (_IOW(GOODIX_TS_IOC_MAGIC, 10, u8) & NEGLECT_SIZE_MASK)
#define MAX_BUF_LENGTH (16*1024)
#define IRQ_FALG (0x01 << 2)
#define I2C_MSG_HEAD_LEN 20
/*
* struct goodix_tools_dev - goodix tools device struct
* @ts_core: The core data struct of ts driver
* @ops_mode: represent device work mode
* @rawdiffcmd: Set slave device into rawdata mode
* @normalcmd: Set slave device into normal mode
* @wq: Wait queue struct use in synchronous data read
* @mutex: Protect goodix_tools_dev
* @in_use: device in use
*/
struct goodix_tools_dev {
struct goodix_ts_core *ts_core;
struct list_head head;
unsigned int ops_mode;
struct goodix_ts_cmd rawdiffcmd, normalcmd;
wait_queue_head_t wq;
struct mutex mutex;
atomic_t in_use;
struct goodix_ext_module module;
} *goodix_tools_dev;
/* read data asynchronous,
* success return data length, otherwise return < 0
*/
static int async_read(struct goodix_tools_dev *dev, void __user *arg)
{
u8 *databuf = NULL;
int ret = 0;
u32 reg_addr, length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
const struct goodix_ts_hw_ops *hw_ops = dev->ts_core->hw_ops;
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
if (ret)
return -EFAULT;
reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
+ (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
+ (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
if (length > MAX_BUF_LENGTH) {
ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
return -EINVAL;
}
databuf = kzalloc(length, GFP_KERNEL);
if (!databuf) {
ts_err("Alloc memory failed");
return -ENOMEM;
}
if (hw_ops->read(dev->ts_core, reg_addr, databuf, length)) {
ret = -EBUSY;
ts_err("Read i2c failed");
goto err_out;
}
ret = copy_to_user((u8 *)arg + I2C_MSG_HEAD_LEN, databuf, length);
if (ret) {
ret = -EFAULT;
ts_err("Copy_to_user failed");
goto err_out;
}
ret = length;
err_out:
kfree(databuf);
return ret;
}
/* if success return config data length */
static int read_config_data(struct goodix_ts_core *ts_core, void __user *arg)
{
int ret = 0;
u32 reg_addr, length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
u8 *tmp_buf;
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
if (ret) {
ts_err("Copy data from user failed");
return -EFAULT;
}
reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
+ (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
+ (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
ts_info("read config,reg_addr=0x%x, length=%d", reg_addr, length);
if (length > MAX_BUF_LENGTH) {
ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
return -EINVAL;
}
tmp_buf = kzalloc(length, GFP_KERNEL);
if (!tmp_buf) {
ts_err("failed alloc memory");
return -ENOMEM;
}
/* if reg_addr == 0, read config data with specific flow */
if (!reg_addr) {
if (ts_core->hw_ops->read_config)
ret = ts_core->hw_ops->read_config(ts_core, tmp_buf, length);
else
ret = -EINVAL;
} else {
ret = ts_core->hw_ops->read(ts_core, reg_addr, tmp_buf, length);
if (!ret)
ret = length;
}
if (ret <= 0)
goto err_out;
if (copy_to_user((u8 *)arg + I2C_MSG_HEAD_LEN, tmp_buf, ret)) {
ret = -EFAULT;
ts_err("Copy_to_user failed");
}
err_out:
kfree(tmp_buf);
return ret;
}
/* write data to i2c asynchronous,
* success return bytes write, else return <= 0
*/
static int async_write(struct goodix_tools_dev *dev, void __user *arg)
{
u8 *databuf;
int ret = 0;
u32 reg_addr, length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
struct goodix_ts_core *ts_core = dev->ts_core;
const struct goodix_ts_hw_ops *hw_ops = ts_core->hw_ops;
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
if (ret) {
ts_err("Copy data from user failed");
return -EFAULT;
}
reg_addr = i2c_msg_head[0] + (i2c_msg_head[1] << 8)
+ (i2c_msg_head[2] << 16) + (i2c_msg_head[3] << 24);
length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
+ (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
if (length > MAX_BUF_LENGTH) {
ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
return -EINVAL;
}
databuf = kzalloc(length, GFP_KERNEL);
if (!databuf) {
ts_err("Alloc memory failed");
return -ENOMEM;
}
ret = copy_from_user(databuf, (u8 *)arg + I2C_MSG_HEAD_LEN, length);
if (ret) {
ret = -EFAULT;
ts_err("Copy data from user failed");
goto err_out;
}
if (hw_ops->write(ts_core, reg_addr, databuf, length)) {
ret = -EBUSY;
ts_err("Write data to device failed");
} else {
ret = length;
}
err_out:
kfree(databuf);
return ret;
}
static int init_cfg_data(struct goodix_ic_config *cfg, void __user *arg)
{
int ret = 0;
u32 length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN] = {0};
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
if (ret) {
ts_err("Copy data from user failed");
return -EFAULT;
}
length = i2c_msg_head[4] + (i2c_msg_head[5] << 8)
+ (i2c_msg_head[6] << 16) + (i2c_msg_head[7] << 24);
if (length > GOODIX_CFG_MAX_SIZE) {
ts_err("buffer too long:%d > %d", length, MAX_BUF_LENGTH);
return -EINVAL;
}
ret = copy_from_user(cfg->data, (u8 *)arg + I2C_MSG_HEAD_LEN, length);
if (ret) {
ts_err("Copy data from user failed");
return -EFAULT;
}
cfg->len = length;
return 0;
}
/**
* goodix_tools_ioctl - ioctl implementation
*
* @filp: Pointer to file opened
* @cmd: Ioctl opertion command
* @arg: Command data
* Returns >=0 - succeed, else failed
*/
static long goodix_tools_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int ret = 0;
struct goodix_tools_dev *dev = filp->private_data;
struct goodix_ts_core *ts_core;
const struct goodix_ts_hw_ops *hw_ops;
struct goodix_ic_config *temp_cfg = NULL;
if (!dev->ts_core) {
ts_err("Tools module not register");
return -EINVAL;
}
ts_core = dev->ts_core;
hw_ops = ts_core->hw_ops;
if (_IOC_TYPE(cmd) != GOODIX_TS_IOC_MAGIC) {
ts_err("Bad magic num:%c", _IOC_TYPE(cmd));
return -ENOTTY;
}
switch (cmd & NEGLECT_SIZE_MASK) {
case GTP_IRQ_ENABLE:
if (arg == 1) {
hw_ops->irq_enable(ts_core, true);
mutex_lock(&dev->mutex);
dev->ops_mode |= IRQ_FALG;
mutex_unlock(&dev->mutex);
ts_info("IRQ enabled");
} else if (arg == 0) {
hw_ops->irq_enable(ts_core, false);
mutex_lock(&dev->mutex);
dev->ops_mode &= ~IRQ_FALG;
mutex_unlock(&dev->mutex);
ts_info("IRQ disabled");
} else {
ts_info("Irq aready set with, arg = %ld", arg);
}
ret = 0;
break;
case GTP_ESD_ENABLE:
if (arg == 0)
goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
else
goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
break;
case GTP_DEV_RESET:
hw_ops->reset(ts_core, GOODIX_NORMAL_RESET_DELAY_MS);
break;
case GTP_SEND_COMMAND:
/* deprecated command */
ts_err("the GTP_SEND_COMMAND function has been removed");
ret = -EINVAL;
break;
case GTP_SEND_CONFIG:
temp_cfg = kzalloc(sizeof(struct goodix_ic_config), GFP_KERNEL);
if (!temp_cfg) {
ts_err("Memory allco err");
ret = -ENOMEM;
goto err_out;
}
ret = init_cfg_data(temp_cfg, (void __user *)arg);
if (!ret && hw_ops->send_config) {
ret = hw_ops->send_config(ts_core, temp_cfg->data, temp_cfg->len);
if (ret) {
ts_err("Failed send config");
ret = -EAGAIN;
} else {
ts_info("Send config success");
ret = 0;
}
}
kfree(temp_cfg);
temp_cfg = NULL;
break;
case GTP_READ_CONFIG:
ret = read_config_data(ts_core, (void __user *)arg);
if (ret > 0)
ts_info("success read config:len=%d", ret);
else
ts_err("failed read config:ret=0x%x", ret);
break;
case GTP_ASYNC_READ:
ret = async_read(dev, (void __user *)arg);
if (ret < 0)
ts_err("Async data read failed");
break;
case GTP_SYNC_READ:
ts_info("unsupport sync read");
break;
case GTP_ASYNC_WRITE:
ret = async_write(dev, (void __user *)arg);
if (ret < 0)
ts_err("Async data write failed");
break;
case GTP_TOOLS_VER:
ret = copy_to_user((u8 *)arg, &goodix_tools_ver, sizeof(u16));
if (ret)
ts_err("failed copy driver version info to user");
break;
case GTP_TOOLS_CTRL_SYNC:
ts_core->tools_ctrl_sync = !!arg;
ts_info("set tools ctrl sync %d", ts_core->tools_ctrl_sync);
break;
default:
ts_info("Invalid cmd");
ret = -ENOTTY;
break;
}
err_out:
return ret;
}
#ifdef CONFIG_COMPAT
static long goodix_tools_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
void __user *arg32 = compat_ptr(arg);
if (!file->f_op || !file->f_op->unlocked_ioctl)
return -ENOTTY;
return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)arg32);
}
#endif
static int goodix_tools_open(struct inode *inode, struct file *filp)
{
int ret = 0;
ts_info("try open tool");
/* Only the first time open device need to register module */
ret = goodix_register_ext_module_no_wait(&goodix_tools_dev->module);
if (ret) {
ts_info("failed register to core module");
return -EFAULT;
}
ts_info("success open tools");
goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
filp->private_data = goodix_tools_dev;
atomic_set(&goodix_tools_dev->in_use, 1);
return 0;
}
static int goodix_tools_release(struct inode *inode, struct file *filp)
{
int ret = 0;
/* when the last close this dev node unregister the module */
goodix_tools_dev->ts_core->tools_ctrl_sync = false;
atomic_set(&goodix_tools_dev->in_use, 0);
goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
ret = goodix_unregister_ext_module(&goodix_tools_dev->module);
return ret;
}
static int goodix_tools_module_init(struct goodix_ts_core *core_data,
struct goodix_ext_module *module)
{
struct goodix_tools_dev *tools_dev = module->priv_data;
if (core_data)
tools_dev->ts_core = core_data;
else
return -ENODEV;
return 0;
}
static int goodix_tools_module_exit(struct goodix_ts_core *core_data,
struct goodix_ext_module *module)
{
struct goodix_tools_dev *tools_dev = module->priv_data;
ts_debug("tools module unregister");
if (atomic_read(&tools_dev->in_use)) {
ts_err("tools module busy, please close it then retry");
return -EBUSY;
}
return 0;
}
static const struct file_operations goodix_tools_fops = {
.owner = THIS_MODULE,
.open = goodix_tools_open,
.release = goodix_tools_release,
.unlocked_ioctl = goodix_tools_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = goodix_tools_compat_ioctl,
#endif
};
static struct miscdevice goodix_tools_miscdev = {
.minor = MISC_DYNAMIC_MINOR,
.name = GOODIX_TOOLS_NAME,
.fops = &goodix_tools_fops,
};
static struct goodix_ext_module_funcs goodix_tools_module_funcs = {
.init = goodix_tools_module_init,
.exit = goodix_tools_module_exit,
};
/**
* goodix_tools_init - init goodix tools device and register a miscdevice
*
* return: 0 success, else failed
*/
int goodix_tools_init(void)
{
int ret;
goodix_tools_dev = kzalloc(sizeof(struct goodix_tools_dev), GFP_KERNEL);
if (goodix_tools_dev == NULL) {
ts_err("Memory allco err");
return -ENOMEM;
}
INIT_LIST_HEAD(&goodix_tools_dev->head);
goodix_tools_dev->ops_mode = 0;
goodix_tools_dev->ops_mode |= IRQ_FALG;
init_waitqueue_head(&goodix_tools_dev->wq);
mutex_init(&goodix_tools_dev->mutex);
atomic_set(&goodix_tools_dev->in_use, 0);
goodix_tools_dev->module.funcs = &goodix_tools_module_funcs;
goodix_tools_dev->module.name = GOODIX_TOOLS_NAME;
goodix_tools_dev->module.priv_data = goodix_tools_dev;
goodix_tools_dev->module.priority = EXTMOD_PRIO_DBGTOOL;
ret = misc_register(&goodix_tools_miscdev);
if (ret)
ts_err("Debug tools miscdev register failed");
else
ts_info("Debug tools miscdev register success");
return ret;
}
void goodix_tools_exit(void)
{
misc_deregister(&goodix_tools_miscdev);
kfree(goodix_tools_dev);
ts_info("Debug tools miscdev exit");
}

View File

@@ -0,0 +1,208 @@
/*
* Goodix Touchscreen Driver
* Copyright (C) 2020 - 2021 Goodix, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be a reference
* to you, when you are integrating the GOODiX's CTP IC into your system,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
*/
#include "goodix_ts_core.h"
bool debug_log_flag = false;
/*****************************************************************************
* goodix_append_checksum
* @summary
* Calcualte data checksum with the specified mode.
*
* @param data
* data need to be calculate
* @param len
* data length
* @param mode
* calculate for u8 or u16 checksum
* @return
* return the data checksum value.
*
*****************************************************************************/
u32 goodix_append_checksum(u8 *data, int len, int mode)
{
u32 checksum = 0;
int i;
checksum = 0;
if (mode == CHECKSUM_MODE_U8_LE) {
for (i = 0; i < len; i++)
checksum += data[i];
} else {
for (i = 0; i < len; i+=2)
checksum += (data[i] + (data[i+1] << 8));
}
if (mode == CHECKSUM_MODE_U8_LE) {
data[len] = checksum & 0xff;
data[len + 1] = (checksum >> 8) & 0xff;
return 0xFFFF & checksum;
}
data[len] = checksum & 0xff;
data[len + 1] = (checksum >> 8) & 0xff;
data[len + 2] = (checksum >> 16) & 0xff;
data[len + 3] = (checksum >> 24) & 0xff;
return checksum;
}
/* checksum_cmp: check data valid or not
* @data: data need to be check
* @size: data length need to be check(include the checksum bytes)
* @mode: compare with U8 or U16 mode
* */
int checksum_cmp(const u8 *data, int size, int mode)
{
u32 cal_checksum = 0;
u32 r_checksum = 0;
u32 i;
if (((mode == CHECKSUM_MODE_U8_LE) && (size < 2)) ||
((mode == CHECKSUM_MODE_U16_LE) && (size < 4)) ||
((mode == CHECKSUM_MODE_U16_LE) && (size % 2 != 0)))
return 1;
if (mode == CHECKSUM_MODE_U8_LE) {
for (i = 0; i < size - 2; i++)
cal_checksum += data[i];
r_checksum += data[i++];
r_checksum += (data[i] << 8);
return (cal_checksum & 0xFFFF) == r_checksum ? 0 : 1;
}
if (mode == CHECKSUM_MODE_U16_LE) {
for (i = 0; i < size - 4; i += 2)
cal_checksum += data[i] + (data[i + 1] << 8);
r_checksum += data[i++];
r_checksum += (data[i++] << 8);
r_checksum += (data[i++] << 16);
r_checksum += (data[i] << 24);
return cal_checksum == r_checksum ? 0 : 1;
}
return 1;
}
/* return 1 if all data is zero or ff
* else return 0
*/
int is_risk_data(const u8 *data, int size)
{
int i;
int zero_count = 0;
int ff_count = 0;
for (i = 0; i < size; i++) {
if (data[i] == 0)
zero_count++;
else if (data[i] == 0xff)
ff_count++;
}
if (zero_count == size || ff_count == size) {
ts_info("warning data is all %s\n",
zero_count == size ? "zero" : "0xff");
return 1;
}
return 0;
}
/* get config id form config file */
#define CONFIG_ID_OFFSET 30
u32 goodix_get_file_config_id(u8 *ic_config)
{
if (!ic_config)
return 0;
return le32_to_cpup((__le32 *)&ic_config[CONFIG_ID_OFFSET]);
}
/* matrix transpose */
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data)
{
s16 *temp_buf = NULL;
int size = tx * rx;
int i;
int j;
int col;
temp_buf = kcalloc(size, sizeof(s16), GFP_KERNEL);
if (!temp_buf) {
ts_err("malloc failed");
return;
}
for (i = 0, j = 0, col = 0; i < size; i++) {
temp_buf[i] = data[j++ * rx + col];
if (j == tx) {
j = 0;
col++;
}
}
memcpy(data, temp_buf, size * sizeof(s16));
kfree(temp_buf);
}
/* get ic type */
int goodix_get_ic_type(struct device_node *node)
{
const char *name_tmp;
int ret;
ret = of_property_read_string(node, "compatible", &name_tmp);
if (ret < 0) {
ts_err("get compatible failed");
return ret;
}
if (strstr(name_tmp, "9897")) {
ts_info("ic type is BerlinA");
ret = IC_TYPE_BERLIN_A;
} else if (strstr(name_tmp, "9966") || strstr(name_tmp, "7986")) {
ts_info("ic type is BerlinB");
ret = IC_TYPE_BERLIN_B;
} else if (strstr(name_tmp, "9916")) {
ts_info("ic type is BerlinD");
ret = IC_TYPE_BERLIN_D;
} else {
ts_info("can't find valid ic_type");
ret = -EINVAL;
}
return ret;
}
/* get touch type */
int goodix_get_touch_type(struct device_node *node)
{
const char *touch_type;
int ret;
ret = of_property_read_string(node, "goodix,touch-type", &touch_type);
if (ret) {
ts_err("No touch type found\n");
return -EINVAL;
}
if (!strcmp(touch_type, "primary"))
ret = PRIMARY_TOUCH_IDX;
else if (!strcmp(touch_type, "secondary"))
ret = SECONDARY_TOUCH_IDX;
else
ret = -EINVAL;
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,386 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 - 2018 Novatek, Inc.
*
* $Revision: 47247 $
* $Date: 2019-07-10 10:41:36 +0800 (Wed, 10 Jul 2019) $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#ifndef _LINUX_NVT_TOUCH_H
#define _LINUX_NVT_TOUCH_H
#if !defined(NVT_NT36XXX_SPI) /* NT36XXX I2C */
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/uaccess.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include "nt36xxx_mem_map.h"
#define NVT_DEBUG 1
//---GPIO number---
#define NVTTOUCH_RST_PIN 980
#define NVTTOUCH_INT_PIN 943
//---INT trigger mode---
//#define IRQ_TYPE_EDGE_RISING 1
//#define IRQ_TYPE_EDGE_FALLING 2
#define INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING
//---I2C driver info.---
#define NVT_I2C_NAME "NVT-ts"
#define I2C_BLDR_Address 0x01
#define I2C_FW_Address 0x01
#define I2C_HW_Address 0x62
#if NVT_DEBUG
#define NVT_LOG(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
#else
#define NVT_LOG(fmt, args...) pr_info("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
#endif
#define NVT_ERR(fmt, args...) pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
//---Input device info.---
#define NVT_TS_NAME "NVTCapacitiveTouchScreen"
//---Touch info.---
#define TOUCH_DEFAULT_MAX_WIDTH 1080
#define TOUCH_DEFAULT_MAX_HEIGHT 2408
#define TOUCH_MAX_FINGER_NUM 10
#define TOUCH_KEY_NUM 0
#if TOUCH_KEY_NUM > 0
extern const uint16_t touch_key_array[TOUCH_KEY_NUM];
#endif
#define TOUCH_FORCE_NUM 1000
/* Enable only when module have tp reset pin and connected to host */
#define NVT_TOUCH_SUPPORT_HW_RST 1
//---Customerized func.---
#define NVT_TOUCH_PROC 1
#define NVT_TOUCH_EXT_PROC 1
#define NVT_TOUCH_MP 1
#define MT_PROTOCOL_B 1
#define WAKEUP_GESTURE 0
#if WAKEUP_GESTURE
extern const uint16_t gesture_key_array[];
#endif
#define BOOT_UPDATE_FIRMWARE 1
#define BOOT_UPDATE_FIRMWARE_NAME "novatek_ts_fw.bin"
//---ESD Protect.---
#define NVT_TOUCH_ESD_PROTECT 0
#define NVT_TOUCH_ESD_CHECK_PERIOD 1500 /* ms */
struct nvt_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct delayed_work nvt_fwu_work;
uint16_t addr;
int8_t phys[32];
const struct i2c_device_id *id;
#if defined(CONFIG_DRM)
struct notifier_block drm_panel_notif;
#elif defined(_MSM_DRM_NOTIFY_H_)
struct notifier_block drm_notif;
#else
struct notifier_block fb_notif;
#endif
uint8_t fw_ver;
uint8_t x_num;
uint8_t y_num;
uint16_t abs_x_max;
uint16_t abs_y_max;
uint8_t max_touch_num;
uint8_t max_button_num;
uint32_t int_trigger_type;
int32_t irq_gpio;
uint32_t irq_flags;
int32_t reset_gpio;
uint32_t reset_flags;
struct mutex lock;
const struct nvt_ts_mem_map *mmap;
uint8_t carrier_system;
uint16_t nvt_pid;
uint8_t xbuf[1025];
struct mutex xbuf_lock;
bool irq_enabled;
void *notifier_cookie;
};
#if NVT_TOUCH_PROC
struct nvt_flash_data{
rwlock_t lock;
struct i2c_client *client;
};
#endif
typedef enum {
RESET_STATE_INIT = 0xA0,// IC reset
RESET_STATE_REK, // ReK baseline
RESET_STATE_REK_FINISH, // baseline is ready
RESET_STATE_NORMAL_RUN, // normal run
RESET_STATE_MAX = 0xAF
} RST_COMPLETE_STATE;
typedef enum {
EVENT_MAP_HOST_CMD = 0x50,
EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE = 0x51,
EVENT_MAP_RESET_COMPLETE = 0x60,
EVENT_MAP_FWINFO = 0x78,
EVENT_MAP_PROJECTID = 0x9A,
} I2C_EVENT_MAP;
//---extern structures---
extern struct nvt_ts_data *ts;
//---extern functions---
extern int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
extern int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
extern void nvt_bootloader_reset(void);
extern void nvt_sw_reset_idle(void);
extern int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state);
extern int32_t nvt_get_fw_info(void);
extern int32_t nvt_clear_fw_status(void);
extern int32_t nvt_check_fw_status(void);
extern int32_t nvt_set_page(uint16_t i2c_addr, uint32_t addr);
#if NVT_TOUCH_ESD_PROTECT
extern void nvt_esd_check_enable(uint8_t enable);
#endif /* #if NVT_TOUCH_ESD_PROTECT */
extern void nvt_stop_crc_reboot(void);
#else /* NT36XXX_SPI */
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
#include <linux/uaccess.h>
#include "nt36xxx_mem_map.h"
#define NVT_SPI_DEBUG 0
//---GPIO number---
#define NVTTOUCH_RST_PIN 980
#define NVTTOUCH_INT_PIN 943
//---INT trigger mode---
//#define NVT_SPI_IRQ_TYPE_EDGE_RISING 1
//#define NVT_SPI_IRQ_TYPE_EDGE_FALLING 2
#define NVT_SPI_INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING
//---SPI driver info.---
#define NVT_SPI_NAME "NVT-SPI"
#if NVT_SPI_DEBUG
#define NVT_LOG(fmt, args...) pr_err("[%s] %s %d: " fmt, "NVT-SPI", __func__, __LINE__, ##args)
#else
#define NVT_LOG(fmt, args...) pr_debug("[%s] %s %d: " fmt, "NVT-SPI", __func__, __LINE__, ##args)
#endif
#define NVT_ERR(fmt, args...) pr_err("[%s] %s %d: " fmt, "NVT-SPI", __func__, __LINE__, ##args)
//---Input device info.---
#define NVT_SPI_TS_NAME "NVTCapacitiveTouchScreen"
#define NVT_SPI_PEN_NAME "NVTCapacitivePen"
//---Touch info.---
#define NVT_SPI_TOUCH_DEFAULT_MAX_WIDTH 1080
#define NVT_SPI_TOUCH_DEFAULT_MAX_HEIGHT 2400
#define NVT_SPI_TOUCH_MAX_FINGER_NUM 10
#define NVT_SPI_TOUCH_KEY_NUM 0
#if NVT_SPI_TOUCH_KEY_NUM > 0
extern const uint16_t nvt_spi_touch_key_array[NVT_SPI_TOUCH_KEY_NUM];
#endif
#define NVT_SPI_TOUCH_FORCE_NUM 1000
//---for Pen---
#define NVT_SPI_PEN_PRESSURE_MAX (4095)
#define NVT_SPI_PEN_DISTANCE_MAX (1)
#define NVT_SPI_PEN_TILT_MIN (-60)
#define NVT_SPI_PEN_TILT_MAX (60)
/* Enable only when module have tp reset pin and connected to host */
#define NVT_SPI_TOUCH_SUPPORT_HW_RST 0
//---Customerized func.---
#define NVT_SPI_TOUCH_PROC 1
#define NVT_SPI_TOUCH_EXT_PROC 1
#define NVT_SPI_TOUCH_MP 0
#define NVT_SPI_MT_PROTOCOL_B 1
#define NVT_SPI_WAKEUP_GESTURE 0
#if NVT_SPI_WAKEUP_GESTURE
extern const uint16_t nvt_spi_gesture_key_array[];
#endif
#define NVT_SPI_BOOT_UPDATE_FIRMWARE 1
#define NVT_SPI_BOOT_UPDATE_FIRMWARE_NAME "novatek_spi_fw.bin"
#define NVT_SPI_MP_UPDATE_FIRMWARE_NAME "novatek_ts_mp.bin"
#define NVT_SPI_POINT_DATA_CHECKSUM 1
#define NVT_SPI_POINT_DATA_CHECKSUM_LEN 65
//---ESD Protect.---
#define NVT_SPI_TOUCH_ESD_PROTECT 0
#define NVT_SPI_TOUCH_ESD_CHECK_PERIOD 1500 /* ms */
#define NVT_SPI_TOUCH_WDT_RECOVERY 1
#define NVT_SPI_CHECK_PEN_DATA_CHECKSUM 0
struct nvt_spi_data_t {
struct spi_device *client;
struct input_dev *input_dev;
struct delayed_work nvt_fwu_work;
uint16_t addr;
int8_t phys[32];
#if defined(CONFIG_DRM)
struct notifier_block drm_panel_notif;
#elif defined(_MSM_DRM_NOTIFY_H_)
struct notifier_block drm_notif;
#else
struct notifier_block fb_notif;
#endif
uint8_t fw_ver;
uint8_t x_num;
uint8_t y_num;
uint16_t abs_x_max;
uint16_t abs_y_max;
uint8_t max_touch_num;
uint8_t max_button_num;
uint32_t int_trigger_type;
int32_t irq_gpio;
uint32_t irq_flags;
int32_t reset_gpio;
uint32_t reset_flags;
struct mutex lock;
const struct nvt_spi_mem_map *mmap;
uint8_t hw_crc;
uint16_t nvt_pid;
uint8_t *rbuf;
uint8_t *xbuf;
struct mutex xbuf_lock;
bool irq_enabled;
bool pen_support;
bool wgp_stylus;
uint8_t x_gang_num;
uint8_t y_gang_num;
struct input_dev *pen_input_dev;
int8_t pen_phys[32];
void *notifier_cookie;
const char *touch_environment;
#ifdef CONFIG_NOVATEK_SPI_TRUSTED_TOUCH
struct trusted_touch_vm_info *vm_info;
struct mutex fts_clk_io_ctrl_mutex;
struct completion trusted_touch_powerdown;
struct clk *core_clk;
struct clk *iface_clk;
atomic_t trusted_touch_initialized;
atomic_t trusted_touch_enabled;
atomic_t trusted_touch_underway;
atomic_t trusted_touch_event;
atomic_t trusted_touch_abort_status;
atomic_t delayed_vm_probe_pending;
atomic_t trusted_touch_mode;
#endif
};
#if NVT_SPI_TOUCH_PROC
struct nvt_spi_flash_data {
rwlock_t lock;
};
#endif
enum NVT_SPI_RST_COMPLETE_STATE {
NVT_SPI_RESET_STATE_INIT = 0xA0,// IC reset
NVT_SPI_RESET_STATE_REK, // ReK baseline
NVT_SPI_RESET_STATE_REK_FINISH, // baseline is ready
NVT_SPI_RESET_STATE_NORMAL_RUN, // normal run
NVT_SPI_RESET_STATE_MAX = 0xAF
};
enum NVT_SPI_EVENT_MAP {
NVT_SPI_EVENT_MAP_HOST_CMD = 0x50,
NVT_SPI_EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE = 0x51,
NVT_SPI_EVENT_MAP_RESET_COMPLETE = 0x60,
NVT_SPI_EVENT_MAP_FWINFO = 0x78,
NVT_SPI_EVENT_MAP_PROJECTID = 0x9A,
};
//---SPI READ/WRITE---
#define NVT_SPI_WRITE_MASK(a) (a | 0x80)
#define NVT_SPI_READ_MASK(a) (a & 0x7F)
#define NVT_SPI_DUMMY_BYTES (1)
#define NVT_SPI_TRANSFER_LEN (63*1024)
#define NVT_SPI_READ_LEN (2*1024)
#define NVT_SPI_XBUF_LEN (NVT_SPI_TRANSFER_LEN+1+NVT_SPI_DUMMY_BYTES)
enum NVT_SPI_RW {
NVT_SPI_WRITE = 0,
NVT_SPI_READ = 1
};
//---extern structures---
extern struct nvt_spi_data_t *nvt_spi_data;
//---extern functions---
int32_t nvt_spi_read(uint8_t *buf, uint16_t len);
int32_t nvt_spi_write(uint8_t *buf, uint16_t len);
void nvt_spi_bootloader_reset(void);
void nvt_spi_eng_reset(void);
void nvt_spi_sw_reset(void);
void nvt_spi_sw_reset_idle(void);
void nvt_spi_boot_ready(void);
void nvt_spi_bld_crc_enable(void);
void nvt_spi_fw_crc_enable(void);
void nvt_spi_tx_auto_copy_mode(void);
int32_t nvt_spi_update_firmware(char *firmware_name);
void nvt_spi_update_firmware_work(struct work_struct *work);
int32_t nvt_spi_check_fw_reset_state(enum NVT_SPI_RST_COMPLETE_STATE reset_state);
int32_t nvt_spi_get_fw_info(void);
int32_t nvt_spi_clear_fw_status(void);
int32_t nvt_spi_check_fw_status(void);
int32_t nvt_spi_check_spi_dma_tx_info(void);
int32_t nvt_spi_set_page(uint32_t addr);
int32_t nvt_spi_write_addr(uint32_t addr, uint8_t data);
#if NVT_SPI_TOUCH_EXT_PROC
int32_t nvt_spi_extra_proc_init(void);
void nvt_spi_extra_proc_deinit(void);
#endif
#if NVT_SPI_TOUCH_MP
extern int32_t nvt_spi_mp_proc_init(void);
extern void nvt_spi_mp_proc_deinit(void);
#endif
#if NVT_SPI_TOUCH_ESD_PROTECT
extern void nvt_spi_esd_check_enable(uint8_t enable);
#endif /* #if NVT_SPI_TOUCH_ESD_PROTECT */
#endif
#endif /* _LINUX_NVT_TOUCH_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,607 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 - 2018 Novatek, Inc.
*
* $Revision: 48764 $
* $Date: 2019-08-08 14:52:12 +0800 (Thu, 08 Aug 2019) $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#define CHIP_VER_TRIM_ADDR 0x3F004
#define CHIP_VER_TRIM_OLD_ADDR 0x1F64E
#if !defined(NVT_NT36XXX_SPI) /* NT36XXX I2C */
struct nvt_ts_mem_map {
uint32_t EVENT_BUF_ADDR;
uint32_t RAW_PIPE0_ADDR;
uint32_t RAW_PIPE1_ADDR;
uint32_t BASELINE_ADDR;
uint32_t BASELINE_BTN_ADDR;
uint32_t DIFF_PIPE0_ADDR;
uint32_t DIFF_PIPE1_ADDR;
uint32_t RAW_BTN_PIPE0_ADDR;
uint32_t RAW_BTN_PIPE1_ADDR;
uint32_t DIFF_BTN_PIPE0_ADDR;
uint32_t DIFF_BTN_PIPE1_ADDR;
uint32_t READ_FLASH_CHECKSUM_ADDR;
uint32_t RW_FLASH_DATA_ADDR;
};
struct nvt_ts_hw_info {
uint8_t carrier_system;
uint8_t hw_crc;
};
static const struct nvt_ts_mem_map NT36526_memory_map = {
.EVENT_BUF_ADDR = 0x22D00,
.RAW_PIPE0_ADDR = 0x24000,
.RAW_PIPE1_ADDR = 0x24000,
.BASELINE_ADDR = 0x21758,
.BASELINE_BTN_ADDR = 0,
.DIFF_PIPE0_ADDR = 0x20AB0,
.DIFF_PIPE1_ADDR = 0x24AB0,
.RAW_BTN_PIPE0_ADDR = 0,
.RAW_BTN_PIPE1_ADDR = 0,
.DIFF_BTN_PIPE0_ADDR = 0,
.DIFF_BTN_PIPE1_ADDR = 0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
};
static const struct nvt_ts_mem_map NT36675_memory_map = {
.EVENT_BUF_ADDR = 0x22D00,
.RAW_PIPE0_ADDR = 0x24000,
.RAW_PIPE1_ADDR = 0x24000,
.BASELINE_ADDR = 0x21B90,
.BASELINE_BTN_ADDR = 0,
.DIFF_PIPE0_ADDR = 0x20C60,
.DIFF_PIPE1_ADDR = 0x24C60,
.RAW_BTN_PIPE0_ADDR = 0,
.RAW_BTN_PIPE1_ADDR = 0,
.DIFF_BTN_PIPE0_ADDR = 0,
.DIFF_BTN_PIPE1_ADDR = 0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
};
static const struct nvt_ts_mem_map NT36672A_memory_map = {
.EVENT_BUF_ADDR = 0x21C00,
.RAW_PIPE0_ADDR = 0x20000,
.RAW_PIPE1_ADDR = 0x23000,
.BASELINE_ADDR = 0x20BFC,
.BASELINE_BTN_ADDR = 0x23BFC,
.DIFF_PIPE0_ADDR = 0x206DC,
.DIFF_PIPE1_ADDR = 0x236DC,
.RAW_BTN_PIPE0_ADDR = 0x20510,
.RAW_BTN_PIPE1_ADDR = 0x23510,
.DIFF_BTN_PIPE0_ADDR = 0x20BF0,
.DIFF_BTN_PIPE1_ADDR = 0x23BF0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
};
static const struct nvt_ts_mem_map NT36772_memory_map = {
.EVENT_BUF_ADDR = 0x11E00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10E70,
.BASELINE_BTN_ADDR = 0x12E70,
.DIFF_PIPE0_ADDR = 0x10830,
.DIFF_PIPE1_ADDR = 0x12830,
.RAW_BTN_PIPE0_ADDR = 0x10E60,
.RAW_BTN_PIPE1_ADDR = 0x12E60,
.DIFF_BTN_PIPE0_ADDR = 0x10E68,
.DIFF_BTN_PIPE1_ADDR = 0x12E68,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
};
static const struct nvt_ts_mem_map NT36525_memory_map = {
.EVENT_BUF_ADDR = 0x11A00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10B08,
.BASELINE_BTN_ADDR = 0x12B08,
.DIFF_PIPE0_ADDR = 0x1064C,
.DIFF_PIPE1_ADDR = 0x1264C,
.RAW_BTN_PIPE0_ADDR = 0x10634,
.RAW_BTN_PIPE1_ADDR = 0x12634,
.DIFF_BTN_PIPE0_ADDR = 0x10AFC,
.DIFF_BTN_PIPE1_ADDR = 0x12AFC,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
};
static const struct nvt_ts_mem_map NT36676F_memory_map = {
.EVENT_BUF_ADDR = 0x11A00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10B08,
.BASELINE_BTN_ADDR = 0x12B08,
.DIFF_PIPE0_ADDR = 0x1064C,
.DIFF_PIPE1_ADDR = 0x1264C,
.RAW_BTN_PIPE0_ADDR = 0x10634,
.RAW_BTN_PIPE1_ADDR = 0x12634,
.DIFF_BTN_PIPE0_ADDR = 0x10AFC,
.DIFF_BTN_PIPE1_ADDR = 0x12AFC,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
};
static struct nvt_ts_hw_info NT36526_hw_info = {
.carrier_system = 2,
.hw_crc = 2,
};
static struct nvt_ts_hw_info NT36675_hw_info = {
.carrier_system = 2,
.hw_crc = 2,
};
static struct nvt_ts_hw_info NT36672A_hw_info = {
.carrier_system = 0,
.hw_crc = 1,
};
static struct nvt_ts_hw_info NT36772_hw_info = {
.carrier_system = 0,
.hw_crc = 0,
};
static struct nvt_ts_hw_info NT36525_hw_info = {
.carrier_system = 0,
.hw_crc = 0,
};
static struct nvt_ts_hw_info NT36676F_hw_info = {
.carrier_system = 0,
.hw_crc = 0,
};
#define NVT_ID_BYTE_MAX 6
struct nvt_ts_trim_id_table {
uint8_t id[NVT_ID_BYTE_MAX];
uint8_t mask[NVT_ID_BYTE_MAX];
const struct nvt_ts_mem_map *mmap;
const struct nvt_ts_hw_info *hwinfo;
};
static const struct nvt_ts_trim_id_table trim_id_table[] = {
{.id = {0x20, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x00, 0xFF, 0xFF, 0x80, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x0C, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0E, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x0C, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x26, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36526_memory_map, .hwinfo = &NT36526_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x75, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36525_memory_map, .hwinfo = &NT36525_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36676F_memory_map, .hwinfo = &NT36676F_hw_info}
};
#else /* NT36XXX_SPI */
#define NVT_SPI_CHIP_VER_TRIM_ADDR 0x3F004
#define NVT_SPI_CHIP_VER_TRIM_OLD_ADDR 0x1F64E
struct nvt_spi_mem_map {
uint32_t EVENT_BUF_ADDR;
uint32_t RAW_PIPE0_ADDR;
uint32_t RAW_PIPE1_ADDR;
uint32_t BASELINE_ADDR;
uint32_t BASELINE_BTN_ADDR;
uint32_t DIFF_PIPE0_ADDR;
uint32_t DIFF_PIPE1_ADDR;
uint32_t RAW_BTN_PIPE0_ADDR;
uint32_t RAW_BTN_PIPE1_ADDR;
uint32_t DIFF_BTN_PIPE0_ADDR;
uint32_t DIFF_BTN_PIPE1_ADDR;
uint32_t PEN_2D_BL_TIP_X_ADDR;
uint32_t PEN_2D_BL_TIP_Y_ADDR;
uint32_t PEN_2D_BL_RING_X_ADDR;
uint32_t PEN_2D_BL_RING_Y_ADDR;
uint32_t PEN_2D_DIFF_TIP_X_ADDR;
uint32_t PEN_2D_DIFF_TIP_Y_ADDR;
uint32_t PEN_2D_DIFF_RING_X_ADDR;
uint32_t PEN_2D_DIFF_RING_Y_ADDR;
uint32_t PEN_2D_RAW_TIP_X_ADDR;
uint32_t PEN_2D_RAW_TIP_Y_ADDR;
uint32_t PEN_2D_RAW_RING_X_ADDR;
uint32_t PEN_2D_RAW_RING_Y_ADDR;
uint32_t PEN_1D_DIFF_TIP_X_ADDR;
uint32_t PEN_1D_DIFF_TIP_Y_ADDR;
uint32_t PEN_1D_DIFF_RING_X_ADDR;
uint32_t PEN_1D_DIFF_RING_Y_ADDR;
uint32_t READ_FLASH_CHECKSUM_ADDR;
uint32_t RW_FLASH_DATA_ADDR;
/* Phase 2 Host Download */
uint32_t BOOT_RDY_ADDR;
uint32_t POR_CD_ADDR;
uint32_t TX_AUTO_COPY_EN;
uint32_t SPI_DMA_TX_INFO;
/* BLD CRC */
uint32_t BLD_LENGTH_ADDR;
uint32_t ILM_LENGTH_ADDR;
uint32_t DLM_LENGTH_ADDR;
uint32_t BLD_DES_ADDR;
uint32_t ILM_DES_ADDR;
uint32_t DLM_DES_ADDR;
uint32_t G_ILM_CHECKSUM_ADDR;
uint32_t G_DLM_CHECKSUM_ADDR;
uint32_t R_ILM_CHECKSUM_ADDR;
uint32_t R_DLM_CHECKSUM_ADDR;
uint32_t BLD_CRC_EN_ADDR;
uint32_t DMA_CRC_EN_ADDR;
uint32_t BLD_ILM_DLM_CRC_ADDR;
uint32_t DMA_CRC_FLAG_ADDR;
};
struct nvt_spi_hw_info {
uint8_t hw_crc;
};
static const struct nvt_spi_mem_map NT36523_memory_map = {
.EVENT_BUF_ADDR = 0x2FE00,
.RAW_PIPE0_ADDR = 0x30FA0,
.RAW_PIPE1_ADDR = 0x30FA0,
.BASELINE_ADDR = 0x36510,
.BASELINE_BTN_ADDR = 0,
.DIFF_PIPE0_ADDR = 0x373E8,
.DIFF_PIPE1_ADDR = 0x38068,
.RAW_BTN_PIPE0_ADDR = 0,
.RAW_BTN_PIPE1_ADDR = 0,
.DIFF_BTN_PIPE0_ADDR = 0,
.DIFF_BTN_PIPE1_ADDR = 0,
.PEN_2D_BL_TIP_X_ADDR = 0x2988A,
.PEN_2D_BL_TIP_Y_ADDR = 0x29A1A,
.PEN_2D_BL_RING_X_ADDR = 0x29BAA,
.PEN_2D_BL_RING_Y_ADDR = 0x29D3A,
.PEN_2D_DIFF_TIP_X_ADDR = 0x29ECA,
.PEN_2D_DIFF_TIP_Y_ADDR = 0x2A05A,
.PEN_2D_DIFF_RING_X_ADDR = 0x2A1EA,
.PEN_2D_DIFF_RING_Y_ADDR = 0x2A37A,
.PEN_2D_RAW_TIP_X_ADDR = 0x2A50A,
.PEN_2D_RAW_TIP_Y_ADDR = 0x2A69A,
.PEN_2D_RAW_RING_X_ADDR = 0x2A82A,
.PEN_2D_RAW_RING_Y_ADDR = 0x2A9BA,
.PEN_1D_DIFF_TIP_X_ADDR = 0x2AB4A,
.PEN_1D_DIFF_TIP_Y_ADDR = 0x2ABAE,
.PEN_1D_DIFF_RING_X_ADDR = 0x2AC12,
.PEN_1D_DIFF_RING_Y_ADDR = 0x2AC76,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x3F10D,
.TX_AUTO_COPY_EN = 0x3F7E8,
.SPI_DMA_TX_INFO = 0x3F7F1,
/* BLD CRC */
.BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes)
.ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes)
.DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes)
.BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes)
.ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes)
.DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes)
.G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes)
.G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes)
.R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes)
.R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes)
.BLD_CRC_EN_ADDR = 0x3F30E,
.DMA_CRC_EN_ADDR = 0x3F136,
.BLD_ILM_DLM_CRC_ADDR = 0x3F133,
.DMA_CRC_FLAG_ADDR = 0x3F134,
};
static const struct nvt_spi_mem_map NT36526_memory_map = {
.EVENT_BUF_ADDR = 0x22D00,
.RAW_PIPE0_ADDR = 0x24000,
.RAW_PIPE1_ADDR = 0x24000,
.BASELINE_ADDR = 0x21758,
.BASELINE_BTN_ADDR = 0,
.DIFF_PIPE0_ADDR = 0x20AB0,
.DIFF_PIPE1_ADDR = 0x24AB0,
.RAW_BTN_PIPE0_ADDR = 0,
.RAW_BTN_PIPE1_ADDR = 0,
.DIFF_BTN_PIPE0_ADDR = 0,
.DIFF_BTN_PIPE1_ADDR = 0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x3F10D,
/* BLD CRC */
.BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes)
.ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes)
.DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes)
.BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes)
.ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes)
.DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes)
.G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes)
.G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes)
.R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes)
.R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes)
.BLD_CRC_EN_ADDR = 0x3F30E,
.DMA_CRC_EN_ADDR = 0x3F136,
.BLD_ILM_DLM_CRC_ADDR = 0x3F133,
.DMA_CRC_FLAG_ADDR = 0x3F134,
};
static const struct nvt_spi_mem_map NT36675_memory_map = {
.EVENT_BUF_ADDR = 0x22D00,
.RAW_PIPE0_ADDR = 0x24000,
.RAW_PIPE1_ADDR = 0x24000,
.BASELINE_ADDR = 0x21B90,
.BASELINE_BTN_ADDR = 0,
.DIFF_PIPE0_ADDR = 0x20C60,
.DIFF_PIPE1_ADDR = 0x24C60,
.RAW_BTN_PIPE0_ADDR = 0,
.RAW_BTN_PIPE1_ADDR = 0,
.DIFF_BTN_PIPE0_ADDR = 0,
.DIFF_BTN_PIPE1_ADDR = 0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x3F10D,
/* BLD CRC */
.BLD_LENGTH_ADDR = 0x3F138, //0x3F138 ~ 0x3F13A (3 bytes)
.ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F11A (3 bytes)
.DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F132 (3 bytes)
.BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes)
.ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes)
.DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes)
.G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes)
.G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes)
.R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes)
.R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes)
.BLD_CRC_EN_ADDR = 0x3F30E,
.DMA_CRC_EN_ADDR = 0x3F136,
.BLD_ILM_DLM_CRC_ADDR = 0x3F133,
.DMA_CRC_FLAG_ADDR = 0x3F134,
};
static const struct nvt_spi_mem_map NT36672A_memory_map = {
.EVENT_BUF_ADDR = 0x21C00,
.RAW_PIPE0_ADDR = 0x20000,
.RAW_PIPE1_ADDR = 0x23000,
.BASELINE_ADDR = 0x20BFC,
.BASELINE_BTN_ADDR = 0x23BFC,
.DIFF_PIPE0_ADDR = 0x206DC,
.DIFF_PIPE1_ADDR = 0x236DC,
.RAW_BTN_PIPE0_ADDR = 0x20510,
.RAW_BTN_PIPE1_ADDR = 0x23510,
.DIFF_BTN_PIPE0_ADDR = 0x20BF0,
.DIFF_BTN_PIPE1_ADDR = 0x23BF0,
.READ_FLASH_CHECKSUM_ADDR = 0x24000,
.RW_FLASH_DATA_ADDR = 0x24002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x3F10D,
/* BLD CRC */
.BLD_LENGTH_ADDR = 0x3F10E, //0x3F10E ~ 0x3F10F (2 bytes)
.ILM_LENGTH_ADDR = 0x3F118, //0x3F118 ~ 0x3F119 (2 bytes)
.DLM_LENGTH_ADDR = 0x3F130, //0x3F130 ~ 0x3F131 (2 bytes)
.BLD_DES_ADDR = 0x3F114, //0x3F114 ~ 0x3F116 (3 bytes)
.ILM_DES_ADDR = 0x3F128, //0x3F128 ~ 0x3F12A (3 bytes)
.DLM_DES_ADDR = 0x3F12C, //0x3F12C ~ 0x3F12E (3 bytes)
.G_ILM_CHECKSUM_ADDR = 0x3F100, //0x3F100 ~ 0x3F103 (4 bytes)
.G_DLM_CHECKSUM_ADDR = 0x3F104, //0x3F104 ~ 0x3F107 (4 bytes)
.R_ILM_CHECKSUM_ADDR = 0x3F120, //0x3F120 ~ 0x3F123 (4 bytes)
.R_DLM_CHECKSUM_ADDR = 0x3F124, //0x3F124 ~ 0x3F127 (4 bytes)
.BLD_CRC_EN_ADDR = 0x3F30E,
.DMA_CRC_EN_ADDR = 0x3F132,
.BLD_ILM_DLM_CRC_ADDR = 0x3F133,
.DMA_CRC_FLAG_ADDR = 0x3F134,
};
static const struct nvt_spi_mem_map NT36772_memory_map = {
.EVENT_BUF_ADDR = 0x11E00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10E70,
.BASELINE_BTN_ADDR = 0x12E70,
.DIFF_PIPE0_ADDR = 0x10830,
.DIFF_PIPE1_ADDR = 0x12830,
.RAW_BTN_PIPE0_ADDR = 0x10E60,
.RAW_BTN_PIPE1_ADDR = 0x12E60,
.DIFF_BTN_PIPE0_ADDR = 0x10E68,
.DIFF_BTN_PIPE1_ADDR = 0x12E68,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x1F141,
.POR_CD_ADDR = 0x1F61C,
/* BLD CRC */
.R_ILM_CHECKSUM_ADDR = 0x1BF00,
};
static const struct nvt_spi_mem_map NT36525_memory_map = {
.EVENT_BUF_ADDR = 0x11A00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10B08,
.BASELINE_BTN_ADDR = 0x12B08,
.DIFF_PIPE0_ADDR = 0x1064C,
.DIFF_PIPE1_ADDR = 0x1264C,
.RAW_BTN_PIPE0_ADDR = 0x10634,
.RAW_BTN_PIPE1_ADDR = 0x12634,
.DIFF_BTN_PIPE0_ADDR = 0x10AFC,
.DIFF_BTN_PIPE1_ADDR = 0x12AFC,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
/* Phase 2 Host Download */
.BOOT_RDY_ADDR = 0x1F141,
.POR_CD_ADDR = 0x1F61C,
/* BLD CRC */
.R_ILM_CHECKSUM_ADDR = 0x1BF00,
};
static const struct nvt_spi_mem_map NT36676F_memory_map = {
.EVENT_BUF_ADDR = 0x11A00,
.RAW_PIPE0_ADDR = 0x10000,
.RAW_PIPE1_ADDR = 0x12000,
.BASELINE_ADDR = 0x10B08,
.BASELINE_BTN_ADDR = 0x12B08,
.DIFF_PIPE0_ADDR = 0x1064C,
.DIFF_PIPE1_ADDR = 0x1264C,
.RAW_BTN_PIPE0_ADDR = 0x10634,
.RAW_BTN_PIPE1_ADDR = 0x12634,
.DIFF_BTN_PIPE0_ADDR = 0x10AFC,
.DIFF_BTN_PIPE1_ADDR = 0x12AFC,
.READ_FLASH_CHECKSUM_ADDR = 0x14000,
.RW_FLASH_DATA_ADDR = 0x14002,
};
static struct nvt_spi_hw_info NT36523_hw_info = {
.hw_crc = 2,
};
static struct nvt_spi_hw_info NT36526_hw_info = {
.hw_crc = 2,
};
static struct nvt_spi_hw_info NT36675_hw_info = {
.hw_crc = 2,
};
static struct nvt_spi_hw_info NT36672A_hw_info = {
.hw_crc = 1,
};
static struct nvt_spi_hw_info NT36772_hw_info = {
.hw_crc = 0,
};
static struct nvt_spi_hw_info NT36525_hw_info = {
.hw_crc = 0,
};
static struct nvt_spi_hw_info NT36676F_hw_info = {
.hw_crc = 0,
};
#define NVT_SPI_ID_BYTE_MAX 6
struct nvt_spi_trim_id_table_t {
uint8_t id[NVT_SPI_ID_BYTE_MAX];
uint8_t mask[NVT_SPI_ID_BYTE_MAX];
const struct nvt_spi_mem_map *mmap;
const struct nvt_spi_hw_info *hwinfo;
};
static const struct nvt_spi_trim_id_table_t nvt_spi_trim_id_table[] = {
{.id = {0x0D, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x20, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x00, 0xFF, 0xFF, 0x80, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x0C, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0E, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x20, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info},
{.id = {0x0C, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x23, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36523_memory_map, .hwinfo = &NT36523_hw_info},
{.id = {0x0C, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x26, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36526_memory_map, .hwinfo = &NT36526_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x75, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36675_memory_map, .hwinfo = &NT36675_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x65, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x82, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0B, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x0A, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
.mmap = &NT36672A_memory_map, .hwinfo = &NT36672A_hw_info},
{.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36772_memory_map, .hwinfo = &NT36772_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36525_memory_map, .hwinfo = &NT36525_hw_info},
{.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
.mmap = &NT36676F_memory_map, .hwinfo = &NT36676F_hw_info}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,460 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2010 - 2018 Novatek, Inc.
*
* $Revision: 46179 $
* $Date: 2019-06-14 13:47:17 +0800 (Fri, 14 Jun 2019) $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#if NVT_TOUCH_MP
static uint32_t IC_X_CFG_SIZE = 18;
static uint32_t IC_Y_CFG_SIZE = 36;
static uint32_t IC_KEY_CFG_SIZE = 4;
static uint32_t X_Channel = 18;
static uint32_t Y_Channel = 36;
static uint32_t Key_Channel = TOUCH_KEY_NUM;
static uint8_t AIN_X[40] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
static uint8_t AIN_Y[40] =
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};
#if TOUCH_KEY_NUM > 0
static uint8_t AIN_KEY[8] = {0, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
#endif /* #if TOUCH_KEY_NUM > 0 */
static int32_t PS_Config_Lmt_Short_Rawdata_P[40 * 40] = {
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,14008,
#if TOUCH_KEY_NUM > 0
14008,14008,14008,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_Short_Rawdata_N[40 * 40] = {
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,
#if TOUCH_KEY_NUM > 0
10000,10000,10000,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_Open_Rawdata_P[40 * 40] = {
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,5120,
#if TOUCH_KEY_NUM > 0
5120,5120,5120,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_Open_Rawdata_N[40 * 40] = {
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
#if TOUCH_KEY_NUM > 0
50,50,50,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_Rawdata_P[40 * 40] = {
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,2560,
#if TOUCH_KEY_NUM > 0
2560,2560,2560,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_Rawdata_N[40 * 40] = {
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
#if TOUCH_KEY_NUM > 0
240,240,240,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_CC_P[40 * 40] = {
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
#if TOUCH_KEY_NUM > 0
314,314,314,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_CC_N[40 * 40] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
#if TOUCH_KEY_NUM > 0
0,0,0,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_Diff_P[40 * 40] = {
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,
#if TOUCH_KEY_NUM > 0
75,75,75,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Lmt_FW_Diff_N[40 *40] = {
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,-75,
#if TOUCH_KEY_NUM > 0
-75,-75,-75,
#endif /* #if TOUCH_KEY_NUM > 0 */
};
static int32_t PS_Config_Diff_Test_Frame = 50;
#endif /* #if NVT_TOUCH_MP */

View File

@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define NVT_NT36XXX_SPI
#include "nt36xxx.c"

View File

@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define NVT_NT36XXX_SPI
#include "nt36xxx_ext_proc.c"

View File

@@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define NVT_NT36XXX_SPI
#include "nt36xxx_fw_update.c"

View File

@@ -0,0 +1,53 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-$(CONFIG_TOUCHSCREEN_PARADE) += pt.o
pt-y := pt_core.o pt_mt_common.o
pt-$(CONFIG_TOUCHSCREEN_PARADE_MT_A) += pt_mta.o
pt-$(CONFIG_TOUCHSCREEN_PARADE_MT_B) += pt_mtb.o
pt-$(CONFIG_TOUCHSCREEN_PARADE_BUTTON) += pt_btn.o
pt-$(CONFIG_TOUCHSCREEN_PARADE_PROXIMITY) += pt_proximity.o
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT) += pt_devtree.o
ifdef CONFIG_TOUCHSCREEN_PARADE
obj-y += pt_platform.o
endif
obj-$(CONFIG_TOUCHSCREEN_PARADE_I2C) += pt_i2c.o
obj-$(CONFIG_TOUCHSCREEN_PARADE_SPI) += pt_spi.o
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEBUG_MDL) += pt_debug.o
obj-$(CONFIG_TOUCHSCREEN_PARADE_LOADER) += pt_loader.o
obj-$(CONFIG_TOUCHSCREEN_PARADE_DEVICE_ACCESS) += pt_device_access.o
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_DEBUG),y)
CFLAGS_pt_core.o += -DDEBUG
CFLAGS_pt_i2c.o += -DDEBUG
CFLAGS_pt_spi.o += -DDEBUG
CFLAGS_pt_mta.o += -DDEBUG
CFLAGS_pt_mtb.o += -DDEBUG
CFLAGS_pt_mt_common.o += -DDEBUG
CFLAGS_pt_btn.o += -DDEBUG
CFLAGS_pt_proximity.o += -DDEBUG
CFLAGS_pt_device_access.o += -DDEBUG
CFLAGS_pt_loader.o += -DDEBUG
CFLAGS_pt_debug.o += -DDEBUG
CFLAGS_pt_devtree.o += -DDEBUG
CFLAGS_pt_platform.o += -DDEBUG
endif
ifeq ($(CONFIG_TOUCHSCREEN_PARADE_VDEBUG),y)
CFLAGS_pt_core.o += -DVERBOSE_DEBUG
CFLAGS_pt_i2c.o += -DVERBOSE_DEBUG
CFLAGS_pt_spi.o += -DVERBOSE_DEBUG
CFLAGS_pt_mta.o += -DVERBOSE_DEBUG
CFLAGS_pt_mtb.o += -DVERBOSE_DEBUG
CFLAGS_pt_mt_common.o += -DVERBOSE_DEBUG
CFLAGS_pt_btn.o += -DVERBOSE_DEBUG
CFLAGS_pt_proximity.o += -DVERBOSE_DEBUG
CFLAGS_pt_device_access.o += -DVERBOSE_DEBUG
CFLAGS_pt_loader.o += -DVERBOSE_DEBUG
CFLAGS_pt_debug.o += -DVERBOSE_DEBUG
CFLAGS_pt_devtree.o += -DVERBOSE_DEBUG
CFLAGS_pt_platform.o += -DVERBOSE_DEBUG
endif

View File

@@ -0,0 +1,522 @@
/*
* pt_btn.c
* Parade TrueTouch(TM) Standard Product CapSense Reports Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
/*******************************************************************************
* FUNCTION: pt_btn_key_action
*
* SUMMARY: Reports key event
*
* PARAMETERS:
* *bd - pointer to button data structure
* btn_no - number of button
* btn_state - state of button
******************************************************************************/
static inline void pt_btn_key_action(struct pt_btn_data *bd,
int btn_no, int btn_state)
{
struct device *dev = bd->dev;
struct pt_sysinfo *si = bd->si;
if (!si->btn[btn_no].enabled ||
si->btn[btn_no].state == btn_state)
return;
si->btn[btn_no].state = btn_state;
input_report_key(bd->input, si->btn[btn_no].key_code, btn_state);
input_sync(bd->input);
pt_debug(dev, DL_INFO, "%s: btn=%d key_code=%d %s\n",
__func__, btn_no, si->btn[btn_no].key_code,
btn_state == PT_BTN_PRESSED ?
"PRESSED" : "RELEASED");
}
/*******************************************************************************
* FUNCTION: pt_get_btn_touches
*
* SUMMARY: Parse and report key event
*
* PARAMETERS:
* *bd - pointer to button data structure
******************************************************************************/
static void pt_get_btn_touches(struct pt_btn_data *bd)
{
struct pt_sysinfo *si = bd->si;
int num_btns = si->num_btns;
int cur_btn;
int cur_btn_state;
for (cur_btn = 0; cur_btn < num_btns; cur_btn++) {
/* Get current button state */
cur_btn_state = (si->xy_data[0] >> (cur_btn * PT_BITS_PER_BTN))
& PT_NUM_BTN_EVENT_ID;
pt_btn_key_action(bd, cur_btn, cur_btn_state);
}
}
/*******************************************************************************
* FUNCTION: pt_btn_lift_all
*
* SUMMARY: Reports button liftoff action
*
* PARAMETERS:
* *bd - pointer to button data structure
******************************************************************************/
static void pt_btn_lift_all(struct pt_btn_data *bd)
{
struct pt_sysinfo *si = bd->si;
int i;
if (!si || si->num_btns == 0)
return;
for (i = 0; i < si->num_btns; i++)
pt_btn_key_action(bd, i, PT_BTN_RELEASED);
}
/*******************************************************************************
* FUNCTION: pt_xy_worker
*
* SUMMARY: Read xy_data for all current CapSense button touches
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *bd - pointer to button data structure
******************************************************************************/
static int pt_xy_worker(struct pt_btn_data *bd)
{
struct pt_sysinfo *si = bd->si;
/* extract button press/release touch information */
if (si->num_btns > 0)
pt_get_btn_touches(bd);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_btn_attention
*
* SUMMARY: Wrapper function for pt_xy_worker() that register to TTDL attention
* list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_btn_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
int rc;
if (bd->si->xy_mode[2] != bd->si->desc.btn_report_id)
return 0;
/* core handles handshake */
mutex_lock(&bd->btn_lock);
rc = pt_xy_worker(bd);
mutex_unlock(&bd->btn_lock);
if (rc < 0)
pt_debug(dev, DL_ERROR,
"%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_startup_attention
*
* SUMMARY: Wrapper function for pt_btn_lift_all() that register to TTDL
* attention list.
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_startup_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
mutex_lock(&bd->btn_lock);
pt_btn_lift_all(bd);
mutex_unlock(&bd->btn_lock);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_btn_suspend_attention
*
* SUMMARY: Function for button to enter suspend state that as following steps:
* 1) Lift all button
* 2) Set flag with suspend state
* 3) Decrese pm system count
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_btn_suspend_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
mutex_lock(&bd->btn_lock);
pt_btn_lift_all(bd);
bd->is_suspended = true;
mutex_unlock(&bd->btn_lock);
pm_runtime_put(dev);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_btn_resume_attention
*
* SUMMARY: Function for button to leave suspend state that as following steps:
* 1) Increse pm system count
* 2) Clear suspend state flag
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_btn_resume_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
pm_runtime_get(dev);
mutex_lock(&bd->btn_lock);
bd->is_suspended = false;
mutex_unlock(&bd->btn_lock);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_btn_open
*
* SUMMARY: Open method for input device(button) that sets up call back
* functions to TTDL attention list
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *input - pointer to input_dev structure
******************************************************************************/
static int pt_btn_open(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
pm_runtime_get_sync(dev);
mutex_lock(&bd->btn_lock);
bd->is_suspended = false;
mutex_unlock(&bd->btn_lock);
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
pt_btn_attention, PT_MODE_OPERATIONAL);
/* set up startup call back */
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
pt_startup_attention, 0);
/* set up suspend call back */
_pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
pt_btn_suspend_attention, 0);
/* set up resume call back */
_pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
pt_btn_resume_attention, 0);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_btn_close
*
* SUMMARY: Close method for input device(button) that clears call back
* functions from TTDL attention list.
*
* PARAMETERS:
* *input - pointer to input_dev structure
******************************************************************************/
static void pt_btn_close(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_BTN_NAME,
pt_btn_attention, PT_MODE_OPERATIONAL);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
pt_startup_attention, 0);
_pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_BTN_NAME,
pt_btn_suspend_attention, 0);
_pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_BTN_NAME,
pt_btn_resume_attention, 0);
mutex_lock(&bd->btn_lock);
if (!bd->is_suspended) {
pm_runtime_put(dev);
bd->is_suspended = true;
}
mutex_unlock(&bd->btn_lock);
}
/*******************************************************************************
* FUNCTION: pt_setup_input_device
*
* SUMMARY: Set up resolution, event signal capabilities and register input
* device for button.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_device(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
int i;
int rc;
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
__func__);
__set_bit(EV_KEY, bd->input->evbit);
pt_debug(dev, DL_INFO, "%s: Number of buttons %d\n",
__func__, bd->si->num_btns);
for (i = 0; i < bd->si->num_btns; i++) {
pt_debug(dev, DL_INFO, "%s: btn:%d keycode:%d\n",
__func__, i, bd->si->btn[i].key_code);
__set_bit(bd->si->btn[i].key_code, bd->input->keybit);
}
rc = input_register_device(bd->input);
if (rc < 0)
pt_debug(dev, DL_ERROR,
"%s: Error, failed register input device r=%d\n",
__func__, rc);
else
bd->input_device_registered = true;
return rc;
}
/*******************************************************************************
* FUNCTION: pt_setup_input_attention
*
* SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
* attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
int rc;
bd->si = _pt_request_sysinfo(dev);
if (!bd->si)
return -EPERM;
rc = pt_setup_input_device(dev);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_BTN_NAME,
pt_setup_input_attention, 0);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_btn_probe
*
* SUMMARY: The probe function for button input device
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_btn_probe(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_btn_data *bd = &cd->bd;
struct pt_platform_data *pdata = dev_get_platdata(dev);
struct pt_btn_platform_data *btn_pdata;
int rc = 0;
if (!pdata || !pdata->btn_pdata) {
pt_debug(dev, DL_ERROR,
"%s: Missing platform data\n", __func__);
rc = -ENODEV;
goto error_no_pdata;
}
btn_pdata = pdata->btn_pdata;
mutex_init(&bd->btn_lock);
bd->dev = dev;
bd->pdata = btn_pdata;
/* Create the input device and register it. */
pt_debug(dev, DL_INFO,
"%s: Create the input device and register it\n", __func__);
bd->input = input_allocate_device();
if (!bd->input) {
pt_debug(dev, DL_ERROR,
"%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
} else
bd->input_device_allocated = true;
if (bd->pdata->inp_dev_name)
bd->input->name = bd->pdata->inp_dev_name;
else
bd->input->name = PT_BTN_NAME;
scnprintf(bd->phys, sizeof(bd->phys), "%s/input%d", dev_name(dev),
cd->phys_num++);
bd->input->phys = bd->phys;
bd->input->dev.parent = bd->dev;
bd->input->open = pt_btn_open;
bd->input->close = pt_btn_close;
input_set_drvdata(bd->input, bd);
/* get sysinfo */
bd->si = _pt_request_sysinfo(dev);
if (bd->si) {
rc = pt_setup_input_device(dev);
if (rc)
goto error_init_input;
} else {
pt_debug(dev, DL_ERROR,
"%s: Fail get sysinfo pointer from core p=%p\n",
__func__, bd->si);
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
PT_BTN_NAME, pt_setup_input_attention, 0);
}
return 0;
error_init_input:
input_free_device(bd->input);
bd->input_device_allocated = false;
error_alloc_failed:
error_no_pdata:
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_btn_release
*
* SUMMARY: The release function for button input device
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_btn_release(struct device *dev)
{
struct pt_core_data *cd;
struct pt_btn_data *bd;
/* Ensure valid pointers before de-referencing them */
if (dev) {
cd = dev_get_drvdata(dev);
if (cd)
bd = &cd->bd;
else
return 0;
} else {
return 0;
}
/*
* Second call this function may cause kernel panic if probe fail.
* Use input_device_registered & input_device_allocated variable to
* avoid unregister or free unavailable devive.
*/
if (bd && bd->input_device_registered) {
bd->input_device_registered = false;
input_unregister_device(bd->input);
/* Unregistering device will free the device too */
bd->input_device_allocated = false;
} else if (bd && bd->input_device_allocated) {
bd->input_device_allocated = false;
input_free_device(bd->input);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
PT_BTN_NAME, pt_setup_input_attention, 0);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,230 @@
/*
* pt_core.h
* Parade TrueTouch(TM) Standard Product Core Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.parade.com <ttdrivers@paradetech.com>
*/
#ifndef _LINUX_PT_CORE_H
#define _LINUX_PT_CORE_H
#include <linux/stringify.h>
#include <drm/drm_panel.h>
#define PT_I2C_NAME "pt_i2c_adapter"
#define PT_SPI_NAME "pt_spi_adapter"
#define PT_CORE_NAME "pt_core"
#define PT_MT_NAME "pt_mt"
#define PT_BTN_NAME "pt_btn"
#define PT_PROXIMITY_NAME "pt_proximity"
#define PT_DRIVER_NAME TTDL
#define PT_DRIVER_MAJOR 04
#define PT_DRIVER_MINOR 11
#define PT_DRIVER_REVCTRL 977092
#define PT_DRIVER_VERSION \
__stringify(PT_DRIVER_NAME) \
"." __stringify(PT_DRIVER_MAJOR) \
"." __stringify(PT_DRIVER_MINOR) \
"." __stringify(PT_DRIVER_REVCTRL)
#define PT_DRIVER_DATE "20201210"
/* abs settings */
#define PT_IGNORE_VALUE -1
enum pt_core_platform_flags {
PT_CORE_FLAG_NONE,
PT_CORE_FLAG_POWEROFF_ON_SLEEP = 0x02,
PT_CORE_FLAG_RESTORE_PARAMETERS = 0x04,
PT_CORE_FLAG_DEEP_STANDBY = 0x08,
PT_CORE_FLAG_SKIP_SYS_SLEEP = 0x10,
PT_CORE_FLAG_SKIP_RUNTIME = 0x20,
PT_CORE_FLAG_SKIP_RESUME = 0x40,
};
enum pt_core_platform_easy_wakeup_gesture {
PT_CORE_EWG_NONE,
PT_CORE_EWG_TAP_TAP,
PT_CORE_EWG_TWO_FINGER_SLIDE,
PT_CORE_EWG_RESERVED,
PT_CORE_EWG_WAKE_ON_INT_FROM_HOST = 0xFF,
};
enum pt_loader_platform_flags {
PT_LOADER_FLAG_NONE,
PT_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE,
/* Use CONFIG_VER field in TT_CFG to decide TT_CFG update */
PT_LOADER_FLAG_CHECK_TTCONFIG_VERSION,
PT_LOADER_FLAG_CALIBRATE_AFTER_TTCONFIG_UPGRADE,
};
enum CONFIG_DUT_GENERATION {
CONFIG_DUT_AUTO_DETECT = 0x00,
CONFIG_DUT_PIP1_ONLY = 0x01,
CONFIG_DUT_PIP2_CAPABLE = 0x02,
};
enum pt_core_platform_panel_id_flags {
PT_PANEL_ID_DISABLE = 0x00,
PT_PANEL_ID_BY_BL = 0x01,
PT_PANEL_ID_BY_SYS_INFO = 0x02,
PT_PANEL_ID_BY_MFG_DATA = 0x04,
};
struct touch_settings {
const uint8_t *data;
uint32_t size;
uint8_t tag;
};
struct pt_touch_firmware {
const uint8_t *img;
uint32_t size;
const uint8_t *ver;
uint8_t vsize;
uint8_t panel_id;
};
struct pt_touch_config {
struct touch_settings *param_regs;
struct touch_settings *param_size;
const uint8_t *fw_ver;
uint8_t fw_vsize;
uint8_t panel_id;
};
struct pt_loader_platform_data {
struct pt_touch_firmware *fw;
struct pt_touch_config *ttconfig;
struct pt_touch_firmware **fws;
struct pt_touch_config **ttconfigs;
u32 flags;
};
typedef int (*pt_platform_read) (struct device *dev, void *buf, int size);
#define PT_TOUCH_SETTINGS_MAX 32
struct pt_core_platform_data {
int irq_gpio;
u32 irq_gpio_flags;
int rst_gpio;
u32 rst_gpio_flags;
int ddi_rst_gpio;
int vddi_gpio;
int vcc_gpio;
int avdd_gpio;
int avee_gpio;
int level_irq_udelay;
u16 hid_desc_register;
u16 vendor_id;
u16 product_id;
int (*xres)(struct pt_core_platform_data *pdata,
struct device *dev);
int (*init)(struct pt_core_platform_data *pdata,
int on, struct device *dev);
int (*power)(struct pt_core_platform_data *pdata,
int on, struct device *dev, atomic_t *ignore_irq);
int (*detect)(struct pt_core_platform_data *pdata,
struct device *dev, pt_platform_read read);
int (*irq_stat)(struct pt_core_platform_data *pdata,
struct device *dev);
int (*setup_power)(struct pt_core_platform_data *pdata,
int on, struct device *dev);
int (*setup_irq)(struct pt_core_platform_data *pdata,
int on, struct device *dev);
struct touch_settings *sett[PT_TOUCH_SETTINGS_MAX];
u32 flags;
u8 easy_wakeup_gesture;
u8 config_dut_generation;
u8 watchdog_force_stop;
u8 panel_id_support;
struct device_node *node;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_suspend;
struct pinctrl_state *pins_release;
struct drm_panel *active_panel;
};
struct touch_framework {
const int16_t *abs;
uint8_t size;
uint8_t enable_vkeys;
} __packed;
enum pt_mt_platform_power_state {
PT_MT_POWER_OFF = 0x00,
PT_MT_POWER_ON = 0x01
};
enum pt_mt_platform_irq_state {
PT_MT_IRQ_FREE = 0x00,
PT_MT_IRQ_REG = 0x01
};
enum pt_mt_platform_flags {
PT_MT_FLAG_NONE,
PT_MT_FLAG_HOVER = 0x04,
PT_MT_FLAG_FLIP = 0x08,
PT_MT_FLAG_INV_X = 0x10,
PT_MT_FLAG_INV_Y = 0x20,
PT_MT_FLAG_VKEYS = 0x40,
PT_MT_FLAG_NO_TOUCH_ON_LO = 0x80,
};
struct pt_mt_platform_data {
struct touch_framework *frmwrk;
unsigned short flags;
char const *inp_dev_name;
int vkeys_x;
int vkeys_y;
};
struct pt_btn_platform_data {
char const *inp_dev_name;
};
struct pt_proximity_platform_data {
struct touch_framework *frmwrk;
char const *inp_dev_name;
};
struct pt_platform_data {
struct pt_core_platform_data *core_pdata;
struct pt_mt_platform_data *mt_pdata;
struct pt_btn_platform_data *btn_pdata;
struct pt_proximity_platform_data *prox_pdata;
struct pt_loader_platform_data *loader_pdata;
};
#endif /* _LINUX_PT_CORE_H */

View File

@@ -0,0 +1,556 @@
/*
* pt_debug.c
* Parade TrueTouch(TM) Standard Product Debug Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
#define PT_DEBUG_NAME "pt_debug"
struct pt_debug_data {
struct device *dev;
struct pt_sysinfo *si;
uint32_t interrupt_count;
uint32_t formated_output;
struct mutex sysfs_lock;
u8 pr_buf[PT_MAX_PRBUF_SIZE];
};
static struct pt_core_commands *cmd;
static struct pt_module debug_module;
/*******************************************************************************
* FUNCTION: pt_get_debug_data
*
* SUMMARY: Inline function to get pt_debug_data pointer from debug module.
*
* RETURN:
* pointer to pt_debug_data structure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static inline struct pt_debug_data *pt_get_debug_data(
struct device *dev)
{
return pt_get_module_data(dev, &debug_module);
}
/*******************************************************************************
* FUNCTION: pt_pr_buf_op_mode
*
* SUMMARY: Formats touch/button report to pr_buf that combined xy_mode and
* xy_data. The feature is required by TTHE.
*
* PARAMETERS:
* *dd - pointer to pt_debug_data structure
* *pr_buf - pointer to print buffer
* *si - pointer to sysinfo structure
* cur_touch - number of current touch
******************************************************************************/
static void pt_pr_buf_op_mode(struct pt_debug_data *dd, u8 *pr_buf,
struct pt_sysinfo *si, u8 cur_touch)
{
const char fmt[] = "%02X ";
int max = (PT_MAX_PRBUF_SIZE - 1) - sizeof(PT_PR_TRUNCATED);
u8 report_id = si->xy_mode[2];
int header_size = 0;
int report_size = 0;
int total_size = 0;
int i, k;
if (report_id == si->desc.tch_report_id) {
header_size = si->desc.tch_header_size;
report_size = cur_touch * si->desc.tch_record_size;
} else if (report_id == si->desc.btn_report_id) {
header_size = BTN_INPUT_HEADER_SIZE;
report_size = BTN_REPORT_SIZE;
}
total_size = header_size + report_size;
pr_buf[0] = 0;
for (i = k = 0; i < header_size && i < max; i++, k += 3)
scnprintf(pr_buf + k, PT_MAX_PRBUF_SIZE, fmt, si->xy_mode[i]);
for (i = 0; i < report_size && i < max; i++, k += 3)
scnprintf(pr_buf + k, PT_MAX_PRBUF_SIZE, fmt, si->xy_data[i]);
pr_info("%s=%s%s\n", "pt_OpModeData", pr_buf,
total_size <= max ? "" : PT_PR_TRUNCATED);
}
/*******************************************************************************
* FUNCTION: pt_debug_print
*
* SUMMARY: This function prints header to show data size and data_name and
* content of "pr_buf" with hex base.
*
* PARAMETERS:
* *dev - pointer to device structure
* *pr_buf - pointer to input buffer which stores the formated data
* *sptr - pointer to the buffer to print
* size - size of data elements
* *data_name - data name to print
******************************************************************************/
static void pt_debug_print(struct device *dev, u8 *pr_buf, u8 *sptr,
int size, const char *data_name)
{
int i, j;
int elem_size = sizeof("XX ") - 1;
int max = (PT_MAX_PRBUF_SIZE - 1) / elem_size;
int limit = size < max ? size : max;
if (limit < 0)
limit = 0;
pr_buf[0] = 0;
for (i = j = 0; i < limit; i++, j += elem_size)
scnprintf(pr_buf + j, PT_MAX_PRBUF_SIZE - j, "%02X ", sptr[i]);
if (size)
pr_info("%s[0..%d]=%s%s\n", data_name, size - 1, pr_buf,
size <= max ? "" : PT_PR_TRUNCATED);
else
pr_info("%s[]\n", data_name);
}
/*******************************************************************************
* FUNCTION: pt_debug_formated
*
* SUMMARY: Formats and prints touch & button report.
*
* PARAMETERS:
* *dev - pointer to device structure
* *pr_buf - pointer to print buffer
* *si - pointer to sysinfo structure
* cur_touch - number of current touch
******************************************************************************/
static void pt_debug_formated(struct device *dev, u8 *pr_buf,
struct pt_sysinfo *si, u8 num_cur_tch)
{
u8 report_id = si->xy_mode[2];
int header_size = 0;
int report_size = 0;
u8 data_name[] = "touch[99]";
int max_print_length = 20;
int i;
if (report_id == si->desc.tch_report_id) {
header_size = si->desc.tch_header_size;
report_size = num_cur_tch * si->desc.tch_record_size;
} else if (report_id == si->desc.btn_report_id) {
header_size = BTN_INPUT_HEADER_SIZE;
report_size = BTN_REPORT_SIZE;
}
/* xy_mode */
pt_debug_print(dev, pr_buf, si->xy_mode, header_size, "xy_mode");
/* xy_data */
if (report_size > max_print_length) {
pr_info("xy_data[0..%d]:\n", report_size);
for (i = 0; i < report_size - max_print_length;
i += max_print_length) {
pt_debug_print(dev, pr_buf, si->xy_data + i,
max_print_length, " ");
}
if (report_size - i)
pt_debug_print(dev, pr_buf, si->xy_data + i,
report_size - i, " ");
} else {
pt_debug_print(dev, pr_buf, si->xy_data, report_size,
"xy_data");
}
/* touches */
if (report_id == si->desc.tch_report_id) {
for (i = 0; i < num_cur_tch; i++) {
scnprintf(data_name, sizeof(data_name) - 1,
"touch[%u]", i);
pt_debug_print(dev, pr_buf,
si->xy_data + (i * si->desc.tch_record_size),
si->desc.tch_record_size, data_name);
}
}
/* buttons */
if (report_id == si->desc.btn_report_id)
pt_debug_print(dev, pr_buf, si->xy_data, report_size,
"button");
}
/*******************************************************************************
* FUNCTION: pt_xy_worker
*
* SUMMARY: Read xy_data for all touches for debug.
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dd - pointer to pt_debug_data structure
******************************************************************************/
static int pt_xy_worker(struct pt_debug_data *dd)
{
struct device *dev = dd->dev;
struct pt_sysinfo *si = dd->si;
u8 report_reg = si->xy_mode[TOUCH_COUNT_BYTE_OFFSET];
u8 num_cur_tch = GET_NUM_TOUCHES(report_reg);
uint32_t formated_output;
mutex_lock(&dd->sysfs_lock);
dd->interrupt_count++;
formated_output = dd->formated_output;
mutex_unlock(&dd->sysfs_lock);
/* Interrupt */
pr_info("Interrupt(%u)\n", dd->interrupt_count);
if (formated_output)
pt_debug_formated(dev, dd->pr_buf, si, num_cur_tch);
else
/* print data for TTHE */
pt_pr_buf_op_mode(dd, dd->pr_buf, si, num_cur_tch);
pr_info("\n");
return 0;
}
/*******************************************************************************
* FUNCTION: pt_debug_attention
*
* SUMMARY: Wrapper function for pt_xy_worker() to subcribe into TTDL attention
* list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_debug_attention(struct device *dev)
{
struct pt_debug_data *dd = pt_get_debug_data(dev);
struct pt_sysinfo *si = dd->si;
u8 report_id = si->xy_mode[2];
int rc = 0;
if (report_id != si->desc.tch_report_id
&& report_id != si->desc.btn_report_id)
return 0;
/* core handles handshake */
rc = pt_xy_worker(dd);
if (rc < 0)
pt_debug(dev, DL_ERROR, "%s: xy_worker error r=%d\n",
__func__, rc);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_status_show
*
* SUMMARY: The show method for the int_count sysfs node. This node displays
* the count of interrupt.
*
* PARAMETERS:
* *dev - pointer to Device structure
* *attr - pointer to the device attribute structure
* *buf - pointer to buffer to print
******************************************************************************/
static ssize_t pt_interrupt_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pt_debug_data *dd = pt_get_debug_data(dev);
int val;
mutex_lock(&dd->sysfs_lock);
val = dd->interrupt_count;
mutex_unlock(&dd->sysfs_lock);
return scnprintf(buf, PT_MAX_PRBUF_SIZE, "Interrupt Count: %d\n", val);
}
/*******************************************************************************
* FUNCTION: pt_interrupt_count_store
*
* SUMMARY: The store method for the int_count sysfs node that allows the count
* of interrput to be cleared.
*
* RETURN: Size of passed in buffer
*
* PARAMETERS:
* *dev - pointer to device structure
* *attr - pointer to device attributes
* *buf - pointer to buffer that hold the command parameters
* size - size of buf
******************************************************************************/
static ssize_t pt_interrupt_count_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct pt_debug_data *dd = pt_get_debug_data(dev);
mutex_lock(&dd->sysfs_lock);
dd->interrupt_count = 0;
mutex_unlock(&dd->sysfs_lock);
return size;
}
static DEVICE_ATTR(int_count, 0600,
pt_interrupt_count_show, pt_interrupt_count_store);
/*******************************************************************************
* FUNCTION: pt_formated_output_show
*
* SUMMARY: Show method for the formated_output sysfs node that will show
* whether to format data to buffer or print directly.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
* *attr - pointer to device attributes
* *buf - pointer to output buffer
******************************************************************************/
static ssize_t pt_formated_output_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pt_debug_data *dd = pt_get_debug_data(dev);
int val;
mutex_lock(&dd->sysfs_lock);
val = dd->formated_output;
mutex_unlock(&dd->sysfs_lock);
return scnprintf(buf, PT_MAX_PRBUF_SIZE,
"Formated debug output: %x\n", val);
}
/*******************************************************************************
* FUNCTION: pt_formated_output_store
*
* SUMMARY: The store method for the formated_output sysfs node. Allows the
* setting to format data to buffer or print directly.
*
* RETURN: Size of passed in buffer
*
* PARAMETERS:
* *dev - pointer to device structure
* *attr - pointer to device attributes
* *buf - pointer to buffer that hold the command parameters
* size - size of buf
******************************************************************************/
static ssize_t pt_formated_output_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct pt_debug_data *dd = pt_get_debug_data(dev);
unsigned long value;
int rc;
rc = kstrtoul(buf, 10, &value);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Invalid value\n", __func__);
return size;
}
/* Expecting only 0 or 1 */
if (value != 0 && value != 1) {
pt_debug(dev, DL_ERROR, "%s: Invalid value %lu\n",
__func__, value);
return size;
}
mutex_lock(&dd->sysfs_lock);
dd->formated_output = value;
mutex_unlock(&dd->sysfs_lock);
return size;
}
static DEVICE_ATTR(formated_output, 0600,
pt_formated_output_show, pt_formated_output_store);
/*******************************************************************************
* FUNCTION: pt_mt_probe
*
* SUMMARY: The probe function for debug module to create sysfs nodes and
* subscribe attention list.
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
* **data - double pointer tothe pt_debug_data structure to be created here
******************************************************************************/
static int pt_debug_probe(struct device *dev, void **data)
{
struct pt_debug_data *dd;
int rc;
/* get context and debug print buffers */
dd = kzalloc(sizeof(*dd), GFP_KERNEL);
if (!dd) {
rc = -ENOMEM;
goto pt_debug_probe_alloc_failed;
}
rc = device_create_file(dev, &dev_attr_int_count);
if (rc) {
pt_debug(dev, DL_ERROR, "%s: Error, could not create int_count\n",
__func__);
goto pt_debug_probe_create_int_count_failed;
}
rc = device_create_file(dev, &dev_attr_formated_output);
if (rc) {
pt_debug(dev, DL_ERROR, "%s: Error, could not create formated_output\n",
__func__);
goto pt_debug_probe_create_formated_failed;
}
mutex_init(&dd->sysfs_lock);
dd->dev = dev;
*data = dd;
dd->si = cmd->request_sysinfo(dev);
if (!dd->si) {
pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core\n",
__func__);
rc = -ENODEV;
goto pt_debug_probe_sysinfo_failed;
}
rc = cmd->subscribe_attention(dev, PT_ATTEN_IRQ, PT_DEBUG_NAME,
pt_debug_attention, PT_MODE_OPERATIONAL);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error, could not subscribe attention cb\n",
__func__);
goto pt_debug_probe_subscribe_failed;
}
return 0;
pt_debug_probe_subscribe_failed:
pt_debug_probe_sysinfo_failed:
device_remove_file(dev, &dev_attr_formated_output);
pt_debug_probe_create_formated_failed:
device_remove_file(dev, &dev_attr_int_count);
pt_debug_probe_create_int_count_failed:
kfree(dd);
pt_debug_probe_alloc_failed:
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_debug_release
*
* SUMMARY: Remove function for debug module that does following cleanup:
* - Unsubscibe all registered attention tasks
* - Removes all created sysfs nodes
*
* PARAMETERS:
* *dev - pointer to device structure
* *data - pointer to the pt_debug_data structure
******************************************************************************/
static void pt_debug_release(struct device *dev, void *data)
{
struct pt_debug_data *dd = data;
int rc;
rc = cmd->unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_DEBUG_NAME,
pt_debug_attention, PT_MODE_OPERATIONAL);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error, could not un-subscribe attention\n",
__func__);
goto pt_debug_release_exit;
}
pt_debug_release_exit:
device_remove_file(dev, &dev_attr_formated_output);
device_remove_file(dev, &dev_attr_int_count);
kfree(dd);
}
static struct pt_module debug_module = {
.name = PT_DEBUG_NAME,
.probe = pt_debug_probe,
.release = pt_debug_release,
};
/*******************************************************************************
* FUNCTION: pt_debug_init
*
* SUMMARY: Initialize function for debug module which to register
* debug_module into TTDL module list.
*
* RETURN:
* 0 = success
******************************************************************************/
static int __init pt_debug_init(void)
{
int rc;
cmd = pt_get_commands();
if (!cmd)
return -EINVAL;
rc = pt_register_module(&debug_module);
if (rc < 0) {
pr_err("%s: Error, failed registering module\n",
__func__);
return rc;
}
pr_info("%s: Parade TTSP Debug Driver (Built %s) rc=%d\n",
__func__, PT_DRIVER_VERSION, rc);
return 0;
}
module_init(pt_debug_init);
/*******************************************************************************
* FUNCTION: pt_debug_exit
*
* SUMMARY: Exit function for debug module which to unregister debug_module
* from TTDL module list.
*
******************************************************************************/
static void __exit pt_debug_exit(void)
{
pt_unregister_module(&debug_module);
}
module_exit(pt_debug_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product Debug Driver");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,328 @@
/*
* pt_i2c.c
* Parade TrueTouch(TM) Standard Product I2C Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
#include <linux/i2c.h>
#include <linux/version.h>
#define PT_I2C_DATA_SIZE (2 * 256)
#define PT_I2C_NAME "pt_i2c_adapter"
/*******************************************************************************
* FUNCTION: pt_i2c_read_default
*
* SUMMARY: Read a certain number of bytes from the I2C bus
*
* PARAMETERS:
* *dev - pointer to Device structure
* *buf - pointer to buffer where the data read will be stored
* size - size to be read
******************************************************************************/
static int pt_i2c_read_default(struct device *dev, void *buf, int size)
{
struct i2c_client *client = to_i2c_client(dev);
int rc;
int read_size = size;
if (!buf || !size || size > PT_I2C_DATA_SIZE)
return -EINVAL;
rc = i2c_master_recv(client, buf, read_size);
return (rc < 0) ? rc : rc != read_size ? -EIO : 0;
}
/*******************************************************************************
* FUNCTION: pt_i2c_read_default_nosize
*
* SUMMARY: Read from the I2C bus in two transactions first reading the HID
* packet size (2 bytes) followed by reading the rest of the packet based
* on the size initially read.
* NOTE: The empty buffer 'size' was redefined in PIP version 1.7.
*
* PARAMETERS:
* *dev - pointer to Device structure
* *buf - pointer to buffer where the data read will be stored
* max - max size that can be read
******************************************************************************/
static int pt_i2c_read_default_nosize(struct device *dev, u8 *buf, u32 max)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_msg msgs[2];
u8 msg_count = 1;
int rc;
u32 size;
if (!buf)
return -EINVAL;
msgs[0].addr = client->addr;
msgs[0].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
msgs[0].len = 2;
msgs[0].buf = buf;
rc = i2c_transfer(client->adapter, msgs, msg_count);
if (rc < 0 || rc != msg_count)
return (rc < 0) ? rc : -EIO;
size = get_unaligned_le16(&buf[0]);
if (!size || size == 2 || size >= PT_PIP_1P7_EMPTY_BUF)
/*
* Before PIP 1.7, empty buffer is 0x0002;
* From PIP 1.7, empty buffer is 0xFFXX
*/
return 0;
if (size > max)
return -EINVAL;
rc = i2c_master_recv(client, buf, size);
return (rc < 0) ? rc : rc != (int)size ? -EIO : 0;
}
/*******************************************************************************
* FUNCTION: pt_i2c_write_read_specific
*
* SUMMARY: Write the contents of write_buf to the I2C device and then read
* the response using pt_i2c_read_default_nosize()
*
* PARAMETERS:
* *dev - pointer to Device structure
* write_len - length of data buffer write_buf
* *write_buf - pointer to buffer to write
* *read_buf - pointer to buffer to read response into
******************************************************************************/
static int pt_i2c_write_read_specific(struct device *dev, u16 write_len,
u8 *write_buf, u8 *read_buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_msg msgs[2];
u8 msg_count = 1;
int rc;
/* Ensure no packet larger than what the PIP spec allows */
if (write_len > PT_MAX_PIP2_MSG_SIZE)
return -EINVAL;
if (!write_buf || !write_len) {
if (!write_buf)
pt_debug(dev, DL_ERROR,
"%s write_buf is NULL", __func__);
if (!write_len)
pt_debug(dev, DL_ERROR,
"%s write_len is NULL", __func__);
return -EINVAL;
}
msgs[0].addr = client->addr;
msgs[0].flags = client->flags & I2C_M_TEN;
msgs[0].len = write_len;
msgs[0].buf = write_buf;
rc = i2c_transfer(client->adapter, msgs, msg_count);
if (rc < 0 || rc != msg_count)
return (rc < 0) ? rc : -EIO;
rc = 0;
if (read_buf) {
rc = pt_i2c_read_default_nosize(dev, read_buf,
PT_I2C_DATA_SIZE);
}
return rc;
}
static struct pt_bus_ops pt_i2c_bus_ops = {
.bustype = BUS_I2C,
.read_default = pt_i2c_read_default,
.read_default_nosize = pt_i2c_read_default_nosize,
.write_read_specific = pt_i2c_write_read_specific,
};
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
static const struct of_device_id pt_i2c_of_match[] = {
{ .compatible = "parade,pt_i2c_adapter", },
{ }
};
MODULE_DEVICE_TABLE(of, pt_i2c_of_match);
#endif
/*******************************************************************************
* FUNCTION: pt_i2c_probe
*
* SUMMARY: Probe functon for the I2C module
*
* PARAMETERS:
* *client - pointer to i2c client structure
* *i2c_id - pointer to i2c device structure
******************************************************************************/
static int pt_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id)
{
struct device *dev = &client->dev;
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
int rc;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
pt_debug(dev, DL_ERROR, "I2C functionality not Supported\n");
return -EIO;
}
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(pt_i2c_of_match), dev);
if (match) {
rc = pt_devtree_create_and_get_pdata(dev);
if (rc < 0)
return rc;
}
#endif
rc = pt_probe(&pt_i2c_bus_ops, &client->dev, client->irq,
PT_I2C_DATA_SIZE);
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
if (rc && match)
pt_devtree_clean_pdata(dev);
#endif
return rc;
}
/*******************************************************************************
* FUNCTION: pt_i2c_remove
*
* SUMMARY: Remove functon for the I2C module
*
* PARAMETERS:
* *client - pointer to i2c client structure
******************************************************************************/
static int pt_i2c_remove(struct i2c_client *client)
{
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
struct device *dev = &client->dev;
struct pt_core_data *cd = i2c_get_clientdata(client);
pt_release(cd);
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(pt_i2c_of_match), dev);
if (match)
pt_devtree_clean_pdata(dev);
#endif
return 0;
}
/*******************************************************************************
* FUNCTION: pt_i2c_shutdown
*
* SUMMARY: Shutdown functon for the I2C module
*
* PARAMETERS:
* *client - pointer to i2c client structure
******************************************************************************/
void pt_i2c_shutdown(struct i2c_client *client)
{
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
struct device *dev = &client->dev;
struct pt_core_data *cd = i2c_get_clientdata(client);
pt_release(cd);
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(pt_i2c_of_match), dev);
if (match)
pt_devtree_clean_pdata(dev);
#endif
}
static const struct i2c_device_id pt_i2c_id[] = {
{ PT_I2C_NAME, 0, },
{ }
};
MODULE_DEVICE_TABLE(i2c, pt_i2c_id);
static struct i2c_driver pt_i2c_driver = {
.driver = {
.name = PT_I2C_NAME,
.owner = THIS_MODULE,
.pm = &pt_pm_ops,
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
.of_match_table = pt_i2c_of_match,
#endif
},
.probe = pt_i2c_probe,
.remove = pt_i2c_remove,
.shutdown = pt_i2c_shutdown,
.id_table = pt_i2c_id,
};
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
module_i2c_driver(pt_i2c_driver);
#else
/*******************************************************************************
* FUNCTION: pt_i2c_init
*
* SUMMARY: Initialize function to register i2c module to kernel.
*
* RETURN:
* 0 = success
* !0 = failure
******************************************************************************/
static int __init pt_i2c_init(void)
{
int rc = i2c_add_driver(&pt_i2c_driver);
pr_info("%s: Parade TTDL I2C Driver (Build %s) rc=%d\n",
__func__, PT_DRIVER_VERSION, rc);
return rc;
}
module_init(pt_i2c_init);
/*******************************************************************************
* FUNCTION: pt_i2c_exit
*
* SUMMARY: Exit function to unregister i2c module from kernel.
*
******************************************************************************/
static void __exit pt_i2c_exit(void)
{
i2c_del_driver(&pt_i2c_driver);
}
module_exit(pt_i2c_exit);
#endif
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product I2C driver");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/*
* pt_mta.c
* Parade TrueTouch(TM) Standard Product Multi-Touch Protocol A Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
/*******************************************************************************
* FUNCTION: pt_final_sync
*
* SUMMARY: Function to create SYN_REPORT
*
* PARAMETERS:
* *input - pointer to input device structure
* max_slots - max support touch number
* mt_sync_count - current valid touch number
* ids - bit map value
******************************************************************************/
static void pt_final_sync(struct input_dev *input, int max_slots,
int mt_sync_count, unsigned long *ids)
{
if (mt_sync_count)
input_sync(input);
}
/*******************************************************************************
* FUNCTION: pt_input_sync
*
* SUMMARY: Function to create SYN_MT_REPORT
*
* PARAMETERS:
* *input - pointer to input device structure
******************************************************************************/
static void pt_input_sync(struct input_dev *input)
{
input_mt_sync(input);
}
/*******************************************************************************
* FUNCTION: pt_input_report
*
* SUMMARY: Function to report coordinate information of touch point
* protocol
*
* PARAMETERS:
* *input - pointer to input device structure
* sig - track id to allow tracking of a touch
* t - event id to indicate an event associated with touch instance
* type - indicate the touch object
******************************************************************************/
static void pt_input_report(struct input_dev *input, int sig,
int t, int type)
{
if (type == PT_OBJ_STANDARD_FINGER || type == PT_OBJ_GLOVE) {
input_report_key(input, BTN_TOOL_FINGER, PT_BTN_PRESSED);
input_report_key(input, BTN_TOOL_PEN, PT_BTN_RELEASED);
} else if (type == PT_OBJ_STYLUS) {
input_report_key(input, BTN_TOOL_PEN, PT_BTN_PRESSED);
input_report_key(input, BTN_TOOL_FINGER, PT_BTN_RELEASED);
}
input_report_key(input, BTN_TOUCH, PT_BTN_PRESSED);
input_report_abs(input, sig, t);
}
/*******************************************************************************
* FUNCTION: pt_report_slot_liftoff
*
* SUMMARY: Function to report all touches are lifted
* protocol
*
* PARAMETERS:
* *md - pointer to input device structure
* max_slots - indicate max number of touch id
******************************************************************************/
static void pt_report_slot_liftoff(struct pt_mt_data *md,
int max_slots)
{
input_report_key(md->input, BTN_TOUCH, PT_BTN_RELEASED);
input_report_key(md->input, BTN_TOOL_FINGER, PT_BTN_RELEASED);
input_report_key(md->input, BTN_TOOL_PEN, PT_BTN_RELEASED);
}
/*******************************************************************************
* FUNCTION: pt_input_register_device
*
* SUMMARY: Function to register input device
* protocol
*
* PARAMETERS:
* *input - pointer to input device structure
* max_slots - indicate max number of touch id
******************************************************************************/
static int pt_input_register_device(struct input_dev *input, int max_slots)
{
__set_bit(BTN_TOUCH, input->keybit);
__set_bit(BTN_TOOL_FINGER, input->keybit);
__set_bit(BTN_TOOL_PEN, input->keybit);
return input_register_device(input);
}
/*******************************************************************************
* FUNCTION: pt_init_function_ptrs
*
* SUMMARY: Function to init function pointer
*
* PARAMETERS:
* *md - pointer to touch data structure
******************************************************************************/
void pt_init_function_ptrs(struct pt_mt_data *md)
{
md->mt_function.report_slot_liftoff = pt_report_slot_liftoff;
md->mt_function.final_sync = pt_final_sync;
md->mt_function.input_sync = pt_input_sync;
md->mt_function.input_report = pt_input_report;
md->mt_function.input_register_device = pt_input_register_device;
}

View File

@@ -0,0 +1,144 @@
/*
* pt_mtb.c
* Parade TrueTouch(TM) Standard Product Multi-Touch Protocol B Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
#include <linux/input/mt.h>
#include <linux/version.h>
/*******************************************************************************
* FUNCTION: pt_final_sync
*
* SUMMARY: Function to create SYN_REPORT
*
* PARAMETERS:
* *input - pointer to input device structure
* max_slots - max support touch number
* mt_sync_count - current valid touch number
* ids - bit map value
******************************************************************************/
static void pt_final_sync(struct input_dev *input, int max_slots,
int mt_sync_count, unsigned long *ids)
{
int t;
for (t = 0; t < max_slots; t++) {
if (test_bit(t, ids))
continue;
input_mt_slot(input, t);
input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
}
input_sync(input);
}
/*******************************************************************************
* FUNCTION: pt_input_report
*
* SUMMARY: Function to report coordinate information of touch point
* protocol
*
* PARAMETERS:
* *input - pointer to input device structure
* sig - track id to allow tracking of a touch
* t - event id to indicate an event associated with touch instance
* type - indicate the touch object
******************************************************************************/
static void pt_input_report(struct input_dev *input, int sig,
int t, int type)
{
input_mt_slot(input, t);
if (type == PT_OBJ_STANDARD_FINGER || type == PT_OBJ_GLOVE)
input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
else if (type == PT_OBJ_STYLUS)
input_mt_report_slot_state(input, MT_TOOL_PEN, true);
}
/*******************************************************************************
* FUNCTION: pt_report_slot_liftoff
*
* SUMMARY: Function to report all touches are lifted
* protocol
*
* PARAMETERS:
* *md - pointer to input device structure
* max_slots - indicate max number of touch id
******************************************************************************/
static void pt_report_slot_liftoff(struct pt_mt_data *md,
int max_slots)
{
int t;
if (md->num_prv_rec == 0)
return;
for (t = 0; t < max_slots; t++) {
input_mt_slot(md->input, t);
input_mt_report_slot_state(md->input,
MT_TOOL_FINGER, false);
}
}
/*******************************************************************************
* FUNCTION: pt_input_register_device
*
* SUMMARY: Function to register input device
* protocol
*
* PARAMETERS:
* *input - pointer to input device structure
* max_slots - indicate max number of touch id
******************************************************************************/
static int pt_input_register_device(struct input_dev *input, int max_slots)
{
#if (KERNEL_VERSION(3, 7, 0) <= LINUX_VERSION_CODE)
input_mt_init_slots(input, max_slots, 0);
#else
input_mt_init_slots(input, max_slots);
#endif
return input_register_device(input);
}
/*******************************************************************************
* FUNCTION: pt_init_function_ptrs
*
* SUMMARY: Function to init function pointer
*
* PARAMETERS:
* *md - pointer to touch data structure
******************************************************************************/
void pt_init_function_ptrs(struct pt_mt_data *md)
{
md->mt_function.report_slot_liftoff = pt_report_slot_liftoff;
md->mt_function.final_sync = pt_final_sync;
md->mt_function.input_sync = NULL;
md->mt_function.input_report = pt_input_report;
md->mt_function.input_register_device = pt_input_register_device;
}

View File

@@ -0,0 +1,572 @@
#ifndef TTDL_KERNEL_SUBMISSION
/*
* pt_pen.c
* Parade TrueTouch(TM) Standard Product CapSense Reports Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2021 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
/*******************************************************************************
* FUNCTION: pt_pen_lift_all
*
* SUMMARY: Reports pen liftoff action
*
* PARAMETERS:
* *pend - pointer to pen data structure
******************************************************************************/
static void pt_pen_lift_all(struct pt_pen_data *pend)
{
input_report_key(pend->input, BTN_STYLUS, 0);
input_report_key(pend->input, BTN_STYLUS2, 0);
input_report_key(pend->input, BTN_TOUCH, 0);
input_report_key(pend->input, BTN_TOOL_PEN, 0);
input_sync(pend->input);
}
/*******************************************************************************
* FUNCTION: pt_get_pen_data
*
* SUMMARY: Gets axis of pen report
*
* PARAMETERS:
* *pend - pointer to pen data structure
* *xy_data - pointer to touch data
******************************************************************************/
static void pt_get_pen(struct pt_pen_data *pend,
struct pt_pen *pen, u8 *xy_data)
{
struct device *dev = pend->dev;
struct pt_sysinfo *si = pend->si;
enum pt_pen_abs abs;
for (abs = PT_PEN_X; abs < PT_PEN_NUM_ABS; abs++) {
if (!si->pen_abs[abs].report)
continue;
pt_get_touch_field(dev, &pen->abs[abs],
si->pen_abs[abs].size,
si->pen_abs[abs].max,
xy_data + si->tch_abs[abs].ofs,
si->pen_abs[abs].bofs);
pt_debug(dev, DL_DEBUG, "%s: get %s=%04X(%d)\n",
__func__, pt_pen_abs_string[abs],
pen->abs[abs], pen->abs[abs]);
}
}
/*******************************************************************************
* FUNCTION: pt_xy_worker
*
* SUMMARY: Read xy_data for current pen touch
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *pend - pointer to pen data structure
******************************************************************************/
static int pt_xy_worker(struct pt_pen_data *pend)
{
struct pt_sysinfo *si = pend->si;
struct pt_pen pen;
bool tool;
pt_get_pen(pend, &pen, si->xy_data + 3);
tool = pen.abs[PT_PEN_IV] ?
BTN_TOOL_RUBBER : BTN_TOOL_PEN;
input_report_abs(pend->input, ABS_X, pen.abs[PT_PEN_X]);
input_report_abs(pend->input, ABS_Y, pen.abs[PT_PEN_Y]);
input_report_abs(pend->input, ABS_PRESSURE, pen.abs[PT_PEN_P]);
input_report_key(pend->input, BTN_STYLUS, pen.abs[PT_PEN_BS]);
if (si->pen_abs[PT_PEN_2ND_BS].report)
input_report_key(pend->input, BTN_STYLUS2,
pen.abs[PT_PEN_2ND_BS]);
input_report_key(pend->input, BTN_TOUCH, pen.abs[PT_PEN_TS]);
input_report_key(pend->input, tool, pen.abs[PT_PEN_IR]);
if (si->pen_abs[PT_PEN_X_TILT].report)
input_report_abs(pend->input, ABS_TILT_X,
pen.abs[PT_PEN_X_TILT]);
if (si->pen_abs[PT_PEN_Y_TILT].report)
input_report_abs(pend->input, ABS_TILT_Y,
pen.abs[PT_PEN_Y_TILT]);
input_sync(pend->input);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_pen_attention
*
* SUMMARY: Wrapper function for pt_xy_worker() that register to TTDL attention
* list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_pen_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
int rc;
if (pend->si->xy_mode[2] != pend->si->desc.pen_report_id)
return 0;
/* core handles handshake */
mutex_lock(&pend->pen_lock);
rc = pt_xy_worker(pend);
mutex_unlock(&pend->pen_lock);
if (rc < 0)
pt_debug(dev, DL_ERROR,
"%s: xy_worker error r=%d\n", __func__, rc);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_startup_attention
*
* SUMMARY: Wrapper function for pt_pen_lift_all() that register to TTDL
* attention list.
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_startup_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
mutex_lock(&pend->pen_lock);
pt_pen_lift_all(pend);
mutex_unlock(&pend->pen_lock);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_pen_suspend_attention
*
* SUMMARY: Function for pen to enter suspend state that as following steps:
* 1) Lift pen touch
* 2) Set flag with suspend state
* 3) Decrese pm system count
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_pen_suspend_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
mutex_lock(&pend->pen_lock);
pt_pen_lift_all(pend);
pend->is_suspended = true;
mutex_unlock(&pend->pen_lock);
pm_runtime_put(dev);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_pen_resume_attention
*
* SUMMARY: Function for pen to leave suspend state that as following steps:
* 1) Increse pm system count
* 2) Clear suspend state flag
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_pen_resume_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
pm_runtime_get(dev);
mutex_lock(&pend->pen_lock);
pend->is_suspended = false;
mutex_unlock(&pend->pen_lock);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_pen_open
*
* SUMMARY: Open method for input device(pen) that sets up call back
* functions to TTDL attention list
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *input - pointer to input_dev structure
******************************************************************************/
static int pt_pen_open(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
pm_runtime_get_sync(dev);
mutex_lock(&pend->pen_lock);
pend->is_suspended = false;
mutex_unlock(&pend->pen_lock);
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_PEN_NAME,
pt_pen_attention, PT_MODE_OPERATIONAL);
/* set up startup call back */
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP, PT_PEN_NAME,
pt_startup_attention, 0);
/* set up suspend call back */
_pt_subscribe_attention(dev, PT_ATTEN_SUSPEND, PT_PEN_NAME,
pt_pen_suspend_attention, 0);
/* set up resume call back */
_pt_subscribe_attention(dev, PT_ATTEN_RESUME, PT_PEN_NAME,
pt_pen_resume_attention, 0);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_pen_close
*
* SUMMARY: Close method for input device(pen) that clears call back
* functions from TTDL attention list.
*
* PARAMETERS:
* *input - pointer to input_dev structure
******************************************************************************/
static void pt_pen_close(struct input_dev *input)
{
struct device *dev = input->dev.parent;
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_PEN_NAME,
pt_pen_attention, PT_MODE_OPERATIONAL);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_PEN_NAME,
pt_startup_attention, 0);
_pt_unsubscribe_attention(dev, PT_ATTEN_SUSPEND, PT_PEN_NAME,
pt_pen_suspend_attention, 0);
_pt_unsubscribe_attention(dev, PT_ATTEN_RESUME, PT_PEN_NAME,
pt_pen_resume_attention, 0);
mutex_lock(&pend->pen_lock);
if (!pend->is_suspended) {
pm_runtime_put(dev);
pend->is_suspended = true;
}
mutex_unlock(&pend->pen_lock);
}
/*******************************************************************************
* FUNCTION: pt_setup_input_device
*
* SUMMARY: Set up resolution, event signal capabilities and register input
* device for pen.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_device(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
int i;
int rc;
u32 usage;
int max_x, max_y, max_p;
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
__func__);
__set_bit(EV_ABS, pend->input->evbit);
__set_bit(EV_KEY, pend->input->evbit);
for (i = PT_PEN_X; i < PT_PEN_NUM_ABS; i++) {
usage = pt_pen_abs_field_map[i];
switch (usage) {
case HID_GD_X:
max_x = pend->si->sensing_conf_data.res_x;
input_set_abs_params(pend->input,
ABS_X, 0, max_x, 0, 0);
break;
case HID_GD_Y:
max_y = pend->si->sensing_conf_data.res_y;
input_set_abs_params(pend->input,
ABS_Y, 0, max_y, 0, 0);
break;
case HID_DG_TIPPRESSURE:
max_p = pend->si->sensing_conf_data.max_z;
input_set_abs_params(pend->input,
ABS_PRESSURE, 0, max_p, 0, 0);
break;
case HID_DG_INRANGE:
input_set_capability(pend->input,
EV_KEY, BTN_TOOL_PEN);
break;
case HID_DG_INVERT:
input_set_capability(pend->input,
EV_KEY, BTN_TOOL_RUBBER);
break;
case HID_DG_TILT_X:
max_x = pend->si->pen_abs[i].max;
input_set_abs_params(pend->input,
ABS_TILT_X, 0, max_x, 0, 0);
break;
case HID_DG_TILT_Y:
max_x = pend->si->pen_abs[i].max;
input_set_abs_params(pend->input,
ABS_TILT_Y, 0, max_x, 0, 0);
break;
case HID_DG_ERASER:
case HID_DG_TIPSWITCH:
input_set_capability(pend->input,
EV_KEY, BTN_TOUCH);
break;
case HID_DG_BARRELSWITCH:
input_set_capability(pend->input,
EV_KEY, BTN_STYLUS);
break;
case HID_DG_BARRELSWITCH2:
input_set_capability(pend->input,
EV_KEY, BTN_STYLUS2);
break;
}
}
rc = input_register_device(pend->input);
if (rc < 0)
pt_debug(dev, DL_ERROR,
"%s: Error, failed register input device r=%d\n",
__func__, rc);
else
pend->input_device_registered = true;
return rc;
}
/*******************************************************************************
* FUNCTION: pt_setup_input_attention
*
* SUMMARY: Wrapper function for pt_setup_input_device() register to TTDL
* attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_attention(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
int rc;
pend->si = _pt_request_sysinfo(dev);
if (!pend->si)
return -1;
rc = pt_setup_input_device(dev);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_PEN_NAME,
pt_setup_input_attention, 0);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_pen_probe
*
* SUMMARY: The probe function for pen input device
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_pen_probe(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_pen_data *pend = &cd->pend;
struct pt_platform_data *pdata = dev_get_platdata(dev);
struct pt_pen_platform_data *pen_pdata;
int rc = 0;
if (!pdata || !pdata->pen_pdata) {
pt_debug(dev, DL_ERROR,
"%s: Missing platform data\n", __func__);
rc = -ENODEV;
goto error_no_pdata;
}
pen_pdata = pdata->pen_pdata;
mutex_init(&pend->pen_lock);
pend->dev = dev;
pend->pdata = pen_pdata;
/* Create the input device and register it. */
pt_debug(dev, DL_INFO,
"%s: Create the input device and register it\n", __func__);
pend->input = input_allocate_device();
if (!pend->input) {
pt_debug(dev, DL_ERROR,
"%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
} else
pend->input_device_allocated = true;
if (pend->pdata->inp_dev_name)
pend->input->name = pend->pdata->inp_dev_name;
else
pend->input->name = PT_PEN_NAME;
scnprintf(pend->phys, sizeof(pend->phys), "%s/input%d", dev_name(dev),
cd->phys_num++);
pend->input->phys = pend->phys;
pend->input->dev.parent = pend->dev;
pend->input->open = pt_pen_open;
pend->input->close = pt_pen_close;
input_set_drvdata(pend->input, pend);
/* get sysinfo */
pend->si = _pt_request_sysinfo(dev);
if (pend->si) {
rc = pt_setup_input_device(dev);
if (rc)
goto error_init_input;
} else {
pt_debug(dev, DL_ERROR,
"%s: Fail get sysinfo pointer from core p=%p\n",
__func__, pend->si);
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PEN_NAME, pt_setup_input_attention, 0);
}
return 0;
error_init_input:
input_free_device(pend->input);
pend->input_device_allocated = false;
error_alloc_failed:
error_no_pdata:
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_pen_release
*
* SUMMARY: The release function for pen input device
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_pen_release(struct device *dev)
{
struct pt_core_data *cd;
struct pt_pen_data *pend;
/* Ensure valid pointers before de-referencing them */
if (dev) {
cd = dev_get_drvdata(dev);
if (cd)
pend = &cd->pend;
else
return 0;
} else {
return 0;
}
/*
* Second call this function may cause kernel panic if probe fail.
* Use input_device_registered & input_device_allocated variable to
* avoid unregister or free unavailable devive.
*/
if (pend && pend->input_device_registered) {
pend->input_device_registered = false;
input_unregister_device(pend->input);
/* Unregistering device will free the device too */
pend->input_device_allocated = false;
} else if (pend && pend->input_device_allocated) {
pend->input_device_allocated = false;
input_free_device(pend->input);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PEN_NAME, pt_setup_input_attention, 0);
}
return 0;
}
#endif /*!TTDL_KERNEL_SUBMISSION */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,69 @@
/*
* pt_platform.h
* Parade TrueTouch(TM) Standard Product Platform Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.parade.com <ttdrivers@paradetech.com>
*/
#ifndef _LINUX_PT_PLATFORM_H
#define _LINUX_PT_PLATFORM_H
#include "pt_core.h"
#include <linux/irq.h>
#if defined(CONFIG_TOUCHSCREEN_PARADE) \
|| defined(CONFIG_TOUCHSCREEN_PARADE_MODULE)
extern struct pt_loader_platform_data _pt_loader_platform_data;
extern irqreturn_t pt_irq(int irq, void *handle);
int pt_xres(struct pt_core_platform_data *pdata, struct device *dev);
int pt_init(struct pt_core_platform_data *pdata, int on,
struct device *dev);
int pt_power(struct pt_core_platform_data *pdata, int on,
struct device *dev, atomic_t *ignore_irq);
#ifdef PT_DETECT_HW
int pt_detect(struct pt_core_platform_data *pdata,
struct device *dev, pt_platform_read read);
#else
#define pt_detect NULL
#endif
int pt_irq_stat(struct pt_core_platform_data *pdata,
struct device *dev);
int pt_setup_power(struct pt_core_platform_data *pdata, int on,
struct device *dev);
int pt_setup_irq(struct pt_core_platform_data *pdata, int on,
struct device *dev);
#else /* !CONFIG_TOUCHSCREEN_PARADE */
static struct pt_loader_platform_data _pt_loader_platform_data;
#define pt_xres NULL
#define pt_init NULL
#define pt_power NULL
#define pt_irq_stat NULL
#define pt_detect NULL
#define pt_setup_power NULL
#define pt_setup_irq NULL
#endif /* CONFIG_TOUCHSCREEN_PARADE */
#endif /* _LINUX_PT_PLATFORM_H */

View File

@@ -0,0 +1,815 @@
/*
* pt_proximity.c
* Parade TrueTouch(TM) Standard Product Proximity Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*
*/
#include "pt_regs.h"
#define PT_PROXIMITY_NAME "pt_proximity"
/* Timeout value in ms. */
#define PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT 1000
#define PT_PROXIMITY_ON 0
#define PT_PROXIMITY_OFF 1
/*******************************************************************************
* FUNCTION: get_prox_data
*
* SUMMARY: Gets pointer of proximity data from core data structure
*
* RETURN:
* pointer of pt_proximity_data structure in core data structure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static inline struct pt_proximity_data *get_prox_data(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
return &cd->pd;
}
/*******************************************************************************
* FUNCTION: pt_report_proximity
*
* SUMMARY: Reports proximity event
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* on - state of proximity(true:on; false:off)
******************************************************************************/
static void pt_report_proximity(struct pt_proximity_data *pd,
bool on)
{
int val = on ? PT_PROXIMITY_ON : PT_PROXIMITY_OFF;
input_report_abs(pd->input, ABS_DISTANCE, val);
input_sync(pd->input);
}
/*******************************************************************************
* FUNCTION: pt_get_touch_axis
*
* SUMMARY: Calculates touch axis
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* *axis - pointer to axis calculation result
* size - size in bytes
* max - max value of result
* *xy_data - pointer to input data to be parsed
* bofs - bit offset
******************************************************************************/
static void pt_get_touch_axis(struct pt_proximity_data *pd,
int *axis, int size, int max, u8 *xy_data, int bofs)
{
int nbyte;
int next;
for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) {
pt_debug(pd->dev, DL_INFO,
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d) bofs=%d\n",
__func__, *axis, *axis, size, max, xy_data, next,
xy_data[next], xy_data[next], bofs);
*axis = *axis + ((xy_data[next] >> bofs) << (nbyte * 8));
next++;
}
*axis &= max - 1;
pt_debug(pd->dev, DL_INFO,
"%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p xy_data[%d]=%02X(%d)\n",
__func__, *axis, *axis, size, max, xy_data, next,
xy_data[next], xy_data[next]);
}
/*******************************************************************************
* FUNCTION: pt_get_touch_hdr
*
* SUMMARY: Gets header of touch report
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* *touch - pointer to pt_touch structure
* *xy_mode - pointer to input mode data
******************************************************************************/
static void pt_get_touch_hdr(struct pt_proximity_data *pd,
struct pt_touch *touch, u8 *xy_mode)
{
struct device *dev = pd->dev;
struct pt_sysinfo *si = pd->si;
enum pt_tch_hdr hdr;
for (hdr = PT_TCH_TIME; hdr < PT_TCH_NUM_HDR; hdr++) {
if (!si->tch_hdr[hdr].report)
continue;
pt_get_touch_axis(pd, &touch->hdr[hdr],
si->tch_hdr[hdr].size,
si->tch_hdr[hdr].max,
xy_mode + si->tch_hdr[hdr].ofs,
si->tch_hdr[hdr].bofs);
pt_debug(dev, DL_INFO, "%s: get %s=%04X(%d)\n",
__func__, pt_tch_hdr_string[hdr],
touch->hdr[hdr], touch->hdr[hdr]);
}
}
/*******************************************************************************
* FUNCTION: pt_get_touch
*
* SUMMARY: Parse proximity touch event
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* *touch - pointer to touch structure
* xy_data - pointer to touch data
******************************************************************************/
static void pt_get_touch(struct pt_proximity_data *pd,
struct pt_touch *touch, u8 *xy_data)
{
struct device *dev = pd->dev;
struct pt_sysinfo *si = pd->si;
enum pt_tch_abs abs;
for (abs = PT_TCH_X; abs < PT_TCH_NUM_ABS; abs++) {
if (!si->tch_abs[abs].report)
continue;
pt_get_touch_axis(pd, &touch->abs[abs],
si->tch_abs[abs].size,
si->tch_abs[abs].max,
xy_data + si->tch_abs[abs].ofs,
si->tch_abs[abs].bofs);
pt_debug(dev, DL_INFO, "%s: get %s=%04X(%d)\n",
__func__, pt_tch_abs_string[abs],
touch->abs[abs], touch->abs[abs]);
}
pt_debug(dev, DL_INFO, "%s: x=%04X(%d) y=%04X(%d)\n",
__func__, touch->abs[PT_TCH_X], touch->abs[PT_TCH_X],
touch->abs[PT_TCH_Y], touch->abs[PT_TCH_Y]);
}
/*******************************************************************************
* FUNCTION: pt_get_proximity_touch
*
* SUMMARY: Parse and report proximity touch event
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* *touch - pointer to pt_touch structure
******************************************************************************/
static void pt_get_proximity_touch(struct pt_proximity_data *pd,
struct pt_touch *tch, int num_cur_tch)
{
struct pt_sysinfo *si = pd->si;
int i;
for (i = 0; i < num_cur_tch; i++) {
pt_get_touch(pd, tch, si->xy_data +
(i * si->desc.tch_record_size));
/* Check for proximity event */
if (tch->abs[PT_TCH_O] == PT_OBJ_PROXIMITY) {
if (tch->abs[PT_TCH_E] == PT_EV_TOUCHDOWN)
pt_report_proximity(pd, true);
else if (tch->abs[PT_TCH_E] == PT_EV_LIFTOFF)
pt_report_proximity(pd, false);
break;
}
}
}
/*******************************************************************************
* FUNCTION: pt_xy_worker
*
* SUMMARY: Read xy_data for all current touches
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
******************************************************************************/
static int pt_xy_worker(struct pt_proximity_data *pd)
{
struct device *dev = pd->dev;
struct pt_sysinfo *si = pd->si;
struct pt_touch tch;
u8 num_cur_tch;
pt_get_touch_hdr(pd, &tch, si->xy_mode + 3);
num_cur_tch = tch.hdr[PT_TCH_NUM];
if (num_cur_tch > si->sensing_conf_data.max_tch) {
pt_debug(dev, DL_ERROR, "%s: Num touch err detected (n=%d)\n",
__func__, num_cur_tch);
num_cur_tch = si->sensing_conf_data.max_tch;
}
if (tch.hdr[PT_TCH_LO])
pt_debug(dev, DL_WARN, "%s: Large area detected\n",
__func__);
/* extract xy_data for all currently reported touches */
pt_debug(dev, DL_INFO, "%s: extract data num_cur_rec=%d\n",
__func__, num_cur_tch);
if (num_cur_tch)
pt_get_proximity_touch(pd, &tch, num_cur_tch);
else
pt_report_proximity(pd, false);
return 0;
}
/*******************************************************************************
* FUNCTION: pt_mt_attention
*
* SUMMARY: Wrapper function for pt_xy_worker() that subscribe into the TTDL
* attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_proximity_attention(struct device *dev)
{
struct pt_proximity_data *pd = get_prox_data(dev);
int rc = 0;
if (pd->si->xy_mode[2] != pd->si->desc.tch_report_id)
return 0;
mutex_lock(&pd->prox_lock);
rc = pt_xy_worker(pd);
mutex_unlock(&pd->prox_lock);
if (rc < 0)
pt_debug(dev, DL_ERROR, "%s: xy_worker error r=%d\n",
__func__, rc);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_startup_attention
*
* SUMMARY: Wrapper function for pt_report_proximity() that subcribe into the
* TTDL attention list.
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_startup_attention(struct device *dev)
{
struct pt_proximity_data *pd = get_prox_data(dev);
mutex_lock(&pd->prox_lock);
pt_report_proximity(pd, false);
mutex_unlock(&pd->prox_lock);
return 0;
}
/*******************************************************************************
* FUNCTION: _pt_set_proximity_via_touchmode_enabled
*
* SUMMARY: Enable/Disable proximity via touchmode parameter
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* enable - enable or disable proximity(true:enable; false:disable)
******************************************************************************/
static int _pt_set_proximity_via_touchmode_enabled(
struct pt_proximity_data *pd, bool enable)
{
struct device *dev = pd->dev;
u32 touchmode_enabled;
int rc;
rc = _pt_request_pip_get_param(dev, 0,
PT_RAM_ID_TOUCHMODE_ENABLED, &touchmode_enabled);
if (rc)
return rc;
if (enable)
touchmode_enabled |= 0x80;
else
touchmode_enabled &= 0x7F;
rc = _pt_request_pip_set_param(dev, 0,
PT_RAM_ID_TOUCHMODE_ENABLED, touchmode_enabled,
PT_RAM_ID_TOUCHMODE_ENABLED_SIZE);
return rc;
}
/*******************************************************************************
* FUNCTION: _pt_set_proximity_via_proximity_enable
*
* SUMMARY: Enable/Disable proximity via proximity parameter
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* enable - enable or disable proximity(true:enable; false:disable)
******************************************************************************/
static int _pt_set_proximity_via_proximity_enable(
struct pt_proximity_data *pd, bool enable)
{
struct device *dev = pd->dev;
u32 proximity_enable;
int rc;
rc = _pt_request_pip_get_param(dev, 0,
PT_RAM_ID_PROXIMITY_ENABLE, &proximity_enable);
if (rc)
return rc;
if (enable)
proximity_enable |= 0x01;
else
proximity_enable &= 0xFE;
rc = _pt_request_pip_set_param(dev, 0,
PT_RAM_ID_PROXIMITY_ENABLE, proximity_enable,
PT_RAM_ID_PROXIMITY_ENABLE_SIZE);
return rc;
}
/*******************************************************************************
* FUNCTION: _pt_set_proximity
*
* SUMMARY: Set proximity mode via touchmode parameter or proximity parameter.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
* enable - enable or disable proximity(true:enable; false:disable)
******************************************************************************/
static int _pt_set_proximity(struct pt_proximity_data *pd,
bool enable)
{
if (!IS_PIP_VER_GE(pd->si, 1, 4))
return _pt_set_proximity_via_touchmode_enabled(pd,
enable);
return _pt_set_proximity_via_proximity_enable(pd, enable);
}
/*******************************************************************************
* FUNCTION: _pt_set_proximity
*
* SUMMARY: Enable proximity mode and subscribe into IRQ and STARTUP TTDL
* attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
******************************************************************************/
static int _pt_proximity_enable(struct pt_proximity_data *pd)
{
struct device *dev = pd->dev;
int rc = 0;
pm_runtime_get_sync(dev);
rc = pt_request_exclusive(dev,
PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on request exclusive r=%d\n",
__func__, rc);
goto exit;
}
rc = _pt_set_proximity(pd, true);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on request enable proximity scantype r=%d\n",
__func__, rc);
goto exit_release;
}
pt_debug(dev, DL_INFO, "%s: setup subscriptions\n", __func__);
/* set up touch call back */
_pt_subscribe_attention(dev, PT_ATTEN_IRQ, PT_PROXIMITY_NAME,
pt_proximity_attention, PT_MODE_OPERATIONAL);
/* set up startup call back */
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PROXIMITY_NAME, pt_startup_attention, 0);
exit_release:
pt_release_exclusive(dev);
exit:
return rc;
}
/*******************************************************************************
* FUNCTION: _pt_proximity_disable
*
* SUMMARY: Disable proximity mode and unsubscribe from IRQ and STARTUP TTDL
* attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *pd - pointer to proximity data structure
******************************************************************************/
static int _pt_proximity_disable(struct pt_proximity_data *pd,
bool force)
{
struct device *dev = pd->dev;
int rc = 0;
rc = pt_request_exclusive(dev,
PT_PROXIMITY_REQUEST_EXCLUSIVE_TIMEOUT);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on request exclusive r=%d\n",
__func__, rc);
goto exit;
}
rc = _pt_set_proximity(pd, false);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: Error on request disable proximity scan r=%d\n",
__func__, rc);
goto exit_release;
}
exit_release:
pt_release_exclusive(dev);
exit:
if (!rc || force) {
_pt_unsubscribe_attention(dev, PT_ATTEN_IRQ,
PT_PROXIMITY_NAME, pt_proximity_attention,
PT_MODE_OPERATIONAL);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PROXIMITY_NAME, pt_startup_attention, 0);
}
pm_runtime_put(dev);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_proximity_enable_show
*
* SUMMARY: Show method for the prox_enable sysfs node that will show the
* enable_count of proximity
*
* RETURN: Size of printed buffer
*
* PARAMETERS:
* *dev - pointer to device structure
* *attr - pointer to device attributes
* *buf - pointer to output buffer
******************************************************************************/
static ssize_t pt_proximity_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct pt_proximity_data *pd = get_prox_data(dev);
int val = 0;
mutex_lock(&pd->sysfs_lock);
val = pd->enable_count;
mutex_unlock(&pd->sysfs_lock);
return scnprintf(buf, PT_MAX_PRBUF_SIZE, "%d\n", val);
}
/*******************************************************************************
* FUNCTION: pt_proximity_enable_store
*
* SUMMARY: The store method for the prox_enable sysfs node that allows to
* enable or disable proxmity mode.
*
* RETURN: Size of passed in buffer
*
* PARAMETERS:
* *dev - pointer to device structure
* *attr - pointer to device attributes
* *buf - pointer to buffer that hold the command parameters
* size - size of buf
******************************************************************************/
static ssize_t pt_proximity_enable_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct pt_proximity_data *pd = get_prox_data(dev);
unsigned long value;
int rc;
rc = kstrtoul(buf, 10, &value);
if (rc < 0 || (value != 0 && value != 1)) {
pt_debug(dev, DL_ERROR, "%s: Invalid value\n", __func__);
return -EINVAL;
}
mutex_lock(&pd->sysfs_lock);
if (value) {
if (pd->enable_count++) {
pt_debug(dev, DL_WARN, "%s: '%s' already enabled\n",
__func__, pd->input->name);
} else {
rc = _pt_proximity_enable(pd);
if (rc)
pd->enable_count--;
}
} else {
if (--pd->enable_count) {
if (pd->enable_count < 0) {
pt_debug(dev, DL_ERROR, "%s: '%s' unbalanced disable\n",
__func__, pd->input->name);
pd->enable_count = 0;
}
} else {
rc = _pt_proximity_disable(pd, false);
if (rc)
pd->enable_count++;
}
}
mutex_unlock(&pd->sysfs_lock);
if (rc)
return rc;
return size;
}
static DEVICE_ATTR(prox_enable, 0600,
pt_proximity_enable_show,
pt_proximity_enable_store);
/*******************************************************************************
* FUNCTION: pt_setup_input_device_and_sysfs
*
* SUMMARY: Create sysnode, set event signal capabilities and register input
* device for proximity.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_device_and_sysfs(struct device *dev)
{
struct pt_proximity_data *pd = get_prox_data(dev);
int signal = PT_IGNORE_VALUE;
int i;
int rc;
rc = device_create_file(dev, &dev_attr_prox_enable);
if (rc) {
pt_debug(dev, DL_ERROR, "%s: Error, could not create enable\n",
__func__);
goto exit;
}
pt_debug(dev, DL_INFO, "%s: Initialize event signals\n",
__func__);
__set_bit(EV_ABS, pd->input->evbit);
/* set event signal capabilities */
for (i = 0; i < NUM_SIGNALS(pd->pdata->frmwrk); i++) {
signal = PARAM_SIGNAL(pd->pdata->frmwrk, i);
if (signal != PT_IGNORE_VALUE) {
input_set_abs_params(pd->input, signal,
PARAM_MIN(pd->pdata->frmwrk, i),
PARAM_MAX(pd->pdata->frmwrk, i),
PARAM_FUZZ(pd->pdata->frmwrk, i),
PARAM_FLAT(pd->pdata->frmwrk, i));
}
}
rc = input_register_device(pd->input);
if (rc) {
pt_debug(dev, DL_ERROR, "%s: Error, failed register input device r=%d\n",
__func__, rc);
goto unregister_enable;
}
pd->input_device_registered = true;
return rc;
unregister_enable:
device_remove_file(dev, &dev_attr_prox_enable);
exit:
return rc;
}
/*******************************************************************************
* FUNCTION: pt_setup_input_attention
*
* SUMMARY: Wrapper function for pt_setup_input_device_and_sysfs() that
* subscribe into TTDL attention list.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
static int pt_setup_input_attention(struct device *dev)
{
struct pt_proximity_data *pd = get_prox_data(dev);
int rc;
pd->si = _pt_request_sysinfo(dev);
if (!pd->si)
return -EINVAL;
rc = pt_setup_input_device_and_sysfs(dev);
if (!rc)
rc = _pt_set_proximity(pd, false);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PROXIMITY_NAME, pt_setup_input_attention, 0);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_proximity_probe
*
* SUMMARY: The probe function for proximity input device
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_proximity_probe(struct device *dev)
{
struct pt_core_data *cd = dev_get_drvdata(dev);
struct pt_proximity_data *pd = &cd->pd;
struct pt_platform_data *pdata = dev_get_platdata(dev);
struct pt_proximity_platform_data *prox_pdata;
int rc = 0;
if (!pdata || !pdata->prox_pdata) {
pt_debug(dev, DL_ERROR,
"%s: Missing platform data\n", __func__);
rc = -ENODEV;
goto error_no_pdata;
}
prox_pdata = pdata->prox_pdata;
mutex_init(&pd->prox_lock);
mutex_init(&pd->sysfs_lock);
pd->dev = dev;
pd->pdata = prox_pdata;
/* Create the input device and register it. */
pt_debug(dev, DL_INFO,
"%s: Create the input device and register it\n", __func__);
pd->input = input_allocate_device();
if (!pd->input) {
pt_debug(dev, DL_ERROR, "%s: Error, failed to allocate input device\n",
__func__);
rc = -ENODEV;
goto error_alloc_failed;
} else
pd->input_device_allocated = true;
if (pd->pdata->inp_dev_name)
pd->input->name = pd->pdata->inp_dev_name;
else
pd->input->name = PT_PROXIMITY_NAME;
scnprintf(pd->phys, sizeof(pd->phys), "%s/input%d", dev_name(dev),
cd->phys_num++);
pd->input->phys = pd->phys;
pd->input->dev.parent = pd->dev;
input_set_drvdata(pd->input, pd);
/* get sysinfo */
pd->si = _pt_request_sysinfo(dev);
if (pd->si) {
rc = pt_setup_input_device_and_sysfs(dev);
if (rc)
goto error_init_input;
rc = _pt_set_proximity(pd, false);
} else {
pt_debug(dev, DL_ERROR, "%s: Fail get sysinfo pointer from core p=%p\n",
__func__, pd->si);
_pt_subscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PROXIMITY_NAME, pt_setup_input_attention,
0);
}
return 0;
error_init_input:
input_free_device(pd->input);
pd->input_device_allocated = false;
error_alloc_failed:
error_no_pdata:
pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_proximity_release
*
* SUMMARY: The release function for proximity input device
*
* RETURN:
* 0 = success
*
* PARAMETERS:
* *dev - pointer to device structure
******************************************************************************/
int pt_proximity_release(struct device *dev)
{
struct pt_proximity_data *pd;
/* Ensure valid pointers before de-referencing them */
if (dev)
pd = get_prox_data(dev);
else
return 0;
/*
* Second call this function may cause kernel panic if probe fail.
* Use input_device_registered & input_device_allocated variable to
* avoid unregister or free unavailable devive.
*/
if (pd && pd->input_device_registered) {
/* Disable proximity sensing */
pd->input_device_registered = false;
mutex_lock(&pd->sysfs_lock);
if (pd->enable_count)
_pt_proximity_disable(pd, true);
mutex_unlock(&pd->sysfs_lock);
device_remove_file(dev, &dev_attr_prox_enable);
input_unregister_device(pd->input);
/* Unregistering device will free the device too */
pd->input_device_allocated = false;
} else if (pd && pd->input_device_allocated) {
pd->input_device_allocated = false;
input_free_device(pd->input);
_pt_unsubscribe_attention(dev, PT_ATTEN_STARTUP,
PT_PROXIMITY_NAME, pt_setup_input_attention,
0);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,429 @@
/*
* pt_spi.c
* Parade TrueTouch(TM) Standard Product SPI Module.
* For use with Parade touchscreen controllers.
* Supported parts include:
* TMA5XX
* TMA448
* TMA445A
* TT21XXX
* TT31XXX
* TT4XXXX
* TT7XXX
* TC3XXX
*
* Copyright (C) 2015-2020 Parade Technologies
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2, and only version 2, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
*/
#include "pt_regs.h"
#include <linux/spi/spi.h>
#include <linux/version.h>
/* TC3315 - DUT Address (0x24 & 0x07) << 1 = 0x08 for write and 0x09 for read */
#define PT_SPI_WR_OP 0x08 /* r/~w */
#define PT_SPI_RD_OP 0x09
#define PT_SPI_BITS_PER_WORD 8
#define PT_SPI_SYNC_ACK 0x62
#define PT_SPI_CMD_BYTES 0
#define PT_SPI_DATA_SIZE (2 * 256)
#define PT_SPI_DATA_BUF_SIZE (PT_SPI_CMD_BYTES + PT_SPI_DATA_SIZE)
#define PT_SPI_OP_SIZE (1)
#define PT_SPI_DUMMY_READ (1)
#define PT_SPI_BUFFER_SIZE \
(PT_MAX_PIP2_MSG_SIZE + PT_SPI_OP_SIZE + PT_SPI_DUMMY_READ)
static u8 *tmp_rbuf;
static u8 *tmp_wbuf;
DEFINE_MUTEX(pt_spi_bus_lock);
/*******************************************************************************
* FUNCTION: pt_spi_xfer
*
* SUMMARY: Read or write date for SPI device.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to device structure
* op - flag to write or read data
* *buf - pointer to data buffer
* length - data length
******************************************************************************/
static int pt_spi_xfer(struct device *dev, u8 op, u8 *buf, int length)
{
struct spi_device *spi = to_spi_device(dev);
struct spi_message msg;
struct spi_transfer xfer;
int rc;
memset(&xfer, 0, sizeof(xfer));
spi_message_init(&msg);
switch (op) {
case PT_SPI_RD_OP:
/* Clear tmp_wbuf with additional OP Code and dummy byte */
memset(tmp_wbuf, 0, length + 2);
tmp_wbuf[0] = op;
/* Total read/write = Read length + Op code + dummy byte */
xfer.tx_buf = tmp_wbuf;
xfer.rx_buf = tmp_rbuf;
xfer.len = length + 2;
break;
case PT_SPI_WR_OP:
memcpy(&tmp_wbuf[1], buf, length);
tmp_wbuf[0] = op;
/* Write length + size of Op code */
xfer.tx_buf = tmp_wbuf;
xfer.len = length + 1;
break;
default:
rc = -EIO;
goto exit;
}
spi_message_add_tail(&xfer, &msg);
rc = spi_sync(spi, &msg);
/* On reads copy only the data content back into the passed in buf */
if (op == PT_SPI_RD_OP)
memcpy(buf, &tmp_rbuf[2], length);
exit:
if (rc < 0)
pt_debug(dev, DL_ERROR, "%s: spi_sync() error %d\n",
__func__, rc);
#if 0 /* TODO TC3315 - need to verify the ACK byte */
if (tmp_rbuf[0] != PT_SPI_SYNC_ACK) {
pt_debug(dev, DL_ERROR, "%s: r_header = 0x%02X\n", __func__,
r_header[0]);
return -EIO;
}
#endif
return rc;
}
/*******************************************************************************
* FUNCTION: pt_spi_read_default
*
* SUMMARY: Read a certain number of bytes from the SPI bus
* NOTE: For TC3315 every response includes a "dummy" prefix byte that
* needs to be stipped off before returning buf.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to Device structure
* *buf - pointer to buffer where the data read will be stored
* size - size to be read
******************************************************************************/
static int pt_spi_read_default(struct device *dev, void *buf, int size)
{
int rc = 0;
if (!buf || !size || size > PT_MAX_PIP2_MSG_SIZE)
return -EINVAL;
mutex_lock(&pt_spi_bus_lock);
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, size);
mutex_unlock(&pt_spi_bus_lock);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_spi_read_default_nosize
*
* SUMMARY: Read from the SPI bus in two transactions first reading the HID
* packet size (2 bytes) followed by reading the rest of the packet based
* on the size initially read.
* NOTE: The empty buffer 'size' was redefined in PIP version 1.7.
* NOTE: For TC3315 every response includes a "dummy" prefix byte that
* needs to be stipped off before returning buf.
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to Device structure
* *buf - pointer to buffer where the data read will be stored
* max - max size that can be read
******************************************************************************/
static int pt_spi_read_default_nosize(struct device *dev, u8 *buf, u32 max)
{
u32 size;
int rc = 0;
if (!buf)
return 0;
mutex_lock(&pt_spi_bus_lock);
/* Separate transaction to retrieve only the length to read */
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, 2);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: SPI transfer error rc = %d\n",
__func__, rc);
goto exit;
}
size = get_unaligned_le16(&buf[0]);
if (!size || size == 2 || size >= PT_PIP_1P7_EMPTY_BUF)
goto exit;
if (size > max || size > PT_MAX_PIP2_MSG_SIZE) {
pt_debug(dev, DL_ERROR, "%s: Invalid size %d !\n", __func__,
size);
rc = -EINVAL;
goto exit;
}
rc = pt_spi_xfer(dev, PT_SPI_RD_OP, buf, size);
if (rc)
pt_debug(dev, DL_ERROR, "%s: SPI transfer error rc = %d\n",
__func__, rc);
exit:
mutex_unlock(&pt_spi_bus_lock);
return rc;
}
/*******************************************************************************
* FUNCTION: pt_spi_write_read_specific
*
* SUMMARY: Write the contents of write_buf to the SPI device and then read
* the response using pt_spi_read_default_nosize()
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *dev - pointer to Device structure
* write_len - length of data buffer write_buf
* *write_buf - pointer to buffer to write
* *read_buf - pointer to buffer to read response into
******************************************************************************/
static int pt_spi_write_read_specific(struct device *dev, u16 write_len,
u8 *write_buf, u8 *read_buf)
{
int rc = 0;
/* Ensure no packet larger than what the PIP spec allows */
if (write_len > PT_MAX_PIP2_MSG_SIZE)
return -EINVAL;
if (!write_buf || !write_len) {
if (!write_buf)
pt_debug(dev, DL_ERROR,
"%s write_buf is NULL", __func__);
if (!write_len)
pt_debug(dev, DL_ERROR,
"%s write_len is NULL", __func__);
return -EINVAL;
}
mutex_lock(&pt_spi_bus_lock);
rc = pt_spi_xfer(dev, PT_SPI_WR_OP, write_buf, write_len);
if (rc < 0)
goto error;
mutex_unlock(&pt_spi_bus_lock);
if (read_buf)
rc = pt_spi_read_default_nosize(dev, read_buf,
PT_SPI_DATA_SIZE);
return rc;
error:
mutex_unlock(&pt_spi_bus_lock);
return rc;
}
static struct pt_bus_ops pt_spi_bus_ops = {
.bustype = BUS_SPI,
.read_default = pt_spi_read_default,
.read_default_nosize = pt_spi_read_default_nosize,
.write_read_specific = pt_spi_write_read_specific,
};
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
static const struct of_device_id pt_spi_of_match[] = {
{ .compatible = "parade,pt_spi_adapter", },
{ }
};
MODULE_DEVICE_TABLE(of, pt_spi_of_match);
#endif
/*******************************************************************************
* FUNCTION: pt_spi_probe
*
* SUMMARY: Probe functon for the SPI module
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *spi - pointer to spi device structure
******************************************************************************/
static int pt_spi_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
int rc;
/* Set up SPI*/
spi->bits_per_word = PT_SPI_BITS_PER_WORD;
spi->mode = SPI_MODE_0;
rc = spi_setup(spi);
if (rc < 0) {
pt_debug(dev, DL_ERROR, "%s: SPI setup error %d\n",
__func__, rc);
return rc;
}
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(pt_spi_of_match), dev);
if (match) {
rc = pt_devtree_create_and_get_pdata(dev);
if (rc < 0)
return rc;
}
#endif
/* Add 2 to the length for the 'OP Code' & 'Dummy' prefix bytes */
tmp_wbuf = kzalloc(PT_SPI_BUFFER_SIZE, GFP_KERNEL);
tmp_rbuf = kzalloc(PT_SPI_BUFFER_SIZE, GFP_KERNEL);
if (!tmp_wbuf || !tmp_rbuf)
return -ENOMEM;
rc = pt_probe(&pt_spi_bus_ops, &spi->dev, spi->irq,
PT_SPI_DATA_BUF_SIZE);
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
if (rc && match)
pt_devtree_clean_pdata(dev);
#endif
return rc;
}
/*******************************************************************************
* FUNCTION: pt_spi_remove
*
* SUMMARY: Remove functon for the SPI module
*
* RETURN:
* 0 = success
* !0 = failure
*
* PARAMETERS:
* *spi - pointer to spi device structure
******************************************************************************/
static int pt_spi_remove(struct spi_device *spi)
{
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
const struct of_device_id *match;
#endif
struct device *dev = &spi->dev;
struct pt_core_data *cd = dev_get_drvdata(dev);
kfree(tmp_rbuf);
kfree(tmp_wbuf);
pt_release(cd);
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
match = of_match_device(of_match_ptr(pt_spi_of_match), dev);
if (match)
pt_devtree_clean_pdata(dev);
#endif
return 0;
}
static const struct spi_device_id pt_spi_id[] = {
{ PT_SPI_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, pt_spi_id);
static struct spi_driver pt_spi_driver = {
.driver = {
.name = PT_SPI_NAME,
.bus = &spi_bus_type,
.owner = THIS_MODULE,
.pm = &pt_pm_ops,
#ifdef CONFIG_TOUCHSCREEN_PARADE_DEVICETREE_SUPPORT
.of_match_table = pt_spi_of_match,
#endif
},
.probe = pt_spi_probe,
.remove = (pt_spi_remove),
.id_table = pt_spi_id,
};
#if (KERNEL_VERSION(3, 3, 0) <= LINUX_VERSION_CODE)
module_spi_driver(pt_spi_driver);
#else
/*******************************************************************************
* FUNCTION: pt_spi_init
*
* SUMMARY: Initialize function to register spi module to kernel.
*
* RETURN:
* 0 = success
* !0 = failure
******************************************************************************/
static int __init pt_spi_init(void)
{
int err = spi_register_driver(&pt_spi_driver);
pr_info("%s: Parade TTDL SPI Driver (Build %s) rc=%d\n",
__func__, PT_DRIVER_VERSION, err);
return err;
}
module_init(pt_spi_init);
/*******************************************************************************
* FUNCTION: pt_spi_exit
*
* SUMMARY: Exit function to unregister spi module from kernel.
*
******************************************************************************/
static void __exit pt_spi_exit(void)
{
spi_unregister_driver(&pt_spi_driver);
}
module_exit(pt_spi_exit);
#endif
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product SPI Driver");
MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/soc/qcom/panel_event_notifier.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/firmware.h>
#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/kthread.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "linux/gunyah/gh_msgq.h"
#include "linux/gunyah/gh_rm_drv.h"
#include <linux/gunyah/gh_irq_lend.h>
#include <linux/gunyah/gh_mem_notifier.h>
#include "qts_core_common.h"
#include <linux/clk.h>
#include <linux/kobject.h>
#define QTS_NAME "qti-ts"
enum trusted_touch_mode_config {
TRUSTED_TOUCH_VM_MODE,
TRUSTED_TOUCH_MODE_NONE
};
enum trusted_touch_pvm_states {
TRUSTED_TOUCH_PVM_INIT,
PVM_I2C_RESOURCE_ACQUIRED,
PVM_INTERRUPT_DISABLED,
PVM_IOMEM_LENT,
PVM_IOMEM_LENT_NOTIFIED,
PVM_IRQ_LENT,
PVM_IRQ_LENT_NOTIFIED,
PVM_IOMEM_RELEASE_NOTIFIED,
PVM_IRQ_RELEASE_NOTIFIED,
PVM_ALL_RESOURCES_RELEASE_NOTIFIED,
PVM_IRQ_RECLAIMED,
PVM_IOMEM_RECLAIMED,
PVM_INTERRUPT_ENABLED,
PVM_I2C_RESOURCE_RELEASED,
TRUSTED_TOUCH_PVM_STATE_MAX
};
enum trusted_touch_tvm_states {
TRUSTED_TOUCH_TVM_INIT,
TVM_IOMEM_LENT_NOTIFIED,
TVM_IRQ_LENT_NOTIFIED,
TVM_ALL_RESOURCES_LENT_NOTIFIED,
TVM_IOMEM_ACCEPTED,
TVM_I2C_SESSION_ACQUIRED,
TVM_IRQ_ACCEPTED,
TVM_INTERRUPT_ENABLED,
TVM_INTERRUPT_DISABLED,
TVM_IRQ_RELEASED,
TVM_I2C_SESSION_RELEASED,
TVM_IOMEM_RELEASED,
TRUSTED_TOUCH_TVM_STATE_MAX
};
#define TRUSTED_TOUCH_MEM_LABEL 0x7
#define TOUCH_RESET_GPIO_BASE 0xf118000
#define TOUCH_RESET_GPIO_SIZE 0x1000
#define TOUCH_RESET_GPIO_OFFSET 0x4
#define TOUCH_INTR_GPIO_BASE 0xf119000
#define TOUCH_INTR_GPIO_SIZE 0x1000
#define TOUCH_INTR_GPIO_OFFSET 0x8
#define TRUSTED_TOUCH_EVENT_LEND_FAILURE -1
#define TRUSTED_TOUCH_EVENT_LEND_NOTIFICATION_FAILURE -2
#define TRUSTED_TOUCH_EVENT_ACCEPT_FAILURE -3
#define TRUSTED_TOUCH_EVENT_FUNCTIONAL_FAILURE -4
#define TRUSTED_TOUCH_EVENT_RELEASE_FAILURE -5
#define TRUSTED_TOUCH_EVENT_RECLAIM_FAILURE -6
#define TRUSTED_TOUCH_EVENT_I2C_FAILURE -7
#define TRUSTED_TOUCH_EVENT_NOTIFICATIONS_PENDING 5
struct trusted_touch_vm_info {
enum gh_irq_label irq_label;
enum gh_mem_notifier_tag mem_tag;
enum gh_vm_names vm_name;
const char *trusted_touch_type;
u32 hw_irq;
gh_memparcel_handle_t vm_mem_handle;
u32 *iomem_bases;
u32 *iomem_sizes;
u32 iomem_list_size;
void *mem_cookie;
atomic_t vm_state;
};
struct qts_data;
struct qts_data {
struct i2c_client *client;
struct spi_device *spi;
struct device *dev;
struct device_node *dp;
void *vendor_data; /* vendor touch driver data */
u32 bus_type; /*i2c or spi*/
u32 client_type; /* primary or secondary */
struct drm_panel *panel;
struct workqueue_struct *ts_workqueue;
struct work_struct resume_work;
struct work_struct suspend_work;
bool schedule_suspend;
bool schedule_resume;
void *notifier_cookie;
/* Resources */
struct regulator *vdd;
struct regulator *avdd;
u32 irq_gpio;
u32 irq_gpio_flags;
u32 reset_gpio;
u32 reset_gpio_flags;
int irq;
bool irq_disabled;
bool power_disabled;
struct mutex transition_lock;
bool suspended;
/* vendor callback ops */
struct qts_vendor_callback_ops vendor_ops;
/* TUI */
bool tui_supported;
struct trusted_touch_vm_info *vm_info;
struct mutex qts_clk_io_ctrl_mutex;
const char *touch_environment;
struct completion trusted_touch_powerdown;
struct clk *core_clk;
struct clk *iface_clk;
atomic_t trusted_touch_initialized;
atomic_t trusted_touch_enabled;
atomic_t trusted_touch_transition;
atomic_t trusted_touch_event;
atomic_t trusted_touch_abort_status;
atomic_t delayed_tvm_probe_pending;
atomic_t delayed_pvm_probe_pending;
atomic_t trusted_touch_mode;
};
struct qts_data_entries;
struct qts_data_entries {
struct kset *qts_kset;
struct qts_data info[QTS_CLIENT_MAX];
struct mutex qts_data_entries_lock;
};
#ifdef CONFIG_ARCH_QTI_VM
void qts_trusted_touch_tvm_i2c_failure_report(struct qts_data *qts_data);
#endif

View File

@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*/
enum qts_client {
QTS_CLIENT_PRIMARY_TOUCH,
QTS_CLIENT_SECONDARY_TOUCH,
QTS_CLIENT_MAX
};
enum qts_bus_type {
QTS_BUS_TYPE_NONE,
QTS_BUS_TYPE_I2C,
QTS_BUS_TYPE_SPI,
QTS_BUS_TYPE_SPI_V2,
QTS_BUS_TYPE_MAX
};
struct qts_vendor_callback_ops {
int (*suspend)(void *data);
int (*resume)(void *data);
int (*enable_touch_irq)(void *data, bool en);
irqreturn_t (*irq_handler)(int irq, void *data);
int (*get_irq_num)(void *data);
int (*pre_la_tui_enable)(void *data);
int (*post_la_tui_enable)(void *data);
int (*pre_la_tui_disable)(void *data);
int (*post_la_tui_disable)(void *data);
int (*pre_le_tui_enable)(void *data);
int (*post_le_tui_enable)(void *data);
int (*pre_le_tui_disable)(void *data);
int (*post_le_tui_disable)(void *data);
};
struct qts_vendor_data {
struct i2c_client *client;
struct spi_device *spi;
void *vendor_data;
struct qts_vendor_callback_ops qts_vendor_ops;
u32 client_type;
u32 bus_type;
bool schedule_suspend;
bool schedule_resume;
};
int qts_client_register(struct qts_vendor_data qts_vendor_data);

View File

@@ -0,0 +1,54 @@
/* config.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*****************************************************************************
** GLOBAL MARCO DEFINITION
******************************************************************************/
#define MINIMUM(x, y) (((x) < (y)) ? (x) : (y)) // Compares two parameters, return minimum.
#define MAXIMUM(x, y) (((x) > (y)) ? (x) : (y)) // Compares two parameters, return maximum.
#define ABS(x) ((x) >= 0 ? (x) : -(x)) // return absolute value
/*****************************************************************************
** GLOBAL FUNCTIONAL DEFINITION
******************************************************************************/
//Bootloader
#define BOOTLOADER 1 //1: with bootloader, 0: without bootloader
#define SELFTEST 1 //1: For System Selftest, 0:For Dongle Open/Short Tool
#if SELFTEST
#define SELFTEST_3X 1
#define SELFTEST_2X 0
#else
#define SELFTEST_3X 0
#define SELFTEST_2X 0
#endif
#define ENABLE_TEST_TIME_MEASURMENT 1
#define ENABLE_TEST_TIME_MEASURMENT_CC 0
#define ENABLE_WDT 0
#define ENABLE_TEST_RSU_DATA_SHOW 0
#define ENABLE_AUO_VERIFY_LOG 0
#define ENABLE_CONTROL_OPENSHORT_WDT 0
#define ENABLE_TEST_GPIO_MEASURMENT 0
#endif /* end __CONFIG_H */
/*****************************************************************************
** End Of File
******************************************************************************/

View File

@@ -0,0 +1,4 @@
#
# Makefile for the touchscreen raydium drivers.
#
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_driver.o raydium_sysfs.o raydium_fw_update.o drv_interface.o raydium_selftest.o chip_raydium/ic_drv_global.o chip_raydium/ic_drv_interface.o chip_raydium/f303_ic_control.o chip_raydium/f303_ic_test.o

View File

@@ -0,0 +1,516 @@
/* f303_ic_control.c
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifdef __KERNEL__
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#else
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#endif
#include "../drv_interface.h"
#include "ic_drv_global.h"
#include "ic_drv_interface.h"
#include "f303_ic_control.h"
#include "f303_ic_reg.h"
unsigned char check_dev_id_3x(unsigned short u16_dev_id)
{
unsigned int u32_read;
if (handle_ic_read(REG_FLASHCTL_DEVID_ADDR, 4, (unsigned char *)(&u32_read), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
if (((u32_read & 0xFFFF0000) >> 16) == u16_dev_id) {
g_u16_dev_id = DEVICE_ID_3X;
return SUCCESS;
}
DEBUGOUT("Device ID NG! 0x%x:0x%x\r\n", ((u32_read & 0xFFFF0000) >> 16), u16_dev_id);
return ERROR;
}
unsigned char check_dev_sub_version_3x(unsigned char u8_version)
{
unsigned int u32_read;
if (handle_ic_read(REG_FLASHCTL_DEVID_ADDR, 4, (unsigned char *)(&u32_read), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
DEBUGOUT("Device Sub Version 0x%x\r\n", u32_read);
if ((u32_read & 0x000000FF) == u8_version)
return SUCCESS;
DEBUGOUT("Device Sub Version NG! 0x%x:0x%x\r\n", (u32_read & 0x000000FF), u8_version);
return ERROR;
}
unsigned char enable_ic_block_3x(void)
{
unsigned int u32_read;
if (handle_ic_read(REG_SYSCON_BLKEN_ADDR, 4, (unsigned char *)(&u32_read), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_read |= 0xc8000000;
/*u32_read |= (BLKEN_FIC_RB_EN | BLKEN_GPIO_RB_EN | BLKEN_SYS_RB_EN);*/
if (handle_ic_write(REG_SYSCON_BLKEN_ADDR, 4, (unsigned char *)&u32_read, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
if (handle_ic_read(REG_SYSCON_MISCIER_ADDR, 4, (unsigned char *)(&u32_read), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_read |= 0x00000404;
/*u32_read |= (MISCIER_RB_MCU_INTO | MISCIER_RB_MCU_INT_EN);*/
if (handle_ic_write(REG_SYSCON_MISCIER_ADDR, 4, (unsigned char *)&u32_read, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
return SUCCESS;
}
unsigned char disable_i2c_deglitch_3x(void)
{
unsigned int u32_buf = 0;
unsigned char u8_retry = 3, u8_comfirm_time = 3;
unsigned char u8_check = 0, u8_i = 0;
unsigned int u32_i2c_deglitch = I2CENG_AUTO_I2C_DGF_MODE2 | I2CENG_DGF_OSC_AUTOSEL | I2CENG_AUTO_I2C_DGF_MODE | I2CENG_I2CS_DGFEN_DLY_NUM(6);
/*check I2C mode*/
while (u8_retry--) {
u32_buf = 0;
handle_ic_read(REG_FLASHCTL_DEVID_ADDR, 4, (unsigned char *)(&u32_buf), g_u8_drv_interface, I2C_WORD_MODE);
if ((u32_buf & 0xFFFF0000) == 0xF3030000)
u8_check++;
else
break;
}
if (u8_check == 3) {
if (!g_u8_mute_i2c_err_log)
DEBUGOUT("PDA2 OK\r\n");
return SUCCESS;
}
u8_retry = 100;
while (u8_retry--) {
if (handle_ic_write(REG_I2CENG_ADDR, 4, (unsigned char *)(&u32_i2c_deglitch), I2C_PDA_MODE, I2C_WORD_MODE) == ERROR) {
/*DEBUGOUT("[disable_i2c_deglitch_3x] handle_ic_write I2C NG!\r\n");*/
if (!g_u8_mute_i2c_err_log)
DEBUGOUT("[DI2CDG]-W");
continue;
}
u8_check = 0;
for (u8_i = 0; u8_i < u8_comfirm_time; u8_i++) {
/*check I2C*/
u32_buf = 0;
if (handle_ic_read(REG_I2CENG_ADDR, 4, (unsigned char *)(&u32_buf), I2C_PDA_MODE, I2C_WORD_MODE) == ERROR) {
/*DEBUGOUT("[disable_i2c_deglitch_3x] 2.handle_ic_read I2C NG!\r\n");*/
if (!g_u8_mute_i2c_err_log)
DEBUGOUT("[DI2CDG]-R");
break;
}
if (u32_buf == u32_i2c_deglitch)
u8_check++;
else
break;
}
if (u8_check == u8_comfirm_time)
break;
}
if (!g_u8_mute_i2c_err_log)
DEBUGOUT("\r\n");
if (u8_retry == 0)
return ERROR;
u32_buf = GPIO_DEGLITCH_EN(3);
if (handle_ic_write(REG_GPIO_DEGLITCH_ENABLE, 4, (unsigned char *)(&u32_buf), I2C_PDA_MODE, I2C_WORD_MODE) == ERROR) {
DEBUGOUT("[DI2CDG_3x] 3.handle_ic_write I2C NG!\r\n");
return ERROR;
}
/*Enable PDA2*/
u32_buf = PDA2CTL_PDA2_EN | PDA2CTL_SIE2;
if (handle_ic_write(REG_PDA2CTL_ADDR, 4, (unsigned char *)(&u32_buf), I2C_PDA_MODE, I2C_WORD_MODE) == ERROR) {
DEBUGOUT("[DI2CDG_3x] 4.i2c_write_pda I2C NG!\r\n");
return ERROR;
}
/*Disable PDA*/
#if SELFTEST
#ifdef __KERNEL__
raydium_i2c_pda_set_address(RAYDIUM_PDA_I2CREG, DISABLE);
#else
sysfs_mode_control(ENABLE_PDA2);
#endif
#else
i2c_set_pda_address(I2C_EID, 0x500006, I2C_PDA2_WORD_MODE);
#endif
return SUCCESS;
}
unsigned char stop_mcu_3x(unsigned char u8_is_tp_reset)
{
unsigned short u16_time_out = 100;
unsigned int u32_read_data;
unsigned int u32_write = 0;
g_u8_mute_i2c_err_log = TRUE;
if (u8_is_tp_reset) {
gpio_touch_hw_reset();
delay_ms(35);
if (disable_i2c_deglitch_3x() == ERROR) {
DEBUGOUT("[%s] 2.DI2CDG NG!\r\n", __func__);
goto EXIT_ERROR;
}
}
/*DEBUGOUT("[stop_mcu_3x] 1\r\n");*/
/*Stop MCU*/
/*memset(wData, 0, sizeof(wData));*/
u32_write = (MCU_HOLD | SKIP_LOAD);
if (handle_ic_write(REG_FLASHCTL_FLASH_STATE_REG_ADDR, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
goto EXIT_ERROR;
u32_write = BLKRST_SW_RST;
if (handle_ic_write(REG_SYSCON_BLKRST_ADDR, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
goto EXIT_ERROR;
delay_ms(20);
if (disable_i2c_deglitch_3x() == ERROR) {
/*DEBUGOUT("[stop_mcu_3x] 3.disable_i2c_deglitch_3x NG!\r\n");*/
DEBUGOUT("[%s] 3.DI2CDG NG!\r\n", __func__);
goto EXIT_ERROR;
}
/*DEBUGOUT("[stop_mcu_3x] 2\r\n");*/
if (handle_ic_read(REG_FLASHCTL_FLASH_STATE_REG_ADDR, 4, (unsigned char *)(&u32_read_data), g_u8_drv_interface, I2C_WORD_MODE) == ERROR) {
DEBUGOUT("[%s] 4.Flash State NG!\r\n", __func__);
goto EXIT_ERROR;
}
while ((u32_read_data & MCU_HOLD_STATUS) == 0 && u16_time_out-- > 0) {
delay_ms(10);
if (handle_ic_read(REG_FLASHCTL_FLASH_STATE_REG_ADDR, 4, (unsigned char *)(&u32_read_data), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
goto EXIT_ERROR;
#if ENABLE_WDT
Chip_WWDT_Feed(LPC_WWDT);/* reload the Watchdog timer*/
#endif
}
DEBUGOUT("Stop MCU=0x%X(0x%x)(%d)!!\r\n", u32_read_data, (u32_read_data & MCU_HOLD_STATUS), u16_time_out);
if ((u32_read_data & MCU_HOLD_STATUS) == 0) {
DEBUGOUT("[%s] 4.STOP MCU NG!\r\n", __func__);
goto EXIT_ERROR;
}
g_u8_mute_i2c_err_log = FALSE;
return SUCCESS;
EXIT_ERROR:
g_u8_mute_i2c_err_log = FALSE;
return ERROR;
}
unsigned char hardware_reset_3x(unsigned char u8_enable_ic_block)
{
unsigned char u8_time_out = 200;
DEBUGOUT("HW Reseting...\r\n");
gpio_touch_hw_reset();
delay_ms(100);
g_u8_mute_i2c_err_log = TRUE;
if (disable_i2c_deglitch_3x() == ERROR) {
/*DEBUGOUT("[hardware_reset_3x] disable_i2c_deglitch_3x NG!\r\n");*/
DEBUGOUT("[%s] DI2CDG NG!\r\n, __func__");
g_u8_mute_i2c_err_log = FALSE;
return ERROR;
}
g_u8_mute_i2c_err_log = FALSE;
if (u8_enable_ic_block) {
if (enable_ic_block_3x() == ERROR) {
DEBUGOUT("HW Reset NG!!\r\n");
return ERROR;
}
}
while (u8_time_out--) {
if (gpio_touch_int_pin_state_access())
break;
if (u8_time_out == 0)
return ERROR;
delay_ms(1);
}
return SUCCESS;
}
unsigned char set_fw_system_cmd_3x(unsigned int u32_sysm_cmd)
{
unsigned char u8_time_out = 100, u8_value;
if (handle_ic_write(FW_SYS_CMD_ADDR, 4, (unsigned char *)&u32_sysm_cmd, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
/* Wait Test Command ready*/
while (--u8_time_out) {
delay_ms(1);
if (handle_ic_read(FW_SYS_CMD_ADDR, 1, &u8_value, g_u8_drv_interface, I2C_BYTE_MODE) == ERROR)
return ERROR;
else if (u8_value == 0)
break;
}
if (u8_time_out == 0)
return ERROR;
return SUCCESS;
}
unsigned char wait_fw_state_3x(unsigned int u32_addr, unsigned int u32_state, unsigned short u16_delay, unsigned short u16_retry)
{
unsigned int u32_read_data = 0;
do {
if (handle_ic_read(u32_addr, 4, (unsigned char *)(&u32_read_data), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
delay_ms(u16_delay);
u16_retry--;
#if ENABLE_WDT
/* reload the Watchdog timer*/
Chip_WWDT_Feed(LPC_WWDT);
#endif
} while ((u32_read_data != u32_state) && (u16_retry != 0));
if (u32_read_data != u32_state)
return ERROR;
return SUCCESS;
}
unsigned char wait_T2D_done_state_3x(unsigned int u32_addr, unsigned short u16_delay, unsigned short u16_retry)
{
unsigned int u32_read_data = 0;
do {
if (handle_ic_read(u32_addr, 4, (unsigned char *)(&u32_read_data), g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
/*DEBUGOUT("[T2DW] ready 0x%x\r\n", u32_read_data);*/
delay_ms(u16_delay);
u16_retry--;
} while (((u32_read_data & 0x01) == 0) && (u16_retry != 0));
if ((u32_read_data & 0x01) == 0)
return ERROR;
return SUCCESS;
}
unsigned char WriteToDriver_3x(unsigned char *p_u8_data, unsigned char u8_data_length)
{
unsigned int u32_write = 0;
if (p_u8_data != NULL) {
if (p_u8_data[0] == 0xFE) {
g_u8_PAGE_ADDR = p_u8_data[1];
return SUCCESS;
}
if (p_u8_data[0] == 0x35) {
u32_write = ((0x00 << 24) | (0x00 << 16) | (p_u8_data[0] << 8) | g_u8_PAGE_ADDR);
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
}
if (u8_data_length == 1) /*cmd mode*/
u32_write = ((0x00 << 24) | (p_u8_data[1] << 16) | (p_u8_data[0] << 8) | g_u8_PAGE_ADDR);
else if (u8_data_length == 2)
u32_write = ((0x01 << 24) | (p_u8_data[1] << 16) | (p_u8_data[0] << 8) | g_u8_PAGE_ADDR);
else if (u8_data_length == 5) {
/* 2A 2B*/
u32_write = ((0x01 << 24) | (p_u8_data[1] << 16) | (p_u8_data[0] << 8) | 0x00);
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = ((0x01 << 24) | (p_u8_data[2] << 16) | (p_u8_data[0] << 8) | 0x01);
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = ((0x01 << 24) | (p_u8_data[3] << 16) | (p_u8_data[0] << 8) | 0x02);
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = ((0x01 << 24) | (p_u8_data[4] << 16) | (p_u8_data[0] << 8) | 0x03);
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
return SUCCESS;
}
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
}
return SUCCESS;
}
unsigned char ReadFromDriver_3x(unsigned char *p_u8_addr, unsigned char u8_read_len, unsigned char *p_u8_output_buf)
{
unsigned int u32_write = 0;
if ((p_u8_addr[0] == 0xFE) || (p_u8_addr[0] == 0xFF) || (u8_read_len > 1)) {
DEBUGOUT("[%s] no use\r\n", __func__);
return FALSE;
}
u32_write = ((p_u8_addr[0] << 24) | (g_u8_PAGE_ADDR << 16) | (0x01 << 8) | 0x82);
DEBUGOUT("read address 0x%x\r\n", u32_write);
if (handle_ic_write(REG_T2D_R_CONFIG_1, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
if (handle_ic_read(REG_T2D_R_CONFIG_2, 4, p_u8_output_buf, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
DEBUGOUT("read data 0x%x\r\n", p_u8_output_buf[0]);
return TRUE;
}
unsigned char WriteDriverByTouchMode(const unsigned char *p_u8_data, uint16_t u16DataLength)
{
unsigned short TotalDataLen = (p_u8_data[3] << 8) + p_u8_data[4] - 7;/*Valid data not include 7 byte header*/
unsigned short u16_i = 0/*, u8_j = 0*/;
unsigned char u8_CurCmdLen = 0;
unsigned int u32_write = 0;
/*
* unsigned char u8_read_buf[4];
* signed char i8_retry_cnt = 3;
* unsigned char u8_error_flag = 0;
*/
for (u16_i = 0; u16_i < (u16DataLength - 7) && u16_i < sizeof(g_u8_data_buf); u16_i++)
g_u8_data_buf[u16_i] = p_u8_data[u16_i + 7];
if (p_u8_data[0] == 0xF3 && p_u8_data[1] == 0x01) {
/*Check Command type*/
DEBUGOUT("Write Key\r\n");
u32_write = 0x015AFABC;
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
if (p_u8_data[2] == 0x01 ||
p_u8_data[2] == 0x10) { /*SPI short multiple command*/
for (u16_i = 0; u16_i < TotalDataLen; u16_i += (u8_CurCmdLen + 1)) {
u8_CurCmdLen = g_u8_data_buf[u16_i];
/*
* DEBUGOUT(" i = %d\r\n", u16_i);
* if (u8_CurCmdLen == 2)
* DEBUGOUT("-Before Parse Data[%d] = 0x%02X, 0x%02X, 0x%02X, %d\r\n", u16_i, g_u8_data_buf[u16_i], g_u8_data_buf[u16_i + 1], g_u8_data_buf[u16_i + 2], u8_CurCmdLen);
* else if (u8_CurCmdLen == 3)
* DEBUGOUT("-Before Parse Data[%d] = 0x%02X, 0x%02X, 0x%02X, 0x%02X, %d\r\n", u16_i, g_u8_data_buf[u16_i], g_u8_data_buf[u16_i + 1], g_u8_data_buf[u16_i + 2], g_u8_data_b uf[u16_i + 3], u8_CurCmdLen);
* else
* DEBUGOUT("-Before Parse Data[%d] = 0x%02X, 0x%02X, %d\r\n", u16_i, g_u8_data_buf[u16_i], g_u8_data_buf[u16_i + 1], u8_CurCmdLen);
*/
/*Check is Delay command*/
if (g_u8_data_buf[u16_i + 1] != 0xFF) { /*Check Command ID*/
if (wait_T2D_done_state_3x(0x50001220, 1, 100) == ERROR) {
DEBUGOUT("[T2DW] Check T2D idle Fail\r\n");
return ERROR;
}
WriteToDriver_3x((unsigned char *)&g_u8_data_buf[u16_i + 1], u8_CurCmdLen);
/*delay_ms(1);*/
/*
* i8_retry_cnt = 3;
* while (i8_retry_cnt) {
* u8_error_flag = 0;
* if (ReadFromDriver_3x((unsigned char *)&g_u8_data_buf[u16_i + 1], u8_CurCmdLen - 1 , u8_read_buf)) {
* for (u8_j = 0 ; u8_j < u8_CurCmdLen - 1 ; u8_j++) {
* if (g_u8_data_buf[u16_i + 2 + u8_j] != u8_read_buf[u8_j]) {
* u8_error_flag = 1;
* DEBUGOUT("write address:%x\r\n", g_u8_data_buf[u16_i + 1]);
* DEBUGOUT("Data:%d\r\n", g_u8_data_buf[u16_i + 2 + u8_j]);
* DEBUGOUT("g_u8_spi_cmd_read_buf[%d]:%x\r\n", u8_j, u8_read_buf[u8_j]);
* }
* }
* if (u8_error_flag == 0)
* break;
* if (u8_error_flag == 1)
* i8_retry_cnt--;
* if (i8_retry_cnt == 0) {
* DEBUGOUT("i8_retry_cnt error!\r\n");
* return ERROR;
* }
* } else
* break;
* }
*/
} else {
DEBUGOUT("Delay\r\n");
delay_ms(g_u8_data_buf[u16_i + 2]);
}
}
} else {
DEBUGOUT("[%s] command type not support\r\n", __func__);
return ERROR;
}
u32_write = 0x0100FABC;
if (handle_ic_write(REG_T2D_CONFIG_2, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
u32_write = 0x0000015A;
if (handle_ic_write(REG_T2D_CONFIG_3, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE) == ERROR)
return ERROR;
}
return SUCCESS;
}

View File

@@ -0,0 +1,31 @@
/* f303_ic_control.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "ic_drv_global.h"
#define HEADER_LENGTH (4)//length + checksum
extern unsigned char enable_ic_block_3x(void);
extern unsigned char stop_mcu_3x(unsigned char u8_is_tp_reset);
extern unsigned char hardware_reset_3x(unsigned char u8_enable_ic_block);
extern unsigned char check_dev_id_3x(unsigned short u16_dev_id);
extern unsigned char check_dev_sub_version_3x(unsigned char u8_version);
extern unsigned char set_fw_system_cmd_3x(unsigned int u32_sysm_cmd);
extern unsigned char wait_fw_state_3x(unsigned int u32_addr, unsigned int u32_state, unsigned short u16_delay, unsigned short u16_retry);
extern unsigned char disable_i2c_deglitch_3x(void);
extern unsigned char WriteDriverByTouchMode(const unsigned char *p_u8_data, uint16_t u16DataLength);

View File

@@ -0,0 +1,281 @@
/* f303_ic_reg.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
// ['h5000_0900], [32'hFFFF_FFFF], PRAM_LOCK
#define I2CTB_LOCK (0x00000001<<6) // [0] (R/W) I2C Table lock
#define BOTLR_LOCK (0x00000001<<5) // [0] (R/W) Boot loader lock
#define USEFW_LOCK (0x00000001<<4) // [0] (R/W) User fw lock
#define CONFIG_LOCK (0x00000001<<3) // [0] (R/W) Configuration lock
#define COMP_LOCK (0x00000001<<2) // [0] (R/W) compensation lock
#define BASEL_LOCK (0x00000001<<1) // [0] (R/W) baseline lock
#define INICO_LOCK (0x00000001<<0) // [0] (R/W) Initial code lock
// ['h5000_0904], [32'h0000_0000], Program RAM store type, PRAM_STORE_TYPE
#define BOTLR_AREA (0x00000001<<5) // [0] (R/W) Boot loader area
#define USEFW_AREA (0x00000001<<4) // [0] (R/W) User fw area
#define CONFIG_AREA (0x00000001<<3) // [0] (R/W) Configuration area
#define COMP_AREA (0x00000001<<2) // [0] (R/W) compensation area
#define BASEL_AREA (0x00000001<<1) // [0] (R/W) baseline area
#define INICO_AREA (0x00000001<<0) // [0] (R/W) Initial code area
// ['h5000_0918], [32'h0000_0000],Flash state control register ,FLASH_STATE_REG
#define BLDR_FINISH (0x00000001<<14) // [0] (R) MCU_HOLD status
#define MCU_HOLD_STATUS (0x00000001<<13) // [0] (R) MCU_HOLD status
#define BOOT_REGION (0x00000001<<12) // [0] (R) boot region index
#define BL_CRC_CHK (0x00000001<<11) // [0] (R/W) boot-loader area CRC check
#define FW_CRC_CHK (0x00000001<<10) // [0] (R/W) user FW CRC check
#define PARA_CRC_CHK (0x00000001<<9) // [0] (R/W) parameter area CRC check
#define COMP_CRC_CHK (0x00000001<<8) // [0] (R/W) compensation area CRC check
#define BASELINE_CRC_CHK (0x00000001<<7) // [0] (R/W) baseline area CRC check
#define INITIAL_CRC_CHK (0x00000001<<6) // [0] (R/W) initial code CRC check
#define MCU_HOLD (0x00000001<<5) // [0] (R/W) MCU hold
#define SKIP_LOAD (0x00000001<<4) // [0] (R/W) Skip all load flash action
#define FW_INICO_ERR (0x00000001<<3) // [0] (R) FW_INICO_ERR
#define FW_CG_ERR (0x00000001<<2) // [0] (R) cc bl CRC error
#define FW_CRC_ERR (0x00000001<<1) // [0] (R) FW_CRC_ERR
#define BL0_CRC_ERR (0x00000001<<0) // [0] (R) BL0_CRC_ERR
// ['h5000_0934], [32'h0000_0000], FLASH Lock and Key Register (main) (FLKEY1)
#define FLKEY1_LOCK (0x00000000<<0) // [7:0] (R/W) FLASH Lock and Key1 Register
#define FLKEY1_KEY (0x000000A5<<0) // [7:0] (R/W) FLASH Unlock and Key1 Register:0xA5
// ['h5000_0938], [32'h0000_0000], FLASH Lock and Key Register (information) (FLKEY2)
#define FLKEY2_LOCK (0x00000000<<0) // [7:0] (R/W) FLASH Lock and Key3 Register
#define FLKEY2_KEY (0x000000D7<<0) // [7:0] (R/W) FLASH Unlock and Key3 Register:0xD7
//#define MAX_SENSING_PIN_NUM 30
// ['h5000_0610], [32'h0106_0300], I2C eng Register (I2CENG)
#define REG_I2CENG_ADDR 0x50000610
#define I2CENG_AUTO_I2C_DGF_MODE2 (0x00000001<<26) // [26:26] (R/W) auto_i2c_dgf_mode2,, 1: switch def_en after next posedge SCL_dgf, 0: switch def_en control auto_i2c_dgf_mode (bit[24]).
#define I2CENG_DGF_OSC_AUTOSEL (0x00000001<<25) // [25:25] (R/W) dgf_osc_autosel,, 0: TP OSC control, 1: TP OSC/DRIVER OSC control
#define I2CENG_AUTO_I2C_DGF_MODE (0x00000001<<24) // [24:24] (R/W) dgf_en signal delay timing select 0: switch def_en after STOP signal 1: switch def_en after next posedge SCL.
#define I2CENG_I2CS_DGFEN_DLY_NUM(u7x) ((u7x&0x0000007F)<<16) // [22:16] (R/W) dgf_en signal delay number (clock by system clock ).
#define I2CENG_I2CS_DEGFIR_NUM(u7x) ((u7x&0x0000007F)<<8) // [14:8] (R/W) I2C Pad (SCL/SDA) deglitch filter number.
#define I2CENG_RB_MANUAL_I2C_DGF (0x00000001<<7) // [7:7] (R/W) I2C Pad (SCL/SDA) deglitch filter manual mode control 1: Enable 0: Disable.
#define I2CENG_RB_I2C_DGF_EN (0x00000001<<6) // [6:6] (R/W) I2C Pad (SCL/SDA) deglitch filter enable control register when rb_manual_i2c_dgf =1, 1: Enable 0: Disable.
#define I2CENG_FIRST_DAT_SEL(u2x) ((u2x&0x00000003)<<0) // [1:0] (R/W) First data request select for PDA2 read. 0: at 2nd SCL; 1: at 3th SCL; 2:at 4th SCL; 3:at 5th SCL.
#define REG_I2C_I2CFLASHPRO 0x50000624
//['h5000_0628], [32'h0000_0000], PDA2 Control Register (PDA2CTL)
#define REG_PDA2CTL_ADDR 0x50000628
#define PDA2CTL_PDA2_EN (0x00000001UL<<2) // [2:2] (R/W) PDA2 enable bit. 1: enable 0: disable.
#define PDA2CTL_SIE2 (0x00000001<<1) // [1:1] (R/W) SIE2 enable register . 1: enable 0: mask.
#define PDA2CTL_SI2 (0x00000001<<0) // [0:0] (R/W) SI2 interrupt flag (write 1 to clear).
//['h5000_0E1C], [32'h0000_0000], GPIO deglitch enable(GPIO_DEGLITCH)
#define REG_GPIO_DEGLITCH_ENABLE 0x50000E1C
#define GPIO_PULLH_EN(u2x) ((u2x&0x00000003)<<0) // [3:2] (R/W) 1: enable pull-high of GPIO, 0: disable pull-high of GPIO
#define GPIO_DEGLITCH_EN(u2x) ((u2x&0x00000003)<<0) // [1:0] (R/W) 1: enable deglitch function of GPIO, 0: disable deglitch function of GPIO
#define REG_SYSCON_BLKEN_ADDR 0x40000000
#define REG_SYSCON_BLKRST_ADDR 0x40000004
//#define REG_SYSCON_MISCIER_ADDR 0x40000014
#define REG_T2D_CONFIG_1 0x5000145c
#define REG_T2D_CONFIG_2 0x50001460
#define REG_T2D_CONFIG_3 0x50001464
#define REG_T2D_R_CONFIG_1 0x50001468
#define REG_T2D_R_CONFIG_2 0x5000146C
#define MCU_HOLD (0x00000001<<5) // [0] (R/W) MCU hold
#define SKIP_LOAD (0x00000001<<4) // [0] (R/W) Skip all load flash action
#define BLKRST_SW_RST (0x00000001<<0) // [0] (R/W) 1: Software reset, all digital block will be reset
#define MCU_HOLD_STATUS (0x00000001<<13) // [0] (R) MCU_HOLD status
#define FLH_RELEASE_PD (0x00000001<<5) // [0] (R/W) Release from deep power down mode
#define BL_CRC_CHK (0x00000001<<11) // [0] (R/W) boot-loader area CRC check
/* Base addresses */
#define RM_PRAM_BASE (0x00000000UL) // Program, AHB
#define RM_RAM_BASE (0x20000000UL) // SRAM, AHB
#define RM_AHB_BASE (0x40000000UL) // Peripheral, AHB
#define RM_APB_BASE (0x50000000UL) // Peripheral, APB
//#define FW_SYS_CMD_ADDR 0x20000288
#define FW_FT_CMD_ADDR 0x20000289
#define FW_FT_ARG0_ADDR 0x2000028A
#define FW_FT_ARG1_ADDR 0x2000028C
//#define FW_FT_IMG_ADDR 0x2000019C
//#define FW_TP_SEQ_NUM_ADDR 0x20000290
#define SYS_CMD_FUNC_DIS_BS_UPDATE 0x20
#define DIS_BASELINE_UPDATE 0x00010000
#define SYS_CMD_DO_BL_CAL 0x5A
#define SYS_CMD_READ_CAL_FLAG 0x5B
#define SYS_CMD_DO_CC_CAL 0x5C
#define SYS_CMD_CAL_WAIT 0x5D
#define SYS_CMD_WAKEUP_GESTURE_ENABLE 0x40
#define SYS_CMD_WAKEUP_GESTURE_DISABLE 0x41
#define SYS_CMD_FT_GET_DSP_NS_PARAM 0x60
#define SYS_CMD_FT_FUN_FLAG 0x62
#define SYS_CMD_FT_DC_DISABLE 0x010000
#define SYS_CMD_FT_DIG_GAIN_ENABLE 0x020000
#define SYS_CMD_FT_TEST_LOG_EN 0x800000
#define FW_FT_CHANNEL_X_ADDR (PRAM_PARA_START + 24)
#define FW_FT_CHANNEL_Y_ADDR (PRAM_PARA_START + 25)
#define FW_FT_PIN_ADDR (PRAM_PARA_START + 27)
#define FW_FT_PWR_MODE_ADDR (PRAM_PARA_START + 26)
#define FW_FT_FW_VERSION (PRAM_PARA_START + 4)
#define FW_FT_SRAM_FW_VERSION 0x200006E0
#define BOOT_SYNC_DATA_ADDR 0x20000200
#define BOOT_MAIN_STATE_ADDR 0x20000204
#define BOOT_NORMAL_STATE_ADDR 0x20000208
#define BOOT_BURNING_STATE_ADDR 0x2000020C
#define BOOT_CMD_TYPE_ADDR 0x20000210
#define BOOT_RET_DATA_ADDR 0x20000214
#define BOOT_TEST_MODE_ADDR 0x20000218
#define FLASH_OFFSET (0x7800)
#define PRAM_BASELINE_LENGTH (0x130)
#define PRAM_COMP_LENGTH (0x304)
#define PRAM_DIS_INIT_LENGTH (0x80)
#define PRAM_PARA_LENGTH (0x174)
#define PRAM_FW_LENGTH (0x7300)
#define PRAM_BOOT_LENGTH (0x800)
#define PRAM_BOOT_START (0x0000)
#define PRAM_DIS_INIT_START (0x7F80)
#define PRAM_COMP_START (0x7C78)
#define PRAM_PARA_START (0x7B00)
#define PRAM_FW_START (0x0800)
#define PRAM_RESERVE_START (0x0800)
#define PRAM_PARA_DC_THD_ADDR (PRAM_PARA_START + 136)
#define PRAM_CC_TABLE_ADDR (0x7F78)
#define PRAM_BASEINE_START (0x6CCC)
#define PRAM_BOOT_CRC_LENGTH (PRAM_BOOT_LENGTH - HEADER_LENGTH)
#define PRAM_FW_CRC_START (0x6B5C)
#define PRAM_FW_CRC_LENGTH (PRAM_FW_LENGTH + PRAM_PARA_LENGTH) //0x7474
#define PRAM_CB_CRC_START (0x6DFC)
#define PRAM_CB_CRC_LENGTH (PRAM_COMP_LENGTH + PRAM_BASELINE_LENGTH)
#define FT_RAWDATA1_SHORT_BUF_ADDR 0x200002E4 //((at(0x200002E4)));
#define FT_RAWDATA2_OPEN_BUF_ADDR (FT_RAWDATA1_SHORT_BUF_ADDR+100) //((at(0x20000348)));
#define FT_RAWDATA3_CC_BUF_ADDR (FT_RAWDATA2_OPEN_BUF_ADDR+100) //((at(0x200003AC)));
#define FT_UC_BUF_ADDR (FT_RAWDATA3_CC_BUF_ADDR+100) //((at(0x20000410)));
#define FT_OPEN_BL_BUF_ADDR (FT_UC_BUF_ADDR+100) //((at(0x20000474)));
#define FT_TEST_RESULT_BUF_ADDR (FT_OPEN_BL_BUF_ADDR+100) //((at(0x200004D8)));
#define FT_TEST_ITEM_RESULT (FT_TEST_RESULT_BUF_ADDR+50+2) //((at(0x2000050C)));
#define FT_TEST_INFO_ADDR 0x20000674//FT_IMG2PIN_BUF_ADDR+72//((at(0x20000674)));
#define FT_TEST_THD_ADDR (FT_TEST_INFO_ADDR+16) //((at(0x20000684)));
#define FT_TEST_PARA_ADDR (FT_TEST_THD_ADDR+36) //((at(0x200006A8)));
#define SRAM_FT_RAWDATA_3_CC_ADDR (RM_RAM_BASE + 0x0000074C) //0x2000074C
#define SRAM_FT_UC_CC_ADDR (RM_RAM_BASE + 0x000006EC) //0x200006EC
#define FLASH_NORMAL_FW_FW_VERSION_ADDR (FW_FT_FW_VERSION)
#define FLASH_NORMAL_FW_CUST_VERSION_ADDR (PRAM_PARA_START + 10)
#define FLASH_TEST_FW_FW_VERSION_ADDR (FW_FT_FW_VERSION + FLASH_OFFSET)
#define FLASH_NORMAL_FW_CC_TABLE_ADDR 0x9300
#define REG_FLASHCTL_FLASH_PRAM_LOCK 0X50000900
#define REG_FLASHCTL_FLASH_PRAM_STORE_TYPE 0X50000904
#define REG_FLASHCTL_FLASH_PRAM_ADDR 0X50000908
#define REG_FLASHCTL_FLASH_PRAM_LENGTH 0X5000090C
#define REG_FLASHCTL_FLASH_ADDR 0X50000910
#define REG_FLASHCTL_FLASH_ISPCTL 0X50000914
#define REG_FLASHCTL_FLASH_STATE_REG_ADDR 0x50000918
#define REG_FLASHCTL_FLASH_FLKEY1 0x50000934
#define REG_FLASHCTL_FLASH_FLKEY2 0x50000938
#define REG_FLASHCTL_FLASH_DATA 0x5000093C
#define REG_FLASHCTL_FLASH_ENG3 0x5000094C
#define REG_FLASHCTL_FLASH_PRGCHKSUM_ADDR 0x50000974
#define REG_FLASHCTL_FLASH_PRGCHKSUM_RESULT 0x50000978
#define REG_FLASHCTL_DEVID_ADDR 0x500009BC
#define REG_SPI_SLAVE_SPIFLASHPRO 0x50000524
#define PRAM_ADDR_CC_INFO 0x00007F78
#define RAM_WRITE_TEST_ADDR1 0x50000950
#define RAM_WRITE_TEST_ADDR2 0x50000B10
#define RAM_WRITE_TEST_ADDR3 0x50000B00
#define RAM_READ_TEST_ADDR1 0x50000954
#define RAM_READ_TEST_ADDR2 0x50000B04
#define RAM_READ_TEST_ADDR3 0x50000B08
#define FT_UPDATE 0x01
#define FT_BASELINE_SF 0x02
#define FT_BASELINE_PS 0x42
#define FT_COMPENSATION_SF 0x04
#define FT_COMPENSATION_PS 0x44
#define FT_RAWDATA_W_BL_SF 0x08
#define FT_RAWDATA_W_BL_PS 0x48
#define FT_RAWDATA_WO_BL_SF 0x10
#define FT_RAWDATA_WO_BL_PS 0x50
#define FT_ALG_RAWDATA 0x20
#define FT_PS_SEL 0x40
#define FT_DEBUG_MESSAGE 0x80
#define FT_UPDATE_CASE 0xFE
#define FT_STATUS_PURE_RAW 0x01
#define FT_STATUS_PURE_AF_DC 0x02
typedef enum {
CRC_CHECK_FAIL = 0x80,
CRC_CHECK_PASS = 0x81,
WAIT_TEST_MODE = 0x82,
PARTITION_CRC = 0xA0,
SET_ADDR_READY = 0xA1,
SET_ADDR_FAIL = 0xA2,
WRT_PRAM_DATA = 0xA3,
WRT_PRAM_FAIL = 0xA4,
WAIT_WRT_ACK = 0xA5,
WAIT_ACK_FAIL = 0xA6,
GET_WRT_ACK = 0xA7,
GET_WRT_UNLOCK = 0xA8,
GET_UNLOCK_FAIL = 0xA9,
} I2C_SYNC_CMD;
typedef enum {
MAIN_STATE_NORMAL_MODE = 0,
MAIN_STATE_BURNING_MODE,
MAIN_STATE_FIRWARE_MODE,
} TCH_BOOTLOADER_STATE;
typedef enum {
BURNING_STATE_INIT = 0,
BURNING_CHECK_ADDR,
BURNING_UNLOCK_PRAM,
BURNING_WRT_PRAM,
BURNING_WRT_FLASH_PREPARE,
BURNING_WRT_FLASH_EXCUTE,
BURNING_WRT_FLASH_FINISH,
BURNING_STATE_HALT,
} BL_BURNING_STATE;
typedef enum {
NORMAL_STATE_CHECK = 0,
NORMAL_CRC_CALC,
NORMAL_CRC_NOTIFY,
NORMAL_FW_CRC,
NORMAL_MODE_CHANGE,
NORMAL_MODE_IDLE,
} BL_NORMAL_STATE;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/* f303_ic_test.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "ic_drv_global.h"
/****************************************************************************
* Defined Const Value
*****************************************************************************/
#define FT_CMD_DO_FT_TEST 0x14
extern STATUS turn_on_flash_3x(void);
extern STATUS read_fpc_flash_3x(unsigned int u32_addr, unsigned int *p_u32_data);
extern STATUS set_test_info_thd_para_3x(void);
extern STATUS check_test_fw_status_3x(unsigned char u8_target_status, unsigned char *p_u8_result);
extern STATUS ft_test_do_fw_test_3x(unsigned short u16_test_items);
extern STATUS enter_fw_test_mode_3x(void);
extern STATUS system_test_3x(void);
extern STATUS ft_test_ctrl_mbist_fun_3x(unsigned char u8_enable);
extern STATUS ft_test_ram_test_3x(unsigned char u8_is_stop_mcu);
extern STATUS ft_test_connect_test_3x(void);
extern STATUS ft_test_reset_pin_test_3x(void);
extern STATUS ft_raw_data_checksum_check_3x(unsigned short *u16_buffer);
extern STATUS ft_test_result_checksum_check_3x(unsigned char *u8_buffer);
extern STATUS burn_cc_to_ic_flash_3x(void);
extern STATUS check_cc_bl_flag_3x(void);
extern STATUS read_test_fw_data_3x(unsigned short u16_test_items);
extern STATUS load_test_fw_3x(void);
extern void dump_image_data_3x(short *p_image_buf, unsigned char u8_remap);
extern void dump_image_hex_data_3x(short *p_image_buf);
extern STATUS ft_test_read_used_pin_infor_3x(unsigned char *p_u8_infor);
extern void ft_raw_data_checksum_cal_3x(unsigned short *u16_buffer);
extern void ft_test_result_checksum_cal_3x(unsigned char *u8_buffer);
extern STATUS baseline_update_control_3x(bool b_enable_baseline_update);
extern STATUS enter_normal_fw_3x(void);
extern STATUS do_calibration_3x(unsigned char u8_do_calibration_cmd, unsigned char u8_burn_flash);
extern STATUS hw_int_pin_Test_3x(void);
extern void test_item_message_3x(void);
extern STATUS burn_cc_3x(unsigned short u16_test_items);
extern void do_ic_test_3x(void);
extern STATUS burn_data_log_to_flash_3x(void);
extern STATUS burn_header_log_to_flash_3x(bool is_test_finish, bool is_in_header_data_page);
//-----------------------------extern FT function ------------------------------------------
extern STATUS load_test_fw_ft_3x(void);
extern void do_ic_panel_test_3x(void);
extern STATUS burn_fw_3x(void);
extern STATUS burn_to_ic_flash_3x(unsigned char u8_type);
extern unsigned char notify_panel_jig_start_test_3x(unsigned char u8_cmd);

View File

@@ -0,0 +1,127 @@
/* i2c_drv_global.c
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../Config.h"
#include "ic_drv_global.h"
#include "ic_drv_interface.h"
#ifdef __KERNEL__
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#endif
#include "../drv_interface.h"
#if !SELFTEST
#include "usb.h"
#include "Descriptors.h"
#endif
/*
*****************************************************************************
**
** Declared Global Variable
**
*****************************************************************************
********************* Global *********************
*/
unsigned short g_u16_dev_id;
unsigned char g_u8_drv_interface;
volatile unsigned char g_u8_gpio_irq_trigger;
unsigned char g_u8_raw_data_buffer[MAX_IMAGE_BUFFER_SIZE * 2];
unsigned short g_u16_raw_data_tmp[MAX_IMAGE_BUFFER_SIZE];
// IC Test
short g_i16_raw_data_1_short_buf[MAX_SENSING_PIN_NUM];
short g_i16_raw_data_2_open_buf[MAX_SENSING_PIN_NUM];
unsigned short g_u16_raw_data3_cc_buf[MAX_SENSING_PIN_NUM];
unsigned short g_u16_uc_buf[MAX_SENSING_PIN_NUM];//CC
unsigned short g_u16_raw_data3_golden_cc_buf[MAX_SENSING_PIN_NUM];
unsigned short g_u16_uc_golden_cc_buf[MAX_SENSING_PIN_NUM];
unsigned int g_u32_test_result[MAX_SENSING_PIN_NUM]; // each node test result (bit[0]:open ng, bit[1]:short ng, bit[2]:uniformity ng..etc)
unsigned char g_u8_test_result[MAX_SENSING_PIN_NUM];
unsigned int g_u32_wearable_test_result;
unsigned char g_u8_wearable_pin_map[MAX_IMAGE_BUFFER_SIZE];
unsigned char g_u8_data_buf[DATA_BUFFER_SIZE];
unsigned char g_u8_mipi_read_buf[56];
unsigned char g_u8_channel_x;
unsigned char g_u8_channel_y;
unsigned char g_u8_is_normal_fw;
volatile unsigned short g_u16_test_items_host_cmd;
unsigned short g_u16_test_items_tool_cmd;
unsigned char g_u8_ic_power_on_ng;
char g_i8_test_baseline_msg[30];
volatile unsigned short g_u16_panel_jig_set_test_items;
bool b_is_auo_jig_testing;
#if ENABLE_TEST_TIME_MEASURMENT || ENABLE_TEST_TIME_MEASURMENT_CC
unsigned int g_u32_spend_time;
#endif
unsigned int g_u32_fw_cc_version;
unsigned char g_u8_print_debug_msg;
unsigned char g_u8_display_interface;
unsigned char g_u8_PAGE_ADDR;
int g_u32_dongle_flash_ini_addr;// 0xF000
int g_u32_ini_threshold_addr;// DONGLE_FLASH_INI_ADDR + 16
int g_u32_ini_para_addr;// INI_THRESHOLD_ADDR + 36
//int u32_ini_raw_data_2_bl_addr;// INI_PARA_ADDR+48
int g_u32_ini_raw_data_3_cc_addr;// INI_RAW_DATA2_BL_ADDR+72
int g_u32_ini_uc_cc_addr;// INI_RAW_DATA_3_CC_ADDR + 72// INI_RAW_DATA2_ADDR
int g_u32_initial_code_start_addr;
void ic_drv_init(void)
{
g_u16_test_items_host_cmd = 0xFFFF;
g_u16_test_items_tool_cmd = 0;
g_u16_dev_id = DEVICE_ID_3X;
g_u8_print_debug_msg = 0;
g_u8_display_interface = DISPLAY_TOUCH_2_DRIVER_MODE;
b_is_auo_jig_testing = false;
#if !SELFTEST
g_u8_ic_power_on_ng = FALSE;
#endif
}
/*
*****************************************************************************
**
* End Of File
******************************************************************************
*/

View File

@@ -0,0 +1,190 @@
/* i2c_drv_global.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _DRVGLOBAL_H_
#define _DRVGLOBAL_H_
#include "../Config.h"
#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
#endif
#if (SELFTEST_2X)
#include "f302_ic_control.h"
#endif
#if !SELFTEST
#include "f302_ic_control.h"
#include "f303_ic_control.h"
#include "usb.h"
#endif
//********* Basic Parameter Definition ***********//
/*****************************************************************************
**
** Declared Global Variable
**
*****************************************************************************/
#define MAX_IMAGE_BUFFER_SIZE 64
#define MAX_SENSING_PIN_NUM 50 // (wearable)
#define F302_MAX_IMAGE_BUFFER_SIZE 36
#define DATA_BUFFER_SIZE (0x100)
#define F302_DONGLE_FLASH_INI_ADDR 0xF000
#define F302_INI_THRESHOLD_ADDR (F302_DONGLE_FLASH_INI_ADDR + 16)
#define F302_INI_PARA_ADDR (F302_INI_THRESHOLD_ADDR + 36)
#define F302_INI_RAW_DATA2_BL_ADDR (F302_INI_PARA_ADDR + 48)
#define F302_INI_RAW_DATA_3_CC_ADDR (F302_INI_RAW_DATA2_BL_ADDR + 72)
#define F302_INI_UC_CC_ADDR (F302_INI_RAW_DATA_3_CC_ADDR + 72) // INI_RAW_DATA2_ADDR
#define F302_NA_P 36
#define F303_DONGLE_FLASH_INI_ADDR 0x10000
#define F303_INI_THRESHOLD_ADDR (F303_DONGLE_FLASH_INI_ADDR + 16)
#define F303_INI_PARA_ADDR (F303_INI_THRESHOLD_ADDR + 36)
#define F303_INI_RAW_DATA2_BL_ADDR (F303_INI_PARA_ADDR + 48)
#define F303_INI_RAW_DATA_3_CC_ADDR (F303_INI_RAW_DATA2_BL_ADDR + 128)
#define F303_INI_UC_CC_ADDR (F303_INI_RAW_DATA_3_CC_ADDR + 128) // INI_RAW_DATA2_ADDR
#define F303_MAX_SENSING_PIN_NUM 48
#define F303_NA_P 65
#define F302_INITIAL_CODE_START_ADDR 0xF400
#define F303_INITIAL_CODE_START_ADDR 0x10400
#define PRINT_DEBUG_MSG_TYPE_1 0x01
#define PRINT_DEBUG_MSG_TYPE_2 0x02
#define PRINT_DEBUG_MSG_TYPE_3 0x04
#define PRINT_DEBUG_MSG_TYPE_4 0x08
#define PRINT_DEBUG_MSG_TYPE_5 0x10
#define PRINT_DEBUG_MSG_TYPE_6 0x20
#define PRINT_DEBUG_MSG_TYPE_7 0x40
#define PRINT_DEBUG_MSG_TYPE_8 0x80
#define FW_SYS_CMD_ADDR 0x20000288
#define SYS_CMD_TP_MANUAL_MODE 0x34
#define SYS_CMD_DO_BL_CAL 0x5A
#define SYS_CMD_DO_CC_CAL 0x5C
#define FW_TP_SEQ_NUM_ADDR 0x20000290
#define FW_TP_POINT_DATA_ADDR 0x20000294
#define REG_SYSCON_MISCIER_ADDR 0x40000014
#define FW_FT_IMG_ADDR 0x2000019C
#define RM_DATAMEM0_BASE 0x20000000
#define F303_DRAM_FT_DBG_START 0x2000004C
//======================= Basic Hardware Define ==============================
//==================== End of Basic Hardware Define ==========================
#if SELFTEST
#ifdef __KERNEL__
typedef enum {
error = -1,
success = 1
} STATUS;
#else
typedef enum {
ERROR = 0,
SUCCESS = 1
} STATUS;
typedef enum {
DISABLE = 0,
ENABLE = 1
} FunctionalState;
typedef enum {
false = 0,
true = 1
} bool;
#endif
#endif
//========== Basic Parameter Information ==========
//********************* Global *********************//
// Global variable for dongle
extern unsigned char g_u8_drv_interface;
extern volatile unsigned char g_u8_gpio_irq_trigger;
extern unsigned short g_u16_dev_id;
extern unsigned char g_u8_raw_data_buffer[MAX_IMAGE_BUFFER_SIZE * 2];
extern unsigned short g_u16_raw_data_tmp[MAX_IMAGE_BUFFER_SIZE];
extern short g_i16_raw_data_1_short_buf[MAX_SENSING_PIN_NUM];
extern short g_i16_raw_data_2_open_buf[MAX_SENSING_PIN_NUM];
extern unsigned short g_u16_raw_data3_cc_buf[MAX_SENSING_PIN_NUM];
extern unsigned short g_u16_uc_buf[MAX_SENSING_PIN_NUM];
extern unsigned short g_u16_raw_data3_golden_cc_buf[MAX_SENSING_PIN_NUM];
extern unsigned short g_u16_uc_golden_cc_buf[MAX_SENSING_PIN_NUM];
extern unsigned int g_u32_test_result[MAX_SENSING_PIN_NUM]; // each node test result (open ng, short ng, uniformity ng..etc)
extern unsigned char g_u8_wearable_pin_map[MAX_IMAGE_BUFFER_SIZE];
extern unsigned char g_u8_test_result[MAX_SENSING_PIN_NUM];
extern volatile unsigned short g_u16_test_items_host_cmd;
extern unsigned short g_u16_test_items_tool_cmd;
extern volatile unsigned short g_u16_panel_jig_set_test_items;
extern unsigned int g_u32_wearable_test_result;
extern unsigned char g_u8_channel_x;
extern unsigned char g_u8_channel_y;
extern unsigned char g_u8_is_normal_fw;
extern unsigned char g_u8_data_buf[DATA_BUFFER_SIZE];
extern unsigned char g_u8_mipi_read_buf[56];
extern unsigned int g_u32_fw_cc_version;
extern unsigned char g_u8_print_debug_msg;
extern char g_i8_test_baseline_msg[30];
extern bool b_is_auo_jig_testing;
#if ENABLE_TEST_TIME_MEASURMENT || ENABLE_TEST_TIME_MEASURMENT_CC
extern unsigned int g_u32_spend_time;
#endif
#if !SELFTEST
extern unsigned char g_u8_ic_power_on_ng;
#endif
extern unsigned char g_u8_display_interface;
extern unsigned char g_u8_PAGE_ADDR;
extern int g_u32_dongle_flash_ini_addr;// 0xF000
extern int g_u32_ini_threshold_addr;// DONGLE_FLASH_INI_ADDR + 16
extern int g_u32_ini_para_addr;// INI_THRESHOLD_ADDR + 36
//int u32_ini_raw_data_2_bl_addr;// INI_PARA_ADDR+48
extern int g_u32_ini_raw_data_3_cc_addr;// INI_RAW_DATA2_BL_ADDR+72
extern int g_u32_ini_uc_cc_addr;// INI_RAW_DATA_3_CC_ADDR + 72// INI_RAW_DATA2_ADDR
extern int g_u32_initial_code_start_addr;
extern void ic_drv_init(void);
#endif /* end _DRVGLOBAL_H_*/
/******************************************************************************
** End Of File
******************************************************************************/

View File

@@ -0,0 +1,229 @@
/* i2c_drv_interface.c
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifdef __KERNEL__
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#else
#include <stdint.h>
#include <string.h>
#endif
#include "ic_drv_interface.h"
#include "../drv_interface.h"
#include "ic_drv_global.h"
#if SELFTEST_2X
#include "f302_ic_control.h"
#include "f302_ic_test.h"
#endif
#if SELFTEST_3X
#include "f303_ic_control.h"
#include "f303_ic_test.h"
#endif
#if !SELFTEST
#include "f302_ic_test.h"
#include "f302_ic_test_ft.h"
#include "f303_ic_test.h"
#include "f303_ic_test_ft.h"
#include "ic_drv_global_ft.h"
#include "main.h"
#endif
st_test_threshold g_st_test_thd;
st_test_info g_st_test_info;
st_test_para_resv g_st_test_para_resv;
unsigned char g_u8_ic_test_state;
STATUS wearable_ic_test_read_info(void)
{
if (read_flash_data(g_u32_dongle_flash_ini_addr, 16) != ERROR) {
memcpy(&g_st_test_info, g_u8_data_buf, sizeof(g_st_test_info));
} else {
DEBUGOUT("Read Flash Data ERROR\r\n");
return ERROR;
}
return SUCCESS;
}
STATUS wearable_ic_test_info_init(void)
{
#if SELFTEST
g_u16_test_items_host_cmd = IC_TEST_ITEMS_SYSTEM | IC_TEST_ITEMS_OPEN | IC_TEST_ITEMS_SHORT | IC_TEST_ITEMS_UC | IC_TEST_ITEMS_UB | IC_TEST_ITEMS_BURN_CC;
#endif
if (!wearable_ic_test_read_info()) {
DEBUGOUT("Read Info ERROR\r\n");
return ERROR;
}
if (g_u16_test_items_host_cmd != 0)
g_st_test_info.u16_ft_test_item &= g_u16_test_items_host_cmd;
g_u16_panel_jig_set_test_items |= g_st_test_info.u16_ft_test_item;
DEBUGOUT("TestItem:0x%x:0x%x\r\n", g_st_test_info.u16_ft_test_item, g_st_test_info.u16_ft_eng_item);
DEBUGOUT("g_u16_panel_jig_set_test_items:0x%x\r\n", g_u16_panel_jig_set_test_items);
if (read_flash_data(g_u32_ini_threshold_addr, 36)) {
memcpy(&g_st_test_thd, g_u8_data_buf, sizeof(g_st_test_thd));
} else {
DEBUGOUT("Read THD Data ERROR\r\n");
return ERROR;
}
DEBUGOUT("THD:\r\n%d,%d,%d,%d,\r\n%d,%d,%d,%d,\r\n%d,%d,%d,%d\r\n",
g_st_test_thd.i16_ft_test_open_lower_thd,
g_st_test_thd.i16_ft_test_short_upper_thd,
g_st_test_thd.i16_ft_test_short_lower_thd,
g_st_test_thd.i16_ft_test_single_cc_upper_thd,
g_st_test_thd.i16_ft_test_single_cc_lower_thd,
g_st_test_thd.i16_ft_test_uniformity_bl_upper_thd,
g_st_test_thd.i16_ft_test_uniformity_bl_lower_thd,
g_st_test_thd.i16_ft_test_uniformity_cc_upper_thd,
g_st_test_thd.i16_ft_test_uniformity_cc_lower_thd,
g_st_test_thd.i16_ft_test_panel_test_1_thd,
g_st_test_thd.i16_ft_test_panel_test_3_thd,
g_st_test_thd.i16_ft_test_panel_test_2_thd);
if (read_flash_data(g_u32_ini_para_addr, 48)) {
memcpy(&g_st_test_para_resv, g_u8_data_buf, sizeof(g_st_test_para_resv));
} else {
DEBUGOUT("Read INI Para ERROR\r\n");
return ERROR;
}
/*
* DEBUGOUT(" g_st_test_para_resv.u32_normal_fw_version = %X ,g_st_test_para_resv.u32_test_fw_version= %X \r\n",
* g_st_test_para_resv.u32_normal_fw_version,
* g_st_test_para_resv.u32_test_fw_version
* );
*/
if (g_u16_dev_id == DEVICE_ID_3X) {
if (read_flash_data(g_u32_ini_raw_data_3_cc_addr, 128)) {
memcpy(g_u16_raw_data3_golden_cc_buf, g_u8_data_buf, sizeof(g_u16_raw_data3_golden_cc_buf));
} else {
DEBUGOUT("read raw data 3 cc ERROR\r\n");
return ERROR;
}
/*
* DEBUGOUT(" g_u16_raw_data3_golden_cc_buf[0] = %d,g_u16_raw_data3_golden_cc_buf[1 =%d g_u16_raw_data3_golden_cc_buf[2]=%d,\r\n",
* g_u16_raw_data3_golden_cc_buf[0],
* g_u16_raw_data3_golden_cc_buf[1],
* g_u16_raw_data3_golden_cc_buf[2]
* );
*/
if (read_flash_data(g_u32_ini_uc_cc_addr, 128)) {
memcpy(g_u16_uc_golden_cc_buf, g_u8_data_buf, sizeof(g_u16_uc_golden_cc_buf));
} else {
DEBUGOUT("read uc cc ERROR\r\n");
return ERROR;
}
} else if (g_u16_dev_id == DEVICE_ID_2X) {
if (read_flash_data(g_u32_ini_raw_data_3_cc_addr, 72)) {
memcpy(g_u16_raw_data3_golden_cc_buf, g_u8_data_buf, sizeof(g_u16_raw_data3_golden_cc_buf));
} else {
DEBUGOUT("read raw data 3 cc ERROR\r\n");
return ERROR;
}
/*
* DEBUGOUT(" g_u16_raw_data3_golden_cc_buf[0] = %d,g_u16_raw_data3_golden_cc_buf[1 =%d g_u16_raw_data3_golden_cc_buf[2]=%d,\r\n",
* g_u16_raw_data3_golden_cc_buf[0],
* g_u16_raw_data3_golden_cc_buf[1],
* g_u16_raw_data3_golden_cc_buf[2]
* );
*/
if (read_flash_data(g_u32_ini_uc_cc_addr, 72)) {
memcpy(g_u16_uc_golden_cc_buf, g_u8_data_buf, sizeof(g_u16_uc_golden_cc_buf));
} else {
DEBUGOUT("read uc cc ERROR\r\n");
return ERROR;
}
}
/* if (read_flash_data(INI_RAW_DATA2_BL_ADDR, 72))
* memcpy(g_i16_raw_data2_golden_bl_buf, g_u8_data_buf, sizeof(g_i16_raw_data2_golden_bl_buf));
*/
return SUCCESS;
}
STATUS wearable_ic_test_init(void)
{
if (!wearable_ic_test_info_init())
return ERROR;
if (!(g_st_test_info.u16_ft_eng_item & IC_TEST_ENG_ITEMS_PANEL_TEST_JIG))
wearable_ic_test_init_buffer();
return SUCCESS;
}
void wearable_ic_test_init_buffer(void)
{
g_u32_wearable_test_result = WEARABLE_FT_TEST_RESULT_IC_INIT_STATE;
memset(g_u32_test_result, 0, sizeof(g_u32_test_result));
memset(g_u8_test_result, 0, sizeof(g_u8_test_result));
g_u8_is_normal_fw = FALSE;
}
STATUS handle_burn_log_to_flash(void)
{
STATUS u8_status = ERROR;
switch (g_u16_dev_id) {
#if (!SELFTEST_2X && (!SELFTEST))
case DEVICE_ID_2X:
burn_data_log_to_flash_2x();
break;
#endif
#if (!SELFTEST_3X && (!SELFTEST))
case DEVICE_ID_3X:
b_is_auo_jig_testing = false;
burn_header_log_to_flash_3x(TRUE, TRUE);
memset(g_u32_save_config, 0, sizeof(g_u32_save_config));
if (burn_data_log_to_flash_3x())
u8_status = SUCCESS;
break;
#endif
}
return u8_status;
}
void handle_ic_test(void)
{
switch (g_u16_dev_id) {
#if (SELFTEST_2X | (!SELFTEST))
case DEVICE_ID_2X:
do_ic_test_2x();
break;
#endif
#if (SELFTEST_3X | (!SELFTEST))
case DEVICE_ID_3X:
do_ic_test_3x();
break;
#endif
}
}
void handle_set_display_interface(unsigned char u8_interface)
{
g_u8_display_interface = u8_interface;
DEBUGOUT("%s: 0x%x \r\n", __func__, u8_interface);
}

View File

@@ -0,0 +1,211 @@
/* i2c_drv_interface.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "ic_drv_global.h"
#define DEVICE_ID_2X 0xF302
#define DEVICE_ID_3X 0xF303
#define I2C_PDA2_BYTE_MODE 0x03
#define I2C_PDA2_WORD_MODE 0x43
#define I2C_BYTE_MODE (0x80|0x20)
#define I2C_WORD_MODE (0xc0|0x20)
#define I2C_MCU_MODE 0x40
#define I2C_PDA2_MODE 0x10
#define I2C_PDA_MODE 0x08
#define SPI_BYTE_MODE (0x80|0x03)
#define SPI_WORD_MODE (0xc0|0x03)
#define SPI_MCU_MODE 0x40
#define I2C_INTERFACE 0
#define SPI_INTERFACE 1
#define DISPLAY_SPI_MODE 0
#define DISPLAY_MIPI_MODE 1
#define DISPLAY_TOUCH_2_DRIVER_MODE 2
#define DATA_REMAP_TO_IC_PIN 1
#define DATA_REMAP_TO_SENSOR_PAD 2
#define IC_TEST_RETRY_TIME 3
#define IC_TEST_TIME_OUT (-1)
#define FT_TEST_STUATUS_PATTERN 0x5A00
#define FT_CMD_INIT 0x11
#define FT_CMD_DO_FT_TEST 0x14
#define IC_TEST_ITEMS_SYSTEM 0x0001
#define IC_TEST_ITEMS_BURN_FW 0x0002
#define IC_TEST_ITEMS_OPEN 0x0004
#define IC_TEST_ITEMS_SHORT 0x0008
#define IC_TEST_ITEMS_UC 0x0010
#define IC_TEST_ITEMS_UB 0x0020
#define IC_TEST_ITEMS_BURN_CC 0x0040
#define IC_TEST_ITEMS_PANEL_TEST_1 0x0080
#define IC_TEST_ITEMS_PANEL_TEST_2 0x0100
#define IC_TEST_ITEMS_PANEL_TEST_3 0x0200
#define IC_TEST_ITEMS_RESV_0 0x0400
#define IC_TEST_ITEMS_RESV_1 0x0800
#define IC_TEST_ITEMS_RESV_2 0x1000
#define IC_TEST_ITEMS_RESV_3 0x2000
#define IC_TEST_ITEMS_RESV_4 0x4000
#define IC_TEST_ITEMS_RESV_5 0x8000
#define IC_TEST_ENG_ITEMS_RESV_1 0x0001
#define IC_TEST_ENG_ITEMS_RESV_2 0x0002
#define IC_TEST_ENG_ITEMS_RESV_3 0x0004
#define IC_TEST_ENG_ITEMS_TEST_ALL 0x0008
#define IC_TEST_ENG_ITEMS_RESV_5 0x0010
#define IC_TEST_ENG_ITEMS_RESV_6 0x0020
#define IC_TEST_ENG_ITEMS_RESV_7 0x0040
#define IC_TEST_ENG_ITEMS_RESV_8 0x0080
#define IC_TEST_ENG_ITEMS_PANEL_TEST_JIG 0x0100
#define IC_TEST_ENG_ITEMS_RESV_10 0x0200
#define IC_TEST_ENG_ITEMS_RESV_11 0x0400
#define IC_TEST_ENG_ITEMS_RESV_12 0x0800
#define IC_TEST_ENG_ITEMS_RESV_13 0x1000
#define IC_TEST_ENG_ITEMS_RESV_14 0x2000
#define IC_TEST_ENG_ITEMS_RESV_15 0x4000
#define IC_TEST_ENG_ITEMS_RESV_16 0x8000
#define WEARABLE_FT_TEST_RESULT_IC_INIT_STATE 0xDFFFE5DF
#define WEARABLE_FT_TEST_RESULT_PANEL_INIT_STATE 0x20001A20
#define WEARABLE_FT_TEST_RESULT_PASS 0x00000000
#define WEARABLE_FT_TEST_RESULT_OPEN_NG 0x00000001
#define WEARABLE_FT_TEST_RESULT_SHORT_NG 0x00000002
#define WEARABLE_FT_TEST_RESULT_UB_NG 0x00000004
#define WEARABLE_FT_TEST_RESULT_I2C_NG 0x00000008
#define WEARABLE_FT_TEST_RESULT_INT_NG 0x00000010
#define WEARABLE_FT_TEST_RESULT_PANEL_TEST_1_NG 0x00000020
#define WEARABLE_FT_TEST_RESULT_RESET_NG 0x00000040
#define WEARABLE_FT_TEST_RESULT_CB_NG 0x00000080
#define WEARABLE_FT_TEST_RESULT_PRAM_NG 0x00000100
#define WEARABLE_FT_TEST_RESULT_NORMAL_FW_NG 0x00000200
#define WEARABLE_FT_TEST_RESULT_BURN_CC_NG 0x00000400
#define WEARABLE_FT_TEST_RESULT_PANEL_TEST_3_NG 0x00000800
#define WEARABLE_FT_TEST_RESULT_GET_DATA_NG 0x00001000
#define WEARABLE_FT_TEST_RESULT_FLASH_ID_NG 0x00002000
#define WEARABLE_FT_TEST_RESULT_NORMAL_FW_VER_NG 0x00004000
#define WEARABLE_FT_TEST_RESULT_TEST_FW_VER_NG 0x00008000
#define WEARABLE_FT_TEST_RESULT_UC_NG 0x00010000
#define WEARABLE_FT_TEST_RESULT_SINGLE_CC_OPEN_NG 0x00020000
#define WEARABLE_FT_TEST_RESULT_SINGLE_CC_SHORT_NG 0x00040000
#define WEARABLE_FT_TEST_RESULT_CC_CALIBRATION_NG 0x00080000
#define WEARABLE_FT_TEST_RESULT_TEST_INIT_NG 0x00100000
#define WEARABLE_FT_TEST_RESULT_LOAD_TESTFW_NG 0x00200000
#define WEARABLE_FT_TEST_RESULT_BURN_FW_NG 0x00400000
#define WEARABLE_FT_TEST_RESULT_IC_FW_VERIFY_NG 0x00800000
#define WEARABLE_FT_TEST_RESULT_EXT_FLASH_EMPTY_NG 0x01000000
#define WEARABLE_FT_TEST_RESULT_MCU_HOLD_NG 0x02000000
#if SELFTEST
#define WEARABLE_FT_TEST_RESULT_SYSFS_NG 0x04000000
#else
#define WEARABLE_FT_TEST_RESULT_AUO_JIG_NG 0x04000000
#endif
#define WEARABLE_FT_TEST_RESULT_NORMAL_FW_RESET_NG 0x08000000
#define WEARABLE_FT_TEST_RESULT_POWER_ON_NG 0x10000000
#define WEARABLE_FT_TEST_RESULT_CMD_NG 0x20000000
#define WEARABLE_FT_TEST_RESULT_IC_SUB_VERSION_NG 0x40000000
#define WEARABLE_FT_TEST_RESULT_IC_VERSION_NG 0x80000000
#define WEARBLE_FT_BURN_CC_SYSTEM_NG_CASE 1
#define WEARBLE_FT_FW_VER_SYSTEM_NG_CASE 2
#define WEARBLE_FT_I2C_SYSTEM_NG_CASE 3
#define WEARBLE_FT_INT_SYSTEM_NG_CASE 4
#define WEARBLE_FT_LOAD_TEST_FW_SYSTEM_NG_CASE 5
#define WEARBLE_FT_PRAM_SYSTEM_NG_CASE 6
#define WEARBLE_FT_RESET_PIN_SYSTEM_NG_CASE 7
// Define ic test state
typedef enum {
IC_TEST_INIT = 0,
IC_TEST_SYSTEM, //1
IC_TEST_BURN_FW, //2
IC_TEST_BURN_CC, //3
IC_TEST_LOAD_TEST_FW, //4
IC_TEST_ENTER_FW_TEST_MODE, //5
IC_TEST_OPEN_SHORT, //6
IC_TEST_READ_TEST_FW_DATA, //7
IC_ENTER_NORMAL_FW, //8
IC_TEST_UC_UB, //9
IC_TEST_PANEL_PATTERN_TEST, //10
IC_TEST_EXIT, //11
} IC_TEST_STATE;
#pragma pack(push)
#pragma pack(1)
typedef struct {
//-------- FT Test Info (Byte 16)-----------------//
unsigned char u8_device_id;
unsigned char u8_company_id;
unsigned char u8_project_id;
unsigned char u8_station_id;
unsigned short u16_ft_test_item;
unsigned short u16_ft_eng_item;
unsigned short u16_ft_test_info_1;
unsigned short u16_ft_test_info_2;
unsigned short u16_ft_test_info_3;
unsigned short u16_ft_test_info_4;
} st_test_info;
extern st_test_info g_st_test_info;
typedef struct {
//-------- FT Test Threshold (Byte 26)----------------//
unsigned char u8_ft_test_company_id;
unsigned char u8_ft_test_station_id;
signed short i16_ft_test_open_lower_thd; //TEST_THD_01
signed short i16_ft_test_short_upper_thd; //TEST_THD_02
signed short i16_ft_test_short_lower_thd; //TEST_THD_03
signed short i16_ft_test_single_cc_upper_thd; //TEST_THD_04
signed short i16_ft_test_single_cc_lower_thd; //TEST_THD_05
signed short i16_ft_test_uniformity_bl_upper_thd; //TEST_THD_06
signed short i16_ft_test_uniformity_bl_lower_thd; //TEST_THD_07
signed short i16_ft_test_uniformity_cc_upper_thd; //TEST_THD_08
signed short i16_ft_test_uniformity_cc_lower_thd; //TEST_THD_09
signed short i16_ft_test_panel_test_1_thd; //TEST_THD_10
signed short i16_ft_test_panel_test_3_thd; //TEST_THD_11
signed short i16_ft_test_panel_test_2_thd; //TEST_THD_12
//-------- reserve (Byte 10)-----------------//
signed short i16_ft_test_panel_test_2_s2_thd; //TEST_THD_13
signed short i16_ft_test_thd_14;
signed short i16_ft_test_thd_15;
signed short i16_ft_test_thd_16;
signed short i16_ft_test_thd_resv;
} st_test_threshold;
extern st_test_threshold g_st_test_thd;
typedef struct {
//-------- FT Test Parameter (Byte 48)-----------------//
unsigned char u8_para_resv_0[40];
unsigned int u32_normal_fw_version;
unsigned int u32_test_fw_version;
} st_test_para_resv;
extern st_test_para_resv g_st_test_para_resv;
#pragma pack(pop)
extern unsigned char g_u8_ic_test_state;
extern STATUS wearable_ic_test_read_info(void);
extern STATUS wearable_ic_test_init(void);
extern void handle_ic_test(void);
extern void wearable_ic_test_init_buffer(void);
extern STATUS handle_burn_log_to_flash(void);
extern void handle_set_display_interface(unsigned char u8_interface);

View File

@@ -0,0 +1,468 @@
/* drv_interface.c
*
* Raydium TouchScreen driver.
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
* Qualcomm Innovation Center, Inc. chooses to use it under GPLv2
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* BSD LICENSE
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. or Linaro Ltd. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/timer.h>
#include <linux/ktime.h>
#include <linux/delay.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/of_gpio.h>
#include <linux/version.h>
#include "chip_raydium/ic_drv_global.h"
#include "chip_raydium/ic_drv_interface.h"
#include "drv_interface.h"
#include "raydium_selftest.h"
#include "raydium_driver.h"
#include "chip_raydium/f303_ic_control.h"
unsigned char g_u8_m_buf[2][128];
unsigned char g_u8_ini_flash[0x400];
struct raydium_ts_data *ts;
unsigned char g_u8_mute_i2c_err_log;
STATUS i2c_burst_read_pda2(unsigned char u8_addr, unsigned short u16ReadLen, unsigned char *p_u8_output_buf)
{
return ERROR;
}
STATUS i2c_burst_write_pda2(unsigned char u8_addr, unsigned char bWriteLen, unsigned char *bValue)
{
return ERROR;
}
unsigned char spi_write_pda(unsigned int u32_addr, unsigned char u8_write_len, unsigned char *bValue, unsigned char u8_trans_mode)
{
return ERROR;
}
unsigned char spi_read_pda(unsigned int u32_addr, unsigned char u8_read_len, unsigned char *p_u8_output_buf)
{
return ERROR;
}
STATUS burn_fw_3x(void)
{
g_u32_wearable_test_result &= ~(WEARABLE_FT_TEST_RESULT_CMD_NG | WEARABLE_FT_TEST_RESULT_BURN_FW_NG);
return SUCCESS;
}
unsigned char fw_upgrade(unsigned char type)
{
int i32_ret = ERROR;
i32_ret = raydium_burn_fw(g_raydium_ts->client);
if (i32_ret < 0)
pr_err("[touch]FW update fail:%d\n", i32_ret);
return i32_ret;
}
unsigned char read_flash_data(unsigned int u32_addr, unsigned short u16_lenth)
{
unsigned int u32_data_offset;
if (g_u16_dev_id == DEVICE_ID_2X) {
u32_data_offset = u32_addr - 0x800;
if (u32_addr < 0x8000) {
if (u32_data_offset >= 0x8000 && u32_addr < F302_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_data_offset - 0x6200;
memcpy(g_u8_data_buf, g_rad_para_image + u32_data_offset, u16_lenth);
} else if (u32_addr >= F302_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_addr - F302_DONGLE_FLASH_INI_ADDR;
memcpy(g_u8_data_buf, g_u8_ini_flash + u32_data_offset, u16_lenth);
} else
memcpy(g_u8_data_buf, g_rad_fw_image + u32_data_offset, u16_lenth);
} else {
u32_data_offset -= 0x8000;
if (u32_data_offset >= 0x6200 && u32_addr < F302_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_data_offset - 0x6200;
memcpy(g_u8_data_buf, g_rad_testpara_image + u32_data_offset, u16_lenth);
} else if (u32_addr >= F302_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_addr - F302_DONGLE_FLASH_INI_ADDR;
memcpy(g_u8_data_buf, g_u8_ini_flash + u32_data_offset, u16_lenth);
} else {
memcpy(g_u8_data_buf, g_rad_testfw_image + u32_data_offset, u16_lenth);
}
}
return TRUE;
} else if (g_u16_dev_id == DEVICE_ID_3X) {
u32_data_offset = u32_addr - 0x800;
if (u32_addr < 0x7800) {
if (u32_data_offset >= 0x7300 && u32_addr < F303_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_data_offset - 0x7300;
memcpy(g_u8_data_buf, g_rad_para_image + u32_data_offset, u16_lenth);
} else
memcpy(g_u8_data_buf, g_rad_fw_image + u32_data_offset, u16_lenth);
} else {
u32_data_offset -= 0x7800;
if (u32_data_offset >= 0x7300 && u32_addr < F303_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_data_offset - 0x7300;
memcpy(g_u8_data_buf, g_rad_testpara_image + u32_data_offset, u16_lenth);
} else if (u32_addr >= F303_DONGLE_FLASH_INI_ADDR) {
u32_data_offset = u32_addr - F303_DONGLE_FLASH_INI_ADDR;
pr_info("ini addr 0x%x offset %d\r\n", u32_addr, u32_data_offset);
memcpy(g_u8_data_buf, g_u8_ini_flash + u32_data_offset, u16_lenth);
} else {
memcpy(g_u8_data_buf, g_rad_testfw_image + u32_data_offset, u16_lenth);
}
}
return TRUE;
}
return FALSE;
}
unsigned int get_system_time(void)
{
/* unsigned int u32_timer;
* struct timeval timer;
* do_gettimeofday(&timer);
* u32_timer = (timer.tv_sec % 1000) * 1000 + (timer.tv_usec / 1000);
* return u32_timer;
*/
#if (KERNEL_VERSION(5, 0, 0) <= LINUX_VERSION_CODE)
struct timespec64 ts;
ktime_get_ts64(&ts);
return (ts.tv_sec*1000 + ts.tv_nsec/1000000);
#else
struct timeval tv;
do_gettimeofday(&tv);
return (tv.tv_sec*1000 + tv.tv_usec/1000);
#endif
}
unsigned char gpio_touch_int_pin_state_access(void)
{
return gpio_get_value(ts->irq_gpio);
}
unsigned char gpio_touch_int_access(unsigned char u8_is_clear_flag)
{
unsigned char u8_flag = g_u8_raydium_flag;
if (u8_is_clear_flag && u8_flag)
g_u8_raydium_flag &= ~INT_FLAG;
return u8_flag;
}
unsigned char sysfs_burn_cc_bl(void)
{
unsigned char ret = ERROR;
DEBUGOUT("%s\r\n", __func__);
ret = raydium_burn_comp(ts->client);
return ret;
}
unsigned char raydium_upgrade_test_fw_2x(unsigned long ul_fw_addr)
{
int ret = ERROR;
unsigned char u8_retry = 2;
unsigned int u32_read;
unsigned int u32_write;
RETRY:
gpio_touch_reset_pin_control(0);
delay_ms(10);
gpio_touch_reset_pin_control(1);
delay_ms(2);
u32_write = 0x00000030;
handle_ic_write(0x50000918, 4, (unsigned char *)&u32_write, g_u8_drv_interface, I2C_WORD_MODE);
if (raydium_load_test_fw(ts->client) == SUCCESS) {
ret = SUCCESS;
DEBUGOUT("### Raydium Load test FW SUCCESS ###\n");
}
handle_ic_read(0x6A04, 4, (unsigned char *)&u32_read, g_u8_drv_interface, I2C_WORD_MODE);
if (u32_read != g_st_test_para_resv.u32_test_fw_version) {
DEBUGOUT("Read FW version NG=0x%x:0x%x!!\r\n", u32_read, g_st_test_para_resv.u32_test_fw_version);
goto ERROR_EXIT;
}
return ret;
ERROR_EXIT:
if (u8_retry) {
u8_retry--;
goto RETRY;
}
return ERROR;
}
unsigned char raydium_upgrade_test_fw_3x(unsigned long ul_fw_addr)
{
int ret = ERROR;
unsigned char u8_retry = 2;
unsigned int u32_read;
RETRY:
if (raydium_load_test_fw(ts->client) == SUCCESS) {
ret = SUCCESS;
DEBUGOUT("### Raydium Load test FW SUCCESS ###\n");
}
handle_ic_read(0x7B04, 4, (unsigned char *)&u32_read, g_u8_drv_interface, I2C_WORD_MODE);
if (u32_read != g_st_test_para_resv.u32_test_fw_version) {
DEBUGOUT("Read FW version NG=0x%x:0x%x!!\r\n", u32_read, g_st_test_para_resv.u32_test_fw_version);
goto ERROR_EXIT;
}
return ret;
ERROR_EXIT:
if (u8_retry) {
u8_retry--;
goto RETRY;
}
return ERROR;
}
void gpio_touch_reset_pin_control(unsigned char u8_high)
{
if (u8_high)
gpio_set_value(ts->rst_gpio, 1);
else
gpio_set_value(ts->rst_gpio, 0);
return;
}
void gpio_touch_hw_reset(void)
{
gpio_touch_reset_pin_control(0);
delay_ms(10);
gpio_touch_reset_pin_control(1);
}
void set_raydium_ts_data(struct raydium_ts_data *ts_old)
{
ts = ts_old;
}
/******************************************************************************
**Function name:handle_ic_read
**
**Descriptions:handle read data from ic
**
**parameters:u32_addr,Address
** u8_read_len,Read datalength
** p_u8_output_buf,Data buffer
** u8_interface,SPI or I2C
** u8_trans_modePDA2_MODE, PDA_WORD_MODE, PDA_BYTE_MODE, MCU_MODE
**
**Returned value:ERROR,SUCCESS
**
******************************************************************************
*/
unsigned char handle_ic_read(
unsigned int u32_addr,
unsigned short u8_read_len,
unsigned char *p_u8_output_buf,
unsigned char u8_interface,
unsigned char u8_trans_mode)
{
if (u8_trans_mode == I2C_PDA2_MODE) {
/*PDA2 MODE */
if (raydium_i2c_pda2_read(g_raydium_ts->client, (unsigned char)u32_addr, p_u8_output_buf, u8_read_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
/*PDA MODE*/
if ((u8_trans_mode == I2C_WORD_MODE) && (u32_addr & 0x00000003)) {
DEBUGOUT("[HRW] Handle Read Word ADDR Not Word Align!!\r\n");
return ERROR;
}
if (u8_interface == SPI_INTERFACE) {
if (spi_read_pda(u32_addr, u8_read_len, p_u8_output_buf) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
if (g_u16_dev_id == DEVICE_ID_3X) {
if ((u8_interface & I2C_PDA_MODE) != 0) {
if (raydium_i2c_pda_read(g_raydium_ts->client, u32_addr, p_u8_output_buf, u8_read_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
if (raydium_i2c_read_pda_via_pda2(g_raydium_ts->client, u32_addr, p_u8_output_buf, u8_read_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
}
} else {
if (raydium_i2c_pda_read(g_raydium_ts->client, u32_addr, p_u8_output_buf, u8_read_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
}
}
}
return SUCCESS;
}
/******************************************************************************
** Function name:handle_ic_write
**
** Descriptions:handle write data to ic
**
** parameters:u32_addr,Address
** u8_write_len,datalength
** bValue,Data
** u8_interface,SPI or I2C
** u8_trans_modePDA2_MODE, PDA_WORD_MODE, PDA_BYTE_MODE, MCU_MODE
**
** Returned value:ERROR,SUCCESS
**
******************************************************************************/
unsigned char handle_ic_write(
unsigned int u32_addr,
unsigned char u8_write_len,
unsigned char *bValue,
unsigned char u8_interface,
unsigned char u8_trans_mode)
{
if (u8_trans_mode == I2C_PDA2_MODE) {
/*PDA2 MODE*/
if (raydium_i2c_pda2_write(g_raydium_ts->client, (unsigned char)u32_addr, bValue, u8_write_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
/*PDA MODE*/
if ((u8_trans_mode == I2C_WORD_MODE) && (u32_addr & 0x00000003)) {
DEBUGOUT("[I2CRW] Handle Write Word ADDR Not Word Align!!\r\n");
return ERROR;
}
if (u8_interface == SPI_INTERFACE) {
switch (u8_trans_mode) {
case I2C_BYTE_MODE:
u8_trans_mode = SPI_BYTE_MODE;
break;
case I2C_WORD_MODE:
u8_trans_mode = SPI_WORD_MODE;
break;
/* case I2C_MCU_MODE:
*
* u8_trans_mode = SPI_MCU_MODE;
*
* break;
*/
case SPI_BYTE_MODE:
case SPI_WORD_MODE:
break;
default:
DEBUGOUT("%s%d\r\n", __func__, u8_trans_mode);
return ERROR;
}
if (spi_write_pda(u32_addr, u8_write_len, bValue, u8_trans_mode) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
if (g_u16_dev_id == DEVICE_ID_3X) {
if ((u8_interface & I2C_PDA_MODE) != 0) {
if (raydium_i2c_pda_write(g_raydium_ts->client, u32_addr, bValue, u8_write_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
} else {
if (raydium_i2c_write_pda_via_pda2(g_raydium_ts->client, u32_addr, bValue, u8_write_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
}
} else {
if (raydium_i2c_pda_write(g_raydium_ts->client, u32_addr, bValue, u8_write_len) == ERROR) {
DEBUGOUT("%s\r\n", __func__);
return ERROR;
}
}
}
}
return SUCCESS;
}
/******************************************************************************
** Function name:handle_display_write
**
** Descriptions:handle write data to display
**
** parameters:p_u8_data,Data
** u16DataLength,datalength
**
**
** Returned value:ERROR,SUCCESS
**
******************************************************************************/
unsigned char handle_display_write(
unsigned char *p_u8_data,
unsigned short u16DataLength)
{
if (WriteDriverByTouchMode(p_u8_data, u16DataLength) == ERROR) {
DEBUGOUT("[HDW] WriteDriverByTouchMode NG!\r\n");
return ERROR;
}
return SUCCESS;
}

View File

@@ -0,0 +1,84 @@
/* drv_interface.h
*
* Raydium TouchScreen driver.
*
* Copyright (c) 2021 Raydium tech Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "Config.h"
#include "raydium_driver.h"
#define DEBUGOUT pr_info
#define delay_ms msleep
#define I2C_INTERFACE 0
#define SPI_INTERFACE 1
#define M_RX_BUF 1
#define M_TX_BUF 0
#define __I volatile
#define __O volatile
#define __IO volatile
#define WORD 4
#define RAD_CMD_START_BURN 0x01
#define RAD_CMD_LOAD_TESTFW 0x04
#define RAD_CMD_UPDATE_BIN 0x80
#define RAD_CMD_UPDATE_END 0x81
#define RAD_CMD_BURN_FINISH 0x82
#define WEARABLE_FT_TEST_RESULT_AUO_JIG_NG WEARABLE_FT_TEST_RESULT_SYSFS_NG
extern unsigned char g_u8_m_buf[2][128];
extern struct timeval timer;
extern unsigned char g_rad_fw_flash[32768], g_rad_testfw_flash[32768];
extern unsigned char g_u8_ini_flash[0x400];
extern unsigned long g_u32_save_config[64];
extern unsigned char g_u8_mute_i2c_err_log;
extern short g_i16_raw_data_frame_buffer[101][50];
extern unsigned char g_u8_test_log_burn_times;
extern unsigned char read_flash_data(unsigned int u32_addr, unsigned short u16_lenth);
extern unsigned int get_system_time(void);
extern unsigned char sysfs_mode_control(unsigned char u8_type);
//extern unsigned char sysfs_read_int_flag(unsigned char *p_u8_flag, unsigned char u8_is_clear_flag);
extern unsigned char sysfs_write_int_flag(char *p_cmd);
//extern unsigned char sysfs_i2c_read(char *p_u8_addr, char u8_len, unsigned char *p_u8_data);
//extern unsigned char sysfs_i2c_write(char *p_u8_addr, char u8_len, unsigned char *p_u8_data);
extern unsigned char sysfs_do_cal(void);
extern unsigned char sysfs_burn_cc_bl(void);
extern void gpio_touch_reset_pin_control(unsigned char u8_high);
extern void gpio_touch_hw_reset(void);
extern unsigned char fw_upgrade(unsigned char type);
extern unsigned char gpio_touch_int_access(unsigned char u8_is_clear_flag);
extern unsigned char gpio_touch_int_pin_state_access(void);
extern unsigned char handle_read_word(unsigned int addr, unsigned int *p_data);
extern unsigned char handle_write_word(unsigned int u32_addr, unsigned int u32_data);
extern unsigned char handle_read_pda(unsigned int u32_addr, unsigned char u8_read_len, unsigned char *p_u8_output_buf);
extern unsigned char handle_write_pda(unsigned int u32_addr, unsigned char u8_write_len, unsigned char *bValue, unsigned char u8_trans_mode);
extern unsigned char handle_ic_read(unsigned int u32_addr, unsigned short u8_read_len, unsigned char *p_u8_output_buf, unsigned char u8_interface, unsigned char u8_trans_mode);
extern unsigned char handle_ic_write(unsigned int u32_addr, unsigned char u8_write_len, unsigned char *bValue, unsigned char u8_interface, unsigned char u8_trans_mode);
extern unsigned char raydium_upgrade_test_fw(unsigned long ul_fw_addr);
extern unsigned char raydium_upgrade_test_fw_3x(unsigned long ul_fw_addr);
extern unsigned char raydium_upgrade_test_fw_2x(unsigned long ul_fw_addr);
extern void set_raydium_ts_data(struct raydium_ts_data *ts_old);

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More