diff --git a/model/input/driver/touchscreen/Kconfig b/model/input/driver/touchscreen/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2bf2eff0d962502ef12e6447bd4d524b6a70c94d --- /dev/null +++ b/model/input/driver/touchscreen/Kconfig @@ -0,0 +1,6 @@ +config ARCH_VIM3L_TOUCH + bool "config vim3l ft5336 touch" + default n + help + Answer Y to enable config ft5336 touch. + diff --git a/model/input/driver/touchscreen/touch_ft5336.c b/model/input/driver/touchscreen/touch_ft5336.c new file mode 100644 index 0000000000000000000000000000000000000000..cb89b037f01cda9fd1e10e2d9808a6eddb4485ba --- /dev/null +++ b/model/input/driver/touchscreen/touch_ft5336.c @@ -0,0 +1,376 @@ +#include +#include "osal_mem.h" +#include "hdf_device_desc.h" +#include "hdf_touch.h" +#include "input_i2c_ops.h" +#include "touch_ft5336.h" +#include "hdf_log.h" +#include +#include "input_config.h" +#include "hdf_input_device_manager.h" +#include "hdf_types.h" +#include "device_resource_if.h" +#include "gpio_if.h" +#include "hdf_device_desc.h" +#include "osal_io.h" +#include "event_hub.h" + +#define TP_SWAP(x, y) do {\ + typeof(x) z = x;\ + x = y;\ + y = z; \ +} while (0) + +static int32_t ChipInit(ChipDevice *device) +{ + return HDF_SUCCESS; +} + +static int32_t ChipResume(ChipDevice *device) +{ + return HDF_SUCCESS; +} + +static int32_t ChipSuspend(ChipDevice *device) +{ + return HDF_SUCCESS; +} + +static int Ft5336_Identify(ChipDevice *device, const InputI2cClient *i2cClient) +{ + u8 rdbuf[EDT_NAME_LEN]; + char *p = NULL; + int error = 0; + char fw_version[EDT_NAME_LEN]; + + memset(rdbuf, 0, sizeof(rdbuf)); + + error = InputI2cRead(i2cClient, "\xbb", 1, rdbuf, EDT_NAME_LEN - 1); + if (error){ + return error; + } + /* Probe content for something consistent. + * M06 starts with a response byte. + * M09/Generic does not provide model number information. + */ + if (!(strncasecmp(rdbuf + 1, "EP0", 3))) { + device->chipCfg->chipVersion = EDT_M06; + HDF_LOGI("%s: version = EDT_M06", __func__); + + rdbuf[EDT_NAME_LEN - 1] = '\0'; + if (rdbuf[EDT_NAME_LEN - 2] == '$'){ + rdbuf[EDT_NAME_LEN - 2] = '\0'; + } + p = strchr(rdbuf, '*'); + if (p){ + *p++ = '\0'; + } + strlcpy(fw_version, p ? p : "", EDT_NAME_LEN); + } else { + /* since there are only two versions around (M06, M09) */ + device->chipCfg->chipVersion = EDT_M09; + HDF_LOGI("%s: version = EDT_M09;", __func__); + + error = InputI2cRead(i2cClient, "\xA6", 1, rdbuf, 2); + if (error){ + return error; + } + strlcpy(fw_version, rdbuf, 2); + } + + HDF_LOGI("%s: fw_version = %s", __func__, fw_version); + return 0; +} + +static int32_t ChipDetect(ChipDevice *device) +{ + uint8_t regAddr; + uint8_t regValue = 0; + int32_t ret; + + InputI2cClient *i2cClient = &device->driver->i2cClient; + + regAddr = WORK_REGISTER_REPORT_RATE; + ret = InputI2cWrite(i2cClient, ®Addr, 1); + CHIP_CHECK_RETURN(ret); + ret = InputI2cRead(i2cClient, ®Addr, 1, ®Value, 1); + CHIP_CHECK_RETURN(ret); + HDF_LOGI("%s: Report rate is %u * 10", __func__, regValue); + + Ft5336_Identify(device, i2cClient); + + (void)ChipInit(device); + (void)ChipResume(device); + (void)ChipSuspend(device); + + return HDF_SUCCESS; +} + +static int32_t ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum, int32_t version) +{ + int32_t i; + int32_t x,y; + int32_t offset, tplen, crclen; + int32_t type; + switch (version) { + case EDT_M06: + offset = 5; /* where the actual touch data starts */ + tplen = 4; /* data comes in so called frames */ + crclen = 1; /* length of the crc data */ + break; + + case EDT_M09: + offset = 3; + tplen = 6; + crclen = 0; + break; + + default: + return HDF_FAILURE; + } + + for (i = 0; i < pointNum; i++) { + u8 *rdbuf = &buf[i * tplen + offset]; + + type = rdbuf[0] >> 6; + /* ignore Reserved events */ + if (type == TOUCH_EVENT_RESERVED){ + continue; + } + + /* M06 sometimes sends bogus coordinates in TOUCH_DOWN */ + if (version == EDT_M06 && type == TOUCH_EVENT_DOWN){ + continue; + } + + if (type == TOUCH_EVENT_UP){ + frame->definedEvent = type; + continue; + } + + x = ((rdbuf[0] << 8) | rdbuf[1]) & 0x0fff; + y = ((rdbuf[2] << 8) | rdbuf[3]) & 0x0fff; + +#if TP_CHANGE_X2Y + TP_SWAP(x, y); +#endif + +#if TP_Y_REVERSE_ENABLE + y = device->boardCfg->attr.resolutionY - y; +#endif + +#if TP_X_REVERSE_ENABLE + x = device->boardCfg->attr.resolutionX - x; +#endif +// HDF_LOGI("%s : x = %u , y = %u ", __func__, x, y); + + frame->fingers[i].x = x; + frame->fingers[i].y = y; + frame->fingers[i].trackId = (rdbuf[2] >> 4) & 0x0f; + frame->fingers[i].status = rdbuf[0] >> 6; + frame->fingers[i].valid = true; + frame->definedEvent = frame->fingers[i].status; + + if ((frame->fingers[i].status == TOUCH_DOWN || frame->fingers[i].status == TOUCH_CONTACT) && (pointNum == 0)) { + HDF_LOGE("%s: abnormal event data from driver chip", __func__); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} + +static int32_t ChipDataHandle(ChipDevice *device) +{ + uint8_t reg = 0x0; + uint8_t pointNum; + uint8_t buf[POINT_BUFFER_LEN_M09] = {0}; + int32_t ret = 0; + + InputI2cClient *i2cClient = &device->driver->i2cClient; + FrameData *frame = &device->driver->frameData; + + switch (device->chipCfg->chipVersion) { + case EDT_M06: + reg = 0xf9; /* tell the controller to send touch data */ + ret = InputI2cRead(i2cClient, ®, 1, buf, POINT_BUFFER_LEN_M06); + break; + + case EDT_M09: + ret = InputI2cRead(i2cClient, ®, 1, buf, POINT_BUFFER_LEN_M09); + break; + + default: + return HDF_FAILURE; + } + CHIP_CHECK_RETURN(ret); + + OsalMutexLock(&device->driver->mutex); + (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData)); + + pointNum = buf[2] & GT_FINGER_NUM_MASK; + if (pointNum > MAX_POINT) { + OsalMutexUnlock(&device->driver->mutex); + return HDF_FAILURE; + } + + if(pointNum == 0){ + frame->realPointNum = 0; + frame->definedEvent = TOUCH_EVENT_UP; + OsalMutexUnlock(&device->driver->mutex); + return HDF_SUCCESS; + } + + frame->realPointNum = pointNum; + + ret = ParsePointData(device, frame, buf, pointNum, device->chipCfg->chipVersion); + if (ret != HDF_SUCCESS) { + OsalMutexUnlock(&device->driver->mutex); + return ret; + } + OsalMutexUnlock(&device->driver->mutex); + + return HDF_SUCCESS; +} + +static void SetAbility(ChipDevice *device) +{ + device->driver->inputDev->abilitySet.devProp[0] = SET_BIT(INPUT_PROP_DIRECT); + device->driver->inputDev->abilitySet.eventType[0] = SET_BIT(EV_SYN) | + SET_BIT(EV_KEY) | SET_BIT(EV_ABS); + device->driver->inputDev->abilitySet.absCode[0] = SET_BIT(ABS_X) | SET_BIT(ABS_Y); + device->driver->inputDev->abilitySet.absCode[1] = SET_BIT(ABS_MT_POSITION_X) | + SET_BIT(ABS_MT_POSITION_Y) | SET_BIT(ABS_MT_TRACKING_ID); + device->driver->inputDev->abilitySet.keyCode[3] = SET_BIT(KEY_UP) | SET_BIT(KEY_DOWN); + device->driver->inputDev->attrSet.axisInfo[ABS_X].min = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_X].max = device->boardCfg->attr.resolutionX - 1; + device->driver->inputDev->attrSet.axisInfo[ABS_X].range = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_Y].min = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_Y].max = device->boardCfg->attr.resolutionY - 1; + device->driver->inputDev->attrSet.axisInfo[ABS_Y].range = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].min = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].max = device->boardCfg->attr.resolutionX - 1; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_X].range = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].min = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].max = device->boardCfg->attr.resolutionY - 1; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_POSITION_Y].range = 0; + device->driver->inputDev->attrSet.axisInfo[ABS_MT_TRACKING_ID].max = MAX_POINT; +} + +static struct TouchChipOps g_ft5336ChipOps = { + .Init = ChipInit, + .Detect = ChipDetect, + .Resume = ChipResume, + .Suspend = ChipSuspend, + .DataHandle = ChipDataHandle, + .SetAbility = SetAbility, +}; + +static void FreeChipConfig(TouchChipCfg *config) +{ + if (config->pwrSeq.pwrOn.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOn.buf); + } + + if (config->pwrSeq.pwrOff.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOff.buf); + } + + if (config->pwrSeq.resume.buf != NULL) { + OsalMemFree(config->pwrSeq.resume.buf); + } + + if (config->pwrSeq.suspend.buf != NULL) { + OsalMemFree(config->pwrSeq.suspend.buf); + } + + OsalMemFree(config); +} + +static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg)); + if (chipCfg == NULL) { + HDF_LOGE("%s: instance chip config failed", __func__); + return NULL; + } + (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg)); + + if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: parse chip config failed", __func__); + OsalMemFree(chipCfg); + chipCfg = NULL; + } + return chipCfg; +} + +static ChipDevice *ChipDeviceInstance(void) +{ + ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice)); + if (chipDev == NULL) { + HDF_LOGE("%s: instance chip device failed", __func__); + return NULL; + } + (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice)); + return chipDev; +} + +extern int tca6408_output_set_value(u8 value, u8 mask); +static int32_t EdtFocalChipInit(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = NULL; + ChipDevice *chipDev = NULL; + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + chipCfg = ChipConfigInstance(device); //解析input_config中的chipConfig + if (chipCfg == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + + chipDev = ChipDeviceInstance(); + if (chipDev == NULL) { + FreeChipConfig(chipCfg); + return HDF_FAILURE; + } + + tca6408_output_set_value(TCA_TP_RST_MASK, TCA_TP_RST_MASK); + usleep_range(5000, 6000); + tca6408_output_set_value(TCA_TP_RSTT_MASK,TCA_TP_RST_MASK); + msleep(300); + tca6408_output_set_value(TCA_TP_RST_MASK,TCA_TP_RST_MASK); + + chipDev->chipCfg = chipCfg; + chipDev->ops = &g_ft5336ChipOps; + chipDev->chipName = chipCfg->chipName; + chipDev->vendorName = chipCfg->vendorName; + + if (RegisterChipDevice(chipDev) != HDF_SUCCESS) { + HDF_LOGI("%s: fail", __func__); + OsalMemFree(chipDev); + } + +#if TP_CHANGE_X2Y + uint32_t resolution = chipDev->boardCfg->attr.resolutionX; + chipDev->boardCfg->attr.resolutionX = chipDev->boardCfg->attr.resolutionY; + chipDev->boardCfg->attr.resolutionY = resolution; +#endif + + HDF_LOGI("%s: init succ, chipName = %s", __func__, chipCfg->chipName); + return HDF_SUCCESS; + +EXIT1: + OsalMemFree(chipDev); +EXIT: + FreeChipConfig(chipCfg); + return HDF_FAILURE; +} + +struct HdfDriverEntry g_edttouchfocalchipentry = { + .moduleVersion = 1, + .moduleName = "EDT_TOUCH_FT5336", + .Init = EdtFocalChipInit, +}; + +HDF_INIT(g_edttouchfocalchipentry); diff --git a/model/input/driver/touchscreen/touch_ft5336.h b/model/input/driver/touchscreen/touch_ft5336.h new file mode 100644 index 0000000000000000000000000000000000000000..ccea38bca040bdc873b706a32cc16fb72a6865ea --- /dev/null +++ b/model/input/driver/touchscreen/touch_ft5336.h @@ -0,0 +1,47 @@ +#ifndef TOUCH_FT5x06_H +#define TOUCH_FT5x06_H + +#define TCA_TP_RST_MASK (1<<6) +#define TCA_TP_RSTT_MASK (0<<6) +#define WORK_REGISTER_THRESHOLD 0x00 +#define WORK_REGISTER_REPORT_RATE 0x08 +#define WORK_REGISTER_GAIN 0x30 +#define WORK_REGISTER_OFFSET 0x31 +#define WORK_REGISTER_NUM_X 0x33 +#define WORK_REGISTER_NUM_Y 0x34 + +#define M09_REGISTER_THRESHOLD 0x80 +#define M09_REGISTER_GAIN 0x92 +#define M09_REGISTER_OFFSET 0x93 +#define M09_REGISTER_NUM_X 0x94 +#define M09_REGISTER_NUM_Y 0x95 + +#define NO_REGISTER 0xff + +#define WORK_REGISTER_OPMODE 0x3c +#define FACTORY_REGISTER_OPMODE 0x01 + +#define TOUCH_EVENT_DOWN 0x00 +#define TOUCH_EVENT_UP 0x01 +#define TOUCH_EVENT_ON 0x02 +#define TOUCH_EVENT_RESERVED 0x03 + +#define EDT_NAME_LEN 23 +#define EDT_SWITCH_MODE_RETRIES 10 +#define EDT_SWITCH_MODE_DELAY 5 /* msec */ +#define EDT_RAW_DATA_RETRIES 100 +#define EDT_RAW_DATA_DELAY 1000 /* usec */ + +#define TP_CHANGE_X2Y 0 +#define TP_X_REVERSE_ENABLE 0 +#define TP_Y_REVERSE_ENABLE 0 + +#define POINT_BUFFER_LEN_M06 26 +#define POINT_BUFFER_LEN_M09 33 +#define MAX_POINT 5 + +#define EDT_M06 0 +#define EDT_M09 1 +#define GT_FINGER_NUM_MASK 0x0F + +#endif