/*
 * VIA south bridges sound support
 *
 * Copyright (c) 2022-2023 BALATON Zoltan
 *
 * This work is licensed under the GNU GPL license version 2 or later.
 */

/*
 * TODO: This is only a basic implementation of one audio playback channel
 *       more functionality should be added here.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/isa/vt82c686.h"
#include "ac97.h"
#include "trace.h"

#define CLEN_IS_EOL(x)  ((x)->clen & BIT(31))
#define CLEN_IS_FLAG(x) ((x)->clen & BIT(30))
#define CLEN_IS_STOP(x) ((x)->clen & BIT(29))
#define CLEN_LEN(x)     ((x)->clen & 0xffffff)

#define STAT_ACTIVE BIT(7)
#define STAT_PAUSED BIT(6)
#define STAT_TRIG   BIT(3)
#define STAT_STOP   BIT(2)
#define STAT_EOL    BIT(1)
#define STAT_FLAG   BIT(0)

#define CNTL_START  BIT(7)
#define CNTL_TERM   BIT(6)
#define CNTL_PAUSE  BIT(3)

static void open_voice_out(ViaAC97State *s);

static uint16_t codec_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100,
                                  48000 };

#define CODEC_REG(s, o)  ((s)->codec_regs[(o) / 2])
#define CODEC_VOL(vol, mask)  ((255 * ((vol) & mask)) / mask)

static void codec_volume_set_out(ViaAC97State *s)
{
    int lvol, rvol, mute;

    lvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f);
    lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f);
    lvol /= 255;
    rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f);
    rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f);
    rvol /= 255;
    mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
    mute |= CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT;
    AUD_set_volume_out(s->vo, mute, lvol, rvol);
}

static void codec_reset(ViaAC97State *s)
{
    memset(s->codec_regs, 0, sizeof(s->codec_regs));
    CODEC_REG(s, AC97_Reset) = 0x6a90;
    CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000;
    CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000;
    CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000;
    CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008;
    CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008;
    CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808;
    CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808;
    CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808;
    CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808;
    CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808;
    CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000;
    CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f;
    CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05;
    CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400;
    CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
    CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
    /* Sigmatel 9766 (STAC9766) */
    CODEC_REG(s, AC97_Vendor_ID1) = 0x8384;
    CODEC_REG(s, AC97_Vendor_ID2) = 0x7666;
}

static uint16_t codec_read(ViaAC97State *s, uint8_t addr)
{
    return CODEC_REG(s, addr);
}

static void codec_write(ViaAC97State *s, uint8_t addr, uint16_t val)
{
    trace_via_ac97_codec_write(addr, val);
    switch (addr) {
    case AC97_Reset:
        codec_reset(s);
        return;
    case AC97_Master_Volume_Mute:
    case AC97_PCM_Out_Volume_Mute:
        if (addr == AC97_Master_Volume_Mute) {
            if (val & BIT(13)) {
                val |= 0x1f00;
            }
            if (val & BIT(5)) {
                val |= 0x1f;
            }
        }
        CODEC_REG(s, addr) = val & 0x9f1f;
        codec_volume_set_out(s);
        return;
    case AC97_Extended_Audio_Ctrl_Stat:
        CODEC_REG(s, addr) &= ~EACS_VRA;
        CODEC_REG(s, addr) |= val & EACS_VRA;
        if (!(val & EACS_VRA)) {
            CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
            CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
            open_voice_out(s);
        }
        return;
    case AC97_PCM_Front_DAC_Rate:
    case AC97_PCM_LR_ADC_Rate:
        if (CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
            int i;
            uint16_t rate = val;

            for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) {
                if (rate < codec_rates[i] +
                    (codec_rates[i + 1] - codec_rates[i]) / 2) {
                    rate = codec_rates[i];
                    break;
                }
            }
            if (rate > 48000) {
                rate = 48000;
            }
            CODEC_REG(s, addr) = rate;
            open_voice_out(s);
        }
        return;
    case AC97_Powerdown_Ctrl_Stat:
        CODEC_REG(s, addr) = (val & 0xff00) | (CODEC_REG(s, addr) & 0xff);
        return;
    case AC97_Extended_Audio_ID:
    case AC97_Vendor_ID1:
    case AC97_Vendor_ID2:
        /* Read only registers */
        return;
    default:
        qemu_log_mask(LOG_UNIMP,
                      "via-ac97: Unimplemented codec register 0x%x\n", addr);
        CODEC_REG(s, addr) = val;
    }
}

