366 lines
11 KiB
C
366 lines
11 KiB
C
/**
|
|
* @file focaltech.c
|
|
* @focaltech touch ic driver file.
|
|
*
|
|
* @Copyright (c) 2022 Semidrive Semiconductor.
|
|
* @All rights reserved.
|
|
*
|
|
**/
|
|
|
|
#include <FreeRTOS.h>
|
|
#include <debug.h>
|
|
#include <task.h>
|
|
#include "event_groups.h"
|
|
#include <sdrv_gpio.h>
|
|
#include "focaltech.h"
|
|
|
|
#define FTS_INCELL 0x1
|
|
#define FTS_CHIP_TYPE_MAPPING {{0x12, 0x72, 0x51, 0x72, 0x51, 0x72, 0xA1, 0x00, 0x00}}
|
|
|
|
#define FTS_ONE_TCH_LEN 6
|
|
|
|
#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_POINT_NUM 2
|
|
#define FTS_TOUCH_EVENT_POS 3
|
|
#define FTS_TOUCH_ID_POS 5
|
|
|
|
/*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_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
|
|
|
|
struct ft_chip_t {
|
|
uint32_t type;
|
|
uint8_t chip_idh;
|
|
uint8_t chip_idl;
|
|
uint8_t rom_idh;
|
|
uint8_t rom_idl;
|
|
uint8_t pb_idh;
|
|
uint8_t pb_idl;
|
|
uint8_t bl_idh;
|
|
uint8_t bl_idl;
|
|
};
|
|
|
|
struct fts_data {
|
|
struct ft_chip_t ids;
|
|
touch_dev_t *ts_dev;
|
|
EventGroupHandle_t ts_event;
|
|
} g_fts;
|
|
|
|
int fts_read(struct fts_data *fts, uint8_t *cmd, uint32_t cmdlen,
|
|
uint8_t *data, uint8_t datalen)
|
|
{
|
|
int ret = 0;
|
|
sdrv_i2cdrv_bus_stat_t bus_stat;
|
|
sdrv_i2cdrv_trans_stat_t trans_stat;
|
|
sdrv_i2c_t *ctrl = fts->ts_dev->i2c_ctrl;
|
|
int addr = fts->ts_dev->i2c_addr;
|
|
|
|
/* get bus stat, if busy can not use */
|
|
bus_stat = sdrv_i2c_get_bus_stat(ctrl);
|
|
if (bus_stat == SDRV_I2CDRV_BUS_BUSY) {
|
|
ssdk_printf(SSDK_CRIT, "i2c ctrl %u busy\r\n", ctrl->cfg->id);
|
|
return -1;
|
|
}
|
|
|
|
/* set bus stat to busy indicate bus be occupied now */
|
|
ret = sdrv_i2c_set_bus_stat(ctrl, SDRV_I2CDRV_BUS_BUSY);
|
|
if (ret < 0) {
|
|
ssdk_printf(SSDK_CRIT, "i2c ctrl %u set bus stat fail\r\n",
|
|
ctrl->cfg->id);
|
|
return -2;
|
|
}
|
|
|
|
sdrv_i2c_write(ctrl, addr, cmd, cmdlen, 1000, false);
|
|
|
|
trans_stat = sdrv_i2c_get_trans_stat(ctrl);
|
|
if (trans_stat != SDRV_I2CDRV_TRANS_OK) {
|
|
ssdk_printf(SSDK_CRIT, "%s write fail\r\n", __func__);
|
|
ret = -3;
|
|
goto end;
|
|
}
|
|
|
|
sdrv_i2c_read(ctrl, addr, data, datalen, 1000, true);
|
|
|
|
trans_stat = sdrv_i2c_get_trans_stat(ctrl);
|
|
if (trans_stat != SDRV_I2CDRV_TRANS_OK) {
|
|
ssdk_printf(SSDK_CRIT, "%s, read fail\r\n", __func__);
|
|
ret = -4;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
sdrv_i2c_set_bus_stat(ctrl, SDRV_I2CDRV_BUS_IDLE);
|
|
return ret;
|
|
}
|
|
|
|
int fts_write(struct fts_data *fts, uint8_t *buf, uint32_t len)
|
|
{
|
|
int ret = 0;
|
|
sdrv_i2cdrv_bus_stat_t bus_stat;
|
|
sdrv_i2cdrv_trans_stat_t trans_stat;
|
|
sdrv_i2c_t *ctrl = fts->ts_dev->i2c_ctrl;
|
|
int addr = fts->ts_dev->i2c_addr;
|
|
|
|
/* get bus stat, if busy can not use */
|
|
bus_stat = sdrv_i2c_get_bus_stat(ctrl);
|
|
if (bus_stat == SDRV_I2CDRV_BUS_BUSY) {
|
|
ssdk_printf(SSDK_CRIT, "i2c ctrl %u busy\r\n", ctrl->cfg->id);
|
|
return -1;
|
|
}
|
|
|
|
/* set bus stat to busy indicate bus be occupied now */
|
|
ret = sdrv_i2c_set_bus_stat(ctrl, SDRV_I2CDRV_BUS_BUSY);
|
|
if (ret < 0) {
|
|
ssdk_printf(SSDK_CRIT, "i2c ctrl %u set bus stat fail\r\n",
|
|
ctrl->cfg->id);
|
|
return -2;
|
|
}
|
|
|
|
sdrv_i2c_write(ctrl, addr, buf, len, 1000, true);
|
|
|
|
trans_stat = sdrv_i2c_get_trans_stat(ctrl);
|
|
if (trans_stat != SDRV_I2CDRV_TRANS_OK) {
|
|
ssdk_printf(SSDK_CRIT, "%s write fail\r\n", __func__);
|
|
ret = -3;
|
|
goto end;
|
|
}
|
|
|
|
end:
|
|
sdrv_i2c_set_bus_stat(ctrl, SDRV_I2CDRV_BUS_IDLE);
|
|
return ret;
|
|
}
|
|
|
|
int fts_read_reg(struct fts_data *fts, uint8_t addr, uint8_t *value)
|
|
{
|
|
return fts_read(fts, &addr, 1, value, 1);
|
|
}
|
|
|
|
int fts_write_reg(struct fts_data *fts, uint8_t addr, uint8_t value)
|
|
{
|
|
uint8_t buf[2] = {0};
|
|
|
|
buf[0] = addr;
|
|
buf[1] = value;
|
|
return fts_write(fts, buf, sizeof(buf));
|
|
}
|
|
|
|
static int fts_get_chip_types(struct fts_data *fts,
|
|
uint8_t id_h, uint8_t id_l, bool fw_valid)
|
|
{
|
|
int i = 0;
|
|
struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
|
|
uint32_t ctype_entries = sizeof(ctype) / sizeof(struct ft_chip_t);
|
|
|
|
if ((0x0 == id_h) || (0x0 == id_l)) {
|
|
ssdk_printf(SSDK_ERR, "id_h/id_l is 0\r\n");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < ctype_entries; i++) {
|
|
if (true == fw_valid) {
|
|
if ((id_h == ctype[i].chip_idh) && (id_l == ctype[i].chip_idl))
|
|
break;
|
|
} else {
|
|
if (((id_h == ctype[i].rom_idh) && (id_l == ctype[i].rom_idl))
|
|
|| ((id_h == ctype[i].pb_idh) && (id_l == ctype[i].pb_idl))
|
|
|| ((id_h == ctype[i].bl_idh) && (id_l == ctype[i].bl_idl)))
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= ctype_entries) {
|
|
return -2;
|
|
}
|
|
|
|
fts->ids = ctype[i];
|
|
return 0;
|
|
}
|
|
|
|
static int fts_get_ic_info(struct fts_data *fts)
|
|
{
|
|
int ret = 0;
|
|
int cnt = 0;
|
|
uint8_t chip_id[2] = {0};
|
|
|
|
do {
|
|
ret = fts_read_reg(fts, FTS_REG_CHIP_ID, &chip_id[0]);
|
|
ret = fts_read_reg(fts, FTS_REG_CHIP_ID2, &chip_id[1]);
|
|
if (ret < 0) {
|
|
ssdk_printf(SSDK_ERR, "i2c read chip fail\r\n");
|
|
} else {
|
|
ret = fts_get_chip_types(fts, chip_id[0], chip_id[1], true);
|
|
if (!ret)
|
|
break;
|
|
else
|
|
ssdk_printf(SSDK_ERR, "TP not ready, read:0x%02x%02x",
|
|
chip_id[0], chip_id[1]);
|
|
}
|
|
|
|
ts_mdelay(100);
|
|
} while (++cnt < 3);
|
|
|
|
if (cnt >= 3) {
|
|
ssdk_printf(SSDK_ERR, "%s: read chip id fail\r\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
ssdk_printf(SSDK_ERR, "%s: chip id = 0x%02x%02x\r\n", __func__,
|
|
fts->ids.chip_idh, fts->ids.chip_idl);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int fts_reset_device(struct fts_data *fts)
|
|
{
|
|
sdrv_gpio_set_pin_output_level(fts->ts_dev->rst, true);
|
|
ts_mdelay(10);
|
|
sdrv_gpio_set_pin_output_level(fts->ts_dev->irq, false);
|
|
ts_mdelay(2);
|
|
sdrv_gpio_set_pin_output_level(fts->ts_dev->rst, true);
|
|
ts_mdelay(100);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void fts_thread(void *arg)
|
|
{
|
|
int i;
|
|
int ret;
|
|
int base;
|
|
int point_num;
|
|
int point_num_down;
|
|
int point_num_flag[10];
|
|
struct fts_data *fts = arg;
|
|
uint8_t buf[FTS_ONE_TCH_LEN * 10 + 4];
|
|
|
|
touch_data_t *sdrv_datap = sdrv_touch_data_pointer();
|
|
|
|
while (1) {
|
|
xEventGroupWaitBits(fts->ts_event, 1, pdTRUE, pdFAIL, portMAX_DELAY);
|
|
|
|
for (i = 0; i < 64; i++)
|
|
buf[i] = 0xff;
|
|
|
|
buf[0] = 0x01;
|
|
|
|
ret = fts_read(fts, buf, 1, buf + 1, 63);
|
|
if (ret < 0) {
|
|
ssdk_printf(SSDK_ERR, "read touch data failed, ret:%d", ret);
|
|
sdrv_gpio_pin_interrupt_enable(fts->ts_dev->irq);
|
|
continue;
|
|
}
|
|
|
|
point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
|
|
|
|
if (FTS_INCELL) {
|
|
if ((point_num == 0x0F) && (buf[2] == 0xFF) && (buf[3] == 0xFF)
|
|
&& (buf[4] == 0xFF) && (buf[5] == 0xFF) && (buf[6] == 0xFF)) {
|
|
ssdk_printf(SSDK_ERR, "buf is 0xff, need recovery state\r\n");
|
|
//fts_release_all_finger();
|
|
//fts_tp_state_recovery(data);
|
|
sdrv_gpio_pin_interrupt_enable(fts->ts_dev->irq);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
point_num_down = point_num;
|
|
|
|
for (i = 0; i < point_num; i++) {
|
|
base = FTS_ONE_TCH_LEN * i;
|
|
sdrv_datap->touch_point[i].id = (buf[FTS_TOUCH_ID_POS + base]) >> 4;
|
|
sdrv_datap->touch_point[i].x = ((buf[FTS_TOUCH_X_H_POS + base] & 0x0F) << 8) +
|
|
(buf[FTS_TOUCH_X_L_POS + base] & 0xFF);
|
|
sdrv_datap->touch_point[i].y = ((buf[FTS_TOUCH_Y_H_POS + base] & 0x0F) << 8) +
|
|
(buf[FTS_TOUCH_Y_L_POS + base] & 0xFF);
|
|
point_num_flag[i] = buf[FTS_TOUCH_EVENT_POS + base] >> 6;
|
|
if (point_num_flag[i] == 1)
|
|
point_num_down--;
|
|
}
|
|
|
|
sdrv_datap->touch_num = point_num_down;
|
|
#if 0
|
|
for (i = 0; i < point_num; i++) {
|
|
ssdk_printf(SSDK_ERR, "%s, num=%d, id=%d, x=%d, y=%d, flag=%d\r\n", __func__,
|
|
sdrv_datap->touch_num, sdrv_datap->touch_point[i].id,
|
|
sdrv_datap->touch_point[i].x, sdrv_datap->touch_point[i].y,
|
|
point_num_flag[i]);
|
|
}
|
|
#endif
|
|
sdrv_gpio_pin_interrupt_enable(fts->ts_dev->irq);
|
|
}
|
|
}
|
|
|
|
static void fts_irq_handler(uint32_t irq, uint32_t pin, void *arg)
|
|
{
|
|
BaseType_t yield = pdFALSE;
|
|
struct fts_data *fts = (struct fts_data *)arg;
|
|
|
|
sdrv_gpio_pin_interrupt_disable(fts->ts_dev->irq);
|
|
//ssdk_printf(SSDK_ERR, "%s\r\n", __func__);
|
|
|
|
if (xEventGroupSetBitsFromISR(fts->ts_event, 1, &yield) != pdFAIL)
|
|
portYIELD_FROM_ISR (yield);
|
|
}
|
|
|
|
static int fts_config_device(struct fts_data *fts)
|
|
{
|
|
fts->ts_event = xEventGroupCreate();
|
|
xTaskCreate(fts_thread, "focaltech", configTASK_IDLE_STACK_SIZE, fts,
|
|
(tskIDLE_PRIORITY + 2), NULL);
|
|
sdrv_gpio_set_pin_interrupt(fts->ts_dev->irq, GPIO_INTR_FALLING_EDGE);
|
|
sdrv_gpio_register_interrupt_handler(fts->ts_dev->irq, fts_irq_handler, fts);
|
|
sdrv_gpio_pin_interrupt_enable(fts->ts_dev->irq);
|
|
return 0;
|
|
}
|
|
|
|
int focaltech_touch_init(touch_dev_t *touch_dev)
|
|
{
|
|
int ret = 0;
|
|
g_fts.ts_dev = touch_dev;
|
|
|
|
fts_reset_device(&g_fts);
|
|
|
|
ret = fts_get_ic_info(&g_fts);
|
|
if (ret) {
|
|
ssdk_printf(SSDK_ERR, "%s: read chip id fail\r\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
ret = fts_config_device(&g_fts);
|
|
if (ret) {
|
|
ssdk_printf(SSDK_ERR, "%s: confif device fail\r\n", __func__);
|
|
return -1;
|
|
}
|
|
|
|
ssdk_printf(SSDK_ERR, "%s, ===done ok===\r\n", __func__);
|
|
return 0;
|
|
}
|
|
|