/*
 * ist40xx_main.c
 *
 * Copyright (C) 2019, Samsung Electronics Co., Ltd.
 *
 * Imagis touchscreen routines
 */

#include <errno.h>
#include <driver/interrupt/interrupt.h>
#include <string.h>
#include <tee_internal_api.h>

#include "board.h"
#include "bsp_common.h"
#include "dbg.h"
#include "device.h"
#include "i2c.h"
#include "ist40xx_driver.h"
#include "secmap.h"
#include "touch_gpio.h"

////////////////////////////////////////////////
////////////    TUI HAL API   ////////////////////
////////////////////////////////////////////////

TEE_Result tuiHalTouchGetInfo(drTouchInfo_ptr touchSize)
{
    touchSize->width = ist_data.max_x;
    touchSize->height = ist_data.max_y;
    return TEE_SUCCESS;
}

TEE_Result tuiHalTouchOpen(uint32_t width, uint32_t height, uint32_t touch_type)
{
    deviceInfo_t *touch_dev = &board.touch;
    deviceInfo_t *i2c_dev = &board.i2c;
    deviceInfo_t *gpio_dev = &board.gpio;
    TEE_Result retHal = TEE_ERROR_GENERIC;
    int ret = TEE_ERROR_GENERIC;

    (void)touch_type;

    dbgPrintf(">> %s\n", __func__);

    /* Initialization */
    retHal = touch_gpio_init(gpio_dev);
    if (retHal != TEE_SUCCESS) {
        errPrintf("touch_gpio_init() Failed\n");
        goto err_init_i2c;
    }

    retHal = i2c_init(i2c_dev);
    if (retHal != TEE_SUCCESS) {
        errPrintf("i2c_init() Failed\n");
        goto err_init_i2c;
    }

    if (touch_dev->state == DEV_UNCONFIGURED) {
        /* Init touch module */
        dbgPrintf("Touch Init Start\n");
        TEE_MemFill(&ist_data, 0, sizeof(ist_data));

        ist_data.width = width;
        ist_data.height = height;

        /* Initialize ist4050 touchscreen */
        ret = ist_driver_init(&ist_data);
        if (ret < 0) {
            errPrintf("ist40xx_driver_init() : retval = %d", ret);
            retHal = E_TUI_HAL_IO;
            goto err_init_i2c;
        }
        touch_dev->state |= DEV_SFR_CONFIGURED;
    }

    sec_release();
    dbgPrintf("<< %s\n", __func__);
    return retHal;

err_init_i2c:
    tuiHalTouchClose();
    dbgPrintf("<< %s\n", __func__);
    return retHal;
}

TEE_Result tuiHalTouchClose(void)
{
    dbgPrintf(">> %s\n", __func__);
    deviceInfo_t *i2c_dev = &board.i2c;
    deviceInfo_t *touch_dev = &board.touch;
    deviceInfo_t *gpio_dev = &board.gpio;
    TEE_Result ret;

    ret = touch_gpio_unregister_int(gpio_dev);
    if (ret != TEE_SUCCESS) {
        errPrintf("touch_gpio_unregister_int Failed!\n");
    }
    if (touch_dev->state & DEV_SFR_CONFIGURED) {
        ret = ist_driver_release();
        if (ret != TEE_SUCCESS) {
            errPrintf("ist40xx_driver_release Failed!\n");
        } else {
            touch_dev->state &= ~DEV_SFR_CONFIGURED;
        }
    }
    ret = i2c_release(i2c_dev);
    if (ret != TEE_SUCCESS) {
        errPrintf("i2c_release Failed!\n");
    }
    ret = touch_gpio_release(gpio_dev);
    if (ret != TEE_SUCCESS) {
        errPrintf("touch_gpio_release Failed!\n");
    }

    sec_release();
    touch_dev->state = DEV_UNCONFIGURED;
    dbgPrintf("<< %s\n", __func__);
    return TEE_SUCCESS;
}

TEE_Result tuiHalTouchProcess(void)
{
    int retval = 0;
    deviceInfo_t *touch_dev = &board.touch;

    if (touch_dev->state != DEV_SFR_CONFIGURED && touch_dev->state != DEV_CONFIGURED) {
        return TEE_ERROR_GENERIC;
    }

#ifdef USE_TOUCH_INTERRUPT
    deviceInfo_t *gpio_dev = &board.gpio;

    if (touch_dev->state == DEV_SFR_CONFIGURED) {
        retval = touch_gpio_register_int(gpio_dev, ist_irq_process);
        if (retval != TEE_SUCCESS) {
            errPrintf("touch_gpio_register_int() : retval = %d\n", retval);
            return TEE_ERROR_GENERIC;
        }
        touch_dev->state = DEV_CONFIGURED;
    }
    retval = gpio_wait_touch_irq();
#else /* USE_TOUCH_INTERRUPT */
    retval = ist_irq_process();
#endif /* USE_TOUCH_INTERRUPT */
    if (retval != 0) {
        return TEE_ERROR_GENERIC;
    }
    return TEE_SUCCESS;
}
