diff --git a/apps/examples/touchscreen/Makefile b/apps/examples/touchscreen/Makefile index 14e13e49e6..a76de841aa 100644 --- a/apps/examples/touchscreen/Makefile +++ b/apps/examples/touchscreen/Makefile @@ -57,7 +57,7 @@ include $(APPDIR)/Make.defs # Power Daemon built-in application info APPNAME = touchscreen PRIORITY = 100 -STACKSIZE = 1024 +STACKSIZE = 4096 FUNCNAME = $(APPNAME)_main THREADEXEC = TASH_EXECMD_ASYNC diff --git a/build/configs/rtl8730e/loadable_ext_ddr/defconfig b/build/configs/rtl8730e/loadable_ext_ddr/defconfig index 4641254901..c4690a0aa7 100644 --- a/build/configs/rtl8730e/loadable_ext_ddr/defconfig +++ b/build/configs/rtl8730e/loadable_ext_ddr/defconfig @@ -326,8 +326,8 @@ CONFIG_SECOND_FLASH_START_ADDR=0x0A000000 CONFIG_RTL8730E_BOARD_REVISION=8 CONFIG_RAM_DDR=y # CONFIG_RAM_PSRAM is not set -CONFIG_USERFS_MNTPT="/mnt0" -CONFIG_USERFS_EXT_MNTPT="/mnt" +CONFIG_USERFS_MNTPT="/mnt" +CONFIG_USERFS_EXT_MNTPT="/ext" # # SPI Flash driver @@ -356,6 +356,7 @@ CONFIG_FLASH_PART_SIZE="60,40,12,400,1844,8476,4780,1844,8476,4780,2048,8," CONFIG_FLASH_PART_TYPE="none,none,none,none,kernel,bin,bin,kernel,bin,bin,smartfs,bootparam," CONFIG_FLASH_PART_NAME="bl1,reserved,ftl,ss,kernel,common,app1,kernel,common,app1,userfs,bootparam," CONFIG_ARCH_BOARD_HAVE_SECOND_FLASH=y +CONFIG_SECOND_FLASH_START_ADDR=0x0A000000 # # Second Flash Partition Options @@ -1451,12 +1452,18 @@ CONFIG_MEMSET_OPTSPEED=y # CONFIG_LIB_ENVPATH is not set CONFIG_LIB_HASHMAP=y +CONFIG_EXAMPLES_TOUCHSCREEN=y # # Program Execution Options # CONFIG_LIBC_EXECFUNCS=y CONFIG_LIBC_SYMTAB=y +CONFIG_DEBUG_TOUCH=y +CONFIG_DEBUG_TOUCH_ERROR=y +CONFIG_DEBUG_TOUCH_WARN=y +CONFIG_DEBUG_TOUCH_INFO=y + # # Basic CXX Support # @@ -1655,7 +1662,7 @@ CONFIG_EXAMPLES_POWER_TIMEDWAKEUP=y # CONFIG_EXAMPLES_SELECT_TEST is not set # CONFIG_EXAMPLES_SENSORBOARD is not set # CONFIG_EXAMPLES_SETJMP_TEST is not set -# CONFIG_EXAMPLES_SIMPLE_FILE_TRANSFER is not set +CONFIG_EXAMPLES_SIMPLE_FILE_TRANSFER=y # # SmartFs Test Applications @@ -1687,7 +1694,10 @@ CONFIG_EXAMPLES_UART_LOOPBACK_PORT=2 # Wifi Manager # # CONFIG_EXAMPLES_TAHI is not set -# CONFIG_EXAMPLES_WIFIMANAGER_TEST is not set +CONFIG_EXAMPLES_WIFIMANAGER_TEST=y +CONFIG_WIFIMANAGER_TEST_TRIAL=5 +CONFIG_EXAMPLES_WIFIMANAGER_AP_LIST_ITEMS_COUNT=10 + # # Platform-specific Support diff --git a/os/board/rtl8730e/src/rtl8730e_ist415.c b/os/board/rtl8730e/src/rtl8730e_ist415.c index 4de5a3f4d1..9135bf7600 100644 --- a/os/board/rtl8730e/src/rtl8730e_ist415.c +++ b/os/board/rtl8730e/src/rtl8730e_ist415.c @@ -46,10 +46,6 @@ #define IST415_I2C_PORT 1 #endif -#define IST415_I2C_FREQ 100000 -#define IST415_I2C_ADDRLEN 7 -#define IST415_I2C_ADDR (0xA0 >> 1) - /* pin config */ #define IST415_GPIO_RESET_PIN PA_5 #if CONFIG_RTL8730E_BOARD_REVISION >= 6 @@ -63,32 +59,32 @@ ****************************************************************************/ struct rtl8730e_ist415_s { gpio_irq_t data_ready; + struct i2c_dev_s *i2c; /* Workaround: IC20 write hang issue */ }; -struct rtl8730e_ist415_s g_rtl8730e_ist415_priv0; /**************************************************************************** * Private Function Prototypes ****************************************************************************/ -static void rtl8730e_ist415_enable_irq(void); -static void rtl8730e_ist415_disable_irq(void); +static void rtl8730e_ist415_enable_irq(struct ist415_config_s *dev); +static void rtl8730e_ist415_disable_irq(struct ist415_config_s *dev); +static void rtl8730e_ist415_power_off(struct ist415_config_s *dev); +static void rtl8730e_ist415_power_on(struct ist415_config_s *dev); /**************************************************************************** * Private Data ****************************************************************************/ +struct rtl8730e_ist415_s g_rtl8730e_ist415_priv0; -static struct ist415_dev_s g_ist415_dev0 = { - .i2c = NULL, - .i2c_config = { - .frequency = IST415_I2C_FREQ, - .address = IST415_I2C_ADDR, - .addrlen = IST415_I2C_ADDRLEN, - }, - .int_pending = false, - .ops = &(struct ist415_ops_s){ - .irq_enable = rtl8730e_ist415_enable_irq, - .irq_disable = rtl8730e_ist415_disable_irq, - }, +struct ist415_ops_s g_rtl8730e_ist415_ops = { + .irq_enable = rtl8730e_ist415_enable_irq, + .irq_disable = rtl8730e_ist415_disable_irq, + .power_off = rtl8730e_ist415_power_off, + .power_on = rtl8730e_ist415_power_on, +}; + +struct ist415_config_s g_rtl8730e_ist415_0 = { + .ops = &g_rtl8730e_ist415_ops, .priv = &g_rtl8730e_ist415_priv0, }; @@ -103,33 +99,41 @@ static void rtl8730e_ist415_irq_handler(uint32_t id, gpio_irq_event event) * until we finish this particular interrupt related work * in the HPWORK thread */ - struct ist415_dev_s *dev; + struct ist415_config_s *dev; if (id == 0) { - dev = &g_ist415_dev0; + dev = &g_rtl8730e_ist415_0; } - struct rtl8730e_ist415_s *priv = dev->priv; if (dev->handler != NULL) { dev->handler(dev); } } -static void rtl8730e_ist415_enable_irq(void) +static void rtl8730e_ist415_enable_irq(struct ist415_config_s *dev) { - gpio_irq_enable(&g_rtl8730e_ist415_priv0.data_ready); + struct rtl8730e_ist415_s *priv = (struct rtl8730e_ist415_s *)dev->priv; + gpio_irq_enable(&priv->data_ready); } -static void rtl8730e_ist415_disable_irq(void) +static void rtl8730e_ist415_disable_irq(struct ist415_config_s *dev) { - gpio_irq_disable(&g_rtl8730e_ist415_priv0.data_ready); + struct rtl8730e_ist415_s *priv = (struct rtl8730e_ist415_s *)dev->priv; + gpio_irq_disable(&priv->data_ready); } -static void rtl8730e_ist415_gpio_reset(void) +static void rtl8730e_ist415_power_off(struct ist415_config_s *dev) { + struct rtl8730e_ist415_s *priv = (struct rtl8730e_ist415_s *)dev->priv; + up_i2cuninitialize(priv->i2c); /* Workaround: IC20 write hang issue */ GPIO_WriteBit(IST415_GPIO_RESET_PIN, PIN_LOW); - DelayMs(300); +} + +static void rtl8730e_ist415_power_on(struct ist415_config_s *dev) +{ + struct rtl8730e_ist415_s *priv = (struct rtl8730e_ist415_s *)dev->priv; GPIO_WriteBit(IST415_GPIO_RESET_PIN, PIN_HIGH); DelayMs(1); /* Wait for stable voltage before i2c commands issued */ + priv->i2c = up_i2cinitialize(IST415_I2C_PORT); /* Workaround: IC20 write hang issue */ } static void rtl8730e_ist415_gpio_init(void) @@ -163,25 +167,25 @@ static void rtl8730e_ist415_gpio_init(void) ****************************************************************************/ void rtl8730e_ist415_initialize(void) { - FAR struct i2c_dev_s *i2c; + struct i2c_dev_s *i2c; + struct ist415_config_s *dev = &g_rtl8730e_ist415_0; + struct rtl8730e_ist415_s *priv = dev->priv; rtl8730e_ist415_gpio_init(); - rtl8730e_ist415_gpio_reset(); + i2c = up_i2cinitialize(IST415_I2C_PORT); if (!i2c) { touchdbg("ERROR: Failed to initialize I2C\n"); return; } - g_ist415_dev0.i2c = i2c; - gpio_irq_init(&g_rtl8730e_ist415_priv0.data_ready, IST415_GPIO_I2C_PIN, rtl8730e_ist415_irq_handler, (uint32_t)0); - gpio_irq_set(&g_rtl8730e_ist415_priv0.data_ready, IRQ_FALL_RISE, 1); - gpio_irq_enable(&g_rtl8730e_ist415_priv0.data_ready); + priv->i2c = i2c; /* Workaround: IC20 write hang issue */ - int ret= ist415_initialize(TOUCH_DEV_PATH, &g_ist415_dev0); + gpio_irq_init(&priv->data_ready, IST415_GPIO_I2C_PIN, rtl8730e_ist415_irq_handler, (uint32_t)0); + gpio_irq_set(&priv->data_ready, IRQ_FALL, 1); - if (ret < 0) { + if (ist415_initialize(TOUCH_DEV_PATH, i2c, dev) < 0) { touchdbg("ERROR: Touch driver register fail\n"); - return; + up_i2cuninitialize(i2c); } - touchvdbg("Touch driver register success\n"); + touchdbg("Touch driver register success\n"); } diff --git a/os/drivers/input/Make.defs b/os/drivers/input/Make.defs index 474148b7b7..eb1a974a62 100755 --- a/os/drivers/input/Make.defs +++ b/os/drivers/input/Make.defs @@ -19,6 +19,8 @@ ifeq ($(CONFIG_TOUCH),y) CSRCS += touchscreen.c ifeq ($(CONFIG_TOUCH_IST415),y) CSRCS += ist415.c +CSRCS += ist415_misc.c +CSRCS += ist415_update.c endif DEPPATH += --dep-path input diff --git a/os/drivers/input/ist415.c b/os/drivers/input/ist415.c old mode 100755 new mode 100644 index d4b89ab06d..06951a83c9 --- a/os/drivers/input/ist415.c +++ b/os/drivers/input/ist415.c @@ -39,32 +39,33 @@ * Included Files ****************************************************************************/ -#include #include #include #include +#include #include #include #include #include #include -#include -#include +#include + +#include #include #include +#include + #include #include -#if defined(CONFIG_TOUCH_CALLBACK) -#include -#endif +#include "ist415.h" +#include "ist415_misc.h" +#include "ist415_update.h" /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ -#define EVENT_PACKET_SIZE 16 - /**************************************************************************** * Private Types ****************************************************************************/ @@ -72,213 +73,794 @@ /**************************************************************************** * Private Function Prototypes ****************************************************************************/ - -static int ist415_read(struct touchscreen_s *dev, FAR char *buffer); -static void ist415_enable(struct touchscreen_s *dev); -static void ist415_disable(struct touchscreen_s *dev); -static bool ist415_istouchSet(struct touchscreen_s *dev); - -#if defined(CONFIG_TOUCH_CALLBACK) -static void get_touch_data(struct ist415_dev_s *priv); -#endif +static void ist415_enable_touch(struct touchscreen_s *upper); +static void ist415_disable_touch(struct touchscreen_s *upper); +static int ist415_read(struct touchscreen_s *upper, FAR char *buffer); +static int ist415_cmd(struct touchscreen_s *upper, int argc, char **argv); +static int ist415_get_touch_data(struct ist415_dev_s *dev, FAR void *buf); /**************************************************************************** * Private Data ****************************************************************************/ -struct touchscreen_ops_s g_ist415_ops = { - .touch_read = ist415_read, - .touch_enable = ist415_enable, - .touch_disable = ist415_disable, - .is_touchSet = ist415_istouchSet, +struct i2c_config_s g_ist415_i2c_config = { + .frequency = IST415_I2C_FREQ, + .address = IST415_I2C_ADDR, + .addrlen = IST415_I2C_ADDRLEN, }; -#if defined(CONFIG_TOUCH_CALLBACK) -static struct work_s ist415_work; -#endif +static const struct touchscreen_ops_s g_ist415_ops = { + ist415_read, /* read */ + ist415_enable_touch, /* enable */ + ist415_disable_touch, /* disable */ + ist415_cmd /* cmd */ +}; /**************************************************************************** * Private Functions ****************************************************************************/ +static void ist415_irq_handler_work(struct ist415_dev_s *dev) +{ + struct touch_sample_s data; + (void)ist415_get_touch_data(dev, &data); +} + +/**************************************************************************** + * Name: touch_interrupt + ****************************************************************************/ + +static void touch_interrupt(struct ist415_config_s *dev) +{ + struct ist415_dev_s *lower = (struct ist415_dev_s *)dev->upper; + struct touchscreen_s *upper = lower->upper; + if (upper && upper->notify_touch) { + upper->notify_touch(upper); + } else { + /* During initialization, we must receive IC ready and + * Calibration complete. */ + work_queue(HPWORK, &lower->work, (worker_t)ist415_irq_handler_work, (void *)lower, 0); + } +} + +/**************************************************************************** + * Name: ist415_read + ****************************************************************************/ + +static int ist415_read(struct touchscreen_s *upper, FAR char *buffer) +{ + struct ist415_dev_s *dev = (struct ist415_dev_s *)upper->priv; + ist415_run_intr_debug(dev); + return ist415_get_touch_data(dev, buffer); +} + +/**************************************************************************** + * Name: ist415_set_palm_state + ****************************************************************************/ + +static void ist415_set_palm_state(struct ist415_dev_s *dev, uint32_t id, uint8_t state) +{ + if (state == PALM_ON) { + dev->palm_state |= (1 << id); + } else { + dev->palm_state &= ~(1 << id); + } +} + +/**************************************************************************** + * Name: ist415_check_coord_palm + ****************************************************************************/ + +static void ist415_check_coord_palm(struct ist415_dev_s *dev, uint32_t id, uint8_t status, uint8_t type) +{ + if ((status == TOUCH_STA_PRESS || status == TOUCH_STA_MOVE) && (type == TOUCH_TYPE_PALMLARGE)) { + ist415_set_palm_state(dev, id, PALM_ON); + } else { + ist415_set_palm_state(dev, id, PALM_OFF); + } +} + +/**************************************************************************** + * Name: ist415_check_event_palm + ****************************************************************************/ + +static void ist415_check_event_palm(struct ist415_dev_s *dev, uint8_t sdata) +{ + if (sdata == 1) { + ist415_set_palm_state(dev, EVENT_PALM_ID, PALM_ON); + } else { + ist415_set_palm_state(dev, EVENT_PALM_ID, PALM_OFF); + } +} + /**************************************************************************** * Name: ist415_get_touch_data ****************************************************************************/ static int ist415_get_touch_data(struct ist415_dev_s *dev, FAR void *buf) { - struct i2c_dev_s *i2c = dev->i2c; - struct i2c_config_s config = dev->i2c_config; struct ts_event_coordinate *p_evt_coord; + struct ts_event_status *p_evt_status; + struct ts_event_gesture *p_evt_gesture; struct touch_sample_s *data = buf; - u8 event[EVENT_PACKET_SIZE]; - u8 touch_point; - u8 *touch_event; - u8 eid; - int reg[2] = {HCOM_GET_EVENT_1ST, 0}; - - int ret = i2c_write(i2c, &config, (uint8_t *)reg, 1); - if (ret != 1) { - touchdbg("ERROR: I2C write failed\n"); - return ret; - } - ret = i2c_read(i2c, &config, (uint8_t *)event, EVENT_PACKET_SIZE); - if (ret != EVENT_PACKET_SIZE) { - touchdbg("ERROR: I2C read failed\n"); + uint8_t event[EVENT_PACKET_SIZE]; + uint8_t left_e; + uint8_t *touch_event; + uint8_t eid; + uint8_t coord_type; + bool is_status_palmlarge = false; + int ret = 0; + ret = ist415_i2c_read(dev, HCOM_GET_EVENT_1ST, (uint8_t *) event, EVENT_PACKET_SIZE); + if (ret) { + touchdbg("Fail to read 1st evnet\n"); return ret; } - touch_point = event[7] & 0x1F; - touch_event = (u8 *)kmm_malloc((touch_point + 1) * EVENT_PACKET_SIZE); + + left_e = event[7] & 0x1F; + touch_event = (uint8_t *)kmm_malloc((left_e + 1) * EVENT_PACKET_SIZE); memcpy(touch_event, event, sizeof(event)); - if ((touch_point > 0) && (touch_point < 0x1F)) { - reg[0] = HCOM_GET_EVENT_ALL; - ret = i2c_write(i2c, &config, (uint8_t *)reg, 1); - if (ret != 1) { - touchdbg("ERROR: I2C write failed\n"); - return ret; - } - ret = i2c_read(i2c, &config, touch_event + EVENT_PACKET_SIZE, touch_point * EVENT_PACKET_SIZE); - if (ret != touch_point * EVENT_PACKET_SIZE) { - touchdbg("ERROR: I2C read failed\n"); + + if ((left_e > 0) && (left_e < 0x1F)) { + ist415_i2c_read(dev, HCOM_GET_EVENT_ALL, (uint8_t *)(touch_event + EVENT_PACKET_SIZE), left_e * EVENT_PACKET_SIZE); + if (ret) { + touchdbg("Fail to read left data\n"); return ret; } - } else if (touch_point >= 0x1F) { - touchdbg("ERROR:touch events bufer overflow\n"); + } else if (left_e >= 0x1F) { + touchdbg("Touch events buffer overflow\n"); return -EIO; } - touchvdbg("touch_point %d\n", touch_point + 1); - if (data == NULL) { - touchdbg("ERROR: application buffer touch data is NULL\n"); - return -EINVAL; + + for (int i = 0; i < (left_e + 1); i++) { + eid = (touch_event + (i * EVENT_PACKET_SIZE))[0] & 0x3; + if (eid == EID_COORD) { + p_evt_coord = (struct ts_event_coordinate *)(touch_event + (i * EVENT_PACKET_SIZE)); + coord_type = (p_evt_coord->ttype_3_2 << 2) | p_evt_coord->ttype_1_0; + ist415_check_coord_palm(dev, p_evt_coord->tid - 1, p_evt_coord->tsta, coord_type); + } } - data->npoints = touch_point + 1; - for (int i = 0; i < (touch_point + 1); i++) { + + data->npoints = 0; + ret = -EAGAIN; + for (int i = 0; i < (left_e + 1); i++) { eid = (touch_event + (i * EVENT_PACKET_SIZE))[0] & 0x3; if (eid == EID_COORD) { + if (dev->pre_palm_state || dev->palm_state) { + continue; + } + p_evt_coord = (struct ts_event_coordinate *)(touch_event + (i * EVENT_PACKET_SIZE)); - data->point[i].id = p_evt_coord->tid - 1; - data->point[i].x = (p_evt_coord->x_11_4 << 4) | p_evt_coord->x_3_0; - data->point[i].y = (p_evt_coord->y_11_4 << 4) | p_evt_coord->y_3_0; - data->point[i].h = 0; - data->point[i].w = 0; - data->point[i].pressure = 0; - switch (p_evt_coord->tsta) { - case 1: - data->point[i].flags = TOUCH_DOWN; + if (p_evt_coord->tsta != TOUCH_STA_NONE) { + data->point[data->npoints].id = p_evt_coord->tid - 1; + data->point[data->npoints].x = (p_evt_coord->x_11_4 << 4) | p_evt_coord->x_3_0; + data->point[data->npoints].y = (p_evt_coord->y_11_4 << 4) | p_evt_coord->y_3_0; + data->point[data->npoints].h = p_evt_coord->major; + data->point[data->npoints].w = p_evt_coord->minor; + data->point[data->npoints].pressure = p_evt_coord->z; + switch (p_evt_coord->tsta) { + case TOUCH_STA_PRESS: + data->point[data->npoints].flags = TOUCH_DOWN; + touchvdbg("COORDDINATES: [P] Point ID=%2d, X=%4d, Y=%4d\n", data->point[data->npoints].id, data->point[data->npoints].x, data->point[data->npoints].y); + break; + case TOUCH_STA_MOVE: + data->point[data->npoints].flags = TOUCH_MOVE; + touchvdbg("COORDDINATES: [M] Point ID=%2d, X=%4d, Y=%4d\n", data->point[data->npoints].id, data->point[data->npoints].x, data->point[data->npoints].y); + break; + case TOUCH_STA_RELEASE: + data->point[data->npoints].flags = TOUCH_UP; + touchvdbg("COORDDINATES: [R] Point ID=%2d, X=%4d, Y=%4d\n", data->point[data->npoints].id, data->point[data->npoints].x, data->point[data->npoints].y); + break; + default: + break; + } + + data->npoints++; + } else { + touchwdbg("COORDDINATES: Not Support Coord status (%d)", p_evt_coord->tsta); + } + } else if (eid == EID_STATUS) { + p_evt_status = (struct ts_event_status *)(touch_event + (i * EVENT_PACKET_SIZE)); + switch (p_evt_status->stype) { + case STS_TYPE_CMD_DRIVEN: + if (p_evt_status->sid == DRIVEN_CALIBRATION) { + dev->calib_result = p_evt_status->sdata[0]; + touchvdbg("Calibration Trigger~ (0x%02X)\n", dev->calib_result); + } + break; + case STS_TYPE_INFO_REPORT: + if (p_evt_status->sid == INFO_TSP_READY) { + dev->ready = true; + touchvdbg("TSC Ready~\n"); + } + break; + case STS_TYPE_EVENT: + if (p_evt_status->sid == EVENT_PALMLARGE) { + is_status_palmlarge = true; + ist415_check_event_palm(dev, p_evt_status->sdata[0]); + } break; - case 2: - data->point[i].flags = TOUCH_MOVE; + case STS_TYPE_VENDOR_INFO: + if (p_evt_status->sid == VENDOR_SELFTEST) { + dev->cmcs = p_evt_status->sdata[0]; + dev->cmcs_msg = p_evt_status->sdata[1]; + dev->cmcs_min = (((uint16_t) p_evt_status->sdata[2] & 0xF) << 8) | (uint16_t) p_evt_status->sdata[3]; + dev->cmcs_max = (((uint16_t) p_evt_status->sdata[2] & 0xF0) << 4) | (uint16_t) p_evt_status->sdata[4]; + touchvdbg("SelfTest Trigger~ (0x%02X, 0x%02X)\n", dev->cmcs, dev->cmcs_msg); + } else if (p_evt_status->sid == VENDOR_REC_REPORT) { + dev->rec_idle = true; + } break; - case 3: - data->point[i].flags = TOUCH_UP; + default: + touchwdbg("Not support status type: %d\n", p_evt_status->stype); break; } - touchvdbg("COORDINATES: id %d status %d type %d x : %d y : %d\n", data->point[i].id, p_evt_coord->tsta, (p_evt_coord->ttype_3_2 << 2) | p_evt_coord->ttype_1_0, data->point[i].x, data->point[i].y); + } else if (eid == EID_GESTURE) { + p_evt_gesture = (struct ts_event_gesture *)(touch_event + (i * EVENT_PACKET_SIZE)); + if (p_evt_gesture->gtype == GESTURE_TYPE_DOUBLETAP) { + if (p_evt_gesture->gid == GESTURE_DOUBLETAP_WAKEUP) { + uint16_t x = ((uint16_t) p_evt_gesture->gdata[1] << 8) | (uint16_t) p_evt_gesture->gdata[0]; + uint16_t y = ((uint16_t) p_evt_gesture->gdata[3] << 8) | (uint16_t) p_evt_gesture->gdata[2]; + touchvdbg("Double Tap Wakeup~(%d, %d)\n", x, y); + // TODO: KnockKnock Event Process~ + } + } else { + touchwdbg("Not support gesture type:%d\n", p_evt_gesture->gtype); + } + } else { + touchwdbg("Not supprot EID: %d\n", eid); + } + + if (eid == EID_COORD) { + if ((dev->pre_palm_state == 0) && dev->palm_state) { + /* + * TODO: PalmLarge On + * 1. All Touch Release + * 2. PalmLarge On Process + */ + touchvdbg("PalmLarge On (T)\n"); + } else if (dev->pre_palm_state && (dev->palm_state == 0)) { + // TODO: PalmLarge Off Process + touchvdbg("PalmLarge Off (T)\n"); + } + } else if ((eid == EID_STATUS) && is_status_palmlarge) { + if (dev->palm_state == 0) { + // TODO: PalmLarge Off Process + touchvdbg("PalmLarge Off (S)\n"); + } else { + /* + * TODO: PalmLarge On + * 1. All Touch Release + * 2. PalmLarge On Process + */ + touchvdbg("PalmLarge On (S)\n"); + } } + + dev->pre_palm_state = dev->palm_state ? 1 : 0; } - return OK; + + kmm_free(touch_event); + + if (data->npoints > 0) { + ret = OK; + } + return ret; } /**************************************************************************** - * Name: ist415_enable + * Name: ist415_cmd_show_usage ****************************************************************************/ -static void ist415_enable(struct touchscreen_s *dev) +static void ist415_cmd_show_usage(void) { - struct ist415_dev_s *priv = (struct ist415_dev_s *)dev->priv; - priv->ops->irq_enable(); + printf("\n\nusage touchscreen \n\n"); + printf("The ist415 touchscreen IC specific test command: \n"); + printf("\n"); + printf(" clb : Auto Calibration\n"); + printf(" raw : Display Raw Data\n"); + printf(" cpc : Display CPC\n"); + printf(" update : Update binary\n"); + printf(" intrdbg : Set Intr Debug\n"); } /**************************************************************************** - * Name: ist415_disable + * Name: ist415_cmd + ****************************************************************************/ + +static int ist415_cmd(struct touchscreen_s *upper, int argc, char **argv) +{ + struct ist415_dev_s *dev = (struct ist415_dev_s *)upper->priv; + int ret = OK; + if (argc < 2 || !strcmp(argv[1], "-h") ||!strcmp(argv[1], "--help")) { + ist415_cmd_show_usage(); + return -EINVAL; + } + + if (strncmp(argv[1], "clb", 4) == 0) { + ist415_autocalibration(dev); + } else if (strncmp(argv[1], "raw", 4) == 0) { + ist415_display_rawdata(dev); + } else if (strncmp(argv[1], "cpc", 4) == 0) { + ist415_display_cpc(dev); + } else if (strncmp(argv[1], "intdbg", 7) == 0) { + ret = ist415_set_intr_debug(dev, argc, argv); + } else if (strncmp(argv[1], "update", 7) == 0) { + ret = ist415_force_update(dev, argc, argv); + } else { + ret = -EINVAL; + } + + if (ret == -EINVAL) { + ist415_cmd_show_usage(); + } + return ret; +} + + +/**************************************************************************** + * Name: ist415_power_on ****************************************************************************/ -static void ist415_disable(struct touchscreen_s *dev) +static void ist415_power_on(struct ist415_dev_s *dev, bool download) { - struct ist415_dev_s *priv = (struct ist415_dev_s *)dev->priv; - priv->ops->irq_disable(); + struct ist415_config_s *lower = dev->lower; + int ready_wait = 50; + + /* + * TODO: Touch Power On Sequence + * 1. 3.3v On + * 2. If download is true, a delay of 10ms is given. + * Otherwise, a delay of 15ms is given. + * 3. Wait ready event + */ + + touchvdbg("%s\n", __func__); + + dev->ready = false; + if (lower->ops && lower->ops->power_on) { + lower->ops->power_on(lower); + } + + if (download) { + msleep(10); + } else { + msleep(1); + ist415_enable(dev); + + while ((!dev->ready) && (ready_wait-- > 0)) { + msleep(1); + } + + if (!dev->pre_enable) { + ist415_disable(dev); + } + } + + dev->ready = true; } /**************************************************************************** - * Name: is_touchSet + * Name: ist415_power_off ****************************************************************************/ -static bool ist415_istouchSet(struct touchscreen_s *dev) +static void ist415_power_off(struct ist415_dev_s *dev) { - struct ist415_dev_s *priv = (struct ist415_dev_s *)dev->priv; - return priv->int_pending; + struct ist415_config_s *lower = dev->lower; + + touchvdbg("%s\n", __func__); + + DEBUGASSERT(dev) + + dev->pre_enable = dev->enable; + + if (dev->enable) { + ist415_disable(dev); + } + + if (lower->ops && lower->ops->power_off) { + lower->ops->power_off(lower); + } } /**************************************************************************** - * Name: ist415_read + * Name: ist415_stop_device + ****************************************************************************/ + +static void ist415_stop_device(struct ist415_dev_s *dev) +{ + touchvdbg("%s\n", __func__); + + if (dev->knockknock) { + if (dev->sys_mode != SYS_MODE_LPM) { + ist415_disable(dev); + dev->sys_mode = SYS_MODE_LPM; + ist415_power_mode(dev, dev->sys_mode); + ist415_enable(dev); + } + } else { + ist415_disable(dev); + ist415_power_off(dev); + } +} + +/**************************************************************************** + * Name: ist415_start_device ****************************************************************************/ -static int ist415_read(struct touchscreen_s *dev, FAR char *buffer) +static void ist415_start_device(struct ist415_dev_s *dev) { - irqstate_t flags; - struct ist415_dev_s *priv = (struct ist415_dev_s *)dev->priv; - if (priv->int_pending) { - flags = enter_critical_section(); - priv->int_pending = false; - leave_critical_section(flags); - return ist415_get_touch_data(priv, buffer); + touchvdbg("%s\n", __func__); + + if (dev->knockknock) { + if (dev->sys_mode != SYS_MODE_TOUCH) { + dev->sys_mode = SYS_MODE_TOUCH; + ist415_power_mode(dev, dev->sys_mode); + } } else { - touchvdbg("No data to read\n"); + ist415_reset(dev, false); + ist415_enable(dev); + ist415_start(dev); } +} + +/**************************************************************************** + * Name: ist415_disable_touch + ****************************************************************************/ + +static void ist415_disable_touch(struct touchscreen_s *upper) +{ + touchvdbg("%s\n", __func__); + ist415_disable(upper->priv); +} + +/**************************************************************************** + * Name: ist415_enable_touch + ****************************************************************************/ + +static void ist415_enable_touch(struct touchscreen_s *upper) +{ + touchvdbg("%s\n", __func__); + ist415_enable(upper->priv); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: put_unaligned_be32 + ****************************************************************************/ + +void put_unaligned_be32(uint32_t value, void *addr) +{ + uint8_t *p = (uint8_t *) addr; + + p[0] = (value >> 24) & 0xFF; // Most significant byte + p[1] = (value >> 16) & 0xFF; + p[2] = (value >> 8) & 0xFF; + p[3] = value & 0xFF; // Least significant byte +} + +/**************************************************************************** + * Name: cpu_to_be32 + ****************************************************************************/ + +uint32_t cpu_to_be32(uint32_t value) +{ + return ((value & 0xFF000000) >> 24) | // Move byte 3 to byte 0 + ((value & 0x00FF0000) >> 8) | // Move byte 2 to byte 1 + ((value & 0x0000FF00) << 8) | // Move byte 1 to byte 2 + ((value & 0x000000FF) << 24); // Move byte 0 to byte 3 +} + +/**************************************************************************** + * Name: ist415_i2c_read + ****************************************************************************/ + +int ist415_i2c_read(struct ist415_dev_s *dev, uint8_t cmd, uint8_t *data, int size) +{ + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + int wsize = sizeof(cmd); + int ret = 0; + + if (size <= 0) { + touchdbg("Check read size (%d)\n", size); + return -EINVAL; + } + + ret = i2c_write(i2c, config, (uint8_t *)&cmd, wsize); + if (ret != wsize) { + touchdbg("Fail to read i2c\n"); + return ret; + } + + ret = i2c_read(i2c, config, (uint8_t *) data, size); + if (ret != size) { + touchdbg("Fail to read i2c\n"); + return ret; + } + return OK; } /**************************************************************************** - * Name: touch_interrupt + * Name: ist415_i2c_write ****************************************************************************/ -#if defined(CONFIG_TOUCH_POLL) -static void touch_interrupt(struct ist415_dev_s *priv) +int ist415_i2c_write(struct ist415_dev_s *dev, uint8_t cmd, uint8_t *data, int size) { + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + int wsize = sizeof(cmd) + size; + uint8_t *buf; + int ret = 0; - FAR struct touchscreen_s *upper = priv->upper; - irqstate_t state = enter_critical_section(); - priv->int_pending = true; - leave_critical_section(state); - if (upper->notify_touch) { - upper->notify_touch(upper); + buf = (uint8_t *)kmm_malloc(wsize); + + buf[0] = cmd; + if (size > 0) { + memcpy(buf + sizeof(cmd), data, size); + } + + ret = i2c_write(i2c, config, (uint8_t *) buf, wsize); + if (ret != wsize) { + kmm_free(buf); + touchdbg("Fail to write i2c\n"); + return ret; } + + kmm_free(buf); + + return OK; } -#elif defined(CONFIG_TOUCH_CALLBACK) +/**************************************************************************** + * Name: ist415_i2c_read_da + ****************************************************************************/ -static void touch_interrupt(struct ist415_dev_s *priv) +int ist415_i2c_read_da(struct ist415_dev_s *dev, uint32_t addr, uint32_t *data, int size) { - FAR struct touchscreen_s *upper = priv->upper; - priv->ops->irq_enable(); - work_queue(HPWORK, &ist415_work, get_touch_data, priv, 0); + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + uint8_t cmd = HCOM_SW_DA; + int wsize = sizeof(cmd) + sizeof(addr); + int rsize = size * sizeof(uint32_t); + uint8_t *buf = NULL; + uint32_t *buf32 = NULL; + int ret = 0; + + if (size <= 0) { + touchdbg("Check read da size (%d)\n", size); + return -EINVAL; + } + + buf = (uint8_t *)kmm_malloc(wsize); + buf32 = (uint32_t *)kmm_malloc(rsize); + + buf[0] = cmd; + put_unaligned_be32(addr, buf + sizeof(cmd)); + + ret = i2c_write(i2c, config, (uint8_t *) buf, wsize); + if (ret != wsize) { + touchdbg("Fail to read DA\n"); + kmm_free(buf); + kmm_free(buf32); + return ret; + } + + ret = i2c_read(i2c, config, (uint8_t *) buf32, rsize); + if (ret != rsize) { + touchdbg("Fail to read DA\n"); + kmm_free(buf); + kmm_free(buf32); + return ret; + } + + for (int i = 0; i < size; i++) { + data[i] = cpu_to_be32(buf32[i]); + } + + kmm_free(buf); + kmm_free(buf32); + + return OK; } -static void get_touch_data(struct ist415_dev_s *priv) +/**************************************************************************** + * Name: ist415_i2c_write_da + ****************************************************************************/ + +int ist415_i2c_write_da(struct ist415_dev_s *dev, uint32_t addr, uint32_t *data, int size) { - FAR struct touchscreen_s *upper = priv->upper; + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + uint8_t cmd = HCOM_SW_DA; + int hsize = sizeof(cmd) + sizeof(addr); + int wsize = hsize + (size * sizeof(uint32_t)); + uint8_t *buf = NULL; + int ret = 0; + + if (size <= 0) { + touchdbg("Check write da size (%d)\n", size); + return -EINVAL; + } - struct touch_sample_s touch_points; + buf = (uint8_t *)kmm_malloc(wsize); - if (!upper->app_touch_point_buffer) { - touchdbg("ERROR: application buffer touch data is NULL\n"); - if (upper->is_touch_detected) { - upper->is_touch_detected(-EINVAL); - return; - } + buf[0] = cmd; + put_unaligned_be32(addr, buf + sizeof(cmd)); + for (int i = 0; i < size; i++) { + put_unaligned_be32(data[i], buf + (i * sizeof(uint32_t)) + hsize); + } + + ret = i2c_write(i2c, config, (uint8_t *) buf, wsize); + if (ret != wsize) { + kmm_free(buf); + touchdbg("Fail to write DA\n"); + return ret; } - int ret = ist415_get_touch_data(priv, upper->app_touch_point_buffer); - if (upper->is_touch_detected) { - upper->is_touch_detected(ret); + kmm_free(buf); + + return OK; +} + +/**************************************************************************** + * Name: ist415_enable + ****************************************************************************/ + +void ist415_enable(struct ist415_dev_s *dev) +{ + struct ist415_config_s *lower = dev->lower; + + if (dev->enable == true) { + return; } + + touchvdbg("%s\n", __func__); + + dev->enable = true; + + lower->ops->irq_enable(lower); } -#endif +/**************************************************************************** + * Name: ist415_disable + ****************************************************************************/ + +void ist415_disable(struct ist415_dev_s *dev) +{ + struct ist415_config_s *lower = dev->lower; + + if (dev->enable == false) { + return; + } + + touchvdbg("%s\n", __func__); + + dev->enable = false; + + lower->ops->irq_disable(lower); +} /**************************************************************************** - * Public Functions + * Name: ist415_reset ****************************************************************************/ +void ist415_reset(struct ist415_dev_s *dev, bool download) +{ + touchvdbg("%s\n", __func__); + + ist415_power_off(dev); + msleep(100); + ist415_power_on(dev, download); +} + +/**************************************************************************** + * Name: ist415_sensor + ****************************************************************************/ + +void ist415_sensor(struct ist415_dev_s *dev, bool on) +{ + uint8_t cmd = 0; + int ret = 0; + + if (on) { + cmd = HCOM_SENSE_ON; + } else { + cmd = HCOM_SENSE_OFF; + } + + ret = ist415_i2c_write(dev, cmd, NULL, 0); + if (ret) { + touchdbg("Fail to write sense on/off command\n"); + } + + touchvdbg("%s %s\n", __func__, on ? "on" : "off"); + + msleep(50); +} + +/**************************************************************************** + * Name: ist415_power_mode + ****************************************************************************/ + +void ist415_power_mode(struct ist415_dev_s *dev, uint8_t data) +{ + int ret = 0; + + ret = ist415_i2c_write(dev, HCOM_CTRL_POWER_MODE, (uint8_t *)&data, 1); + if (ret) { + touchdbg("Fail to write power mode command\n"); + } +} + +/**************************************************************************** + * Name: ist415_touchtype + ****************************************************************************/ + +void ist415_touchtype(struct ist415_dev_s *dev, uint8_t *data) +{ + int ret = 0; + + ret = ist415_i2c_write(dev, HCOM_CTRL_TOUCH_TYPE, (uint8_t *) data, 2); + if (ret) { + touchdbg("Fail to write touchtype command\n"); + } +} + +/**************************************************************************** + * Name: ist415_fw_integrity + ****************************************************************************/ + +uint8_t ist415_fw_integrity(struct ist415_dev_s *dev) +{ + uint8_t integrity = 0; + int ret = 0; + + ret = ist415_i2c_read(dev, HCOM_GET_FW_INTEGRITY, (uint8_t *)&integrity, 1); + + touchvdbg("firmware integrity : 0x%02X (%d)\n", integrity, ret); + + return (ret < 0) ? 0xFF : integrity; +} + +/**************************************************************************** + * Name: ist415_start + ****************************************************************************/ + +void ist415_start(struct ist415_dev_s *dev) +{ + uint8_t mode; + int ret = 0; + + if (dev->rec_mode) { + mode = REC_ENABLE; + ret = ist415_i2c_write(dev, HCOM_SET_REC_MODE, &mode, 1); + if (ret) { + touchdbg("Fail to write Recording mode command (Enable)\n"); + } else { + touchvdbg("Recording mode start\n"); + } + } + + ist415_touchtype(dev, (uint8_t *)&dev->touch_type); + ist415_power_mode(dev, dev->sys_mode); + ist415_sensor(dev, true); + + if (dev->rec_mode) { + msleep(100); + mode = REC_START_SCAN; + ret = ist415_i2c_write(dev, HCOM_SET_REC_MODE, &mode, 1); + if (ret) { + touchdbg("Fail to write Recording mode command (Start scan)\n"); + } + } + + touchvdbg("%s\n", __func__); +} + + /**************************************************************************** * Name: ist415_touchinitialize * @@ -297,28 +879,78 @@ static void get_touch_data(struct ist415_dev_s *priv) * ****************************************************************************/ -int ist415_initialize(const char*path, struct ist415_dev_s *priv) +int ist415_initialize(const char *path, struct i2c_dev_s *i2c, struct ist415_config_s *lower) { - int ret = 0; - uint8_t reg[1]; - priv->ops->irq_disable(); + int ret; + struct touchscreen_s *upper; + struct ist415_dev_s *dev; + + dev = (struct ist415_dev_s*)kmm_zalloc(sizeof(struct ist415_dev_s)); + if (!dev) { + touchdbg("Fail to alloc ist415_dev_s\n"); + return ERROR; + } + dev->i2c = i2c; + dev->i2c_config = &g_ist415_i2c_config; + dev->lower = lower; + lower->upper = dev; + + dev->ready = false; + dev->enable = false; + dev->pre_enable = false; + + dev->sys_mode = SYS_MODE_TOUCH; + dev->touch_type = (1 << TOUCH_TYPE_NORMAL) | (1 << TOUCH_TYPE_WET) | (1 << TOUCH_TYPE_PALMLARGE); + dev->knockknock = false; + + dev->pre_palm_state = 0; + dev->palm_state = 0; + + dev->rec_mode = 0; + dev->rec_addr = 0; + dev->rec_size = 0; + dev->cmcs = 0; + + dev->intr_debug_addr = 0; + dev->intr_debug_size = 0; + + ist415_disable(dev); - reg[0] = 0x23; - ret = i2c_write(priv->i2c, &(priv->i2c_config), (uint8_t *)reg, 1); - if (ret < OK) { - touchdbg("ERROR: i2c_write failed\n"); - return NULL; + dev->lower->handler = touch_interrupt; + + /* Init System Power */ + ist415_reset(dev, false); + + // check to need firmwar update + ret = ist415_check_fw((void *)dev); + if (ret) { + touchdbg("Fail to check firmware\n"); + } + + // get to touch info + ret = ist415_get_info((void *)dev); + if (ret) { + touchdbg("Fail to get info\n"); + kmm_free(dev); + return ret; + } else { + touchvdbg("Get info success\n"); + } + + ist415_start(dev); + // ist415_enable(dev); + + upper = (struct touchscreen_s *)kmm_zalloc(sizeof(struct touchscreen_s)); + if (!upper) { + touchdbg("Fail to alloc touchscreen_s\n"); + kmm_free(dev); + ist415_disable(dev); + return ERROR; } - struct touchscreen_s *upper = (struct touchscreen_s *)kmm_zalloc(sizeof(struct touchscreen_s)); upper->ops = &g_ist415_ops; - upper->priv = priv; -#if defined(CONFIG_TOUCH_CALLBACK) - upper->is_touch_detected = NULL; /* Callback function will be set by UI */ - upper->app_touch_point_buffer = NULL; /* Buffer to store touch point data, set by UI */ -#endif - priv->upper = upper; - priv->handler = touch_interrupt; - - touchvdbg("Touch Driver registered Successfully\n"); + upper->priv = dev; + dev->upper = upper; + + touchdbg("Touch Driver registered Successfully\n"); return touch_register(path, upper); } diff --git a/os/drivers/input/ist415.h b/os/drivers/input/ist415.h new file mode 100644 index 0000000000..b946a15d67 --- /dev/null +++ b/os/drivers/input/ist415.h @@ -0,0 +1,457 @@ +/**************************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/input/ist415.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ +#ifndef __DRIVERS_INPUT_IST415_H +#define __DRIVERS_INPUT_IST415_H + +#include +#include + +#define IST415_I2C_FREQ 100000 +#define IST415_I2C_ADDRLEN 7 +#define IST415_I2C_ADDR (0xA0 >> 1) + +#define IST415_MAX_TOUCH_DATA 30 + +////////////////////////////////////////////////////////////// +// Elementary Definitions & Variable +////////////////////////////////////////////////////////////// +#define MAX_MTL_NODE 720 +#define MAX_SLF_NODE 58 + +//////////////////////////////////////////////////////////////// +// SEC Command +// System (Write) +#define HCOM_SENSE_ON 0x10 // FwHold = 0 +#define HCOM_SENSE_OFF 0x11 // FwHold = 1 +#define HCOM_SW_RESET 0x12 +#define HCOM_CALIBRATION 0x13 +#define HCOM_MISCALIBRATION 0x14 +#define HCOM_MISCALIBRATION2 0x15 + +// Info (Read) +#define HCOM_GET_GPIO_STS 0x20 +#define HCOM_GET_FW_INTEGRITY 0x21 +#define HCOM_GET_DEV_ID 0x22 +#define HCOM_GET_PANEL_INFO 0x23 +#define HCOM_GET_FW_VER 0x24 +#define HCOM_GET_MAX_DCM 0x25 + +// Control (Read/Write) +#define HCOM_CTRL_TOUCH_TYPE 0x30 +#define HCOM_CTRL_POWER_MODE 0x31 +#define HCOM_CTRL_CHARGER_MODE 0x32 +#define HCOM_CTRL_NOISE_MODE 0x33 +#define HCOM_CTRL_REPORT_RATE 0x34 +#define HCOM_CTRL_MODE_FOR_TH 0x35 +#define HCOM_CTRL_TOUCH_TH 0x36 +#define HCOM_CTRL_KEY_TH 0x37 +#define HCOM_CTRL_COVER_TYPE 0x38 +#define HCOM_CTRL_WAKEUP_GESTURE 0x39 +#define HCOM_CTRL_COORDINATE_FILTER 0x3A +#define HCOM_CTRL_WET_MODE 0x3B +#define HCOM_CTRL_JIG_MODE 0x3C +#define HCOM_CTRL_NUM_OF_DOT_TOUCH 0x3D +#define HCOM_CTRL_EDGE_DEADZONE 0x3E +#define HCOM_CTRL_TOUCHABLE_AREA 0x3F +#define HCOM_CTRL_SENSITIVITY 0x40 + +// Event +#define HCOM_GET_EVENT_1ST 0x60 +#define HCOM_GET_EVENT_ALL 0x61 +#define HCOM_CLEAR_EVENT_ALL 0x62 + +// Panel Test +#define HCOM_SET_MTL_DATA_TYPE 0x70 +#define HCOM_SET_SLF_DATA_TYPE 0x71 +#define HCOM_GET_MTL_DATA 0x72 +#define HCOM_GET_SLF_DATA 0x73 +#define HCOM_SET_PROX_DATA_TYPE 0x74 +#define HCOM_GET_PROX_DATA 0x75 + +// Vendor +#define HCOM_DA_R 0x80 // DA // Don't Use +#define HCOM_DA_W 0x8F // DA // Don't Use +#define HCOM_ISP 0xAE // ISP // Don't Use + +#define HCOM_GET_CRC 0x82 +#define HCOM_GET_CAL_RESULT 0x83 +#define HCOM_GET_PROXIMITY_TH 0x84 +#define HCOM_GET_PROXIMITY_SENSITIVITY 0x85 +#define HCOM_GET_BASELINE_TH 0x86 +#define HCOM_GET_VER_MAIN 0x87 +#define HCOM_GET_VER_TEST 0x88 + +#define HCOM_GET_JITTER_GAP_SPEC 0x90 +#define HCOM_GET_CM_SPEC 0x91 +#define HCOM_GET_CS_SPEC 0x92 +#define HCOM_GET_CR_SPEC 0x93 +#define HCOM_GET_BASELINE 0x94 +#define HCOM_GET_SWAP_INFO 0x95 +#define HCOM_GET_ALGO_INFO 0x96 +#define HCOM_GET_ALGO_STATUS 0x97 +#define HCOM_GET_SEC_INFO_BASE 0x98 +#define HCOM_GET_COPY_SEC_INFO_BASE 0x99 +#define HCOM_GET_CUR_SCAN_FB 0x9A +#define HCOM_GET_SP_REG_BASE 0x9B +#define HCOM_GET_MISCAL_BASE 0x9C +#define HCOM_GET_SELFTEST_BASE 0x9D +#define HCOM_GET_REC_INFO 0x9E + +#define HCOM_WRITE_SEC_INFO 0xA1 +#define HCOM_SET_SP_REG_IDX 0xA2 +#define HCOM_SET_SP_REG_DATA 0xA3 +#define HCOM_SET_SP_NOTIFY_PACKET 0xA4 +#define HCOM_SET_AOD_RECT 0xA5 +#define HCOM_SET_FOD_RECT 0xA6 +#define HCOM_SET_UTC 0xA7 + +#define HCOM_RUN_SELFTEST 0xB0 +#define HCOM_SET_GRIP_DATA 0xB1 +#define HCOM_SET_POCKET_MODE 0xB2 +#define HCOM_SET_CALL_MODE 0xB3 +#define HCOM_SET_HALF_AOD_MODE 0xB4 + +#define HCOM_GET_SELFTEST_DATA 0xC0 +#define HCOM_GET_SELFTEST_RES 0xC1 +#define HCOM_GET_TOUCH_EN 0xC2 +#define HCOM_GET_WET_STATUS 0xC3 +#define HCOM_GET_FOD_INFO 0xC4 +#define HCOM_GET_FOD_POS 0xC5 + +#define HCOM_SET_REC_MODE 0xF0 +#define HCOM_SET_REG 0xF1 +#define HCOM_GENERATE_INT 0xF2 + +#define HCOM_SW_DA 0xFE + +// Event +#define EVENT_PACKET_SIZE 16 +#define LEFT_NUM_MASK 0x3F + +// EventId (stEventCoord_t) +#define EID_MASK 0x3 +#define EID_COORD 0 +#define EID_STATUS 1 +#define EID_GESTURE 2 + +// TouchStatus +#define TOUCH_STA_NONE 0 +#define TOUCH_STA_PRESS 1 +#define TOUCH_STA_MOVE 2 +#define TOUCH_STA_RELEASE 3 + +// TouchType +#define TOUCH_TYPE_NORMAL 0 +#define TOUCH_TYPE_HOVER 1 +#define TOUCH_TYPE_COVER 2 +#define TOUCH_TYPE_GLOVE 3 +#define TOUCH_TYPE_STYLUS 4 +#define TOUCH_TYPE_PALM 5 +#define TOUCH_TYPE_WET 6 +#define TOUCH_TYPE_PROXIMITY 7 +#define TOUCH_TYPE_JIG 8 +#define TOUCH_TYPE_PALMLARGE 9 + +// StatusType +#define STS_TYPE_CMD_DRIVEN 0 +#define STS_TYPE_ERR_REPORT 1 +#define STS_TYPE_INFO_REPORT 2 +#define STS_TYPE_USER_INPUT 3 +#define STS_TYPE_EVENT 6 +#define STS_TYPE_VENDOR_INFO 7 + +// StatusId +#define DRIVEN_CALIBRATION 0 +#define INFO_TSP_READY 0 +#define EVENT_PALMLARGE 2 +#define VENDOR_SELFTEST 0 +#define VENDOR_REC_REPORT 1 +#define ERROR_CORE 0 +#define ERROR_QUEUE_OVERFLOW 1 +#define ERROR_ESD 2 + +// aStatusData +#define STS_DATA_FW_INTEGRITY_PASS 0x80 +#define STS_DATA_FW_INTEGRITY_FAIL 0x40 +#define STS_DATA_CAL_PASS 0x10 +#define STS_DATA_CAL_FAIL 0x80 +#define STS_DATA_CMCS_PASS 0x10 +#define STS_DATA_CMCS_FAIL 0x80 +#define STS_DATA_CMCS_CM 0x00 +#define STS_DATA_CMCS_CMJIT 0x02 + +// GestureType +#define GESTURE_TYPE_SWIPE 0 +#define GESTURE_TYPE_DOUBLETAP 1 +#define GESTURE_TYPE_PRESSURE 2 +#define GESTURE_TYPE_PRESS 3 +#define GESTURE_TYPE_SINGLETAP 4 + +// GestureID +#define GESTURE_SWIPE_UP 0 +#define GESTURE_DOUBLETAP_WAKEUP 1 +#define GESTURE_SINGLETAP 0 + +// Palm +#define EVENT_PALM_ID 31 +#define PALM_ON 1 +#define PALM_OFF 0 + +#define IST415_WAIT_TIME 50 // unit : 100ms +#define IST415_RETRY_CNT 3 + +#define TSP_INFO_SWAP_XY (1 << 0) + +struct ts_event_coordinate { + uint8_t eid: 2; + uint8_t tid: 4; + uint8_t tsta: 2; + + uint8_t x_11_4; + uint8_t y_11_4; + + uint8_t y_3_0: 4; + uint8_t x_3_0: 4; + + uint8_t major; + uint8_t minor; + + uint8_t z: 6; + uint8_t ttype_3_2: 2; + + uint8_t left_e: 5; + uint8_t max_e: 1; + uint8_t ttype_1_0: 2; + + uint8_t noise_lv; + uint8_t max_str; + + uint8_t hover_id_num: 4; + uint8_t noise_sta: 2; + uint8_t eom: 1; + uint8_t reserved: 1; + + uint8_t reserved0; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t reserved4; +}; + +struct ts_event_status { + uint8_t eid: 2; + uint8_t stype: 4; + uint8_t sf: 2; + + uint8_t sid; + + uint8_t sdata[5]; + + uint8_t left_e: 5; + uint8_t reserved: 3; + + uint8_t reserved0; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t reserved4; + uint8_t reserved5; + uint8_t reserved6; + uint8_t reserved7; +}; + +struct ts_event_gesture { + uint8_t eid: 2; + uint8_t gtype: 4; + uint8_t sf: 2; + + uint8_t gid; + + uint8_t gdata[4]; + + uint8_t reserved0; + + uint8_t left_e: 6; + uint8_t reserved1: 2; +}; + +typedef enum { + SYS_MODE_TOUCH = 0, + SYS_MODE_LPM, +} touch_system_mode; + +/**************************************************************************** + * Private Types + ****************************************************************************/ +// fw +#define FW_INTEGRITY_VALID 0x80 +#define FW_INTEGRITY_INVALID 0x40 + +#define IST415_TAG_MAGIC "ISTV4TAG" +struct ist415_tags { + char magic1[8]; + + uint32_t rom_base; + uint32_t ram_base; + uint32_t algo_base; + uint32_t reserved1; + + uint32_t fw_addr; + uint32_t fw_size; + uint32_t cfg_addr; + uint32_t cfg_size; + uint32_t sensor_addr; + uint32_t sensor_size; + uint32_t flag_addr; + uint32_t flag_size; + + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + + uint32_t chksum; + uint32_t chksum_all; + + char magic2[8]; +}; + +struct ist415_version { + uint32_t core_ver; + uint32_t config_ver; + uint32_t main_ver; + uint32_t release_ver; + uint32_t test_ver; +}; + +struct ist415_fw { + struct ist415_version cur; + struct ist415_version bin; + uint32_t index; + uint32_t size; + uint32_t chksum; + uint32_t buf_size; + uint8_t *buf; +}; + +#define msleep(x) usleep(x * 1000) + +/* IST415 Device */ +struct ist415_dev_s { + struct i2c_dev_s *i2c; + struct i2c_config_s *i2c_config; + + struct touchscreen_s *upper; + struct ist415_config_s *lower; + + /* firmware */ + struct ist415_fw fw; + struct ist415_tags tags; + + /* touch variable */ + bool ready; + bool enable; + bool pre_enable; + + uint8_t sys_mode; /* System Mode (NPM or LPM) */ + uint16_t touch_type; /* Touch Type */ + bool knockknock; + + uint16_t width; + uint16_t height; + + uint8_t tx_num; + uint8_t rx_num; + + uint16_t slf_node_len; + uint16_t mtl_node_len; + + bool swap_xy; + + uint8_t cmcs; + uint8_t cmcs_msg; + uint16_t cmcs_min; + uint16_t cmcs_max; + uint32_t spec_gap; + uint32_t spec_jitter; + uint32_t spec_cm_min; + uint32_t spec_cm_max; + uint32_t spec_cs_min; + uint32_t spec_cs_max; + uint32_t spec_cr_min; + uint32_t spec_cr_max; + + uint8_t rec_mode; + bool rec_idle; + int rec_type; + int rec_delay; + uint32_t recording_scancnt; + uint32_t rec_addr; + uint32_t rec_size; + + uint8_t calib_result; + uint32_t calib_msg[2]; + + uint32_t pre_palm_state; + uint32_t palm_state; + + /* debug variable */ + uint32_t intr_debug_addr; + int intr_debug_size; + + struct work_s work; +}; + +void put_unaligned_be32(uint32_t value, void *addr); +uint32_t cpu_to_be32(uint32_t value); + +int ist415_i2c_read(struct ist415_dev_s *dev, uint8_t cmd, uint8_t *data, int size); +int ist415_i2c_write(struct ist415_dev_s *dev, uint8_t cmd, uint8_t *data, int size); +int ist415_i2c_read_da(struct ist415_dev_s *dev, uint32_t addr, uint32_t *data, int size); +int ist415_i2c_write_da(struct ist415_dev_s *dev, uint32_t addr, uint32_t *data, int size); + +void ist415_enable(struct ist415_dev_s *dev); +void ist415_disable(struct ist415_dev_s *dev); +void ist415_reset(struct ist415_dev_s *dev, bool download); +void ist415_sensor(struct ist415_dev_s *dev, bool on); +void ist415_touchtype(struct ist415_dev_s *dev, uint8_t *data); +uint8_t ist415_fw_integrity(struct ist415_dev_s *dev); +void ist415_power_mode(struct ist415_dev_s *dev, uint8_t data); + +void ist415_start(struct ist415_dev_s *dev); + +#endif /* __DRIVERS_INPUT_IST415_H */ diff --git a/os/drivers/input/ist415_misc.c b/os/drivers/input/ist415_misc.c new file mode 100644 index 0000000000..d7791e592b --- /dev/null +++ b/os/drivers/input/ist415_misc.c @@ -0,0 +1,658 @@ +/**************************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/input/ist415.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "ist415_misc.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ist415_print_info + ****************************************************************************/ + +static void ist415_print_info(struct ist415_dev_s *dev) +{ + touchvdbg("*** TSP info ***\n"); + touchvdbg(" swap_xy: %d\n", dev->swap_xy); + touchvdbg(" tx: %d, rx: %d\n", dev->tx_num, dev->rx_num); + touchvdbg(" touch width: %d, height: %d\n", dev->width, dev->height); + touchvdbg(" mutual node len: %d\n", dev->mtl_node_len); + touchvdbg(" self node len: %d\n", dev->slf_node_len); + touchvdbg("Main Ver: %X, Test Ver: %X\n", dev->fw.cur.main_ver, dev->fw.cur.test_ver); + touchvdbg("Core Ver: %X, Config Ver: %X, Release Ver: %X\n", dev->fw.cur.core_ver, dev->fw.cur.config_ver, dev->fw.cur.release_ver); +} + +/**************************************************************************** + * Name: ist415_wait_calibrate + ****************************************************************************/ + +static int ist415_wait_calibrate(struct ist415_dev_s *dev) +{ + int wait = IST415_WAIT_TIME; + + dev->calib_result = 0; + memset(dev->calib_msg, 0, sizeof(dev->calib_msg)); + + while (wait-- > 0) { + msleep(100); + + if ((dev->calib_result == 0x10) || (dev->calib_result == 0x80)) { + ist415_i2c_read(dev, HCOM_GET_CAL_RESULT, (uint8_t *) dev->calib_msg, sizeof(dev->calib_msg)); + touchvdbg("MTL Calibration: %d, Max gap : %d - (%08x)\n", CALIB_TO_STATUS(dev->calib_msg[0]), CALIB_TO_GAP(dev->calib_msg[0]), dev->calib_msg[0]); + touchvdbg("SLF Calibration: %d, Max gap : %d - (%08x)\n", CALIB_TO_STATUS(dev->calib_msg[1]), CALIB_TO_GAP(dev->calib_msg[1]), dev->calib_msg[1]); + } + + if (dev->calib_result == 0x10) { + touchvdbg("Calibration success\n"); + return OK; + } else if (dev->calib_result == 0x80) { + touchvdbg("Calibration fail\n"); + return -EAGAIN; + } + } + + touchvdbg("Calibration time out\n"); + + return -ETIME; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ist415_calibrate + ****************************************************************************/ + +void ist415_calibrate(struct ist415_dev_s *dev, uint8_t retry) +{ + int ret = 0; + + touchvdbg("*** Calibrate %ds ***\n", IST415_WAIT_TIME / 10); + + while (retry-- > 0) { + ist415_disable(dev); + ist415_reset(dev, false); + ist415_enable(dev); + + ret = ist415_i2c_write(dev, HCOM_CALIBRATION, NULL, 0); + if (ret) { + touchdbg("Fail to write calibration commnad\n"); + continue; + } + ret = ist415_wait_calibrate(dev); + if (ret == OK) { + break; + } + } + + ist415_reset(dev, false); +} + +/**************************************************************************** + * Name: ist415_read_info + ****************************************************************************/ + +int ist415_read_info(struct ist415_dev_s *dev) +{ + int ret = 0; + uint8_t panel_info[11]; + uint8_t version[6]; + uint8_t tsp_swap; + uint8_t recording_info[6]; + uint32_t spec_temp; + + ret = ist415_i2c_read(dev, HCOM_GET_PANEL_INFO, panel_info, sizeof(panel_info)); + if (ret) { + touchdbg("Fail to get panel info\n"); + return ret; + } + + dev->width = ((uint16_t) panel_info[0] << 8) | (uint16_t) panel_info[1]; + dev->height = ((uint16_t) panel_info[2] << 8) | (uint16_t) panel_info[3]; + dev->tx_num = panel_info[8]; + dev->rx_num = panel_info[9]; + dev->slf_node_len = dev->tx_num + dev->rx_num; + dev->mtl_node_len = dev->tx_num * dev->rx_num; + + ret = ist415_i2c_read(dev, HCOM_GET_FW_VER, version, sizeof(version)); + if (ret) { + touchdbg("Fail to get version\n"); + return ret; + } + + dev->fw.cur.core_ver = ((uint16_t) version[0] << 8) | (uint16_t) version[1]; + dev->fw.cur.config_ver = ((uint16_t) version[2] << 8) | (uint16_t) version[3]; + dev->fw.cur.release_ver = ((uint16_t) version[4] << 8) | (uint16_t) version[5]; + + ret = ist415_i2c_read(dev, HCOM_GET_SWAP_INFO, &tsp_swap, sizeof(tsp_swap)); + if (ret) { + touchdbg("Fail to get swap info\n"); + return ret; + } + + dev->swap_xy = (tsp_swap & TSP_INFO_SWAP_XY) ? true : false; + + ret = ist415_i2c_read(dev, HCOM_GET_VER_MAIN, (uint8_t *)&dev->fw.cur.main_ver, sizeof(dev->fw.cur.main_ver)); + if (ret) { + touchdbg("Fail to get main version\n"); + return ret; + } + + ret = ist415_i2c_read(dev, HCOM_GET_VER_TEST, (uint8_t *)&dev->fw.cur.test_ver, sizeof(dev->fw.cur.test_ver)); + if (ret) { + touchdbg("Fail to get test version\n"); + return ret; + } + + ret = ist415_i2c_read(dev, HCOM_GET_ALGO_STATUS, recording_info, sizeof(recording_info)); + if (ret) { + touchdbg("Fail to get recording info\n"); + return ret; + } + + dev->rec_addr = ((uint32_t) recording_info[3] << 24) | ((uint32_t) recording_info[2] << 16) | ((uint32_t) recording_info[1] << 8) | (uint32_t) recording_info[0]; + dev->rec_size = ((uint16_t) recording_info[5] << 8) | (uint16_t) recording_info[4]; + + ret = ist415_i2c_read(dev, HCOM_GET_JITTER_GAP_SPEC, (uint8_t *)&spec_temp, sizeof(spec_temp)); + if (ret) { + touchdbg("Fail to get jitter & gap spec\n"); + return ret; + } + + dev->spec_gap = spec_temp & 0xFFFF; + dev->spec_jitter = (spec_temp >> 16) & 0xFFFF; + + ret = ist415_i2c_read(dev, HCOM_GET_CM_SPEC, (uint8_t *)&spec_temp, sizeof(spec_temp)); + if (ret) { + touchdbg("Fail to get cm spec\n"); + return ret; + } + + dev->spec_cm_min = spec_temp & 0xFFFF; + dev->spec_cm_max = (spec_temp >> 16) & 0xFFFF; + + ret = ist415_i2c_read(dev, HCOM_GET_CS_SPEC, (uint8_t *)&spec_temp, sizeof(spec_temp)); + if (ret) { + touchdbg("Fail to get cs spec\n"); + return ret; + } + + dev->spec_cs_min = spec_temp & 0xFFFF; + dev->spec_cs_max = (spec_temp >> 16) & 0xFFFF; + + ret = ist415_i2c_read(dev, HCOM_GET_CR_SPEC, (uint8_t *)&spec_temp, sizeof(spec_temp)); + if (ret) { + touchdbg("Fail to get cr spec\n"); + return ret; + } + + dev->spec_cr_min = spec_temp & 0xFFFF; + dev->spec_cr_max = (spec_temp >> 16) & 0xFFFF; + + return ret; +} + +/**************************************************************************** + * Name: ist415_get_info + ****************************************************************************/ + +int ist415_get_info(struct ist415_dev_s *dev) +{ + int ret = 0; + + ret = ist415_read_info(dev); + if (ret) { + return ret; + } + + ist415_print_info(dev); + + return 0; +} + +/**************************************************************************** + * Name: ist415_autocalibration + * + * Description + * This function is called by Uart Command. + ****************************************************************************/ + +void ist415_autocalibration(struct ist415_dev_s *dev) +{ + ist415_calibrate(dev, 1); + ist415_start(dev); + ist415_enable(dev); +} + +/**************************************************************************** + * Name: ist415_set_intr_debug + * + * Description + * This function is called by Uart Command. + ****************************************************************************/ + +int ist415_set_intr_debug(struct ist415_dev_s *dev, int argc, char **argv) +{ + if (argc < 4) { + return -EINVAL; + } + + dev->intr_debug_addr = strtoul(argv[2], NULL, 16); + dev->intr_debug_size = atoi(argv[3]); + + touchvdbg("intr debug addr: 0x%x, size: %d\n", dev->intr_debug_addr, dev->intr_debug_size); + + return OK; +} + +/**************************************************************************** + * Name: ist415_run_intr_debug + ****************************************************************************/ + +void ist415_run_intr_debug(struct ist415_dev_s *dev) +{ + uint32_t *buf32; + int ret = 0; + + if (dev->intr_debug_size <= 0) { + return; + } + + buf32 = (uint32_t *)kmm_malloc(dev->intr_debug_size); + + ret = ist415_i2c_read_da(dev, dev->intr_debug_addr, (uint32_t *) buf32, dev->intr_debug_size); + if (ret) { + kmm_free(buf32); + touchdbg("Fail to read intr debug\n"); + return; + } + + touchvdbg("Intr Debug (Addr : 0x%08X)\n", dev->intr_debug_addr); + for (int i = 0; i < dev->intr_debug_size; i++) { + touchvdbg(" %08X\n", buf32[i]); + } + + kmm_free(buf32); +} + +/**************************************************************************** + * Name: ist415_display_rawdata + * + * Description + * This function is called by Uart Command. + ****************************************************************************/ + +void ist415_display_rawdata(struct ist415_dev_s *dev) +{ + uint32_t *bufslf; + uint32_t *bufmtl; + int tx, rx; + uint32_t cdc, baseline, diff; + int ret = 0; + + bufslf = (uint32_t *)kmm_malloc((int)dev->slf_node_len * sizeof(uint32_t)); + bufmtl = (uint32_t *)kmm_malloc((int)dev->mtl_node_len * sizeof(uint32_t)); + + ist415_sensor(dev, false); + + touchvdbg("SLF addr: %08X, size : %d\n", SLF_CDC_REGISTER, (int)dev->slf_node_len); + ret = ist415_i2c_read_da(dev, SLF_CDC_REGISTER, (uint32_t *) bufslf, (int)dev->slf_node_len); + if (ret) { + kmm_free(bufslf); + kmm_free(bufmtl); + touchdbg("Fail to read self raw data\n"); + return; + } + + touchvdbg("MTL addr: %08X, size : %d\n", MTL_CDC_REGISTER, (int)dev->mtl_node_len); + ret = ist415_i2c_read_da(dev, MTL_CDC_REGISTER, (uint32_t *) bufmtl, (int)dev->mtl_node_len); + if (ret) { + kmm_free(bufslf); + kmm_free(bufmtl); + touchdbg("Fail to read mutual raw data\n"); + return; + } + + ist415_sensor(dev, true); + + touchvdbg("[CDC]\n"); + if (dev->swap_xy) { + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (tx = 0; tx < dev->tx_num; tx++) { + cdc = bufslf[tx] & 0xFFF; + touchvdbg(" %4d", cdc); + } + touchvdbg("\n\n"); + } + + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + cdc = bufslf[dev->tx_num + rx] & 0xFFF; + touchvdbg(" %4d", cdc); + touchvdbg(" %4s", " "); + } + + cdc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + touchvdbg(" %4d", cdc); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } else { + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (rx = 0; rx < dev->rx_num; rx++) { + cdc = bufslf[dev->tx_num + rx] & 0xFFF; + touchvdbg(" %4d", cdc); + } + touchvdbg("\n\n"); + } + + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + cdc = bufslf[tx] & 0xFFF; + touchvdbg(" %4d", cdc); + touchvdbg(" %4s", " "); + } + + cdc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + touchvdbg(" %4d", cdc); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } + + touchvdbg("[BASELINE]\n"); + if (dev->swap_xy) { + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (tx = 0; tx < dev->tx_num; tx++) { + baseline = (bufslf[tx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + } + touchvdbg("\n\n"); + } + + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + baseline = (bufslf[dev->tx_num + rx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + touchvdbg(" %4s", " "); + } + + baseline = (bufmtl[(tx * dev->rx_num) + rx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } else { + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (rx = 0; rx < dev->rx_num; rx++) { + baseline = (bufslf[dev->tx_num + rx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + } + touchvdbg("\n\n"); + } + + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + baseline = (bufslf[tx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + touchvdbg(" %4s", " "); + } + + baseline = (bufmtl[(tx * dev->rx_num) + rx] >> 16) & 0xFFF; + touchvdbg(" %4d", baseline); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } + + touchvdbg("[DIFF]\n"); + if (dev->swap_xy) { + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (tx = 0; tx < dev->tx_num; tx++) { + cdc = bufslf[tx] & 0xFFF; + baseline = (bufslf[tx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + } + touchvdbg("\n\n"); + } + + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + cdc = bufslf[dev->tx_num + rx] & 0xFFF; + baseline = (bufslf[dev->tx_num + rx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + touchvdbg(" %4s", " "); + } + + cdc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + baseline = (bufmtl[(tx * dev->rx_num) + rx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } else { + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (rx = 0; rx < dev->rx_num; rx++) { + cdc = bufslf[dev->tx_num + rx] & 0xFFF; + baseline = (bufslf[dev->tx_num + rx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + } + touchvdbg("\n\n"); + } + + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + cdc = bufslf[tx] & 0xFFF; + baseline = (bufslf[tx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + touchvdbg(" %4s", " "); + } + + cdc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + baseline = (bufmtl[(tx * dev->rx_num) + rx] >> 16) & 0xFFF; + diff = cdc - baseline; + touchvdbg(" %4d", diff); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } + + kmm_free(bufslf); + kmm_free(bufmtl); +} + +/**************************************************************************** + * Name: ist415_display_cpc + * + * Description + * This function is called by Uart Command. + ****************************************************************************/ + +void ist415_display_cpc(struct ist415_dev_s *dev) +{ + uint32_t *bufslf; + uint32_t *bufmtl; + int tx, rx; + uint32_t cpc; + int ret = 0; + + bufslf = (uint32_t *)kmm_malloc(dev->slf_node_len * sizeof(uint32_t)); + bufmtl = (uint32_t *)kmm_malloc(dev->mtl_node_len * sizeof(uint32_t)); + + ist415_sensor(dev, false); + + touchvdbg("SLF addr: %08X, size : %d\n", SLF_CPC_REGISTER, dev->slf_node_len); + ret = ist415_i2c_read_da(dev, SLF_CPC_REGISTER, (uint32_t *) bufslf, dev->slf_node_len); + if (ret) { + kmm_free(bufslf); + kmm_free(bufmtl); + touchdbg("Fail to read self cpc data\n"); + return; + } + + touchvdbg("MTL addr: %08X, size : %d\n", MTL_CPC_REGISTER, dev->mtl_node_len); + ret = ist415_i2c_read_da(dev, MTL_CPC_REGISTER, (uint32_t *) bufmtl, dev->mtl_node_len); + if (ret) { + kmm_free(bufslf); + kmm_free(bufmtl); + touchdbg("Fail to read mutual cpc data\n"); + return; + } + + ist415_sensor(dev, true); + + touchvdbg("[CPC]\n"); + if (dev->swap_xy) { + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (tx = 0; tx < dev->tx_num; tx++) { + cpc = bufslf[tx] & 0xFFF; + touchvdbg(" %4d", cpc); + } + touchvdbg("\n\n"); + } + + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + cpc = bufslf[dev->tx_num + rx] & 0xFFF; + touchvdbg(" %4d", cpc); + touchvdbg(" %4s", " "); + } + + cpc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + touchvdbg(" %4d", cpc); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } else { + for (tx = 0; tx < dev->tx_num; tx++) { + if (tx == 0) { + touchvdbg(" %4s", " "); + touchvdbg(" %4s", " "); + for (rx = 0; rx < dev->rx_num; rx++) { + cpc = bufslf[dev->tx_num + rx] & 0xFFF; + touchvdbg(" %4d", cpc); + } + touchvdbg("\n\n"); + } + + for (rx = 0; rx < dev->rx_num; rx++) { + if (rx == 0) { + cpc = bufslf[tx] & 0xFFF; + touchvdbg(" %4d", cpc); + touchvdbg(" %4s", " "); + } + + cpc = bufmtl[(tx * dev->rx_num) + rx] & 0xFFF; + touchvdbg(" %4d", cpc); + } + touchvdbg("\n"); + } + touchvdbg("\n"); + } + + kmm_free(bufslf); + kmm_free(bufmtl); +} diff --git a/os/drivers/input/ist415_misc.h b/os/drivers/input/ist415_misc.h new file mode 100644 index 0000000000..fefda87500 --- /dev/null +++ b/os/drivers/input/ist415_misc.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/input/ist415_misc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_INPUT_IST415_MISC_H +#define __DRIVERS_INPUT_IST415_MISC_H + +#include "ist415.h" + +// Recording +#define REC_START_SCAN 2 +#define REC_ENABLE 1 +#define REC_DISABLE 0 + +// SelfTest +#define SELFTEST_CM (1 << 0) +#define SELFTEST_JITTER (1 << 2) + +#define SELFTEST_CM_MSG (0xC3) +#define SELFTEST_JITTER_MSG (0x71) + +#define SELFTEST_PASS (0x10) +#define SELFTEST_FAIL (0x80) + +// RawData +#define MTL_CDC_REGISTER 0x40000000 +#define SLF_CDC_REGISTER 0x40001768 + +#define MTL_CPC_REGISTER 0x300505A0 +#define SLF_CPC_REGISTER 0x30040290 + +// Calibration +#define CALIB_MSG_MASK 0xF0000FFF +#define CALIB_MSG_VALID 0x80000CAB +#define CALIB_TO_GAP(n) ((n >> 16) & 0xFFF) +#define CALIB_TO_STATUS(n) ((n >> 12) & 0xF) + + +void ist415_calibrate(struct ist415_dev_s *dev, uint8_t retry); +int ist415_read_info(struct ist415_dev_s *dev); +int ist415_get_info(struct ist415_dev_s *dev); +void ist415_autocalibration(struct ist415_dev_s *dev); +int ist415_set_intr_debug(struct ist415_dev_s *dev, int argc, char **argv); +void ist415_run_intr_debug(struct ist415_dev_s *dev); +void ist415_display_cpc(struct ist415_dev_s *dev); +void ist415_display_rawdata(struct ist415_dev_s *dev); + +#endif /* __DRIVERS_INPUT_IST415_MISC_H */ diff --git a/os/drivers/input/ist415_update.c b/os/drivers/input/ist415_update.c new file mode 100644 index 0000000000..2cc1db95db --- /dev/null +++ b/os/drivers/input/ist415_update.c @@ -0,0 +1,667 @@ +/**************************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/input/ist415_update.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "ist415_misc.h" +#include "ist415_update.h" + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +#define FIRMWARE_PATH_WASHING_MACHINE "/res/241128_AV_Display_V02060103.bin" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int ist415_i2c_wait_isp(struct ist415_dev_s *dev) +{ + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + uint8_t cmd = HCOM_ISP; + uint8_t sub1 = ISP_TARGET_STATUS; + uint8_t sub2 = ISP_CMD_READ; + uint32_t addr = 0; + int wsize = sizeof(cmd) + sizeof(sub1) + sizeof(sub2) + sizeof(addr); + uint8_t *buf; + uint32_t buf32 = ISP_STATUS_BUSY; + uint32_t status; + int ret = 0; + int retry = 200; + + buf = (uint8_t *)kmm_malloc(wsize); + + buf[0] = cmd; + buf[1] = sub1; + buf[2] = sub2; + put_unaligned_be32(addr, buf + sizeof(cmd) + sizeof(sub1) + sizeof(sub2)); + + do { + retry--; + if (retry == 0) { + kmm_free(buf); + touchdbg("Fail to wait ISP\n"); + return ERROR; + } + + msleep(1); + ret = i2c_write(i2c, config, (uint8_t *)buf, wsize); + if (ret != wsize) { + continue; + } + ret = i2c_read(i2c, config, (uint8_t *)&buf32, sizeof(status)); + if (ret != sizeof(status)) { + continue; + } + + status = cpu_to_be32(buf32); + } while (status != ISP_STATUS_DONE); + + kmm_free(buf); + + return OK; +} + +/**************************************************************************** + * Name: ist415_i2c_write_isp + ****************************************************************************/ + +int ist415_i2c_write_isp(struct ist415_dev_s *dev, uint8_t sub1, uint8_t sub2, uint32_t addr, uint32_t *data, int size) +{ + struct i2c_dev_s *i2c = dev->i2c; + struct i2c_config_s *config = dev->i2c_config; + uint8_t cmd = HCOM_ISP; + int hsize = sizeof(cmd) + sizeof(sub1) + sizeof(sub2) + sizeof(addr); + int wsize = hsize + (size * sizeof(uint32_t)); + uint8_t *buf = NULL; + int ret = 0; + + buf = (uint8_t *)kmm_malloc(wsize); + + buf[0] = cmd; + buf[1] = sub1; + buf[2] = sub2; + put_unaligned_be32(addr, buf + sizeof(cmd) + sizeof(sub1) + sizeof(sub2)); + for (int i = 0; i < size; i++) { + put_unaligned_be32(data[i], buf + (i * sizeof(uint32_t)) + hsize); + } + + ret = i2c_write(i2c, config, (uint8_t *) buf, wsize); + if (ret != wsize) { + kmm_free(buf); + touchdbg("Fail to write ISP\n"); + return ret; + } + + ret = ist415_i2c_wait_isp(dev); + if (ret < 0) { + kmm_free(buf); + touchdbg("Fail to write ISP\n"); + return ret; + } + + kmm_free(buf); + + return OK; +} + +/**************************************************************************** + * Name: ist415_parse_ver + ****************************************************************************/ + +static uint32_t ist415_parse_ver(struct ist415_dev_s *dev, int flag, const uint8_t *buf) +{ + uint32_t ver = 0; + uint32_t *buf32 = (uint32_t *) buf; + + if (flag == FLAG_MAIN) { + ver = (uint32_t) buf32[(dev->tags.flag_addr + 0xFC) >> 2]; + } else if (flag == FLAG_RELEASE) { + ver = (uint32_t) buf32[(dev->tags.flag_addr + 0xF0) >> 2]; + } else if (flag == FLAG_TEST) { + ver = (uint32_t) buf32[(dev->tags.flag_addr + 0xF4) >> 2]; + } else if (flag == FLAG_CORE) { + ver = ((uint32_t) buf32[(dev->tags.flag_addr + 0xEC) >> 2] >> 16) & 0xFFFF; + } else if (flag == FLAG_CONFIG) { + ver = (uint32_t) buf32[(dev->tags.flag_addr + 0xEC) >> 2] & 0xFFFF; + } else { + touchdbg("Parsing ver's flag is not corrent\n"); + } + + return ver; +} + +/**************************************************************************** + * Name: ist415_parse_tags + ****************************************************************************/ + +static int ist415_parse_tags(struct ist415_dev_s *dev, const uint8_t *buf, const uint32_t size) +{ + int ret = -ENOENT; + struct ist415_tags *tags; + + tags = (struct ist415_tags *)(&buf[size - sizeof(struct ist415_tags)]); + + if (!strncmp(tags->magic1, IST415_TAG_MAGIC, sizeof(tags->magic1)) && !strncmp(tags->magic2, IST415_TAG_MAGIC, sizeof(tags->magic2))) { + dev->tags = *tags; + + dev->tags.fw_addr -= dev->tags.rom_base; + dev->tags.cfg_addr -= dev->tags.rom_base; + dev->tags.sensor_addr -= dev->tags.rom_base; + dev->tags.flag_addr -= dev->tags.rom_base; + + dev->fw.index = dev->tags.fw_addr; + dev->fw.size = tags->flag_addr - tags->fw_addr + tags->flag_size; + dev->fw.chksum = tags->chksum; + + touchvdbg("Tagts magic1: %s, magic2: %s\n", dev->tags.magic1, dev->tags.magic2); + touchvdbg(" rom: %x\n", dev->tags.rom_base); + touchvdbg(" ram: %x\n", dev->tags.ram_base); + touchvdbg(" fw: %x(%x)\n", dev->tags.fw_addr, dev->tags.fw_size); + touchvdbg(" cfg: %x(%x)\n", dev->tags.cfg_addr, dev->tags.cfg_size); + touchvdbg(" sensor: %x(%x)\n", dev->tags.sensor_addr, dev->tags.sensor_size); + touchvdbg(" flag: %x(%x)\n", dev->tags.flag_addr, dev->tags.flag_size); + touchvdbg(" chksum: %x\n", dev->tags.chksum); + touchvdbg(" chksum_all: %x\n", dev->tags.chksum_all); + + ret = OK; + } + + return ret; +} + +/**************************************************************************** + * Name: ist415_get_update_info + ****************************************************************************/ + +static int ist415_get_update_info(struct ist415_dev_s *dev, const uint8_t *buf, const uint32_t size) +{ + int ret = 0; + + ret = ist415_parse_tags(dev, buf, size); + if (ret) { + touchdbg("Can't find tags of firmware\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: request_firmware + ****************************************************************************/ + +static int request_firmware(struct firmware *firmware, char *path, struct ist415_dev_s **dev) +{ + int fd; + int ret = 0; + struct stat file_stat; + + if (firmware == NULL || path == NULL) { + return ERROR; + } + + if (stat(path, &file_stat) != 0) { + dbg("Failed to stat file: %d\n", get_errno()); + return ERROR; + } + + firmware->size = file_stat.st_size; + firmware->data = (char *)kmm_malloc(firmware->size); + + fd = open(path, O_RDONLY); + if (fd < 0) { + dbg("Failed to open file: %d\n", get_errno()); + return ERROR; + } + + ret = read(fd, firmware->data, firmware->size); + if (ret != firmware->size) { + dbg("Failed to read file: %d\n", get_errno()); + close(fd); + return ERROR; + } + close(fd); + return OK; +} + +static void release_firmware(struct firmware *firmware) +{ + firmware->size = 0; + kmm_free(firmware->data); + + dbg("firmware released \n"); +} + +/**************************************************************************** + * Name: ist415_isp_enable + ****************************************************************************/ + +static int ist415_isp_enable(struct ist415_dev_s *dev, bool enable) +{ + int ret = 0; + + if (enable) { + ret = ist415_i2c_write_isp(dev, ISP_TARGET_ENTER, ISP_CMD_ENTER, 0, NULL, 0); + } else { + ret = ist415_i2c_write_isp(dev, ISP_TARGET_EXIT, ISP_CMD_EXIT, 0, NULL, 0); + } + + if (ret < 0) { + touchdbg("Fail to isp %s\n", enable ? "enable" : "disable"); + return ret; + } + + return OK; +} + +/**************************************************************************** + * Name: ist415_isp_erase + ****************************************************************************/ + +static int ist415_isp_erase(struct ist415_dev_s *dev, uint8_t target, uint8_t area, uint32_t addr, int size) +{ + int count = 0; + int unit = 0; + int ret = 0; + int i; + + touchvdbg("%s\n", __func__); + + if (area == ISP_CMD_MASS_ERASE) { + count = 1; + } else if (area == ISP_CMD_SECTOR_ERASE) { + count = size / IST415_ROM_SECTOR_SIZE; + unit = IST415_ROM_SECTOR_SIZE; + } else if (area == ISP_CMD_PAGE_ERASE) { + count = size / IST415_ROM_PAGE_SIZE; + unit = IST415_ROM_PAGE_SIZE; + } + + for (i = 0; i < count; i++) { + ret = ist415_i2c_write_isp(dev, target, area, addr + (i * unit), NULL, 0); + if (ret < 0) { + touchdbg("Fail to erase ISP\n"); + } + } + + return ret; +} + +/**************************************************************************** + * Name: ist415_isp_program + ****************************************************************************/ + +static int ist415_isp_program(struct ist415_dev_s *dev, uint8_t target, uint32_t addr, uint32_t *buf32, int size) +{ + int ret = 0; + int i; + + touchvdbg("%s\n", __func__); + + for (i = 0; i < (size / IST415_ROM_SECTOR_SIZE); i++) { + ret = ist415_i2c_write_isp(dev, target, ISP_CMD_PROG, addr, buf32, IST415_ROM_SECTOR_SIZE / sizeof(uint32_t)); + if (ret < 0) { + touchdbg("Fail to write ISP (Sector %d)\n", i); + break; + } + addr += IST415_ROM_SECTOR_SIZE; + buf32 += (IST415_ROM_SECTOR_SIZE / sizeof(uint32_t)); + } + + return ret; +} + +/**************************************************************************** + * Name: ist415_isp_fw_update + ****************************************************************************/ + +static int ist415_isp_fw_update(struct ist415_dev_s *dev, const uint8_t *buf) +{ + int ret = 0; + + touchvdbg("%s\n", __func__); + + ist415_reset(dev, true); + + ret = ist415_isp_enable(dev, true); + if (ret < 0) { + return ret; + } + + ret = ist415_isp_erase(dev, ISP_TARGET_MAIN, ISP_CMD_SECTOR_ERASE, IST415_ROM_BASE_ADDR, IST415_ROM_MAIN_SIZE); + if (ret < 0) { + return ret; + } + + msleep(1); + + ret = ist415_isp_program(dev, ISP_TARGET_MAIN, IST415_ROM_BASE_ADDR, (uint32_t *) buf, IST415_ROM_MAIN_SIZE); + if (ret < 0) { + touchdbg("Fail to program ISP\n"); + return ret; + } + + ist415_reset(dev, false); + + return ret; +} + +/**************************************************************************** + * Name: ist415_check_auto_update + ****************************************************************************/ + +int ist415_check_auto_update(struct ist415_dev_s *dev) +{ + int retry = IST415_RETRY_CNT; + bool tsp_check = false; + uint32_t chksum = 0; + struct ist415_fw *fw = &dev->fw; + int ret = 0; + + while (retry--) { + ret = ist415_fw_integrity(dev); + if (ret == FW_INTEGRITY_VALID) { + tsp_check = true; + break; + } else if (ret == FW_INTEGRITY_INVALID) { + break; + } + + ist415_reset(dev, false); + } + + if (!tsp_check) { + return -EAGAIN; + } + + ret = ist415_read_info(dev); + if (ret < 0) { + return -EAGAIN; + } + + if ((fw->cur.release_ver > 0) && (fw->cur.release_ver < 0xFFFF)) { + if (((fw->cur.main_ver & MAIN_VER_MASK) == MAIN_VER_MASK) || ((fw->cur.main_ver & MAIN_VER_MASK) == 0)) { + return -EAGAIN; + } + + touchvdbg("Version compare IC: %x(%x, %x), BIN: %x(%x, %x)\n", fw->cur.release_ver, fw->cur.core_ver, fw->cur.config_ver, fw->bin.release_ver, fw->bin.core_ver, fw->bin.config_ver); + + /* If FW version is same, check FW checksum */ + if ((fw->cur.core_ver == fw->bin.core_ver) && (fw->cur.config_ver == fw->bin.config_ver) && (fw->cur.release_ver == fw->bin.release_ver) && (fw->cur.test_ver == 0)) { + ret = ist415_i2c_read(dev, HCOM_GET_CRC, (uint8_t *)&chksum, 2); + if (ret || (chksum != fw->chksum)) { + touchdbg("Mismatch checksum IC: %x, Bin: %x (ret: %d)\n", chksum, fw->chksum, ret); + return -EAGAIN; + } + } + + /* If the ver of binary is higher than ver of IC, FW update operate. */ + if ((fw->cur.core_ver >= fw->bin.core_ver) && (fw->cur.config_ver >= fw->bin.config_ver) && (fw->cur.release_ver >= fw->bin.release_ver)) { + return OK; + } + } + + return -EAGAIN; +} + +/**************************************************************************** + * Name: ist415_fw_update + ****************************************************************************/ + +static int ist415_fw_update(struct ist415_dev_s *dev, const uint8_t *buf, int size) +{ + struct ist415_fw *fw = &dev->fw; + uint32_t core_ver = ist415_parse_ver(dev, FLAG_CORE, buf); + uint32_t config_ver = ist415_parse_ver(dev, FLAG_CONFIG, buf); + uint32_t release_ver = ist415_parse_ver(dev, FLAG_RELEASE, buf); + uint32_t test_ver = ist415_parse_ver(dev, FLAG_TEST, buf); + uint32_t chksum = 0; + int ret = 0; + + touchvdbg("*** Firmware update ***\n"); + touchvdbg("core: %x, config: %x, release: %x, test: %x(addr: 0x%x ~ 0x%x)\n", core_ver, config_ver, release_ver, test_ver, fw->index, fw->index + fw->size); + + ret = ist415_isp_fw_update(dev, buf); + if (ret < 0) { + touchdbg("Fail to update firmware\n"); + goto reset; + } + + ret = ist415_i2c_read(dev, HCOM_GET_CRC, (uint8_t *)&chksum, 2); + if (ret < 0) { + touchdbg("Fail to read checksum\n"); + goto reset; + } + + if (chksum != fw->chksum) { + touchdbg("Mismatch checksum IC: %x, Bin: %x\n", chksum, fw->chksum); + goto reset; + } + + ret = ist415_read_info(dev); + if (ret < 0) { + touchdbg("Fail to read info\n"); + goto reset; + } + + touchvdbg("Firmware update success\n"); + + return OK; + +reset: + + ist415_reset(dev, false); + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ist415_check_fw + ****************************************************************************/ + +int ist415_check_fw(struct ist415_dev_s *dev) +{ + struct firmware firmware; + struct ist415_fw *fw = &dev->fw; + int retry = 0; + int ret = 0; + + ret = request_firmware(&firmware, FIRMWARE_PATH_WASHING_MACHINE, &dev); + if (ret < 0) { + touchdbg("Don't request firmware\n"); + return -ENOENT; + } + + fw->buf = (uint8_t *)kmm_malloc(firmware.size); + if (!fw->buf) { + release_firmware(&firmware); + touchdbg("Failed to allocate buffer\n"); + return -ENOMEM; + } else { + memcpy(fw->buf, firmware.data, firmware.size); + fw->buf_size = firmware.size; + } + + release_firmware(&firmware); + + touchvdbg("Firmware loaded successfully.\n"); + + ret = ist415_get_update_info(dev, fw->buf, fw->buf_size); + if (ret < 0) { + kmm_free(fw->buf); + return ret; + } + + fw->bin.main_ver = ist415_parse_ver(dev, FLAG_MAIN, fw->buf); + fw->bin.release_ver = ist415_parse_ver(dev, FLAG_RELEASE, fw->buf); + fw->bin.test_ver = ist415_parse_ver(dev, FLAG_TEST, fw->buf); + fw->bin.core_ver = ist415_parse_ver(dev, FLAG_CORE, fw->buf); + fw->bin.config_ver = ist415_parse_ver(dev, FLAG_CONFIG, fw->buf); + + touchvdbg("Main : %08X Core: %x, Config %x, Release: %x, Test: %x\n", fw->bin.main_ver, fw->bin.core_ver, fw->bin.config_ver, fw->bin.release_ver, fw->bin.test_ver); + + ret = ist415_check_auto_update(dev); + if (ret >= 0) { + kmm_free(fw->buf); + return OK; + } + + touchvdbg("Update version. release(core, config, test): %x(%x, %x, %x) -> %x(%x, %x, %x)\n", fw->cur.release_ver, fw->cur.core_ver, fw->cur.config_ver, fw->cur.test_ver, fw->bin.release_ver, fw->bin.core_ver, fw->bin.config_ver, fw->bin.test_ver); + + retry = IST415_RETRY_CNT; + while (retry--) { + ret = ist415_fw_update(dev, fw->buf, fw->buf_size); + if (ret == OK) { + ist415_calibrate(dev, IST415_RETRY_CNT); + break; + } + } + + kmm_free(fw->buf); + return ret; +} + +/**************************************************************************** + * Name: ist415_force_update + * + * Description + * This function is called by Uart Command. + ****************************************************************************/ + +int ist415_force_update(struct ist415_dev_s *dev, int argc, char **argv) +{ + struct firmware firmware; + struct ist415_fw *fw = &dev->fw; + + char *path; + bool cal; + int ret; + + if (argc < 4) { + return -EINVAL; + } + + path = argv[2]; + cal = atoi(argv[3]); + + ret = request_firmware(&firmware, path, &dev); + if (ret < 0) { + touchdbg("do not request firmware\n"); + return -ENOENT; + } + + fw->buf = (uint8_t *)kmm_malloc(firmware.size); + if (!fw->buf) { + release_firmware(&firmware); + touchdbg("Fail to allocate memory for firmware\n"); + return -ENOMEM; + } else { + memcpy(fw->buf, firmware.data, firmware.size); + fw->buf_size = firmware.size; + } + + release_firmware(&firmware); + + touchvdbg("Firmware loaded successfully.\n"); + + ret = ist415_get_update_info(dev, fw->buf, fw->buf_size); + if (ret < 0) { + kmm_free(fw->buf); + return ret; + } + + fw->bin.main_ver = ist415_parse_ver(dev, FLAG_MAIN, fw->buf); + fw->bin.release_ver = ist415_parse_ver(dev, FLAG_RELEASE, fw->buf); + fw->bin.test_ver = ist415_parse_ver(dev, FLAG_TEST, fw->buf); + fw->bin.core_ver = ist415_parse_ver(dev, FLAG_CORE, fw->buf); + fw->bin.config_ver = ist415_parse_ver(dev, FLAG_CONFIG, fw->buf); + + touchvdbg("Update version. release(core, config, test): %x(%x, %x, %x) -> %x(%x, %x, %x)\n", fw->cur.release_ver, fw->cur.core_ver, fw->cur.config_ver, fw->cur.test_ver, fw->bin.release_ver, fw->bin.core_ver, fw->bin.config_ver, fw->bin.test_ver); + + ist415_disable(dev); + + ret = ist415_fw_update(dev, fw->buf, fw->buf_size); + if (ret == OK) { + if (cal) { + ist415_calibrate(dev, 1); + } + } + + ist415_start(dev); + ist415_enable(dev); + + kmm_free(fw->buf); + + return ret; +} diff --git a/os/drivers/input/ist415_update.h b/os/drivers/input/ist415_update.h new file mode 100644 index 0000000000..1b7f6802a2 --- /dev/null +++ b/os/drivers/input/ist415_update.h @@ -0,0 +1,95 @@ +/**************************************************************************** + * + * Copyright 2024 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/input/ist415_update.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_INPUT_IST415_UPDATE_H +#define __DRIVERS_INPUT_IST415_UPDATE_H + +#include "ist415.h" + +// Flash size +#define IST415_ROM_BASE_ADDR 0 +#define IST415_ROM_MAIN_SIZE 0x1F000 +#define IST415_ROM_INFO_BASE_ADDR 0x1F000 +#define IST415_ROM_INFO_SIZE 0x1000 +#define IST415_ROM_PAGE_SIZE 0x400 +#define IST415_ROM_SECTOR_SIZE 0x800 + +// ISP CMD +#define ISP_TARGET_MAIN 0x33 +#define ISP_TARGET_INFO 0x55 +#define ISP_TARGET_DTC 0x57 +#define ISP_TARGET_RED 0x59 +#define ISP_TARGET_LDT0 0x5A +#define ISP_TARGET_LDT1 0x5C +#define ISP_TARGET_TESTREG 0x5F +#define ISP_TARGET_STATUS 0x2F +#define ISP_TARGET_CHIP_VER 0x3F +#define ISP_TARGET_ENTER 0x27 +#define ISP_TARGET_EXIT 0x51 + +#define ISP_CMD_PAGE_ERASE 0x1C +#define ISP_CMD_SECTOR_ERASE 0xCC +#define ISP_CMD_MASS_ERASE 0xFF +#define ISP_CMD_PROG 0x00 +#define ISP_CMD_BURST_PROG 0xAA +#define ISP_CMD_READ 0xF0 +#define ISP_CMD_RUN_CRC 0x73 +#define ISP_CMD_READ_CRC 0x55 +#define ISP_CMD_ENTER 0x27 +#define ISP_CMD_EXIT 0x51 + +#define ISP_STATUS_BUSY 0x96 +#define ISP_STATUS_DONE 0xAD + +// Version flag +#define FLAG_MAIN 1 +#define FLAG_RELEASE 2 +#define FLAG_TEST 3 +#define FLAG_CORE 4 +#define FLAG_CONFIG 5 + +#define MAIN_VER_MASK 0xFF000000 + +struct firmware { + char *data; + int size; +}; + +int ist415_check_fw(struct ist415_dev_s *dev); +int ist415_force_update(struct ist415_dev_s *dev, int argc, char **argv); + +#endif /* __DRIVERS_INPUT_IST415_UPDATE_H */ \ No newline at end of file diff --git a/os/drivers/input/touchscreen.c b/os/drivers/input/touchscreen.c index d095f85672..0f86773f10 100755 --- a/os/drivers/input/touchscreen.c +++ b/os/drivers/input/touchscreen.c @@ -123,7 +123,7 @@ static inline void touch_semgive(sem_t *sem) static int touch_open(FAR struct file *filep) { - FAR struct touchscreen_s *priv; + struct touchscreen_s *priv; priv = filep->f_inode->i_private; if (!priv) { @@ -158,6 +158,7 @@ static int touch_close(FAR struct file *filep) priv->crefs--; if (priv->crefs == 0) { priv->ops->touch_disable(priv); + priv->pending = false; #if !defined(CONFIG_DISABLE_POLL) /* Check if this file is registered in a list of waiters for polling. * For example, when task A is blocked by calling poll and task B try to terminate task A, @@ -184,22 +185,27 @@ static int touch_close(FAR struct file *filep) static ssize_t touch_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { FAR struct touchscreen_s *priv; - size_t outlen; + irqstate_t flags; int ret; priv = filep->f_inode->i_private; - if (!priv || buflen < 1) { + if (!priv || buflen < sizeof(struct touch_sample_s)) { return -EINVAL; } /* Wait for semaphore to prevent concurrent reads */ touch_semtake(&priv->sem, false); /* Read the touch data, only if screen has been touched or if we're waiting for touch up */ - outlen = sizeof(struct touch_sample_s); ret = priv->ops->touch_read(priv, buffer); + + flags = enter_critical_section(); + priv->pending = false; + leave_critical_section(flags); + touch_semgive(&priv->sem); - return ret < 0 ? ret : outlen; + + return ret < 0 ? ret : sizeof(struct touch_sample_s); } /**************************************************************************** @@ -232,7 +238,6 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } touch_semtake(&priv->sem, false); - switch (cmd) { #if defined(CONFIG_TOUCH_CALLBACK) case TSIOC_SETAPPNOTIFY: { @@ -240,9 +245,11 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) priv->app_touch_point_buffer = touch_app->touch_points; priv->is_touch_detected = touch_app->is_touch_detected; touchvdbg("App notification callback register is successful\n"); + priv->ops->touch_enable(priv); } break; #endif +#ifdef CONFIG_TOUCH_CALLBACK case TSIOC_DISABLE: { priv->ops->touch_disable(priv); } @@ -252,7 +259,7 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) priv->ops->touch_enable(priv); } break; - +#endif case TSIOC_CMD: args = (struct touchscreen_cmd_s *)arg; if (priv->ops && priv->ops->cmd) { @@ -279,6 +286,8 @@ static int touch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) void touch_pollnotify(FAR struct touchscreen_s *dev, pollevent_t eventset) { int itr; + irqstate_t flags; + for (itr = 0; itr < CONFIG_TOUCH_NPOLLWAITERS; itr++) { struct pollfd *fds = dev->fds[itr]; if (fds) { @@ -288,6 +297,9 @@ void touch_pollnotify(FAR struct touchscreen_s *dev, pollevent_t eventset) } } } + irqstate_t state = enter_critical_section(); + dev->pending = true; + leave_critical_section(state); } /**************************************************************************** @@ -300,7 +312,6 @@ int touch_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) pollevent_t eventset; int ret; int i; - bool pending = false; if (!priv || !fds) { return -ENODEV; @@ -338,9 +349,7 @@ int touch_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) eventset = 0; touch_semtake(&priv->sem, false); - pending = priv->ops->is_touchSet(priv); - - if (pending) { + if (priv->pending) { eventset |= (fds->events & POLLIN); } touch_semgive(&priv->sem); @@ -376,6 +385,35 @@ void touch_notify(struct touchscreen_s *dev) * Public Functions ****************************************************************************/ +#ifdef CONFIG_TOUCH_CALLBACK + + +static void get_touch_data(struct touchscreen_s *dev) +{ + int ret = 0; + + if (!dev->app_touch_point_buffer) { + touchdbg("Application buffer touch data is NULL\n"); + if (dev->is_touch_detected) { + dev->is_touch_detected(-EINVAL); + return; + } + } + + ret = dev->ops->touch_read(dev, dev->app_touch_point_buffer); + + if (dev->is_touch_detected) { + dev->is_touch_detected(ret); + } +} + +static void touch_notify(struct touchscreen_s *dev) +{ + dev->ops->touch_enable(dev); + work_queue(HPWORK, &ist415_work, get_touch_data, dev, 0); +} + +#endif /**************************************************************************** * Name: touch_register * @@ -395,6 +433,8 @@ int touch_register(const char *path, struct touchscreen_s *dev) { sem_init(&dev->sem, 0, 1); sem_init(&dev->pollsem, 0, 1); + dev->crefs = 0; + dev->pending = false; dev->notify_touch = touch_notify; #if !defined(CONFIG_DISABLE_POLL) (void)touch_semtake(&dev->pollsem, false); diff --git a/os/include/debug.h b/os/include/debug.h index f428d0f742..c4104e33fa 100644 --- a/os/include/debug.h +++ b/os/include/debug.h @@ -1131,7 +1131,7 @@ int get_errno(void); #endif #ifdef CONFIG_DEBUG_TOUCH_INFO -#define touchvdbg(format, ...) vdbg(format, ##__VA_ARGS__) +#define touchvdbg(format, ...) dbg_noarg(format, ##__VA_ARGS__) #define touchllvdbg(format, ...) llvdbg(format, ##__VA_ARGS__) #else #define touchvdbg(...) @@ -1884,7 +1884,7 @@ else #endif #ifdef CONFIG_DEBUG_TOUCH_INFO -#define touchvdbg vdbg +#define touchvdbg dbg_noarg #define touchllvdbg llvdbg #else #define touchvdbg (void) diff --git a/os/include/tinyara/input/ist415.h b/os/include/tinyara/input/ist415.h index a4faee4402..dd13089aaf 100644 --- a/os/include/tinyara/input/ist415.h +++ b/os/include/tinyara/input/ist415.h @@ -35,244 +35,26 @@ * ****************************************************************************/ -////////////////////////////////////////////////////////////// -// Elementary Definitions & Variable -////////////////////////////////////////////////////////////// -#define MAX_MTL_NODE 720 -#define MAX_SLF_NODE 58 +#include -#define SWAP_XY (1 << 0) -#define FLIP_X (1 << 1) -#define FLIP_Y (1 << 2) - -#define MAX_FINGER_NUM 5 - -//////////////////////////////////////////////////////////////// -// SEC Command -// System (Write) -#define HCOM_SENSE_ON 0x10 // FwHold = 0 -#define HCOM_SENSE_OFF 0x11 // FwHold = 1 -#define HCOM_SW_RESET 0x12 -#define HCOM_CALIBRATION 0x13 -#define HCOM_MISCALIBRATION 0x14 -#define HCOM_MISCALIBRATION2 0x15 - -// Info (Read) -#define HCOM_GET_GPIO_STS 0x20 -#define HCOM_GET_FW_INTEGRITY 0x21 -#define HCOM_GET_DEV_ID 0x22 -#define HCOM_GET_PANEL_INFO 0x23 -#define HCOM_GET_FW_VER 0x24 -#define HCOM_GET_MAX_DCM 0x25 - -// Control (Read/Write) -#define HCOM_CTRL_TOUCH_TYPE 0x30 -#define HCOM_CTRL_OP_MODE 0x31 -#define HCOM_CTRL_CHARGER_MODE 0x32 -#define HCOM_CTRL_NOISE_MODE 0x33 -#define HCOM_CTRL_REPORT_RATE 0x34 -#define HCOM_CTRL_TH_MODE 0x35 -#define HCOM_CTRL_TOUCH_TH 0x36 -#define HCOM_CTRL_KEY_TH 0x37 -#define HCOM_CTRL_COVER_TYPE 0x38 -#define HCOM_CTRL_LPM 0x39 -#define HCOM_CTRL_COORD_FILTER 0x3A -#define HCOM_CTRL_WET_MODE 0x3B -#define HCOM_CTRL_JIG_MODE 0x3C -#define HCOM_CTRL_NUM_OF_DOT_TOUCH 0x3D -#define HCOM_CTRL_EDGE_DEADZONE 0x3E -#define HCOM_CTRL_TOUCHABLE_AREA 0x3F -#define HCOM_CTRL_SENSITIVITY 0x40 - -// Event -#define HCOM_GET_EVENT_1ST 0x60 -#define HCOM_GET_EVENT_ALL 0x61 -#define HCOM_CLEAR_EVENT_ALL 0x62 - -// Panel Test -#define HCOM_SET_MTL_DATA_TYPE 0x70 -#define HCOM_SET_SLF_DATA_TYPE 0x71 -#define HCOM_GET_DATA_MTL 0x72 -#define HCOM_GET_DATA_SLF 0x73 -#define HCOM_SET_PROX_DATA_TYPE 0x74 -#define HCOM_GET_DATA_PROX 0x75 - -// Vendor -#define HCOM_DA_R 0x80 // DA // Don't Use -#define HCOM_DA_W 0x8F // DA // Don't Use -#define HCOM_ISP 0xAE // ISP // Don't Use - -#define HCOM_GET_CRC 0x82 -#define HCOM_GET_CAL_RESULT 0x83 -#define HCOM_GET_PROXIMITY_TH 0x84 -#define HCOM_GET_PROXIMITY_SENSITIVITY 0x85 -#define HCOM_GET_BASELINE_TH 0x86 -#define HCOM_GET_VER_MAIN 0x87 -#define HCOM_GET_VER_TEST 0x88 - -#define HCOM_GET_JITTER_GAP_SPEC 0x90 -#define HCOM_GET_CM_SPEC 0x91 -#define HCOM_GET_CS_SPEC 0x92 -#define HCOM_GET_CR_SPEC 0x93 -#define HCOM_GET_BASELINE 0x94 -#define HCOM_GET_SWAP_INFO 0x95 -#define HCOM_GET_ALGO_INFO 0x96 -#define HCOM_GET_ALGO_STATUS 0x97 -#define HCOM_GET_SEC_INFO_BASE 0x98 -#define HCOM_GET_COPY_SEC_INFO_BASE 0x99 -#define HCOM_GET_CUR_SCAN_FB 0x9A -#define HCOM_GET_SP_REG_BASE 0x9B -#define HCOM_GET_MISCAL_BASE 0x9C -#define HCOM_GET_SELFTEST_BASE 0x9D -#define HCOM_GET_REC_INFO 0x9E - -#define HCOM_WRITE_SEC_INFO 0xA1 -#define HCOM_SET_SP_REG_IDX 0xA2 -#define HCOM_SET_SP_REG_DATA 0xA3 -#define HCOM_SET_SP_NOTIFY_PACKET 0xA4 -#define HCOM_SET_AOD_RECT 0xA5 -#define HCOM_SET_FOD_RECT 0xA6 -#define HCOM_SET_UTC 0xA7 - -#define HCOM_RUN_SELFTEST 0xB0 -#define HCOM_SET_GRIP_DATA 0xB1 -#define HCOM_SET_POCKET_MODE 0xB2 -#define HCOM_SET_CALL_MODE 0xB3 -#define HCOM_SET_HALF_AOD_MODE 0xB4 - -#define HCOM_GET_SELFTEST_DATA 0xC0 -#define HCOM_GET_SELFTEST_RES 0xC1 -#define HCOM_GET_TOUCH_EN 0xC2 -#define HCOM_GET_WET_STATUS 0xC3 -#define HCOM_GET_FOD_INFO 0xC4 -#define HCOM_GET_FOD_POS 0xC5 - -// USE HID Only -#define HCOM_SET_USE_LIBCLOSE 0xD0 -#define HCOM_GET_DEVICE_DESC 0xD1 -#define HCOM_REPORT_COORD 0xD2 -#define HCOM_GET_REPORT_DESC 0xD3 -#define HCOM_CMD_REG 0xD4 -#define HCOM_DAT_REG 0xD5 -#define HCOM_INPUT_REPORT_REG 0xD6 -#define HCOM_OUTPUT_REPORT_REG 0xD7 -#define HCOM_USE_REPORT_COORD 0xD8 - -#define HCOM_SET_REC_MODE 0xF0 -#define HCOM_SET_REG 0xF1 -#define HCOM_GENERATE_INT 0xF2 -#define HCOM_GET_DOMEKEY_STATUS 0xF3 - -#define HCOM_SW_DA 0xFE - -#define EVENT_BYTE 16 - -// EventId (stEventCoord_t) -#define EID_MASK 0x3 -#define EID_COORD 0 -#define EID_STATUS 1 -#define EID_GESTURE 2 - -#define LEFT_NUM_MASK 0x3F - -// TouchStatus -#define TCH_PRESS 2 - -// StatusType (stEventStatus_t) -#define STS_TYPE_CMD_DRIVEN 0 -#define STS_TYPE_VENDOR_INFO 7 - -// StatusId (stEventStatus_t) -#define STS_ID_CMD_CALIB 0 -#define STS_ID_VENDOR_SELFTEST 0 - -// aStatusData (stEventStatus_t) -#define STS_DATA_FW_INTEGRITY_PASS 0x80 -#define STS_DATA_FW_INTEGRITY_FAIL 0x40 -#define STS_DATA_CAL_PASS 0x10 -#define STS_DATA_CAL_FAIL 0x80 -#define STS_DATA_CMCS_PASS 0x10 -#define STS_DATA_CMCS_FAIL 0x80 -#define STS_DATA_CMCS_CM 0x00 -#define STS_DATA_CMCS_CMJIT 0x02 - -#define PARSE_HW_ID(n) ((n >> 10) & 0x3) -#define HW_ID 0x01 - -#define PARSE_TACT_SWITCH(n) ((n >> 3) & 0x1) - -#define SELFTEST_CM (1 << 0) -#define SELFTEST_JITTER (1 << 2) - -#define SELFTEST_CM_MSG (0xC3) -#define SELFTEST_JITTER_MSG (0x71) - -#define SELFTEST_PASS (0x10) -#define SELFTEST_FAIL (0x80) - -#define MTL_CR_REGISTER 0x40000000 -#define SLF_CR_REGISTER 0x40001768 - -#define HW_ID_REGISTER 0x30030000 - -#define TOUCH_MAX_POINTS 15 /* Maximum number of simultaneous touch point supported */ - -struct ts_event_coordinate { - u8 eid:2; - u8 tid:4; - u8 tsta:2; - - u8 x_11_4; - u8 y_11_4; - - u8 y_3_0:4; - u8 x_3_0:4; - - u8 major; - u8 minor; - - u8 z:6; - u8 ttype_3_2:2; - - u8 left_e:5; - u8 max_e:1; - u8 ttype_1_0:2; - - u8 noise_lv; - u8 max_str; - - u8 hover_id_num:4; - u8 noise_sta:2; - u8 eom:1; - u8 reserved:1; - - u8 reserved0; - u8 reserved1; - u8 reserved2; - u8 reserved3; - u8 reserved4; -}; - -/**************************************************************************** - * Private Types - ****************************************************************************/ +struct ist415_config_s; struct ist415_ops_s { - CODE void (*irq_enable)(void); /* Enables the irq */ - CODE void (*irq_disable)(void); /* Disables the irq */ + CODE void (*irq_enable)(struct ist415_config_s *dev); /* Enables the irq */ + CODE void (*irq_disable)(struct ist415_config_s *dev); /* Disables the irq */ + CODE void (*power_off)(struct ist415_config_s *dev); /* low the reset */ + CODE void (*power_on)(struct ist415_config_s *dev); /* High the reset */ }; /* IST415 Device */ -struct ist415_dev_s { - struct i2c_dev_s *i2c; - struct i2c_config_s i2c_config; - bool int_pending; - /* - * This is a interrupt handler for touch. The lower level code will intercept the interrupt - * and provide the uppper level code with private data with interrupt attached. - */ - void (*handler)(struct ist415_dev_s *dev); +struct ist415_config_s { + + void (*handler)(struct ist415_config_s *dev); struct ist415_ops_s *ops; - struct touchscreen_s *upper; - void *priv; /* Used by the chipset-specific logic */ + + void *upper; /* Used by the ist415 common upper structure */ + void *priv; /* Used by the chipset-specific logic */ + }; + +int ist415_initialize(const char *path, struct i2c_dev_s *i2c, struct ist415_config_s *conifg); diff --git a/os/include/tinyara/input/touchscreen.h b/os/include/tinyara/input/touchscreen.h index 3be5720c4a..b121c7c4b8 100644 --- a/os/include/tinyara/input/touchscreen.h +++ b/os/include/tinyara/input/touchscreen.h @@ -190,12 +190,9 @@ struct touch_set_callback_s { * This structure is upper level driver operations which will use lower level calls internally */ struct touchscreen_ops_s { - int (*touch_read)(struct touchscreen_s *priv, FAR char *buffer); /* Read touch point */ - void (*touch_enable)(struct touchscreen_s *dev); /* Enable touch */ - void (*touch_disable)(struct touchscreen_s *dev); /* Disable touch */ - - /* It's set to true when there is touch interrupt and set to false after data is read from device */ - bool (*is_touchSet)(struct touchscreen_s *dev); + int (*touch_read)(struct touchscreen_s *upper, FAR char *buffer); /* Read touch point */ + void (*touch_enable)(struct touchscreen_s *upper); /* Enable touch */ + void (*touch_disable)(struct touchscreen_s *upper); /* Disable touch */ int (*cmd)(struct touchscreen_s *upper, int argc, char **argvc); }; @@ -211,6 +208,7 @@ struct touchscreen_s { sem_t pollsem; struct pollfd *fds[CONFIG_TOUCH_NPOLLWAITERS]; #endif + bool pending; void (*notify_touch)(struct touchscreen_s *dev);