/*
 * Silicon Image SiI9022
 *
 * This is a pretty hollow emulation: all we do is acknowledge that we
 * exist (chip ID) and confirm that we get switched over into DDC mode
 * so the emulated host can proceed to read out EDID data. All subsequent
 * set-up of connectors etc will be acknowledged and ignored.
 *
 * Copyright (C) 2018 Linus Walleij
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/i2c-ddc.h"
#include "trace.h"

#define SII9022_SYS_CTRL_DATA 0x1a
#define SII9022_SYS_CTRL_PWR_DWN 0x10
#define SII9022_SYS_CTRL_AV_MUTE 0x08
#define SII9022_SYS_CTRL_DDC_BUS_REQ 0x04
#define SII9022_SYS_CTRL_DDC_BUS_GRTD 0x02
#define SII9022_SYS_CTRL_OUTPUT_MODE 0x01
#define SII9022_SYS_CTRL_OUTPUT_HDMI 1
#define SII9022_SYS_CTRL_OUTPUT_DVI 0
#define SII9022_REG_CHIPID 0x1b
#define SII9022_INT_ENABLE 0x3c
#define SII9022_INT_STATUS 0x3d
#define SII9022_INT_STATUS_HOTPLUG 0x01;
#define SII9022_INT_STATUS_PLUGGED 0x04;

#define TYPE_SII9022 "sii9022"
#define SII9022(obj) OBJECT_CHECK(sii9022_state, (obj), TYPE_SII9022)

typedef struct sii9022_state {
    I2CSlave parent_obj;
    uint8_t ptr;
    bool addr_byte;
    bool ddc_req;
    bool ddc_skip_finish;
    bool ddc;
} sii9022_state;

static const VMStateDescription vmstate_sii9022 = {
    .name = "sii9022",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_I2C_SLAVE(parent_obj, sii9022_state),
        VMSTATE_UINT8(ptr, sii9022_state),
        VMSTATE_BOOL(addr_byte, sii9022_state),
        VMSTATE_BOOL(ddc_req, sii9022_state),
        VMSTATE_BOOL(ddc_skip_finish, sii9022_state),
        VMSTATE_BOOL(ddc, sii9022_state),
        VMSTATE_END_OF_LIST()
    }
};

static int sii9022_event(I2CSlave *i2c, enum i2c_event event)
{
    sii9022_state *s = SII9022(i2c);

    switch (event) {
    case I2C_START_SEND:
        s->addr_byte = true;
        break;
    case I2C_START_RECV:
        break;
    case I2C_FINISH:
        break;
    case I2C_NACK:
        break;
    }

    return 0;
}

static int sii9022_rx(I2CSlave *i2c)
{
    sii9022_state *s = SII9022(i2c);
    uint8_t res = 0x00;

    switch (s->ptr) {
    case SII9022_SYS_CTRL_DATA:
        if (s->ddc_req) {
            /* Acknowledge DDC bus request */
            res = SII9022_SYS_CTRL_DDC_BUS_GRTD | SII9022_SYS_CTRL_DDC_BUS_REQ;
        }
        break;
    case SII9022_REG_CHIPID:
        res = 0xb0;
        break;
    case SII9022_INT_STATUS:
        /* Something is cold-plugged in, no interrupts */
        res = SII9022_INT_STATUS_PLUGGED;
        break;
    default:
        break;
    }

    trace_sii9022_read_reg(s->ptr, res);
    s->ptr++;

    return res;
}

static int sii9022_tx(I2CSlave *i2c, uint8_t data)
{
    sii9022_state *s = SII9022(i2c);

    if (s->addr_byte) {
        s->ptr = data;
        s->addr_byte = false;
        return 0;
    }

    switch (s->ptr) {
    case SII9022_SYS_CTRL_DATA:
        if (data & SII9022_SYS_CTRL_DDC_BUS_REQ) {
            s->ddc_req = true;
            if (data & SII9022_SYS_CTRL_DDC_BUS_GRTD) {
                s->ddc = true;
                /* Skip this finish since we just switched to DDC */
                s->ddc_skip_finish = true;
                trace_sii9022_switch_mode("DDC");
            }
        } else {
            s->ddc_req = false;
            s->ddc = false;
            trace_sii9022_switch_mode("normal");
        }
        break;
    default:
        break;
    }

    trace_sii9022_write_reg(s->ptr, data);
    s->ptr++;

    return 0;
}

static void sii9022_reset(DeviceState *dev)
{
    sii9022_state *s = SII9022(dev);

    s->ptr = 0;
    s->addr_byte = false;
    s->ddc_req = false;
    s->ddc_skip_finish = false;
    s->ddc = false;
}

static void sii9022_realize(DeviceState *dev, Error **errp)
{
    I2CBus *bus;

    bus = I2C_BUS(qdev_get_parent_bus(dev));
    i2c_create_slave(bus, TYPE_I2CDDC, 0x50);
}

static void sii9022_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);

    k->event = sii9022_event;
    k->recv = sii9022_rx;
    k->send = sii9022_tx;
    dc->reset = sii9022_reset;
    dc->realize = sii9022_realize;
    dc->vmsd = &vmstate_sii9022;
}

static const TypeInfo sii9022_info = {
    .name          = TYPE_SII9022,
    .parent        = TYPE_I2C_SLAVE,
    .instance_size = sizeof(sii9022_state),
    .class_init    = sii9022_class_init,
};

static void sii9022_register_types(void)
{
    type_register_static(&sii9022_info);
}

type_init(sii9022_register_types)
