diff --git a/drivers/input/touchscreen/stmicro_mmi/Android.mk b/drivers/input/touchscreen/stmicro_mmi/Android.mk new file mode 100644 index 000000000000..5468320e88ed --- /dev/null +++ b/drivers/input/touchscreen/stmicro_mmi/Android.mk @@ -0,0 +1,12 @@ +DLKM_DIR := motorola/kernel/modules +LOCAL_PATH := $(call my-dir) + +ifneq ($(findstring touchscreen_mmi.ko,$(BOARD_VENDOR_KERNEL_MODULES)),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_MMI=y +endif + +include $(CLEAR_VARS) +LOCAL_MODULE := stmicro_mmi.ko +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) +include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/input/touchscreen/stmicro_mmi/Kbuild b/drivers/input/touchscreen/stmicro_mmi/Kbuild new file mode 100644 index 000000000000..dccd269b6a9c --- /dev/null +++ b/drivers/input/touchscreen/stmicro_mmi/Kbuild @@ -0,0 +1,22 @@ +# add -Wall to try to catch everything we canss +# EXTRA_CFLAGS += -Wallss +EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include \ + -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/stmicro_mmi + +obj-m := stmicro_mmi.o +stmicro_mmi-objs := fts.o fts_proc.o +stmicro_mmi-objs += fts_lib/ftsCompensation.o +stmicro_mmi-objs += fts_lib/ftsCore.o +stmicro_mmi-objs += fts_lib/ftsError.o +stmicro_mmi-objs += fts_lib/ftsFlash.o +stmicro_mmi-objs += fts_lib/ftsFrame.o +stmicro_mmi-objs += fts_lib/ftsGesture.o +stmicro_mmi-objs += fts_lib/ftsIO.o +stmicro_mmi-objs += fts_lib/ftsTest.o +stmicro_mmi-objs += fts_lib/ftsTime.o +stmicro_mmi-objs += fts_lib/ftsTool.o + +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_MMI)),) + EXTRA_CFLAGS += -DCONFIG_INPUT_TOUCHSCREEN_MMI + stmicro_mmi-objs += fts_mmi_class.o +endif diff --git a/drivers/input/touchscreen/stmicro_mmi/Kconfig b/drivers/input/touchscreen/stmicro_mmi/Kconfig new file mode 100644 index 000000000000..296bbc65a819 --- /dev/null +++ b/drivers/input/touchscreen/stmicro_mmi/Kconfig @@ -0,0 +1,13 @@ +# +# STmicro TOUCH driver configuration +# + +config TOUCHSCREEN_FTS_TS + tristate "STmicro Touchscreen" + depends on I2C + help + Say Y here if you want support for FTS touchscreen controllers. + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called stmicro_mmi. diff --git a/drivers/input/touchscreen/stmicro_mmi/Makefile b/drivers/input/touchscreen/stmicro_mmi/Makefile index cbc87ef09709..34b09dd815a7 100644 --- a/drivers/input/touchscreen/stmicro_mmi/Makefile +++ b/drivers/input/touchscreen/stmicro_mmi/Makefile @@ -1,6 +1,10 @@ -# -# Makefile for the touchscreen drivers. -# +KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build -obj-y += fts.o fts_proc.o fts_lib/ +all: + $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) +modules_install: + $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean \ No newline at end of file diff --git a/drivers/input/touchscreen/stmicro_mmi/fts.c b/drivers/input/touchscreen/stmicro_mmi/fts.c index f19149cb9ed2..b822895c61c8 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts.c @@ -72,7 +72,7 @@ #include "fts_lib/ftsTime.h" #include "fts_lib/ftsTool.h" - +#include "fts_mmi.h" /** * Event handler installer helpers @@ -2823,6 +2823,7 @@ int fts_fw_update(struct fts_ts_info *info) int crc_status = 0; int error = 0; int init_type = NO_INIT; + const char *firmware_name; #if defined(PRE_SAVED_METHOD) || defined (COMPUTE_INIT_METHOD) int keep_cx = 1; @@ -2844,15 +2845,20 @@ int fts_fw_update(struct fts_ts_info *info) "%s %s: NO CRC Error or Impossible to read CRC register!\n", tag, __func__); } + /* support arbitrary firmware file */ + if (info->fw_file) + firmware_name = info->fw_file; + else + firmware_name = PATH_FILE_FW; - retval = flashProcedure(PATH_FILE_FW, crc_status, keep_cx); + retval = flashProcedure(firmware_name, crc_status, keep_cx); if ((retval & 0xFF000000) == ERROR_FLASH_PROCEDURE) { logError(1, "%s %s: firmware update failed and retry! ERROR %08X\n", tag, __func__, retval); fts_chip_powercycle(info); /* power reset */ - retval1 = flashProcedure(PATH_FILE_FW, crc_status, keep_cx); + retval1 = flashProcedure(firmware_name, crc_status, keep_cx); if ((retval1 & 0xFF000000) == ERROR_FLASH_PROCEDURE) { logError(1, "%s %s: firmware update failed again! ERROR %08X\n", @@ -3448,29 +3454,33 @@ static int fts_mode_handler(struct fts_ts_info *info, int force) return res; } +void fts_resume_func(struct fts_ts_info *info) +{ + __pm_wakeup_event(&info->wakesrc, jiffies_to_msecs(HZ)); + info->resume_bit = 1; + fts_system_reset(); + release_all_touches(info); + fts_mode_handler(info, 0); + info->sensor_sleep = false; + fts_enableInterrupt(); +} + /** * Resume work function which perform a system reset, clean all the touches *from the linux input system and prepare the ground for enabling the sensing */ -static void fts_resume_work(struct work_struct *work) +static void inline fts_resume_work(struct work_struct *work) { - struct fts_ts_info *info; - - - info = container_of(work, struct fts_ts_info, resume_work); + fts_resume_func(container_of(work, struct fts_ts_info, resume_work)); +} +void fts_suspend_func(struct fts_ts_info *info) +{ __pm_wakeup_event(&info->wakesrc, jiffies_to_msecs(HZ)); - - info->resume_bit = 1; - - fts_system_reset(); - - release_all_touches(info); - + info->resume_bit = 0; fts_mode_handler(info, 0); - - info->sensor_sleep = false; - + release_all_touches(info); + info->sensor_sleep = true; fts_enableInterrupt(); } @@ -3478,23 +3488,9 @@ static void fts_resume_work(struct work_struct *work) * Suspend work function which clean all the touches from Linux input system *and prepare the ground to disabling the sensing or enter in gesture mode */ -static void fts_suspend_work(struct work_struct *work) +static void inline fts_suspend_work(struct work_struct *work) { - struct fts_ts_info *info; - - info = container_of(work, struct fts_ts_info, suspend_work); - - __pm_wakeup_event(&info->wakesrc, jiffies_to_msecs(HZ)); - - info->resume_bit = 0; - - fts_mode_handler(info, 0); - - release_all_touches(info); - - info->sensor_sleep = true; - - fts_enableInterrupt(); + fts_suspend_func(container_of(work, struct fts_ts_info, suspend_work)); } /** @}*/ @@ -4050,6 +4046,9 @@ static int fts_probe(struct spi_device *client) goto ProbeErrorExit_6; } + /* register touchscreen class if provisioned */ + fts_mmi_init(info, true); + #if defined(FW_UPDATE_ON_PROBE) && defined(FW_H_FILE) logError(1, "%s FW Update and Sensing Initialization:\n", tag); error = fts_fw_update(info); @@ -4097,6 +4096,8 @@ static int fts_probe(struct spi_device *client) ProbeErrorExit_7: + fts_mmi_init(info, false); + #ifdef FW_UPDATE_ON_PROBE fb_unregister_client(&info->notifier); #endif @@ -4169,6 +4170,8 @@ static int fts_remove(struct spi_device *client) fts_enable_reg(info, false); fts_get_reg(info, false); + fts_mmi_init(info, false); + /* free all */ kfree(info); diff --git a/drivers/input/touchscreen/stmicro_mmi/fts.h b/drivers/input/touchscreen/stmicro_mmi/fts.h index 7c28b439d082..6e9db4a71486 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts.h +++ b/drivers/input/touchscreen/stmicro_mmi/fts.h @@ -233,6 +233,7 @@ struct fts_hw_platform_data { * Forward declaration */ struct fts_ts_info; +struct fts_sys_info; extern char tag[8]; /* /< forward the definition of the label used * to print the log in the kernel log */ @@ -340,8 +341,10 @@ struct fts_ts_info { * when allowed */ int grip_enabled; /* /< if set, the grip mode mode will be enabled * when allowed */ -}; + struct fts_sys_info *sysinfo; + const char *fw_file; +}; int fts_chip_powercycle(struct fts_ts_info *info); diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCompensation.c b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCompensation.c index 2286efa91733..36a1defeb6c9 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCompensation.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCompensation.c @@ -326,12 +326,13 @@ int readSelfSenseGlobalData(u64 *address, SelfSenseData *global) int readSelfSenseNodeData(u64 address, SelfSenseData *node) { int size = node->header.force_node * 2 + node->header.sense_node * 2; - u8 data[size]; + u8 *data = NULL; int ret; + data = (u8 *)kzalloc(size, GFP_KERNEL); node->ix2_fm = (u8 *)kmalloc(node->header.force_node * (sizeof(u8)), GFP_KERNEL); - if (node->ix2_fm == NULL) { + if (node->ix2_fm == NULL || data == NULL) { logError(1, "%s %s: can not allocate memory for ix2_fm... ERROR %08X", tag, @@ -347,6 +348,7 @@ int readSelfSenseNodeData(u64 address, SelfSenseData *node) tag, __func__, ERROR_ALLOC); kfree(node->ix2_fm); + kfree(data); return ERROR_ALLOC; } node->ix2_sn = (u8 *)kmalloc(node->header.sense_node * (sizeof(u8)), @@ -358,6 +360,7 @@ int readSelfSenseNodeData(u64 address, SelfSenseData *node) __func__, ERROR_ALLOC); kfree(node->ix2_fm); kfree(node->cx2_fm); + kfree(data); return ERROR_ALLOC; } node->cx2_sn = (i8 *)kmalloc(node->header.sense_node * (sizeof(i8)), @@ -370,6 +373,7 @@ int readSelfSenseNodeData(u64 address, SelfSenseData *node) kfree(node->ix2_fm); kfree(node->cx2_fm); kfree(node->ix2_sn); + kfree(data); return ERROR_ALLOC; } @@ -387,6 +391,7 @@ int readSelfSenseNodeData(u64 address, SelfSenseData *node) kfree(node->cx2_fm); kfree(node->ix2_sn); kfree(node->cx2_sn); + kfree(data); return ret; } @@ -401,6 +406,7 @@ int readSelfSenseNodeData(u64 address, SelfSenseData *node) memcpy(node->cx2_sn, &data[node->header.force_node * 2 + node->header.sense_node], node->header.sense_node); + kfree(data); return OK; } @@ -517,13 +523,13 @@ int readTotMutualSenseNodeData(u64 address, TotMutualSenseData *node) int ret, i; int size = node->header.force_node * node->header.sense_node; int toRead = size * sizeof(u16); - u8 data[toRead]; + u8 *data; logError(0, "%s Address for Node data = %04llX\n", tag, address); + data = (u8 *)kzalloc(toRead, GFP_KERNEL); node->node_data = (short *)kmalloc(size * (sizeof(short)), GFP_KERNEL); - - if (node->node_data == NULL) { + if (node->node_data == NULL || data == NULL) { logError(1, "%s %s: can not allocate node_data... ERROR %08X", tag, __func__, ERROR_ALLOC); return ERROR_ALLOC; @@ -539,6 +545,7 @@ int readTotMutualSenseNodeData(u64 address, TotMutualSenseData *node) tag, __func__, ret); kfree(node->node_data); + kfree(data); return ret; } node->node_data_size = size; @@ -548,6 +555,7 @@ int readTotMutualSenseNodeData(u64 address, TotMutualSenseData *node) 2]; logError(0, "%s Read node data OK!\n", tag); + kfree(data); return size; } @@ -663,12 +671,13 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) { int size = node->header.force_node * 2 + node->header.sense_node * 2; int toRead = size * 2; /* *2 2 bytes each node */ - u8 data[toRead]; + u8 *data; int ret, i, j = 0; + data = (u8 *)kzalloc(toRead, GFP_KERNEL); node->ix_fm = (u16 *)kmalloc(node->header.force_node * (sizeof(u16)), GFP_KERNEL); - if (node->ix_fm == NULL) { + if (node->ix_fm == NULL || data == NULL) { logError(1, "%s %s: can not allocate memory for ix2_fm... ERROR %08X", tag, @@ -684,6 +693,7 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) tag, __func__, ERROR_ALLOC); kfree(node->ix_fm); + kfree(data); return ERROR_ALLOC; } node->ix_sn = (u16 *)kmalloc(node->header.sense_node * (sizeof(u16)), @@ -695,6 +705,7 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) __func__, ERROR_ALLOC); kfree(node->ix_fm); kfree(node->cx_fm); + kfree(data); return ERROR_ALLOC; } node->cx_sn = (short *)kmalloc(node->header.sense_node * @@ -707,6 +718,7 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) kfree(node->ix_fm); kfree(node->cx_fm); kfree(node->ix_sn); + kfree(data); return ERROR_ALLOC; } @@ -724,6 +736,7 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) kfree(node->cx_fm); kfree(node->ix_sn); kfree(node->cx_sn); + kfree(data); return ret; } @@ -753,6 +766,7 @@ int readTotSelfSenseNodeData(u64 address, TotSelfSenseData *node) if (j != toRead) logError(1, "%s %s: parsed a wrong number of bytes %d!=%d\n", tag, __func__, j, toRead); + kfree(data); return OK; } diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.c b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.c index b498fcf6cd72..7fd1e38c3d4c 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.c @@ -66,6 +66,8 @@ int initCore(struct fts_ts_info *info) { int ret = OK; + info->sysinfo = &systemInfo; + logError(0, "%s %s: Initialization of the Core...\n", tag, __func__); ret |= openChannel(info->client); ret |= resetErrorList(); @@ -406,10 +408,14 @@ int setScanMode(u8 mode, u8 settings) */ int setFeatures(u8 feat, u8 *settings, int size) { - u8 cmd[2 + size]; + u8 *cmd; int i = 0; int ret; + cmd = (u8 *)kzalloc(2 + size, GFP_KERNEL); + if (!cmd) + return ret | ERROR_SET_FEATURE_FAIL; + logError(0, "%s %s: Setting feature: feat = %02X !\n", tag, __func__, feat); cmd[0] = FTS_CMD_FEATURE; @@ -429,6 +435,7 @@ int setFeatures(u8 feat, u8 *settings, int size) return ret | ERROR_SET_FEATURE_FAIL; } logError(0, "%s %s: Setting feature OK!\n", tag, __func__); + kfree(cmd); return OK; } /** @}*/ @@ -448,9 +455,13 @@ int setFeatures(u8 feat, u8 *settings, int size) */ int writeSysCmd(u8 sys_cmd, u8 *sett, int size) { - u8 cmd[2 + size]; + u8 *cmd; int ret; + cmd = (u8 *)kzalloc(2 + size, GFP_KERNEL); + if (!cmd) + return ret | ERROR_SET_FEATURE_FAIL; + cmd[0] = FTS_CMD_SYSTEM; cmd[1] = sys_cmd; @@ -470,6 +481,7 @@ int writeSysCmd(u8 sys_cmd, u8 *sett, int size) else { logError(1, "%s %s: No setting argument! ERROR %08X\n", tag, __func__, ERROR_OP_NOT_ALLOW); + kfree(cmd); return ERROR_OP_NOT_ALLOW; } } @@ -478,6 +490,7 @@ int writeSysCmd(u8 sys_cmd, u8 *sett, int size) else logError(0, "%s %s: FINISHED!\n", tag, __func__); + kfree(cmd); return ret; } @@ -925,6 +938,11 @@ int fts_resetDisableIrqCount(void) return OK; } +int fts_is_InterruptEnabled(void) +{ + return !disable_irq_count ? 1 : 0; +} + /** * Enable the interrupt so the ISR of the driver can be called * @return OK if success or an error code which specify the type of error diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.h b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.h index 3ffe21df319b..0732787a5236 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.h +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsCore.h @@ -80,7 +80,7 @@ typedef enum { * Struct which contains fundamental informations about the chip and its *configuration */ -typedef struct { +struct fts_sys_info { u16 u16_apiVer_rev; /* /< API revision version */ u8 u8_apiVer_minor; /* /< API minor version */ u8 u8_apiVer_major; /* /< API major version */ @@ -187,7 +187,9 @@ typedef struct { * frame */ u16 u16_ssDetBaselineAddr; /* /< Offset of SS detect baseline * frame */ -} SysInfo; +}; + +typedef struct fts_sys_info SysInfo; /** @}*/ @@ -212,6 +214,7 @@ int fts_disableInterrupt(void); int fts_disableInterruptNoSync(void); int fts_resetDisableIrqCount(void); int fts_enableInterrupt(void); +int fts_is_InterruptEnabled(void); int fts_crc_check(void); int requestSyncFrame(u8 type); int saveMpFlag(u8 mpflag); diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.c b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.c index 610c181cee8b..8b7dd0f5f8c8 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.c @@ -503,9 +503,9 @@ int parseBinFile(u8 *fw_data, int fw_size, Firmware *fwData, int keep_cx) fwData->fw_code_size, fwData->panel_config_size, fwData->cx_area_size, fwData->fw_config_size); - if((fwData->fw_code_size == 0) || + if((fwData->fw_code_size == 0) || (fwData->panel_config_size == 0) || - (fwData->cx_area_size == 0) || + (fwData->cx_area_size == 0) || (fwData->fw_config_size == 0)) { logError(0, "%s Using default flash Address\n", tag); diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.h b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.h index a41d36da4b8f..e0efd84cbffe 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.h +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsFlash.h @@ -102,13 +102,13 @@ typedef struct { u32 sec1_size; /* /< dimension of section 1 (Config) in .ftb file */ u32 sec2_size; /* /< dimension of section 2 (Cx) in .ftb file */ u32 sec3_size; /* /< dimension of section 3 (TBD) in .ftb file */ - u8 fw_code_size; /* /< size of fw code in pages in + u8 fw_code_size; /* /< size of fw code in pages in .ftb file */ - u8 panel_config_size;/* /< size of panel area in pages in + u8 panel_config_size;/* /< size of panel area in pages in .ftb file */ - u8 cx_area_size;/* /< size of cx area in pages in + u8 cx_area_size;/* /< size of cx area in pages in .ftb file */ - u8 fw_config_size;/* /< size of fw config in pages in + u8 fw_config_size;/* /< size of fw config in pages in .ftb file */ u32 code_start_addr; /* start addr for fw code */ u32 cx_start_addr; /* start addr for cx area */ diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsIO.c b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsIO.c index db8dea961042..81d26ab494fe 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsIO.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsIO.c @@ -476,10 +476,14 @@ int fts_writeThenWriteRead(u8 *writeCmd1, int writeCmdLength, u8 *readCmd1, int int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, int dataSize) { - u8 finalCmd[1 + addrSize + WRITE_CHUNK]; + u8 *finalCmd; int remaining = dataSize; int toWrite = 0, i = 0; + finalCmd = (u8 *)kzalloc(1 + addrSize + WRITE_CHUNK, GFP_KERNEL); + if (!finalCmd) + return ERROR_ALLOC; + if (addrSize <= sizeof(u64)) { while (remaining > 0) { if (remaining >= WRITE_CHUNK) { @@ -506,6 +510,7 @@ int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, int if (fts_write(finalCmd, 1 + addrSize + toWrite) < OK) { logError(1, "%s %s: ERROR %08X\n", tag, __func__, ERROR_BUS_W); + kfree(finalCmd); return ERROR_BUS_W; } @@ -517,7 +522,7 @@ int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, int logError(1, "%s %s: address size bigger than max allowed %ld... ERROR %08X\n", tag, __func__, sizeof(u64), ERROR_OP_NOT_ALLOW); - + kfree(finalCmd); return OK; } @@ -537,11 +542,15 @@ int fts_writeU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *data, int int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, int byteToRead, int hasDummyByte) { - u8 finalCmd[1 + addrSize]; + u8 *finalCmd; u8 buff[READ_CHUNK + 1];/* worst case has dummy byte */ int remaining = byteToRead; int toRead = 0, i = 0; + finalCmd = (u8 *)kzalloc(1 + addrSize, GFP_KERNEL); + if (!finalCmd) + return ERROR_ALLOC; + while (remaining > 0) { if (remaining >= READ_CHUNK) { toRead = READ_CHUNK; @@ -563,6 +572,7 @@ int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, int "%s %s: read error... ERROR %08X\n", tag, __func__, ERROR_BUS_WR); + kfree(finalCmd); return ERROR_BUS_WR; } memcpy(outBuf, buff + 1, toRead); @@ -573,6 +583,7 @@ int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, int "%s %s: read error... ERROR %08X\n", tag, __func__, ERROR_BUS_WR); + kfree(finalCmd); return ERROR_BUS_WR; } memcpy(outBuf, buff, toRead); @@ -582,7 +593,7 @@ int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, int outBuf += toRead; } - + kfree(finalCmd); return OK; } @@ -604,11 +615,21 @@ int fts_writeReadU8UX(u8 cmd, AddrSize addrSize, u64 address, u8 *outBuf, int int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, AddrSize addrSize2, u64 address, u8 *data, int dataSize) { - u8 finalCmd1[1 + addrSize1]; - u8 finalCmd2[1 + addrSize2 + WRITE_CHUNK]; + u8 *finalCmd1; + u8 *finalCmd2; int remaining = dataSize; int toWrite = 0, i = 0; + finalCmd1 = (u8 *)kzalloc(1 + addrSize1, GFP_KERNEL); + if (!finalCmd1) + return ERROR_ALLOC; + + finalCmd2 = (u8 *)kzalloc(1 + addrSize2 + WRITE_CHUNK, GFP_KERNEL); + if (!finalCmd2) { + kfree(finalCmd1); + return ERROR_ALLOC; + } + while (remaining > 0) { if (remaining >= WRITE_CHUNK) { toWrite = WRITE_CHUNK; @@ -636,6 +657,8 @@ int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, AddrSize if (fts_write(finalCmd1, 1 + addrSize1) < OK) { logError(1, "%s %s: first write error... ERROR %08X\n", tag, __func__, ERROR_BUS_W); + kfree(finalCmd1); + kfree(finalCmd2); return ERROR_BUS_W; } @@ -644,6 +667,8 @@ int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, AddrSize "%s %s: second write error... ERROR %08X\n", tag, __func__, ERROR_BUS_W); + kfree(finalCmd1); + kfree(finalCmd2); return ERROR_BUS_W; } @@ -651,7 +676,8 @@ int fts_writeU8UXthenWriteU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, AddrSize data += toWrite; } - + kfree(finalCmd1); + kfree(finalCmd2); return OK; } @@ -676,12 +702,21 @@ int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, AddrSize addrSize2, u64 address, u8 *outBuf, int byteToRead, int hasDummyByte) { - u8 finalCmd1[1 + addrSize1]; - u8 finalCmd2[1 + addrSize2]; + u8 *finalCmd1; + u8 *finalCmd2; u8 buff[READ_CHUNK + 1];/* worst case has dummy byte */ int remaining = byteToRead; int toRead = 0, i = 0; + finalCmd1 = (u8 *)kzalloc(1 + addrSize1, GFP_KERNEL); + if (!finalCmd1) + return ERROR_ALLOC; + + finalCmd2 = (u8 *)kzalloc(1 + addrSize2, GFP_KERNEL); + if (!finalCmd2) { + kfree(finalCmd1); + return ERROR_ALLOC; + } while (remaining > 0) { if (remaining >= READ_CHUNK) { @@ -711,6 +746,8 @@ int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, if (fts_write(finalCmd1, 1 + addrSize1) < OK) { logError(1, "%s %s: first write error... ERROR %08X\n", tag, __func__, ERROR_BUS_W); + kfree(finalCmd1); + kfree(finalCmd2); return ERROR_BUS_W; } @@ -721,6 +758,8 @@ int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, "%s %s: read error... ERROR %08X\n", tag, __func__, ERROR_BUS_WR); + kfree(finalCmd1); + kfree(finalCmd2); return ERROR_BUS_WR; } memcpy(outBuf, buff + 1, toRead); @@ -731,6 +770,8 @@ int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, "%s %s: read error... ERROR %08X\n", tag, __func__, ERROR_BUS_WR); + kfree(finalCmd1); + kfree(finalCmd2); return ERROR_BUS_WR; } memcpy(outBuf, buff, toRead); @@ -740,6 +781,7 @@ int fts_writeU8UXthenWriteReadU8UX(u8 cmd1, AddrSize addrSize1, u8 cmd2, outBuf += toRead; } - + kfree(finalCmd1); + kfree(finalCmd2); return OK; } diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsSoftware.h b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsSoftware.h index e3162ce45cea..8c77fa9eb24e 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsSoftware.h +++ b/drivers/input/touchscreen/stmicro_mmi/fts_lib/ftsSoftware.h @@ -28,10 +28,10 @@ /* unsigned types */ -typedef uint8_t u8; /* /< basic type that represent one byte (or 8 bits) */ -typedef uint16_t u16; /* /< basic type that represent 2 bytes (or 16 bits) */ -typedef uint32_t u32; /* /< basic type that represent 4 bytes (or 32 bits) */ -typedef uint64_t u64; /* /< basic type that represent 8 bytes (or 64 bits) */ +#define u8 uint8_t /* /< basic type that represent one byte (or 8 bits) */ +#define u16 uint16_t /* /< basic type that represent 2 bytes (or 16 bits) */ +#define u32 uint32_t /* /< basic type that represent 4 bytes (or 32 bits) */ +#define u64 uint64_t /* /< basic type that represent 8 bytes (or 64 bits) */ /* signed type */ typedef signed char i8; /* /< basic type that represent one signed byte (or 8 diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_mmi.h b/drivers/input/touchscreen/stmicro_mmi/fts_mmi.h new file mode 100644 index 000000000000..45044e0ec83f --- /dev/null +++ b/drivers/input/touchscreen/stmicro_mmi/fts_mmi.h @@ -0,0 +1,17 @@ +#ifndef _FTS_MMI_H_ +#define _FTS_MMI_H_ + +#include +#include + +struct fts_ts_info; + +#ifdef CONFIG_INPUT_TOUCHSCREEN_MMI +int fts_mmi_init(struct fts_ts_info *info, bool enable); +#else +static int inline fts_mmi_init(struct fts_ts_info *info, bool enable) +{ + return -ENOSYS; +} +#endif +#endif diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_mmi_class.c b/drivers/input/touchscreen/stmicro_mmi/fts_mmi_class.c new file mode 100644 index 000000000000..1584a50b08f9 --- /dev/null +++ b/drivers/input/touchscreen/stmicro_mmi/fts_mmi_class.c @@ -0,0 +1,217 @@ +/* +* Copyright (C) 2020 Motorola Mobility LLC + * + * 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. + */ +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include "fts.h" +#include "fts_mmi.h" +#include "fts_lib/ftsCore.h" + +extern void fts_resume_func(struct fts_ts_info *info); +extern void fts_suspend_func(struct fts_ts_info *info); +extern int fts_fw_update(struct fts_ts_info *info); + +#define ASSERT_PTR(p) if (p == NULL) { \ + dev_err(dev, "Failed to get driver data"); \ + return -ENODEV; \ + } + +static int fts_mmi_get_class_entry_name(struct device *dev, void *cdata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "primary"); +} + +static int fts_mmi_get_vendor(struct device *dev, void *cdata) { + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_VENDOR_LEN, "stmicro"); +} + +static int fts_mmi_get_productinfo(struct device *dev, void *cdata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + char buffer[64]; + ssize_t blen = 0; + ASSERT_PTR(ts); + blen += scnprintf(buffer+blen, sizeof(buffer)-blen, "%02x%02x%02x%02x", + ts->sysinfo->u8_dieInfo[0], ts->sysinfo->u8_dieInfo[1], + ts->sysinfo->u8_dieInfo[2], ts->sysinfo->u8_dieInfo[3]); + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_INFO_LEN, "%s", buffer); +} + +static int fts_mmi_get_build_id(struct device *dev, void *cdata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + char buffer[64]; + ssize_t blen = 0; + ASSERT_PTR(ts); + blen += scnprintf(buffer+blen, sizeof(buffer)-blen, "%08x%02x", + ts->sysinfo->u16_cfgVer, ts->sysinfo->u8_cfgAfeVer); + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%s", buffer); +} + +static int fts_mmi_get_config_id(struct device *dev, void *cdata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + char buffer[64]; + ssize_t blen = 0; + ASSERT_PTR(ts); + blen += scnprintf(buffer+blen, sizeof(buffer)-blen, "%02x%02x%02x%02x", + ts->sysinfo->u8_releaseInfo[0], ts->sysinfo->u8_releaseInfo[1], + ts->sysinfo->u8_releaseInfo[2], ts->sysinfo->u8_releaseInfo[3]); + return scnprintf(TO_CHARP(cdata), TS_MMI_MAX_ID_LEN, "%s", buffer); +} + +static int fts_mmi_get_bus_type(struct device *dev, void *idata) { + TO_INT(idata) = TOUCHSCREEN_MMI_BUS_TYPE_I2C; + return 0; +} + +static int fts_mmi_get_irq_status(struct device *dev, void *idata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + TO_INT(idata) = gpio_get_value(ts->board->irq_gpio); + return 0; +} + +static int fts_mmi_get_drv_irq(struct device *dev, void *idata) { + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + TO_INT(idata) = fts_is_InterruptEnabled(); + return 0; +} + +static int fts_mmi_get_poweron(struct device *dev, void *idata) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + //TO_INT(idata) = (atomic_read(&ts->touch_stopped) == 0 && ts->flash_enabled) ? 1 : 0; + return 0; +} + +static int fts_mmi_get_flashprog(struct device *dev, void *idata) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + + ASSERT_PTR(ts); + //TO_INT(idata) = ts->in_bootloader ? 1 : 0; + + return 0; +} + +static int fts_mmi_drv_irq(struct device *dev, int state) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + dev_dbg(dev, "%s\n", __func__); + switch (state) { + case 0: /* Disable irq */ + fts_disableInterrupt(); + break; + case 1: /* Enable irq */ + fts_enableInterrupt(); + break; + default: + dev_err(dev, "%s: invalid value\n", __func__); + return -EINVAL; + } + return 0; +} + +static int fts_mmi_reset(struct device *dev, int type) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + dev_dbg(dev, "%s\n", __func__); + return fts_system_reset(); +} + +static int fts_mmi_panel_state(struct device *dev, + enum ts_mmi_pm_mode from, enum ts_mmi_pm_mode to) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + dev_dbg(dev, "%s: panel state change: %d->%d\n", __func__, from, to); + switch (to) { + case TS_MMI_PM_GESTURE: + case TS_MMI_PM_DEEPSLEEP: + fts_suspend_func(ts); + break; + case TS_MMI_PM_ACTIVE: + break; + default: + dev_warn(dev, "invalid panel state %d\n", to); + return -EINVAL; + } + return 0; +} + +static int fts_mmi_post_resume(struct device *dev) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + dev_dbg(dev, "%s\n", __func__); + fts_resume_func(ts); + return 0; +} + +static int fts_mmi_fw_update(struct device *dev, char *fwname) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + int ret; + ASSERT_PTR(ts); + dev_dbg(dev, "%s\n", __func__); + ts->fw_file = fwname; + ret = fts_fw_update(ts); + ts->fw_file = NULL; + return ret; +} + +static int fts_mmi_charger_mode(struct device *dev, int mode) +{ + struct fts_ts_info *ts = dev_get_drvdata(dev); + ASSERT_PTR(ts); + dev_dbg(dev, "%s\n", __func__); + return 0; +} + +static struct ts_mmi_methods fts_mmi_methods = { + .get_vendor = fts_mmi_get_vendor, + .get_productinfo = fts_mmi_get_productinfo, + .get_build_id = fts_mmi_get_build_id, + .get_config_id = fts_mmi_get_config_id, + .get_bus_type = fts_mmi_get_bus_type, + .get_irq_status = fts_mmi_get_irq_status, + .get_drv_irq = fts_mmi_get_drv_irq, + .get_poweron = fts_mmi_get_poweron, + .get_flashprog = fts_mmi_get_flashprog, + .get_class_entry_name = fts_mmi_get_class_entry_name, + /* SET methods */ + .reset = fts_mmi_reset, + .drv_irq = fts_mmi_drv_irq, + .charger_mode = fts_mmi_charger_mode, + /* Firmware */ + .firmware_update = fts_mmi_fw_update, + /* vendor specific attribute group */ + /* PM callback */ + .panel_state = fts_mmi_panel_state, + .post_resume = fts_mmi_post_resume, +}; + +int fts_mmi_init(struct fts_ts_info *ts, bool enable) +{ + int ret = 0; + + if (enable) { + ret = ts_mmi_dev_register(ts->dev, &fts_mmi_methods); + if (ret) + dev_err(ts->dev, "Failed to register ts mmi\n"); + } else + ts_mmi_dev_unregister(ts->dev); + return ret; +} diff --git a/drivers/input/touchscreen/stmicro_mmi/fts_proc.c b/drivers/input/touchscreen/stmicro_mmi/fts_proc.c index 496c16ca3c4c..3c6f42ed8fac 100644 --- a/drivers/input/touchscreen/stmicro_mmi/fts_proc.c +++ b/drivers/input/touchscreen/stmicro_mmi/fts_proc.c @@ -637,7 +637,7 @@ static ssize_t fts_driver_test_write(struct file *file, const char __user *buf, int numberParam = 0; struct fts_ts_info *info = dev_get_drvdata(getDev()); char *p = NULL; - char pbuf[count]; + char *pbuf = NULL; char path[100] = { 0 }; int res = -1, j, index = 0; int size = 6; @@ -645,8 +645,8 @@ static ssize_t fts_driver_test_write(struct file *file, const char __user *buf, u16 byteToRead = 0; u32 fileSize = 0; u8 *readData = NULL; - u8 cmd[count]; /* worst case needs count bytes */ - u32 funcToTest[((count + 1) / 3)]; + u8 *cmd = NULL; + u32 *funcToTest = NULL; u64 addr = 0; MutualSenseFrame frameMS; SelfSenseFrame frameSS; @@ -666,6 +666,14 @@ static ssize_t fts_driver_test_write(struct file *file, const char __user *buf, mess.action = 0; mess.msg_size = 0; + pbuf = (char *)kzalloc(count + 1, GFP_KERNEL); + cmd = (u8 *)kzalloc(count, GFP_KERNEL); + funcToTest = (u32 *)kzalloc((int)((count + 1)/3), GFP_KERNEL); + if (!pbuf || !cmd || !funcToTest) { + res = ERROR_ALLOC; + goto END; + } + /*for(temp = 0; temp