static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
{
    uint32_t b[2];

    if (c->curr < c->base) {
        c->curr = c->base;
    }
    if (unlikely(pci_dma_read(d, c->curr, b, sizeof(b)) != MEMTX_OK)) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "via-ac97: DMA error reading SGD table\n");
        return;
    }
    c->addr = le32_to_cpu(b[0]);
    c->clen = le32_to_cpu(b[1]);
    trace_via_ac97_sgd_fetch(c->curr, c->addr, CLEN_IS_STOP(c) ? 'S' : '-',
                             CLEN_IS_EOL(c) ? 'E' : '-',
                             CLEN_IS_FLAG(c) ? 'F' : '-', CLEN_LEN(c));
}

static void out_cb(void *opaque, int avail)
{
    ViaAC97State *s = opaque;
    ViaAC97SGDChannel *c = &s->aur;
    int temp, to_copy, copied;
    bool stop = false;
    uint8_t tmpbuf[4096];

    if (c->stat & STAT_PAUSED) {
        return;
    }
    c->stat |= STAT_ACTIVE;
    while (avail && !stop) {
        if (!c->clen) {
            fetch_sgd(c, &s->dev);
        }
        temp = MIN(CLEN_LEN(c), avail);
        while (temp) {
            to_copy = MIN(temp, sizeof(tmpbuf));
            pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy);
            copied = AUD_write(s->vo, tmpbuf, to_copy);
            if (!copied) {
                stop = true;
                break;
            }
            temp -= copied;
            avail -= copied;
            c->addr += copied;
            c->clen -= copied;
        }
        if (CLEN_LEN(c) == 0) {
            c->curr += 8;
            if (CLEN_IS_EOL(c)) {
                c->stat |= STAT_EOL;
                if (c->type & CNTL_START) {
                    c->curr = c->base;
                    c->stat |= STAT_PAUSED;
                } else {
                    c->stat &= ~STAT_ACTIVE;
                    AUD_set_active_out(s->vo, 0);
                }
                if (c->type & STAT_EOL) {
                    via_isa_set_irq(&s->dev, 0, 1);
                }
            }
            if (CLEN_IS_FLAG(c)) {
                c->stat |= STAT_FLAG;
                c->stat |= STAT_PAUSED;
                if (c->type & STAT_FLAG) {
                    via_isa_set_irq(&s->dev, 0, 1);
                }
            }
            if (CLEN_IS_STOP(c)) {
                c->stat |= STAT_STOP;
                c->stat |= STAT_PAUSED;
            }
            c->clen = 0;
            stop = true;
        }
    }
}

static void open_voice_out(ViaAC97State *s)
{
    struct audsettings as = {
        .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate),
        .nchannels = s->aur.type & BIT(4) ? 2 : 1,
        .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
        .endianness = 0,
    };
    s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as);
}

static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size)
{
    ViaAC97State *s = opaque;
    uint64_t val = 0;

    switch (addr) {
    case 0:
        val = s->aur.stat;
        if (s->aur.type & CNTL_START) {
            val |= STAT_TRIG;
        }
        break;
    case 1:
        val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0;
        break;
    case 2:
        val = s->aur.type;
        break;
    case 4:
        val = s->aur.curr;
        break;
    case 0xc:
        val = CLEN_LEN(&s->aur);
        break;
    case 0x10:
        /* silence unimplemented log message that happens at every IRQ */
        break;
    case 0x80:
        val = s->ac97_cmd;
        break;
    case 0x84:
        val = s->aur.stat & STAT_FLAG;
        if (s->aur.stat & STAT_EOL) {
            val |= BIT(4);
        }
        if (s->aur.stat & STAT_STOP) {
            val |= BIT(8);
        }
        if (s->aur.stat & STAT_ACTIVE) {
            val |= BIT(12);
        }
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register read 0x%"
                      HWADDR_PRIx"\n", addr);
    }
    trace_via_ac97_sgd_read(addr, size, val);
    return val;
}

static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
    ViaAC97State *s = opaque;

    trace_via_ac97_sgd_write(addr, size, val);
    switch (addr) {
    case 0:
        if (val & STAT_STOP) {
            s->aur.stat &= ~STAT_PAUSED;
        }
        if (val & STAT_EOL) {
            s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
            if (s->aur.type & STAT_EOL) {
                via_isa_set_irq(&s->dev, 0, 0);
            }
        }
        if (val & STAT_FLAG) {
            s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
            if (s->aur.type & STAT_FLAG) {
                via_isa_set_irq(&s->dev, 0, 0);
            }
        }
        break;
    case 1:
        if (val & CNTL_START) {
            AUD_set_active_out(s->vo, 1);
            s->aur.stat = STAT_ACTIVE;
        }
        if (val & CNTL_TERM) {
            AUD_set_active_out(s->vo, 0);
            s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED);
            s->aur.clen = 0;
        }
        if (val & CNTL_PAUSE) {
            AUD_set_active_out(s->vo, 0);
            s->aur.stat &= ~STAT_ACTIVE;
            s->aur.stat |= STAT_PAUSED;
        } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) {
            AUD_set_active_out(s->vo, 1);
            s->aur.stat |= STAT_ACTIVE;
            s->aur.stat &= ~STAT_PAUSED;
        }
        break;
    case 2:
    {
        uint32_t oldval = s->aur.type;
        s->aur.type = val;
        if ((oldval & 0x30) != (val & 0x30)) {
            open_voice_out(s);
        }
        break;
    }
    case 4:
        s->aur.base = val & ~1ULL;
        s->aur.curr = s->aur.base;
        break;
    case 0x80:
        if (val >> 30) {
            /* we only have primary codec */
            break;
        }
        if (val & BIT(23)) { /* read reg */
            s->ac97_cmd = val & 0xc0ff0000ULL;
            s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f);
            s->ac97_cmd |= BIT(25); /* data valid */
        } else {
            s->ac97_cmd = val & 0xc0ffffffULL;
            codec_write(s, (val >> 16) & 0x7f, val);
        }
        break;
    case 0xc:
    case 0x84:
        /* Read only */
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register write 0x%"
                      HWADDR_PRIx"\n", addr);
    }
}

