]> git.proxmox.com Git - qemu.git/commitdiff
hw: move audio devices to hw/audio/, configure via default-configs/
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 5 Feb 2013 11:55:19 +0000 (12:55 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 8 Apr 2013 16:13:13 +0000 (18:13 +0200)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12 files changed:
default-configs/arm-softmmu.mak
default-configs/sparc-softmmu.mak
hw/arm/Makefile.objs
hw/audio/Makefile.objs
hw/audio/cs4231.c [new file with mode: 0644]
hw/audio/marvell_88w8618.c [new file with mode: 0644]
hw/audio/milkymist-ac97.c [new file with mode: 0644]
hw/cs4231.c [deleted file]
hw/lm32/Makefile.objs
hw/marvell_88w8618_audio.c [deleted file]
hw/milkymist-ac97.c [deleted file]
hw/sparc/Makefile.objs

index 7717ea66725c995314f760830dc8481ca8743483..c0e011084b20eeb7dc16e97bcbd5b9b472882ae5 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_PL310=y
 CONFIG_PL330=y
 CONFIG_CADENCE=y
 CONFIG_XGMAC=y
+CONFIG_MARVELL_88W8618=y
 CONFIG_ONENAND=y
 
 CONFIG_VERSATILE_PCI=y
index 6d11ba03690d2c7b74af2e0b2aef19215b0dfe0a..eda87976623cd4e6b6e52260e60fb0f7f08ad586 100644 (file)
@@ -9,3 +9,4 @@ CONFIG_FDC=y
 CONFIG_EMPTY_SLOT=y
 CONFIG_PCNET_COMMON=y
 CONFIG_LANCE=y
+CONFIG_CS4231=y
index ede019da02e09623618362b2d7bcc050379c514b..6582f5a0aad71d35b79a8300ad2a1b71263062c2 100644 (file)
@@ -19,7 +19,7 @@ obj-y += omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
 obj-y += tsc210x.o
 obj-y += blizzard.o cbus.o tusb6010.o
 obj-y += mst_fpga.o
-obj-y += bitbang_i2c.o marvell_88w8618_audio.o
+obj-y += bitbang_i2c.o
 obj-y += framebuffer.o
 obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
index c50c367da7298d58a27f2b9880b4f57ad4e1341e..237510204b46b47ce0e7ace9b428f684690d184a 100644 (file)
@@ -13,4 +13,8 @@ common-obj-$(CONFIG_PCSPK) += pcspk.o
 common-obj-$(CONFIG_WM8750) += wm8750.o
 common-obj-$(CONFIG_PL041) += pl041.o lm4549.o
 
+common-obj-$(CONFIG_CS4231) += cs4231.o
+common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o
+common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o
+
 $(obj)/adlib.o $(obj)/fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c
new file mode 100644 (file)
index 0000000..2975336
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * 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 "hw/sysbus.h"
+#include "trace.h"
+
+/*
+ * In addition to Crystal CS4231 there is a DMA controller on Sparc.
+ */
+#define CS_SIZE 0x40
+#define CS_REGS 16
+#define CS_DREGS 32
+#define CS_MAXDREG (CS_DREGS - 1)
+
+typedef struct CSState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    uint32_t regs[CS_REGS];
+    uint8_t dregs[CS_DREGS];
+} CSState;
+
+#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
+#define CS_VER 0xa0
+#define CS_CDC_VER 0x8a
+
+static void cs_reset(DeviceState *d)
+{
+    CSState *s = container_of(d, CSState, busdev.qdev);
+
+    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 uint64_t cs_mem_read(void *opaque, hwaddr addr,
+                            unsigned size)
+{
+    CSState *s = opaque;
+    uint32_t saddr, ret;
+
+    saddr = addr >> 2;
+    switch (saddr) {
+    case 1:
+        switch (CS_RAP(s)) {
+        case 3: // Write only
+            ret = 0;
+            break;
+        default:
+            ret = s->dregs[CS_RAP(s)];
+            break;
+        }
+        trace_cs4231_mem_readl_dreg(CS_RAP(s), ret);
+        break;
+    default:
+        ret = s->regs[saddr];
+        trace_cs4231_mem_readl_reg(saddr, ret);
+        break;
+    }
+    return ret;
+}
+
+static void cs_mem_write(void *opaque, hwaddr addr,
+                         uint64_t val, unsigned size)
+{
+    CSState *s = opaque;
+    uint32_t saddr;
+
+    saddr = addr >> 2;
+    trace_cs4231_mem_writel_reg(saddr, s->regs[saddr], val);
+    switch (saddr) {
+    case 1:
+        trace_cs4231_mem_writel_dreg(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->busdev.qdev);
+        }
+        val &= 0x7f;
+        s->regs[saddr] = val;
+        break;
+    default:
+        s->regs[saddr] = val;
+        break;
+    }
+}
+
+static const MemoryRegionOps cs_mem_ops = {
+    .read = cs_mem_read,
+    .write = cs_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_cs4231 = {
+    .name ="cs4231",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
+        VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static int cs4231_init1(SysBusDevice *dev)
+{
+    CSState *s = FROM_SYSBUS(CSState, dev);
+
+    memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    return 0;
+}
+
+static Property cs4231_properties[] = {
+    {.name = NULL},
+};
+
+static void cs4231_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = cs4231_init1;
+    dc->reset = cs_reset;
+    dc->vmsd = &vmstate_cs4231;
+    dc->props = cs4231_properties;
+}
+
+static const TypeInfo cs4231_info = {
+    .name          = "SUNW,CS4231",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(CSState),
+    .class_init    = cs4231_class_init,
+};
+
+static void cs4231_register_types(void)
+{
+    type_register_static(&cs4231_info);
+}
+
+type_init(cs4231_register_types)
diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c
new file mode 100644 (file)
index 0000000..f9b68fd
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Marvell 88w8618 audio emulation extracted from
+ * Marvell MV88w8618 / Freecom MusicPal emulation.
+ *
+ * Copyright (c) 2008 Jan Kiszka
+ *
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+#include "hw/i2c/i2c.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+
+#define MP_AUDIO_SIZE           0x00001000
+
+/* Audio register offsets */
+#define MP_AUDIO_PLAYBACK_MODE  0x00
+#define MP_AUDIO_CLOCK_DIV      0x18
+#define MP_AUDIO_IRQ_STATUS     0x20
+#define MP_AUDIO_IRQ_ENABLE     0x24
+#define MP_AUDIO_TX_START_LO    0x28
+#define MP_AUDIO_TX_THRESHOLD   0x2C
+#define MP_AUDIO_TX_STATUS      0x38
+#define MP_AUDIO_TX_START_HI    0x40
+
+/* Status register and IRQ enable bits */
+#define MP_AUDIO_TX_HALF        (1 << 6)
+#define MP_AUDIO_TX_FULL        (1 << 7)
+
+/* Playback mode bits */
+#define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
+#define MP_AUDIO_PLAYBACK_EN    (1 << 7)
+#define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
+#define MP_AUDIO_MONO           (1 << 14)
+
+typedef struct mv88w8618_audio_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq irq;
+    uint32_t playback_mode;
+    uint32_t status;
+    uint32_t irq_enable;
+    uint32_t phys_buf;
+    uint32_t target_buffer;
+    uint32_t threshold;
+    uint32_t play_pos;
+    uint32_t last_free;
+    uint32_t clock_div;
+    void *wm;
+} mv88w8618_audio_state;
+
+static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
+{
+    mv88w8618_audio_state *s = opaque;
+    int16_t *codec_buffer;
+    int8_t buf[4096];
+    int8_t *mem_buffer;
+    int pos, block_size;
+
+    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
+        return;
+    }
+    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
+        free_out <<= 1;
+    }
+    if (!(s->playback_mode & MP_AUDIO_MONO)) {
+        free_out <<= 1;
+    }
+    block_size = s->threshold / 2;
+    if (free_out - s->last_free < block_size) {
+        return;
+    }
+    if (block_size > 4096) {
+        return;
+    }
+    cpu_physical_memory_read(s->target_buffer + s->play_pos, (void *)buf,
+                             block_size);
+    mem_buffer = buf;
+    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
+        if (s->playback_mode & MP_AUDIO_MONO) {
+            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
+            for (pos = 0; pos < block_size; pos += 2) {
+                *codec_buffer++ = *(int16_t *)mem_buffer;
+                *codec_buffer++ = *(int16_t *)mem_buffer;
+                mem_buffer += 2;
+            }
+        } else {
+            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
+                   (uint32_t *)mem_buffer, block_size);
+        }
+    } else {
+        if (s->playback_mode & MP_AUDIO_MONO) {
+            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
+            for (pos = 0; pos < block_size; pos++) {
+                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
+                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
+            }
+        } else {
+            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
+            for (pos = 0; pos < block_size; pos += 2) {
+                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
+                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
+            }
+        }
+    }
+    wm8750_dac_commit(s->wm);
+
+    s->last_free = free_out - block_size;
+
+    if (s->play_pos == 0) {
+        s->status |= MP_AUDIO_TX_HALF;
+        s->play_pos = block_size;
+    } else {
+        s->status |= MP_AUDIO_TX_FULL;
+        s->play_pos = 0;
+    }
+
+    if (s->status & s->irq_enable) {
+        qemu_irq_raise(s->irq);
+    }
+}
+
+static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
+{
+    int rate;
+
+    if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) {
+        rate = 24576000 / 64; /* 24.576MHz */
+    } else {
+        rate = 11289600 / 64; /* 11.2896MHz */
+    }
+    rate /= ((s->clock_div >> 8) & 0xff) + 1;
+
+    wm8750_set_bclk_in(s->wm, rate);
+}
+
+static uint64_t mv88w8618_audio_read(void *opaque, hwaddr offset,
+                                    unsigned size)
+{
+    mv88w8618_audio_state *s = opaque;
+
+    switch (offset) {
+    case MP_AUDIO_PLAYBACK_MODE:
+        return s->playback_mode;
+
+    case MP_AUDIO_CLOCK_DIV:
+        return s->clock_div;
+
+    case MP_AUDIO_IRQ_STATUS:
+        return s->status;
+
+    case MP_AUDIO_IRQ_ENABLE:
+        return s->irq_enable;
+
+    case MP_AUDIO_TX_STATUS:
+        return s->play_pos >> 2;
+
+    default:
+        return 0;
+    }
+}
+
+static void mv88w8618_audio_write(void *opaque, hwaddr offset,
+                                  uint64_t value, unsigned size)
+{
+    mv88w8618_audio_state *s = opaque;
+
+    switch (offset) {
+    case MP_AUDIO_PLAYBACK_MODE:
+        if (value & MP_AUDIO_PLAYBACK_EN &&
+            !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
+            s->status = 0;
+            s->last_free = 0;
+            s->play_pos = 0;
+        }
+        s->playback_mode = value;
+        mv88w8618_audio_clock_update(s);
+        break;
+
+    case MP_AUDIO_CLOCK_DIV:
+        s->clock_div = value;
+        s->last_free = 0;
+        s->play_pos = 0;
+        mv88w8618_audio_clock_update(s);
+        break;
+
+    case MP_AUDIO_IRQ_STATUS:
+        s->status &= ~value;
+        break;
+
+    case MP_AUDIO_IRQ_ENABLE:
+        s->irq_enable = value;
+        if (s->status & s->irq_enable) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+
+    case MP_AUDIO_TX_START_LO:
+        s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
+        s->target_buffer = s->phys_buf;
+        s->play_pos = 0;
+        s->last_free = 0;
+        break;
+
+    case MP_AUDIO_TX_THRESHOLD:
+        s->threshold = (value + 1) * 4;
+        break;
+
+    case MP_AUDIO_TX_START_HI:
+        s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
+        s->target_buffer = s->phys_buf;
+        s->play_pos = 0;
+        s->last_free = 0;
+        break;
+    }
+}
+
+static void mv88w8618_audio_reset(DeviceState *d)
+{
+    mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state,
+                                           SYS_BUS_DEVICE(d));
+
+    s->playback_mode = 0;
+    s->status = 0;
+    s->irq_enable = 0;
+    s->clock_div = 0;
+    s->threshold = 0;
+    s->phys_buf = 0;
+}
+
+static const MemoryRegionOps mv88w8618_audio_ops = {
+    .read = mv88w8618_audio_read,
+    .write = mv88w8618_audio_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int mv88w8618_audio_init(SysBusDevice *dev)
+{
+    mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
+
+    sysbus_init_irq(dev, &s->irq);
+
+    wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
+
+    memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
+                          "audio", MP_AUDIO_SIZE);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static const VMStateDescription mv88w8618_audio_vmsd = {
+    .name = "mv88w8618_audio",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
+        VMSTATE_UINT32(status, mv88w8618_audio_state),
+        VMSTATE_UINT32(irq_enable, mv88w8618_audio_state),
+        VMSTATE_UINT32(phys_buf, mv88w8618_audio_state),
+        VMSTATE_UINT32(target_buffer, mv88w8618_audio_state),
+        VMSTATE_UINT32(threshold, mv88w8618_audio_state),
+        VMSTATE_UINT32(play_pos, mv88w8618_audio_state),
+        VMSTATE_UINT32(last_free, mv88w8618_audio_state),
+        VMSTATE_UINT32(clock_div, mv88w8618_audio_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property mv88w8618_audio_properties[] = {
+    DEFINE_PROP_PTR("wm8750", mv88w8618_audio_state, wm),
+    {/* end of list */},
+};
+
+static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = mv88w8618_audio_init;
+    dc->reset = mv88w8618_audio_reset;
+    dc->vmsd = &mv88w8618_audio_vmsd;
+    dc->props = mv88w8618_audio_properties;
+}
+
+static const TypeInfo mv88w8618_audio_info = {
+    .name          = "mv88w8618_audio",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(mv88w8618_audio_state),
+    .class_init    = mv88w8618_audio_class_init,
+};
+
+static void mv88w8618_register_types(void)
+{
+    type_register_static(&mv88w8618_audio_info);
+}
+
+type_init(mv88w8618_register_types)
diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c
new file mode 100644 (file)
index 0000000..e08e9dc
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ *  QEMU model of the Milkymist System Controller.
+ *
+ *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Specification available at:
+ *   http://www.milkymist.org/socdoc/ac97.pdf
+ */
+
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "trace.h"
+#include "audio/audio.h"
+#include "qemu/error-report.h"
+
+enum {
+    R_AC97_CTRL = 0,
+    R_AC97_ADDR,
+    R_AC97_DATAOUT,
+    R_AC97_DATAIN,
+    R_D_CTRL,
+    R_D_ADDR,
+    R_D_REMAINING,
+    R_RESERVED,
+    R_U_CTRL,
+    R_U_ADDR,
+    R_U_REMAINING,
+    R_MAX
+};
+
+enum {
+    AC97_CTRL_RQEN  = (1<<0),
+    AC97_CTRL_WRITE = (1<<1),
+};
+
+enum {
+    CTRL_EN = (1<<0),
+};
+
+struct MilkymistAC97State {
+    SysBusDevice busdev;
+    MemoryRegion regs_region;
+
+    QEMUSoundCard card;
+    SWVoiceIn *voice_in;
+    SWVoiceOut *voice_out;
+
+    uint32_t regs[R_MAX];
+
+    qemu_irq crrequest_irq;
+    qemu_irq crreply_irq;
+    qemu_irq dmar_irq;
+    qemu_irq dmaw_irq;
+};
+typedef struct MilkymistAC97State MilkymistAC97State;
+
+static void update_voices(MilkymistAC97State *s)
+{
+    if (s->regs[R_D_CTRL] & CTRL_EN) {
+        AUD_set_active_out(s->voice_out, 1);
+    } else {
+        AUD_set_active_out(s->voice_out, 0);
+    }
+
+    if (s->regs[R_U_CTRL] & CTRL_EN) {
+        AUD_set_active_in(s->voice_in, 1);
+    } else {
+        AUD_set_active_in(s->voice_in, 0);
+    }
+}
+
+static uint64_t ac97_read(void *opaque, hwaddr addr,
+                          unsigned size)
+{
+    MilkymistAC97State *s = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    switch (addr) {
+    case R_AC97_CTRL:
+    case R_AC97_ADDR:
+    case R_AC97_DATAOUT:
+    case R_AC97_DATAIN:
+    case R_D_CTRL:
+    case R_D_ADDR:
+    case R_D_REMAINING:
+    case R_U_CTRL:
+    case R_U_ADDR:
+    case R_U_REMAINING:
+        r = s->regs[addr];
+        break;
+
+    default:
+        error_report("milkymist_ac97: read access to unknown register 0x"
+                TARGET_FMT_plx, addr << 2);
+        break;
+    }
+
+    trace_milkymist_ac97_memory_read(addr << 2, r);
+
+    return r;
+}
+
+static void ac97_write(void *opaque, hwaddr addr, uint64_t value,
+                       unsigned size)
+{
+    MilkymistAC97State *s = opaque;
+
+    trace_milkymist_ac97_memory_write(addr, value);
+
+    addr >>= 2;
+    switch (addr) {
+    case R_AC97_CTRL:
+        /* always raise an IRQ according to the direction */
+        if (value & AC97_CTRL_RQEN) {
+            if (value & AC97_CTRL_WRITE) {
+                trace_milkymist_ac97_pulse_irq_crrequest();
+                qemu_irq_pulse(s->crrequest_irq);
+            } else {
+                trace_milkymist_ac97_pulse_irq_crreply();
+                qemu_irq_pulse(s->crreply_irq);
+            }
+        }
+
+        /* RQEN is self clearing */
+        s->regs[addr] = value & ~AC97_CTRL_RQEN;
+        break;
+    case R_D_CTRL:
+    case R_U_CTRL:
+        s->regs[addr] = value;
+        update_voices(s);
+        break;
+    case R_AC97_ADDR:
+    case R_AC97_DATAOUT:
+    case R_AC97_DATAIN:
+    case R_D_ADDR:
+    case R_D_REMAINING:
+    case R_U_ADDR:
+    case R_U_REMAINING:
+        s->regs[addr] = value;
+        break;
+
+    default:
+        error_report("milkymist_ac97: write access to unknown register 0x"
+                TARGET_FMT_plx, addr);
+        break;
+    }
+
+}
+
+static const MemoryRegionOps ac97_mmio_ops = {
+    .read = ac97_read,
+    .write = ac97_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void ac97_in_cb(void *opaque, int avail_b)
+{
+    MilkymistAC97State *s = opaque;
+    uint8_t buf[4096];
+    uint32_t remaining = s->regs[R_U_REMAINING];
+    int temp = audio_MIN(remaining, avail_b);
+    uint32_t addr = s->regs[R_U_ADDR];
+    int transferred = 0;
+
+    trace_milkymist_ac97_in_cb(avail_b, remaining);
+
+    /* prevent from raising an IRQ */
+    if (temp == 0) {
+        return;
+    }
+
+    while (temp) {
+        int acquired, to_copy;
+
+        to_copy = audio_MIN(temp, sizeof(buf));
+        acquired = AUD_read(s->voice_in, buf, to_copy);
+        if (!acquired) {
+            break;
+        }
+
+        cpu_physical_memory_write(addr, buf, acquired);
+
+        temp -= acquired;
+        addr += acquired;
+        transferred += acquired;
+    }
+
+    trace_milkymist_ac97_in_cb_transferred(transferred);
+
+    s->regs[R_U_ADDR] = addr;
+    s->regs[R_U_REMAINING] -= transferred;
+
+    if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) {
+        trace_milkymist_ac97_pulse_irq_dmaw();
+        qemu_irq_pulse(s->dmaw_irq);
+    }
+}
+
+static void ac97_out_cb(void *opaque, int free_b)
+{
+    MilkymistAC97State *s = opaque;
+    uint8_t buf[4096];
+    uint32_t remaining = s->regs[R_D_REMAINING];
+    int temp = audio_MIN(remaining, free_b);
+    uint32_t addr = s->regs[R_D_ADDR];
+    int transferred = 0;
+
+    trace_milkymist_ac97_out_cb(free_b, remaining);
+
+    /* prevent from raising an IRQ */
+    if (temp == 0) {
+        return;
+    }
+
+    while (temp) {
+        int copied, to_copy;
+
+        to_copy = audio_MIN(temp, sizeof(buf));
+        cpu_physical_memory_read(addr, buf, to_copy);
+        copied = AUD_write(s->voice_out, buf, to_copy);
+        if (!copied) {
+            break;
+        }
+        temp -= copied;
+        addr += copied;
+        transferred += copied;
+    }
+
+    trace_milkymist_ac97_out_cb_transferred(transferred);
+
+    s->regs[R_D_ADDR] = addr;
+    s->regs[R_D_REMAINING] -= transferred;
+
+    if ((s->regs[R_D_CTRL] & CTRL_EN) && (s->regs[R_D_REMAINING] == 0)) {
+        trace_milkymist_ac97_pulse_irq_dmar();
+        qemu_irq_pulse(s->dmar_irq);
+    }
+}
+
+static void milkymist_ac97_reset(DeviceState *d)
+{
+    MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev);
+    int i;
+
+    for (i = 0; i < R_MAX; i++) {
+        s->regs[i] = 0;
+    }
+
+    AUD_set_active_in(s->voice_in, 0);
+    AUD_set_active_out(s->voice_out, 0);
+}
+
+static int ac97_post_load(void *opaque, int version_id)
+{
+    MilkymistAC97State *s = opaque;
+
+    update_voices(s);
+
+    return 0;
+}
+
+static int milkymist_ac97_init(SysBusDevice *dev)
+{
+    MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
+
+    struct audsettings as;
+    sysbus_init_irq(dev, &s->crrequest_irq);
+    sysbus_init_irq(dev, &s->crreply_irq);
+    sysbus_init_irq(dev, &s->dmar_irq);
+    sysbus_init_irq(dev, &s->dmaw_irq);
+
+    AUD_register_card("Milkymist AC'97", &s->card);
+
+    as.freq = 48000;
+    as.nchannels = 2;
+    as.fmt = AUD_FMT_S16;
+    as.endianness = 1;
+
+    s->voice_in = AUD_open_in(&s->card, s->voice_in,
+            "mm_ac97.in", s, ac97_in_cb, &as);
+    s->voice_out = AUD_open_out(&s->card, s->voice_out,
+            "mm_ac97.out", s, ac97_out_cb, &as);
+
+    memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
+            "milkymist-ac97", R_MAX * 4);
+    sysbus_init_mmio(dev, &s->regs_region);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_milkymist_ac97 = {
+    .name = "milkymist-ac97",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .post_load = ac97_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = milkymist_ac97_init;
+    dc->reset = milkymist_ac97_reset;
+    dc->vmsd = &vmstate_milkymist_ac97;
+}
+
+static const TypeInfo milkymist_ac97_info = {
+    .name          = "milkymist-ac97",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MilkymistAC97State),
+    .class_init    = milkymist_ac97_class_init,
+};
+
+static void milkymist_ac97_register_types(void)
+{
+    type_register_static(&milkymist_ac97_info);
+}
+
+type_init(milkymist_ac97_register_types)
diff --git a/hw/cs4231.c b/hw/cs4231.c
deleted file mode 100644 (file)
index 2975336..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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 "hw/sysbus.h"
-#include "trace.h"
-
-/*
- * In addition to Crystal CS4231 there is a DMA controller on Sparc.
- */
-#define CS_SIZE 0x40
-#define CS_REGS 16
-#define CS_DREGS 32
-#define CS_MAXDREG (CS_DREGS - 1)
-
-typedef struct CSState {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t regs[CS_REGS];
-    uint8_t dregs[CS_DREGS];
-} CSState;
-
-#define CS_RAP(s) ((s)->regs[0] & CS_MAXDREG)
-#define CS_VER 0xa0
-#define CS_CDC_VER 0x8a
-
-static void cs_reset(DeviceState *d)
-{
-    CSState *s = container_of(d, CSState, busdev.qdev);
-
-    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 uint64_t cs_mem_read(void *opaque, hwaddr addr,
-                            unsigned size)
-{
-    CSState *s = opaque;
-    uint32_t saddr, ret;
-
-    saddr = addr >> 2;
-    switch (saddr) {
-    case 1:
-        switch (CS_RAP(s)) {
-        case 3: // Write only
-            ret = 0;
-            break;
-        default:
-            ret = s->dregs[CS_RAP(s)];
-            break;
-        }
-        trace_cs4231_mem_readl_dreg(CS_RAP(s), ret);
-        break;
-    default:
-        ret = s->regs[saddr];
-        trace_cs4231_mem_readl_reg(saddr, ret);
-        break;
-    }
-    return ret;
-}
-
-static void cs_mem_write(void *opaque, hwaddr addr,
-                         uint64_t val, unsigned size)
-{
-    CSState *s = opaque;
-    uint32_t saddr;
-
-    saddr = addr >> 2;
-    trace_cs4231_mem_writel_reg(saddr, s->regs[saddr], val);
-    switch (saddr) {
-    case 1:
-        trace_cs4231_mem_writel_dreg(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->busdev.qdev);
-        }
-        val &= 0x7f;
-        s->regs[saddr] = val;
-        break;
-    default:
-        s->regs[saddr] = val;
-        break;
-    }
-}
-
-static const MemoryRegionOps cs_mem_ops = {
-    .read = cs_mem_read,
-    .write = cs_mem_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const VMStateDescription vmstate_cs4231 = {
-    .name ="cs4231",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields      = (VMStateField []) {
-        VMSTATE_UINT32_ARRAY(regs, CSState, CS_REGS),
-        VMSTATE_UINT8_ARRAY(dregs, CSState, CS_DREGS),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static int cs4231_init1(SysBusDevice *dev)
-{
-    CSState *s = FROM_SYSBUS(CSState, dev);
-
-    memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-    sysbus_init_irq(dev, &s->irq);
-
-    return 0;
-}
-
-static Property cs4231_properties[] = {
-    {.name = NULL},
-};
-
-static void cs4231_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = cs4231_init1;
-    dc->reset = cs_reset;
-    dc->vmsd = &vmstate_cs4231;
-    dc->props = cs4231_properties;
-}
-
-static const TypeInfo cs4231_info = {
-    .name          = "SUNW,CS4231",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(CSState),
-    .class_init    = cs4231_class_init,
-};
-
-static void cs4231_register_types(void)
-{
-    type_register_static(&cs4231_info);
-}
-
-type_init(cs4231_register_types)
index d72756c8778ef0b2d887f4f080c0eb8cd770f6e0..e328ec8400cb2519a1636d9e7d9b085694ec4717 100644 (file)
@@ -4,7 +4,6 @@ obj-y += lm32_juart.o
 obj-y += lm32_timer.o
 obj-y += lm32_uart.o
 obj-y += lm32_sys.o
-obj-y += milkymist-ac97.o
 obj-y += milkymist-hpdmc.o
 obj-y += milkymist-memcard.o
 obj-y += milkymist-pfpu.o
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
deleted file mode 100644 (file)
index f9b68fd..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Marvell 88w8618 audio emulation extracted from
- * Marvell MV88w8618 / Freecom MusicPal emulation.
- *
- * Copyright (c) 2008 Jan Kiszka
- *
- * This code is licensed under the GNU GPL v2.
- *
- * Contributions after 2012-01-13 are licensed under the terms of the
- * GNU GPL, version 2 or (at your option) any later version.
- */
-#include "hw/sysbus.h"
-#include "hw/hw.h"
-#include "hw/i2c/i2c.h"
-#include "hw/sysbus.h"
-#include "audio/audio.h"
-
-#define MP_AUDIO_SIZE           0x00001000
-
-/* Audio register offsets */
-#define MP_AUDIO_PLAYBACK_MODE  0x00
-#define MP_AUDIO_CLOCK_DIV      0x18
-#define MP_AUDIO_IRQ_STATUS     0x20
-#define MP_AUDIO_IRQ_ENABLE     0x24
-#define MP_AUDIO_TX_START_LO    0x28
-#define MP_AUDIO_TX_THRESHOLD   0x2C
-#define MP_AUDIO_TX_STATUS      0x38
-#define MP_AUDIO_TX_START_HI    0x40
-
-/* Status register and IRQ enable bits */
-#define MP_AUDIO_TX_HALF        (1 << 6)
-#define MP_AUDIO_TX_FULL        (1 << 7)
-
-/* Playback mode bits */
-#define MP_AUDIO_16BIT_SAMPLE   (1 << 0)
-#define MP_AUDIO_PLAYBACK_EN    (1 << 7)
-#define MP_AUDIO_CLOCK_24MHZ    (1 << 9)
-#define MP_AUDIO_MONO           (1 << 14)
-
-typedef struct mv88w8618_audio_state {
-    SysBusDevice busdev;
-    MemoryRegion iomem;
-    qemu_irq irq;
-    uint32_t playback_mode;
-    uint32_t status;
-    uint32_t irq_enable;
-    uint32_t phys_buf;
-    uint32_t target_buffer;
-    uint32_t threshold;
-    uint32_t play_pos;
-    uint32_t last_free;
-    uint32_t clock_div;
-    void *wm;
-} mv88w8618_audio_state;
-
-static void mv88w8618_audio_callback(void *opaque, int free_out, int free_in)
-{
-    mv88w8618_audio_state *s = opaque;
-    int16_t *codec_buffer;
-    int8_t buf[4096];
-    int8_t *mem_buffer;
-    int pos, block_size;
-
-    if (!(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
-        return;
-    }
-    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
-        free_out <<= 1;
-    }
-    if (!(s->playback_mode & MP_AUDIO_MONO)) {
-        free_out <<= 1;
-    }
-    block_size = s->threshold / 2;
-    if (free_out - s->last_free < block_size) {
-        return;
-    }
-    if (block_size > 4096) {
-        return;
-    }
-    cpu_physical_memory_read(s->target_buffer + s->play_pos, (void *)buf,
-                             block_size);
-    mem_buffer = buf;
-    if (s->playback_mode & MP_AUDIO_16BIT_SAMPLE) {
-        if (s->playback_mode & MP_AUDIO_MONO) {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
-            for (pos = 0; pos < block_size; pos += 2) {
-                *codec_buffer++ = *(int16_t *)mem_buffer;
-                *codec_buffer++ = *(int16_t *)mem_buffer;
-                mem_buffer += 2;
-            }
-        } else {
-            memcpy(wm8750_dac_buffer(s->wm, block_size >> 2),
-                   (uint32_t *)mem_buffer, block_size);
-        }
-    } else {
-        if (s->playback_mode & MP_AUDIO_MONO) {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size);
-            for (pos = 0; pos < block_size; pos++) {
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer);
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-            }
-        } else {
-            codec_buffer = wm8750_dac_buffer(s->wm, block_size >> 1);
-            for (pos = 0; pos < block_size; pos += 2) {
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-                *codec_buffer++ = cpu_to_le16(256 * *mem_buffer++);
-            }
-        }
-    }
-    wm8750_dac_commit(s->wm);
-
-    s->last_free = free_out - block_size;
-
-    if (s->play_pos == 0) {
-        s->status |= MP_AUDIO_TX_HALF;
-        s->play_pos = block_size;
-    } else {
-        s->status |= MP_AUDIO_TX_FULL;
-        s->play_pos = 0;
-    }
-
-    if (s->status & s->irq_enable) {
-        qemu_irq_raise(s->irq);
-    }
-}
-
-static void mv88w8618_audio_clock_update(mv88w8618_audio_state *s)
-{
-    int rate;
-
-    if (s->playback_mode & MP_AUDIO_CLOCK_24MHZ) {
-        rate = 24576000 / 64; /* 24.576MHz */
-    } else {
-        rate = 11289600 / 64; /* 11.2896MHz */
-    }
-    rate /= ((s->clock_div >> 8) & 0xff) + 1;
-
-    wm8750_set_bclk_in(s->wm, rate);
-}
-
-static uint64_t mv88w8618_audio_read(void *opaque, hwaddr offset,
-                                    unsigned size)
-{
-    mv88w8618_audio_state *s = opaque;
-
-    switch (offset) {
-    case MP_AUDIO_PLAYBACK_MODE:
-        return s->playback_mode;
-
-    case MP_AUDIO_CLOCK_DIV:
-        return s->clock_div;
-
-    case MP_AUDIO_IRQ_STATUS:
-        return s->status;
-
-    case MP_AUDIO_IRQ_ENABLE:
-        return s->irq_enable;
-
-    case MP_AUDIO_TX_STATUS:
-        return s->play_pos >> 2;
-
-    default:
-        return 0;
-    }
-}
-
-static void mv88w8618_audio_write(void *opaque, hwaddr offset,
-                                  uint64_t value, unsigned size)
-{
-    mv88w8618_audio_state *s = opaque;
-
-    switch (offset) {
-    case MP_AUDIO_PLAYBACK_MODE:
-        if (value & MP_AUDIO_PLAYBACK_EN &&
-            !(s->playback_mode & MP_AUDIO_PLAYBACK_EN)) {
-            s->status = 0;
-            s->last_free = 0;
-            s->play_pos = 0;
-        }
-        s->playback_mode = value;
-        mv88w8618_audio_clock_update(s);
-        break;
-
-    case MP_AUDIO_CLOCK_DIV:
-        s->clock_div = value;
-        s->last_free = 0;
-        s->play_pos = 0;
-        mv88w8618_audio_clock_update(s);
-        break;
-
-    case MP_AUDIO_IRQ_STATUS:
-        s->status &= ~value;
-        break;
-
-    case MP_AUDIO_IRQ_ENABLE:
-        s->irq_enable = value;
-        if (s->status & s->irq_enable) {
-            qemu_irq_raise(s->irq);
-        }
-        break;
-
-    case MP_AUDIO_TX_START_LO:
-        s->phys_buf = (s->phys_buf & 0xFFFF0000) | (value & 0xFFFF);
-        s->target_buffer = s->phys_buf;
-        s->play_pos = 0;
-        s->last_free = 0;
-        break;
-
-    case MP_AUDIO_TX_THRESHOLD:
-        s->threshold = (value + 1) * 4;
-        break;
-
-    case MP_AUDIO_TX_START_HI:
-        s->phys_buf = (s->phys_buf & 0xFFFF) | (value << 16);
-        s->target_buffer = s->phys_buf;
-        s->play_pos = 0;
-        s->last_free = 0;
-        break;
-    }
-}
-
-static void mv88w8618_audio_reset(DeviceState *d)
-{
-    mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state,
-                                           SYS_BUS_DEVICE(d));
-
-    s->playback_mode = 0;
-    s->status = 0;
-    s->irq_enable = 0;
-    s->clock_div = 0;
-    s->threshold = 0;
-    s->phys_buf = 0;
-}
-
-static const MemoryRegionOps mv88w8618_audio_ops = {
-    .read = mv88w8618_audio_read,
-    .write = mv88w8618_audio_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int mv88w8618_audio_init(SysBusDevice *dev)
-{
-    mv88w8618_audio_state *s = FROM_SYSBUS(mv88w8618_audio_state, dev);
-
-    sysbus_init_irq(dev, &s->irq);
-
-    wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s);
-
-    memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s,
-                          "audio", MP_AUDIO_SIZE);
-    sysbus_init_mmio(dev, &s->iomem);
-
-    return 0;
-}
-
-static const VMStateDescription mv88w8618_audio_vmsd = {
-    .name = "mv88w8618_audio",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .fields = (VMStateField[]) {
-        VMSTATE_UINT32(playback_mode, mv88w8618_audio_state),
-        VMSTATE_UINT32(status, mv88w8618_audio_state),
-        VMSTATE_UINT32(irq_enable, mv88w8618_audio_state),
-        VMSTATE_UINT32(phys_buf, mv88w8618_audio_state),
-        VMSTATE_UINT32(target_buffer, mv88w8618_audio_state),
-        VMSTATE_UINT32(threshold, mv88w8618_audio_state),
-        VMSTATE_UINT32(play_pos, mv88w8618_audio_state),
-        VMSTATE_UINT32(last_free, mv88w8618_audio_state),
-        VMSTATE_UINT32(clock_div, mv88w8618_audio_state),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static Property mv88w8618_audio_properties[] = {
-    DEFINE_PROP_PTR("wm8750", mv88w8618_audio_state, wm),
-    {/* end of list */},
-};
-
-static void mv88w8618_audio_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = mv88w8618_audio_init;
-    dc->reset = mv88w8618_audio_reset;
-    dc->vmsd = &mv88w8618_audio_vmsd;
-    dc->props = mv88w8618_audio_properties;
-}
-
-static const TypeInfo mv88w8618_audio_info = {
-    .name          = "mv88w8618_audio",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(mv88w8618_audio_state),
-    .class_init    = mv88w8618_audio_class_init,
-};
-
-static void mv88w8618_register_types(void)
-{
-    type_register_static(&mv88w8618_audio_info);
-}
-
-type_init(mv88w8618_register_types)
diff --git a/hw/milkymist-ac97.c b/hw/milkymist-ac97.c
deleted file mode 100644 (file)
index e08e9dc..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *  QEMU model of the Milkymist System Controller.
- *
- *  Copyright (c) 2010 Michael Walle <michael@walle.cc>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Specification available at:
- *   http://www.milkymist.org/socdoc/ac97.pdf
- */
-
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "audio/audio.h"
-#include "qemu/error-report.h"
-
-enum {
-    R_AC97_CTRL = 0,
-    R_AC97_ADDR,
-    R_AC97_DATAOUT,
-    R_AC97_DATAIN,
-    R_D_CTRL,
-    R_D_ADDR,
-    R_D_REMAINING,
-    R_RESERVED,
-    R_U_CTRL,
-    R_U_ADDR,
-    R_U_REMAINING,
-    R_MAX
-};
-
-enum {
-    AC97_CTRL_RQEN  = (1<<0),
-    AC97_CTRL_WRITE = (1<<1),
-};
-
-enum {
-    CTRL_EN = (1<<0),
-};
-
-struct MilkymistAC97State {
-    SysBusDevice busdev;
-    MemoryRegion regs_region;
-
-    QEMUSoundCard card;
-    SWVoiceIn *voice_in;
-    SWVoiceOut *voice_out;
-
-    uint32_t regs[R_MAX];
-
-    qemu_irq crrequest_irq;
-    qemu_irq crreply_irq;
-    qemu_irq dmar_irq;
-    qemu_irq dmaw_irq;
-};
-typedef struct MilkymistAC97State MilkymistAC97State;
-
-static void update_voices(MilkymistAC97State *s)
-{
-    if (s->regs[R_D_CTRL] & CTRL_EN) {
-        AUD_set_active_out(s->voice_out, 1);
-    } else {
-        AUD_set_active_out(s->voice_out, 0);
-    }
-
-    if (s->regs[R_U_CTRL] & CTRL_EN) {
-        AUD_set_active_in(s->voice_in, 1);
-    } else {
-        AUD_set_active_in(s->voice_in, 0);
-    }
-}
-
-static uint64_t ac97_read(void *opaque, hwaddr addr,
-                          unsigned size)
-{
-    MilkymistAC97State *s = opaque;
-    uint32_t r = 0;
-
-    addr >>= 2;
-    switch (addr) {
-    case R_AC97_CTRL:
-    case R_AC97_ADDR:
-    case R_AC97_DATAOUT:
-    case R_AC97_DATAIN:
-    case R_D_CTRL:
-    case R_D_ADDR:
-    case R_D_REMAINING:
-    case R_U_CTRL:
-    case R_U_ADDR:
-    case R_U_REMAINING:
-        r = s->regs[addr];
-        break;
-
-    default:
-        error_report("milkymist_ac97: read access to unknown register 0x"
-                TARGET_FMT_plx, addr << 2);
-        break;
-    }
-
-    trace_milkymist_ac97_memory_read(addr << 2, r);
-
-    return r;
-}
-
-static void ac97_write(void *opaque, hwaddr addr, uint64_t value,
-                       unsigned size)
-{
-    MilkymistAC97State *s = opaque;
-
-    trace_milkymist_ac97_memory_write(addr, value);
-
-    addr >>= 2;
-    switch (addr) {
-    case R_AC97_CTRL:
-        /* always raise an IRQ according to the direction */
-        if (value & AC97_CTRL_RQEN) {
-            if (value & AC97_CTRL_WRITE) {
-                trace_milkymist_ac97_pulse_irq_crrequest();
-                qemu_irq_pulse(s->crrequest_irq);
-            } else {
-                trace_milkymist_ac97_pulse_irq_crreply();
-                qemu_irq_pulse(s->crreply_irq);
-            }
-        }
-
-        /* RQEN is self clearing */
-        s->regs[addr] = value & ~AC97_CTRL_RQEN;
-        break;
-    case R_D_CTRL:
-    case R_U_CTRL:
-        s->regs[addr] = value;
-        update_voices(s);
-        break;
-    case R_AC97_ADDR:
-    case R_AC97_DATAOUT:
-    case R_AC97_DATAIN:
-    case R_D_ADDR:
-    case R_D_REMAINING:
-    case R_U_ADDR:
-    case R_U_REMAINING:
-        s->regs[addr] = value;
-        break;
-
-    default:
-        error_report("milkymist_ac97: write access to unknown register 0x"
-                TARGET_FMT_plx, addr);
-        break;
-    }
-
-}
-
-static const MemoryRegionOps ac97_mmio_ops = {
-    .read = ac97_read,
-    .write = ac97_write,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static void ac97_in_cb(void *opaque, int avail_b)
-{
-    MilkymistAC97State *s = opaque;
-    uint8_t buf[4096];
-    uint32_t remaining = s->regs[R_U_REMAINING];
-    int temp = audio_MIN(remaining, avail_b);
-    uint32_t addr = s->regs[R_U_ADDR];
-    int transferred = 0;
-
-    trace_milkymist_ac97_in_cb(avail_b, remaining);
-
-    /* prevent from raising an IRQ */
-    if (temp == 0) {
-        return;
-    }
-
-    while (temp) {
-        int acquired, to_copy;
-
-        to_copy = audio_MIN(temp, sizeof(buf));
-        acquired = AUD_read(s->voice_in, buf, to_copy);
-        if (!acquired) {
-            break;
-        }
-
-        cpu_physical_memory_write(addr, buf, acquired);
-
-        temp -= acquired;
-        addr += acquired;
-        transferred += acquired;
-    }
-
-    trace_milkymist_ac97_in_cb_transferred(transferred);
-
-    s->regs[R_U_ADDR] = addr;
-    s->regs[R_U_REMAINING] -= transferred;
-
-    if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) {
-        trace_milkymist_ac97_pulse_irq_dmaw();
-        qemu_irq_pulse(s->dmaw_irq);
-    }
-}
-
-static void ac97_out_cb(void *opaque, int free_b)
-{
-    MilkymistAC97State *s = opaque;
-    uint8_t buf[4096];
-    uint32_t remaining = s->regs[R_D_REMAINING];
-    int temp = audio_MIN(remaining, free_b);
-    uint32_t addr = s->regs[R_D_ADDR];
-    int transferred = 0;
-
-    trace_milkymist_ac97_out_cb(free_b, remaining);
-
-    /* prevent from raising an IRQ */
-    if (temp == 0) {
-        return;
-    }
-
-    while (temp) {
-        int copied, to_copy;
-
-        to_copy = audio_MIN(temp, sizeof(buf));
-        cpu_physical_memory_read(addr, buf, to_copy);
-        copied = AUD_write(s->voice_out, buf, to_copy);
-        if (!copied) {
-            break;
-        }
-        temp -= copied;
-        addr += copied;
-        transferred += copied;
-    }
-
-    trace_milkymist_ac97_out_cb_transferred(transferred);
-
-    s->regs[R_D_ADDR] = addr;
-    s->regs[R_D_REMAINING] -= transferred;
-
-    if ((s->regs[R_D_CTRL] & CTRL_EN) && (s->regs[R_D_REMAINING] == 0)) {
-        trace_milkymist_ac97_pulse_irq_dmar();
-        qemu_irq_pulse(s->dmar_irq);
-    }
-}
-
-static void milkymist_ac97_reset(DeviceState *d)
-{
-    MilkymistAC97State *s = container_of(d, MilkymistAC97State, busdev.qdev);
-    int i;
-
-    for (i = 0; i < R_MAX; i++) {
-        s->regs[i] = 0;
-    }
-
-    AUD_set_active_in(s->voice_in, 0);
-    AUD_set_active_out(s->voice_out, 0);
-}
-
-static int ac97_post_load(void *opaque, int version_id)
-{
-    MilkymistAC97State *s = opaque;
-
-    update_voices(s);
-
-    return 0;
-}
-
-static int milkymist_ac97_init(SysBusDevice *dev)
-{
-    MilkymistAC97State *s = FROM_SYSBUS(typeof(*s), dev);
-
-    struct audsettings as;
-    sysbus_init_irq(dev, &s->crrequest_irq);
-    sysbus_init_irq(dev, &s->crreply_irq);
-    sysbus_init_irq(dev, &s->dmar_irq);
-    sysbus_init_irq(dev, &s->dmaw_irq);
-
-    AUD_register_card("Milkymist AC'97", &s->card);
-
-    as.freq = 48000;
-    as.nchannels = 2;
-    as.fmt = AUD_FMT_S16;
-    as.endianness = 1;
-
-    s->voice_in = AUD_open_in(&s->card, s->voice_in,
-            "mm_ac97.in", s, ac97_in_cb, &as);
-    s->voice_out = AUD_open_out(&s->card, s->voice_out,
-            "mm_ac97.out", s, ac97_out_cb, &as);
-
-    memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s,
-            "milkymist-ac97", R_MAX * 4);
-    sysbus_init_mmio(dev, &s->regs_region);
-
-    return 0;
-}
-
-static const VMStateDescription vmstate_milkymist_ac97 = {
-    .name = "milkymist-ac97",
-    .version_id = 1,
-    .minimum_version_id = 1,
-    .minimum_version_id_old = 1,
-    .post_load = ac97_post_load,
-    .fields      = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, MilkymistAC97State, R_MAX),
-        VMSTATE_END_OF_LIST()
-    }
-};
-
-static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
-
-    k->init = milkymist_ac97_init;
-    dc->reset = milkymist_ac97_reset;
-    dc->vmsd = &vmstate_milkymist_ac97;
-}
-
-static const TypeInfo milkymist_ac97_info = {
-    .name          = "milkymist-ac97",
-    .parent        = TYPE_SYS_BUS_DEVICE,
-    .instance_size = sizeof(MilkymistAC97State),
-    .class_init    = milkymist_ac97_class_init,
-};
-
-static void milkymist_ac97_register_types(void)
-{
-    type_register_static(&milkymist_ac97_info);
-}
-
-type_init(milkymist_ac97_register_types)
index 56eeb9012b7b3678469469e4af98862c68675066..b2a921e7e10e1bd5035f2ba4b0aea3fa9604ee0f 100644 (file)
@@ -1,6 +1,6 @@
 obj-y = tcx.o sun4m_iommu.o slavio_intctl.o
 obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o
+obj-y += eccmemctl.o sbi.o sun4c_intctl.o
 
 # GRLIB
 obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o