Lines Matching +full:left +full:- +full:shift

7  * Copyright (c) 2012-2018 Laurent Vivier <laurent@vivier.eu>
8 * Copyright (c) 2022 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
10 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include "hw/qdev-properties.h"
45 * bit 1="non-ROM companding",
53 * bits 0-3 wavetables 0-3 start
55 * bits 2-4 = 3 bit internal ASC volume,
56 * bits 5-7 = volume control sent to Sony sound chip
64 * bits 6-7 = digital test,
65 * bits 4-5 = analog test
67 * big-endian 9.15 fixed-point, only 24 bits valid
69 * big-endian 9.15 fixed-point, only 24 bits valid
110 qemu_set_irq(s->irq, 1); in asc_raise_irq()
115 qemu_set_irq(s->irq, 0); in asc_lower_irq()
120 ASCState *s = container_of(fs, ASCState, fifos[fs->index]); in asc_fifo_get()
121 bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1; in asc_fifo_get()
124 assert(fs->cnt); in asc_fifo_get()
126 val = fs->fifo[fs->rptr]; in asc_fifo_get()
127 trace_asc_fifo_get('A' + fs->index, fs->rptr, fs->cnt, val); in asc_fifo_get()
129 fs->rptr++; in asc_fifo_get()
130 fs->rptr &= 0x3ff; in asc_fifo_get()
131 fs->cnt--; in asc_fifo_get()
133 if (fs->cnt <= 0x1ff) { in asc_fifo_get()
135 fs->int_status |= ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_get()
138 fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_get()
141 if (fs->cnt == 0x1ff && fifo_half_irq_enabled) { in asc_fifo_get()
146 if (fs->cnt == 0) { in asc_fifo_get()
148 fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY; in asc_fifo_get()
158 uint8_t *buf = s->mixbuf; in generate_fifo()
165 int shift, filter; in generate_fifo() local
169 ASCFIFOState *fs = &s->fifos[i]; in generate_fifo()
171 switch (fs->extregs[ASC_EXTREGS_FIFOCTRL] & 0x83) { in generate_fifo()
174 * CD-XA BRR mode: decompress 15 bytes into 28 16-bit in generate_fifo()
177 if (!fs->cnt) { in generate_fifo()
182 if (fs->xa_cnt == -1) { in generate_fifo()
184 fs->xa_flags = asc_fifo_get(fs); in generate_fifo()
185 fs->xa_cnt = 0; in generate_fifo()
188 shift = fs->xa_flags & 0xf; in generate_fifo()
189 filter = fs->xa_flags >> 4; in generate_fifo()
190 f0 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT + in generate_fifo()
192 f1 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT + in generate_fifo()
195 if ((fs->xa_cnt & 1) == 0) { in generate_fifo()
196 if (!fs->cnt) { in generate_fifo()
201 fs->xa_val = asc_fifo_get(fs); in generate_fifo()
202 d = (fs->xa_val & 0xf) << 12; in generate_fifo()
204 d = (fs->xa_val & 0xf0) << 8; in generate_fifo()
206 t = (d >> shift) + (((fs->xa_last[0] * f0) + in generate_fifo()
207 (fs->xa_last[1] * f1) + 32) >> 6); in generate_fifo()
208 if (t < -32768) { in generate_fifo()
209 t = -32768; in generate_fifo()
215 * CD-XA BRR generates 16-bit signed output, so convert to in generate_fifo()
216 * 8-bit before writing to buffer. Does real hardware do the in generate_fifo()
221 fs->xa_cnt++; in generate_fifo()
223 fs->xa_last[1] = fs->xa_last[0]; in generate_fifo()
224 fs->xa_last[0] = (int16_t)t; in generate_fifo()
226 if (fs->xa_cnt == 28) { in generate_fifo()
228 fs->xa_cnt = -1; in generate_fifo()
236 if (fs->cnt) { in generate_fifo()
261 if (s->fifos[0].cnt == 0 && s->fifos[1].cnt == 0) { in generate_fifo()
262 if (!s->fifo_empty_ns) { in generate_fifo()
264 s->fifo_empty_ns = now; in generate_fifo()
265 } else if (now > (s->fifo_empty_ns + ASC_FIFO_CYCLE_TIME)) { in generate_fifo()
267 s->fifos[0].int_status |= ASC_FIFO_STATUS_HALF_FULL | in generate_fifo()
269 s->fifos[1].int_status |= ASC_FIFO_STATUS_HALF_FULL | in generate_fifo()
271 s->fifo_empty_ns = now; in generate_fifo()
276 s->fifo_empty_ns = 0; in generate_fifo()
284 uint8_t *buf = s->mixbuf; in generate_wavetable()
288 uint32_t left = 0, right = 0; in generate_wavetable() local
292 ASCFIFOState *fs = &s->fifos[channel >> 1]; in generate_wavetable()
296 phase = ldl_be_p(&s->regs[chanreg]); in generate_wavetable()
297 incr = ldl_be_p(&s->regs[chanreg + sizeof(uint32_t)]); in generate_wavetable()
301 sample = fs->fifo[0x200 * (channel >> 1) + offset]; in generate_wavetable()
303 stl_be_p(&s->regs[chanreg], phase); in generate_wavetable()
305 left += sample; in generate_wavetable()
309 buf[count * 2] = left >> 2; in generate_wavetable()
327 samples = MIN(s->samples, free_b >> s->shift); in asc_out_cb()
329 switch (s->regs[ASC_MODE] & 3) { in asc_out_cb()
347 int silent_samples = muldiv64(now - s->fifo_empty_ns, in asc_out_cb()
358 AUD_write(s->voice, s->silentbuf, samples << s->shift); in asc_out_cb()
363 AUD_write(s->voice, s->mixbuf, generated << s->shift); in asc_out_cb()
371 trace_asc_read_fifo('A' + fs->index, addr, size, fs->fifo[addr]); in asc_fifo_read()
372 return fs->fifo[addr]; in asc_fifo_read()
379 ASCState *s = container_of(fs, ASCState, fifos[fs->index]); in asc_fifo_write()
380 bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1; in asc_fifo_write()
382 trace_asc_write_fifo('A' + fs->index, addr, size, fs->wptr, fs->cnt, value); in asc_fifo_write()
384 if (s->regs[ASC_MODE] == 1) { in asc_fifo_write()
385 fs->fifo[fs->wptr++] = value; in asc_fifo_write()
386 fs->wptr &= 0x3ff; in asc_fifo_write()
387 fs->cnt++; in asc_fifo_write()
389 if (fs->cnt <= 0x1ff) { in asc_fifo_write()
391 fs->int_status |= ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_write()
394 fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_write()
397 if (fs->cnt == 0x200 && fifo_half_irq_enabled) { in asc_fifo_write()
402 if (fs->cnt == 0x3ff) { in asc_fifo_write()
404 fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY; in asc_fifo_write()
408 fs->fifo[addr] = value; in asc_fifo_write()
432 switch (s->type) { in asc_read()
443 prev = (s->fifos[0].int_status & 0x3) | in asc_read()
444 (s->fifos[1].int_status & 0x3) << 2; in asc_read()
446 s->fifos[0].int_status = 0; in asc_read()
447 s->fifos[1].int_status = 0; in asc_read()
452 value = s->regs[addr]; in asc_read()
468 if (value != s->regs[ASC_MODE]) { in asc_write()
469 asc_fifo_reset(&s->fifos[0]); in asc_write()
470 asc_fifo_reset(&s->fifos[1]); in asc_write()
473 AUD_set_active_out(s->voice, 1); in asc_write()
475 AUD_set_active_out(s->voice, 0); in asc_write()
481 asc_fifo_reset(&s->fifos[0]); in asc_write()
482 asc_fifo_reset(&s->fifos[1]); in asc_write()
492 AUD_set_volume_out(s->voice, 0, vol, vol); in asc_write()
498 s->regs[addr] = value; in asc_write()
517 value = fs->extregs[addr]; in asc_ext_read()
519 trace_asc_read_extreg('A' + fs->index, addr, size, value); in asc_ext_read()
528 trace_asc_write_extreg('A' + fs->index, addr, size, value); in asc_ext_write()
530 fs->extregs[addr] = value; in asc_ext_write()
547 if (s->regs[ASC_MODE] != 0) { in asc_post_load()
548 AUD_set_active_out(s->voice, 1); in asc_post_load()
555 .name = "apple-sound-chip.fifo",
574 .name = "apple-sound-chip",
589 fs->wptr = 0; in asc_fifo_reset()
590 fs->rptr = 0; in asc_fifo_reset()
591 fs->cnt = 0; in asc_fifo_reset()
592 fs->xa_cnt = -1; in asc_fifo_reset()
593 fs->int_status = 0; in asc_fifo_reset()
601 fs->index = index; in asc_fifo_init()
603 memory_region_init_io(&fs->mem_fifo, OBJECT(s), &asc_fifo_ops, fs, in asc_fifo_init()
608 memory_region_init_io(&fs->mem_extregs, OBJECT(s), &asc_extregs_ops, in asc_fifo_init()
617 AUD_set_active_out(s->voice, 0); in asc_reset_hold()
619 memset(s->regs, 0, sizeof(s->regs)); in asc_reset_hold()
620 asc_fifo_reset(&s->fifos[0]); in asc_reset_hold()
621 asc_fifo_reset(&s->fifos[1]); in asc_reset_hold()
622 s->fifo_empty_ns = 0; in asc_reset_hold()
624 if (s->type == ASC_TYPE_ASC) { in asc_reset_hold()
626 s->fifos[0].extregs[ASC_EXTREGS_INTCTRL] = 1; in asc_reset_hold()
627 s->fifos[1].extregs[ASC_EXTREGS_INTCTRL] = 1; in asc_reset_hold()
635 g_free(s->mixbuf); in asc_unrealize()
636 g_free(s->silentbuf); in asc_unrealize()
638 AUD_remove_card(&s->card); in asc_unrealize()
646 if (!AUD_register_card("Apple Sound Chip", &s->card, errp)) { in asc_realize()
655 s->voice = AUD_open_out(&s->card, s->voice, "asc.out", s, asc_out_cb, in asc_realize()
657 if (!s->voice) { in asc_realize()
658 AUD_remove_card(&s->card); in asc_realize()
663 s->shift = 1; in asc_realize()
664 s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift; in asc_realize()
665 s->mixbuf = g_malloc0(s->samples << s->shift); in asc_realize()
667 s->silentbuf = g_malloc(s->samples << s->shift); in asc_realize()
668 memset(s->silentbuf, 0x80, s->samples << s->shift); in asc_realize()
671 if (s->type == ASC_TYPE_EASC) { in asc_realize()
672 memory_region_add_subregion(&s->asc, ASC_EXTREG_OFFSET, in asc_realize()
673 &s->fifos[0].mem_extregs); in asc_realize()
674 memory_region_add_subregion(&s->asc, in asc_realize()
676 &s->fifos[1].mem_extregs); in asc_realize()
685 memory_region_init(&s->asc, OBJECT(obj), "asc", ASC_SIZE); in asc_init()
687 asc_fifo_init(&s->fifos[0], 0); in asc_init()
688 asc_fifo_init(&s->fifos[1], 1); in asc_init()
690 memory_region_add_subregion(&s->asc, ASC_FIFO_OFFSET, in asc_init()
691 &s->fifos[0].mem_fifo); in asc_init()
692 memory_region_add_subregion(&s->asc, in asc_init()
694 &s->fifos[1].mem_fifo); in asc_init()
696 memory_region_init_io(&s->mem_regs, OBJECT(obj), &asc_regs_ops, s, in asc_init()
698 memory_region_add_subregion(&s->asc, ASC_REG_OFFSET, &s->mem_regs); in asc_init()
700 sysbus_init_irq(sbd, &s->irq); in asc_init()
701 sysbus_init_mmio(sbd, &s->asc); in asc_init()
714 dc->realize = asc_realize; in asc_class_init()
715 dc->unrealize = asc_unrealize; in asc_class_init()
716 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); in asc_class_init()
717 dc->vmsd = &vmstate_asc; in asc_class_init()
719 rc->phases.hold = asc_reset_hold; in asc_class_init()