static const MemoryRegionOps sgd_ops = {
    .read = sgd_read,
    .write = sgd_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static uint64_t fm_read(void *opaque, hwaddr addr, unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
    return 0;
}

static void fm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
                  __func__, addr, size, val);
}

static const MemoryRegionOps fm_ops = {
    .read = fm_read,
    .write = fm_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static uint64_t midi_read(void *opaque, hwaddr addr, unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
    return 0;
}

static void midi_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
    qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
                  __func__, addr, size, val);
}

static const MemoryRegionOps midi_ops = {
    .read = midi_read,
    .write = midi_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void via_ac97_reset(DeviceState *dev)
{
    ViaAC97State *s = VIA_AC97(dev);

    codec_reset(s);
}

static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
{
    ViaAC97State *s = VIA_AC97(pci_dev);
    Object *o = OBJECT(s);

    if (!AUD_register_card ("via-ac97", &s->card, errp)) {
        return;
    }

    /*
     * Command register Bus Master bit is documented to be fixed at 0 but it's
     * needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here
     * and the AmigaOS driver writes 1 only enabling IO bit which works on
     * real hardware. So set it here and fix it to 1 to allow DMA.
     */
    pci_set_word(pci_dev->config + PCI_COMMAND, PCI_COMMAND_MASTER);
    pci_set_word(pci_dev->wmask + PCI_COMMAND, PCI_COMMAND_IO);
    pci_set_word(pci_dev->config + PCI_STATUS,
                 PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM);
    pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
    pci_set_byte(pci_dev->config + 0x40, 1); /* codec ready */

    memory_region_init_io(&s->sgd, o, &sgd_ops, s, "via-ac97.sgd", 256);
    pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->sgd);
    memory_region_init_io(&s->fm, o, &fm_ops, s, "via-ac97.fm", 4);
    pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm);
    memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4);
    pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi);
}

static void via_ac97_exit(PCIDevice *dev)
{
    ViaAC97State *s = VIA_AC97(dev);

    AUD_close_out(&s->card, s->vo);
    AUD_remove_card(&s->card);
}

static Property via_ac97_properties[] = {
    DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
    DEFINE_PROP_END_OF_LIST(),
};

static void via_ac97_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->realize = via_ac97_realize;
    k->exit = via_ac97_exit;
    k->vendor_id = PCI_VENDOR_ID_VIA;
    k->device_id = PCI_DEVICE_ID_VIA_AC97;
    k->revision = 0x50;
    k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
    device_class_set_props(dc, via_ac97_properties);
    set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
    dc->desc = "VIA AC97";
    dc->reset = via_ac97_reset;
    /* Reason: Part of a south bridge chip */
    dc->user_creatable = false;
}

static const TypeInfo via_ac97_info = {
    .name          = TYPE_VIA_AC97,
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(ViaAC97State),
    .class_init    = via_ac97_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

static void via_mc97_realize(PCIDevice *pci_dev, Error **errp)
{
    pci_set_word(pci_dev->config + PCI_COMMAND,
                 PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE);
    pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
    pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
}

static void via_mc97_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->realize = via_mc97_realize;
    k->vendor_id = PCI_VENDOR_ID_VIA;
    k->device_id = PCI_DEVICE_ID_VIA_MC97;
    k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
    k->revision = 0x30;
    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
    dc->desc = "VIA MC97";
    /* Reason: Part of a south bridge chip */
    dc->user_creatable = false;
}

static const TypeInfo via_mc97_info = {
    .name          = TYPE_VIA_MC97,
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIDevice),
    .class_init    = via_mc97_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

static void via_ac97_register_types(void)
{
    type_register_static(&via_ac97_info);
    type_register_static(&via_mc97_info);
}

type_init(via_ac97_register_types)
