/** * @file focaltech.c * @focaltech touch ic driver file. * * @Copyright (c) 2022 Semidrive Semiconductor. * @All rights reserved. * **/ #include #include #include #include "event_groups.h" #include #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; }