/*
 *
 * Copyright (C) 2012-2019, Samsung Electronics Co., Ltd.
 *
 * RMI4 func.0x01 implementation
 */

#include "rmi.h"
#include "rmi_driver.h"

#define F01_SLEEP_MASK	 0x03
#define F01_CONFIGURED	 (1 << 7)

enum f01_sleep_modes {
    normal_operation = 0x00,
    sensor_sleep     = 0x01,
    reserved_1       = 0x02,
    reserved_2       = 0x03,
};

static int rmi_f01_init(rmi_function_container_t *fc);
static int rmi_f01_attention(rmi_function_container_t *fc, uint8_t irq_bits);

static rmi_function_container_t function_handler = {
    .func      = 0x01,
    .init      = rmi_f01_init,
    .attention = rmi_f01_attention,
};

static int rmi_f01_init(rmi_function_container_t *fc)
{
    int error;
    uint8_t temp;
    rmi_device_t *rmi_dev;

    rmi_dev = fc->rmi_dev;

    /* set F01_CONFIGURED bit */
    error = rmi_read_byte(rmi_dev, fc->fd.control_base_addr, &temp);
    if (error < 0) {
        return error;
    }
    temp = (temp & ~F01_SLEEP_MASK) | F01_CONFIGURED;
    error = rmi_write_byte(rmi_dev, fc->fd.control_base_addr, temp);
    if (error < 0) {
        return error;
    }
    /* enable irqs and then read them to clear them */
    error = rmi_write_byte(rmi_dev, fc->fd.control_base_addr + 1, 0xff);
    if (error < 0) {
        return error;
    }
    error = rmi_read_byte(rmi_dev, fc->fd.data_base_addr + 1, &temp);
    if (error < 0) {
        return error;
    }
    error = rmi_read_byte(rmi_dev, fc->fd.query_base_addr, &rmi_dev->manufacturer_id);
    if (error < 0) {
        return error;
    }
    error = rmi_read_block(rmi_dev, fc->fd.query_base_addr + 11, rmi_dev->product_id, RMI_PRODUCT_ID_LENGTH);
    if (error != RMI_PRODUCT_ID_LENGTH) {
        return error;
    }
    rmi_dev->product_id[RMI_PRODUCT_ID_LENGTH] = '\0';
    RMI_DBG("Product: %s\n", rmi_dev->product_id);

    error = rmi_read_byte(rmi_dev, fc->fd.data_base_addr, &temp);
    if (error < 0) {
        return error;
    }
    if (temp & F01_CONFIGURED) {
        RMI_ERR("Device reset during configuration process!");
        return ERROR_RMI_FAILED;
    }
    RMI_DBG("F01 Function init done.");
    return 0;
}

static int rmi_f01_attention(rmi_function_container_t *fc, uint8_t irq_bits)
{
    (void)fc;
    (void)irq_bits;
    return 0;
}

int rmi_fn01_register(rmi_device_t *rmi_dev, rmi_function_descriptor_t *fd)
{
    int error;

    error = rmi_bus_register_function(rmi_dev, &function_handler, fd);
    if (error < 0) {
        RMI_ERR("registration failed. err = %d", error);
        return error;
    }
    return 0;
}
