From: Laurent Vivier
This is broken as the linux driver seems broken too...
Co-developed-by: Mark Cave-Ayland
Signed-off-by: Mark Cave-Ayland
Signed-off-by: Laurent Vivier
---
hw/audio/Makefile.objs | 1 +
hw/audio/asc.c | 446 +
include/hw/audio/asc.h | 48 ++
3 files changed, 495 insertions(+)
create mode 100644 hw/audio/asc.c
create mode 100644 include/hw/audio/asc.h
diff --git a/hw/audio/Makefile.objs b/hw/audio/Makefile.objs
index 63db383709..44d1ada7b0 100644
--- a/hw/audio/Makefile.objs
+++ b/hw/audio/Makefile.objs
@@ -16,3 +16,4 @@ common-obj-$(CONFIG_MARVELL_88W8618) += marvell_88w8618.o
common-obj-$(CONFIG_MILKYMIST) += milkymist-ac97.o
common-obj-y += soundhw.o
+common-obj-$(CONFIG_ASC) += asc.o
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
new file mode 100644
index 00..4fd23eb8e1
--- /dev/null
+++ b/hw/audio/asc.c
@@ -0,0 +1,446 @@
+/*
+ * QEMU Apple Sound Chip emulation
+ *
+ * Apple Sound Chip (ASC) 344S0063
+ * Enhanced Apple Sound Chip (EASC) 343S1063
+ *
+ * Copyright (c) 2012-2018 Laurent Vivier
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "audio/audio.h"
+#include "hw/audio/asc.h"
+
+/*
+ * Linux doesn't provide information about ASC, see arch/m68k/mac/macboing.c
+ * and arch/m68k/include/asm/mac_asc.h
+ *
+ * best information is coming from MAME:
+ * http://mamedev.org/source/src/emu/sound/asc.h.html
+ * http://mamedev.org/source/src/emu/sound/asc.c.html
+ * Emulation by R. Belmont
+ *
+ * 0x800: VERSION
+ * 0x801: MODE
+ *1=FIFO mode,
+ *2=wavetable mode
+ * 0x802: CONTROL
+ *bit 0=analog or PWM output,
+ *1=stereo/mono,
+ *7=processing time exceeded
+ * 0x803: FIFO MODE
+ *bit 7=clear FIFO,
+ *bit 1="non-ROM companding",
+ *bit 0="ROM companding")
+ * 0x804: FIFO IRQ STATUS
+ *bit 0=ch A 1/2 full,
+ *1=ch A full,
+ *2=ch B 1/2 full,
+ *3=ch B full)
+ * 0x805: WAVETABLE CONTROL
+ *bits 0-3 wavetables 0-3 start
+ * 0x806: VOLUME
+ *bits 2-4 = 3 bit internal ASC volume,
+ *bits 5-7 = volume control sent to Sony sound chip
+ * 0x807: CLOCK RATE
+ *0 = Mac 22257 Hz,
+ *1 = undefined,
+ *2 = 22050 Hz,
+ *3 = 44100 Hz
+ * 0x80a: PLAY REC A
+ * 0x80f: TEST
+ *bits 6-7 = digital test,
+ *bits 4-5 = analog test
+ * 0x810: WAVETABLE 0 PHASE
+ *big-endian 9.15 fixed-point, only 24 bits valid
+ * 0x814: WAVETABLE 0 INCREMENT
+ *big-endian 9.15 fixed-point, only 24 bits valid
+ * 0x818: WAVETABLE 1 PHASE
+ * 0x81C: WAVETABLE 1 INCREMENT
+ * 0x820: WAVETABLE 2 PHASE
+ * 0x824: WAVETABLE 2 INCREMENT
+ * 0x828: WAVETABLE 3 PHASE
+ * 0x82C: WAVETABLE 3 INCREMENT
+ */
+
+#define ASC_LENGTH 0x2000
+#define ASC_BUF_SIZE 0x0800
+
+#define ASC_REG_BASE 0x0800
+enum {
+ASC_VERSION = 0x00,
+ASC_MODE= 0x01,
+ASC_CONTROL = 0x02,
+ASC_FIFOMODE= 0x03,
+ASC_FIFOIRQ = 0x04,
+ASC_WAVECTRL= 0x05,
+ASC_VOLUME = 0x06,
+ASC_CLOCK = 0x07,
+ASC_PLAYRECA= 0x0a,
+ASC_TEST= 0x0f,
+ASC_WAVETABLE = 0x10
+};
+
+static inline uint32_t get_phase(ASCState *s, int channel)
+{
+return be32_to_cpu(*(uint32_t *)(s->regs + ASC_WAVETABLE + channel * 8));
+}
+
+static inline void set_phase(ASCState *s, int channel, uint32_t phase)
+{
+*(uint32_t *)(s->regs + ASC_WAVETABLE + channel * 8) = cpu_to_be32(phase);
+}
+
+static inline uint32_t get_incr(ASCState *s, int channel)
+{
+return be32_to_cpu(*(uint32_t *)(s->regs + ASC_WAVETABLE + 4 +
+ channel * 8));
+}
+
+static inline uint32_t incr_phase(ASCState *s, int channel)
+{
+uint32_t incr = get_incr(s, channel);
+uint32_t phase = get_phase(s, channel);
+
+set_phase(s, channel, phase + incr);
+
+return get_phase(s, channel);
+}
+
+static void generate_fifo(ASCState *s, int free_b)
+{
+int8_t buf[2048];
+int i;
+int to_copy;
+
+do {
+to_copy = audio_MIN(sizeof(buf), free_b);
+for (i = 0; i < (to_copy >> 1); to_copy++) {
+int8_t left, right;
+
+left = s->fifo[s->a_rptr] ^ 0x80;
+right = s->fifo[s->b_rptr + 0x400] ^ 0x80;
+
+if (s->a_cnt) {
+s->a_rptr++;
+s->a_rptr &= 0x3ff;
+s->a_cnt--;
+}
+
+if (s->b_cnt) {
+s->b_rptr++;
+s->b_rptr &= 0x3ff;
+s->b_cnt--;
+}
+
+if (s->type == ASC_TYPE_SONORA) {
+