fts: support touchscreen class

Make initial driver's code buildable in MMI products. Added initial
support for touchscreen class.

Change-Id: Iabe4b047b8fbe7f1d1c4f0991ff9b261e4dbf673
Signed-off-by: Konstantin Makariev <hcv867@motorola.com>
Reviewed-on: https://gerrit.mot.com/1682834
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Igor Kovalenko <igork@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
Konstantin Makariev 2020-07-14 15:34:16 -05:00 • committed by Konstantin Makariev
commit 9d501e96ea
16 changed files with 452 additions and 69 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View file

@ -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

View file

@ -0,0 +1,17 @@
#ifndef _FTS_MMI_H_
#define _FTS_MMI_H_
#include <linux/gpio.h>
#include <linux/touchscreen_mmi.h>
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

View file

@ -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;
}

View file

@ -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<count; temp++){
* logError(0,"%s p[%d] = %02X\n",tag, temp, p[temp]);
* }*/
@ -3004,6 +3012,13 @@ ERROR:
if (readData != NULL)
kfree(readData);
if (pbuf)
kfree(pbuf);
if (cmd)
kfree(cmd);
if (funcToTest)
kfree(funcToTest);
return count;
}