/*
 *
 * Copyright (C) 2012-2020, Samsung Electronics Co., Ltd.
 *
 * NoVaTek touchscreen routines
 */

#include <errno.h>
#include <driver/interrupt/interrupt.h>
#include <string.h>
#include <tee_internal_api.h>
#include <tee_spi.h>
#include "board.h"
#include "bsp_common.h"
#include "dbg.h"
#include "device.h"
#include "novatek_driver.h"
#include "secmap.h"
#include "touch_gpio.h"

TEE_Result tuiHalTouchGetInfo(drTouchInfo_ptr touchSize)
{
    touchSize->width = novatek_data.max_x;
    touchSize->height = novatek_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 *gpio_dev = &board.gpio;
    TEE_Result retHal = TEE_ERROR_GENERIC;
    int ret = TEE_ERROR_GENERIC;

    (void)touch_type;

    dbgPrintf(">> %s, %d\n", __func__, touch_type);

    /* Initialization */
    retHal = touch_gpio_init(gpio_dev);
    if (retHal != TEE_SUCCESS) {
        errPrintf("touch_gpio_init() Failed\n");
        goto err_init;
    }

    if (touch_dev->state == DEV_UNCONFIGURED) {
        /* Init touch module */
        dbgPrintf("Touch Init Start\n");
        TEE_MemFill(&novatek_data, 0, sizeof(novatek_data));

        novatek_data.width = width;
        novatek_data.height = height;

        /* Initialize NOVATEK touchscreen */
        ret = nvt_driver_init(&novatek_data);
        if (ret < 0) {
            errPrintf("nvt_driver_init() : retval = %d", ret);
            retHal = E_TUI_HAL_IO;
            goto err_init;
        }
        touch_dev->state |= DEV_SFR_CONFIGURED;
    }

    sec_release();
    dbgPrintf("<< %s\n", __func__);
    return retHal;

err_init:
    tuiHalTouchClose();
    dbgPrintf("<< %s\n", __func__);
    return retHal;
}

TEE_Result tuiHalTouchClose(void)
{
    dbgPrintf(">> %s\n", __func__);
    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 = nvt_driver_release();
        if (ret != TEE_SUCCESS) {
            errPrintf("nvt_driver_release Failed!\n");
        } else {
            touch_dev->state &= ~DEV_SFR_CONFIGURED;
        }
    }

    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;
    dbgPrintf("<< %s\n", __func__);

    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, nvt_irq_process);
        if (retval != TEE_SUCCESS) {
            errPrintf("touch_gpio_register_int() : retval = %d\n", retval);
            return TEE_ERROR_GENERIC;
        }
        touch_dev->state = DEV_CONFIGURED;
        dbgPrintf(" %s, nvt_irq_process int handler registered!\n", __func__);	
    }
    gpio_wait_touch_irq();
#else /* USE_TOUCH_INTERRUPT */
    retval = nvt_irq_process();
#endif /* USE_TOUCH_INTERRUPT */
    if (retval != 0) {
        return TEE_ERROR_GENERIC;
    }
    return TEE_SUCCESS;
}
