/*
 * QEMU Crystal CS4231 audio chip emulation
 *
 * Copyright (c) 2006 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"

/* debug CS4231 */
//#define DEBUG_CS

/*
 * In addition to Crystal CS4231 there is a DMA controller on Sparc.
 */
#define CS_MAXADDR 0x3f
#define CS_SIZE (CS_MAXADDR + 1)
#define CS_REGS 16
#define CS_DREGS 32
#define CS_MAXDREG (CS_DREGS - 1)

typedef struct CSState {
    uint32_t regs[CS_REGS];
    uint8_t dregs[CS_DREGS];
    void *intctl;
} CSState;

#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
#define CS_VER 0xa0
#define CS_CDC_VER 0x8a

#ifdef DEBUG_CS
#define DPRINTF(fmt, args...)                           \
    do { printf("CS: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif

static void cs_reset(void *opaque)
{
    CSState *s = opaque;

    memset(s->regs, 0, CS_REGS * 4);
    memset(s->dregs, 0, CS_DREGS);
    s->dregs[12] = CS_CDC_VER;
    s->dregs[25] = CS_VER;
}

static uint32_t cs_mem_readl(void *opaque, target_phys_addr_t addr)
{
    CSState *s = opaque;
    uint32_t saddr, ret;

    saddr = (addr & CS_MAXADDR) >> 2;
    switch (saddr) {
    case 1:
        switch (CS_RAP(s)) {
        case 3: // Write only
            ret = 0;
            break;
        default:
            ret = s->dregs[CS_RAP(s)];
            break;
        }
        DPRINTF("read dreg[%d]: 0x%8.8x\n", CS_RAP(s), ret);
        break;
    default:
        ret = s->regs[saddr];
        DPRINTF("read reg[%d]: 0x%8.8x\n", saddr, ret);
        break;
    }
    return ret;
}

static void cs_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
    CSState *s = opaque;
    uint32_t saddr;

    saddr = (addr & CS_MAXADDR) >> 2;
    DPRINTF("write reg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->regs[saddr], val);
    switch (saddr) {
    case 1:
        DPRINTF("write dreg[%d]: 0x%2.2x -> 0x%2.2x\n", CS_RAP(s), s->dregs[CS_RAP(s)], val);
        switch(CS_RAP(s)) {
        case 11:
        case 25: // Read only
            break;
        case 12:
            val &= 0x40;
            val |= CS_CDC_VER; // Codec version
            s->dregs[CS_RAP(s)] = val;
            break;
        default:
            s->dregs[CS_RAP(s)] = val;
            break;
        }
        break;
    case 2: // Read only
        break;
    case 4:
        if (val & 1)
            cs_reset(s);
        val &= 0x7f;
        s->regs[saddr] = val;
        break;
    default:
        s->regs[saddr] = val;
        break;
    }
}

static CPUReadMemoryFunc *cs_mem_read[3] = {
    cs_mem_readl,
    cs_mem_readl,
    cs_mem_readl,
};

static CPUWriteMemoryFunc *cs_mem_write[3] = {
    cs_mem_writel,
    cs_mem_writel,
    cs_mem_writel,
};

static void cs_save(QEMUFile *f, void *opaque)
{
    CSState *s = opaque;
    unsigned int i;

    for (i = 0; i < CS_REGS; i++)
        qemu_put_be32s(f, &s->regs[i]);

    qemu_put_buffer(f, s->dregs, CS_DREGS);
}

static int cs_load(QEMUFile *f, void *opaque, int version_id)
{
    CSState *s = opaque;
    unsigned int i;

    if (version_id > 1)
        return -EINVAL;

    for (i = 0; i < CS_REGS; i++)
        qemu_get_be32s(f, &s->regs[i]);

    qemu_get_buffer(f, s->dregs, CS_DREGS);
    return 0;
}

void cs_init(target_phys_addr_t base, int irq, void *intctl)
{
    int cs_io_memory;
    CSState *s;

    s = qemu_mallocz(sizeof(CSState));
    if (!s)
        return;

    cs_io_memory = cpu_register_io_memory(0, cs_mem_read, cs_mem_write, s);
    cpu_register_physical_memory(base, CS_SIZE, cs_io_memory);
    register_savevm("cs4231", base, 1, cs_save, cs_load, s);
    qemu_register_reset(cs_reset, s);
    cs_reset(s);
}
