/*
 * dpcd.c
 *
 *  Copyright (C) 2015 : GreenSocs Ltd
 *      http://www.greensocs.com/ , email: info@greensocs.com
 *
 *  Developed by :
 *  Frederic Konrad   <fred.konrad@greensocs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option)any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 * This is a simple AUX slave which emulates a connected screen.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/misc/auxbus.h"
#include "hw/display/dpcd.h"

#ifndef DEBUG_DPCD
#define DEBUG_DPCD 0
#endif

#define DPRINTF(fmt, ...) do {                                                 \
    if (DEBUG_DPCD) {                                                          \
        qemu_log("dpcd: " fmt, ## __VA_ARGS__);                                \
    }                                                                          \
} while (0)

#define DPCD_READABLE_AREA                      0x600

struct DPCDState {
    /*< private >*/
    AUXSlave parent_obj;

    /*< public >*/
    /*
     * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
     */
    uint8_t dpcd_info[DPCD_READABLE_AREA];

    MemoryRegion iomem;
};

static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
{
    uint8_t ret;
    DPCDState *e = DPCD(opaque);

    if (offset < DPCD_READABLE_AREA) {
        ret = e->dpcd_info[offset];
    } else {
        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
                                       offset);
        ret = 0;
    }

    DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
    return ret;
}

static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
                       unsigned size)
{
    DPCDState *e = DPCD(opaque);

    DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);

    if (offset < DPCD_READABLE_AREA) {
        e->dpcd_info[offset] = value;
    } else {
        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
                                       offset);
    }
}

static const MemoryRegionOps aux_ops = {
    .read = dpcd_read,
    .write = dpcd_write,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

static void dpcd_reset(DeviceState *dev)
{
    DPCDState *s = DPCD(dev);

    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));

    s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
    s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
    s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
    /* buffer size */
    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;

    s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
                                      | DPCD_LANE0_CHANNEL_EQ_DONE
                                      | DPCD_LANE0_SYMBOL_LOCKED
                                      | DPCD_LANE1_CR_DONE
                                      | DPCD_LANE1_CHANNEL_EQ_DONE
                                      | DPCD_LANE1_SYMBOL_LOCKED;
    s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
                                      | DPCD_LANE2_CHANNEL_EQ_DONE
                                      | DPCD_LANE2_SYMBOL_LOCKED
                                      | DPCD_LANE3_CR_DONE
                                      | DPCD_LANE3_CHANNEL_EQ_DONE
                                      | DPCD_LANE3_SYMBOL_LOCKED;

    s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
    s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
}

static void dpcd_init(Object *obj)
{
    DPCDState *s = DPCD(obj);

    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
}

static const VMStateDescription vmstate_dpcd = {
    .name = TYPE_DPCD,
    .version_id = 0,
    .minimum_version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
        VMSTATE_END_OF_LIST()
    }
};

static void dpcd_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->reset = dpcd_reset;
    dc->vmsd = &vmstate_dpcd;
}

static const TypeInfo dpcd_info = {
    .name          = TYPE_DPCD,
    .parent        = TYPE_AUX_SLAVE,
    .instance_size = sizeof(DPCDState),
    .class_init    = dpcd_class_init,
    .instance_init = dpcd_init,
};

static void dpcd_register_types(void)
{
    type_register_static(&dpcd_info);
}

type_init(dpcd_register_types)
