Lines Matching +full:fifo +full:- +full:size

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
19 #include "hw/qdev-properties.h"
36 * 1=FIFO mode,
42 * 0x803: FIFO MODE
43 * bit 7=clear FIFO,
44 * bit 1="non-ROM companding",
46 * 0x804: FIFO IRQ STATUS
52 * bits 0-3 wavetables 0-3 start
54 * bits 2-4 = 3 bit internal ASC volume,
55 * bits 5-7 = volume control sent to Sony sound chip
63 * bits 6-7 = digital test,
64 * bits 4-5 = analog test
66 * big-endian 9.15 fixed-point, only 24 bits valid
68 * big-endian 9.15 fixed-point, only 24 bits valid
109 qemu_set_irq(s->irq, 1); in asc_raise_irq()
114 qemu_set_irq(s->irq, 0); in asc_lower_irq()
119 ASCState *s = container_of(fs, ASCState, fifos[fs->index]); in asc_fifo_get()
120 bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1; in asc_fifo_get()
123 assert(fs->cnt); in asc_fifo_get()
125 val = fs->fifo[fs->rptr]; in asc_fifo_get()
126 trace_asc_fifo_get('A' + fs->index, fs->rptr, fs->cnt, val); in asc_fifo_get()
128 fs->rptr++; in asc_fifo_get()
129 fs->rptr &= 0x3ff; in asc_fifo_get()
130 fs->cnt--; in asc_fifo_get()
132 if (fs->cnt <= 0x1ff) { in asc_fifo_get()
133 /* FIFO less than half full */ in asc_fifo_get()
134 fs->int_status |= ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_get()
136 /* FIFO more than half full */ in asc_fifo_get()
137 fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_get()
140 if (fs->cnt == 0x1ff && fifo_half_irq_enabled) { in asc_fifo_get()
141 /* Raise FIFO half full IRQ */ in asc_fifo_get()
145 if (fs->cnt == 0) { in asc_fifo_get()
146 /* Raise FIFO empty IRQ */ in asc_fifo_get()
147 fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY; in asc_fifo_get()
157 uint8_t *buf = s->mixbuf; in generate_fifo()
168 ASCFIFOState *fs = &s->fifos[i]; in generate_fifo()
170 switch (fs->extregs[ASC_EXTREGS_FIFOCTRL] & 0x83) { in generate_fifo()
173 * CD-XA BRR mode: decompress 15 bytes into 28 16-bit in generate_fifo()
176 if (!fs->cnt) { in generate_fifo()
181 if (fs->xa_cnt == -1) { in generate_fifo()
183 fs->xa_flags = asc_fifo_get(fs); in generate_fifo()
184 fs->xa_cnt = 0; in generate_fifo()
187 shift = fs->xa_flags & 0xf; in generate_fifo()
188 filter = fs->xa_flags >> 4; in generate_fifo()
189 f0 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT + in generate_fifo()
191 f1 = (int8_t)fs->extregs[ASC_EXTREGS_CDXA_DECOMP_FILT + in generate_fifo()
194 if ((fs->xa_cnt & 1) == 0) { in generate_fifo()
195 if (!fs->cnt) { in generate_fifo()
200 fs->xa_val = asc_fifo_get(fs); in generate_fifo()
201 d = (fs->xa_val & 0xf) << 12; in generate_fifo()
203 d = (fs->xa_val & 0xf0) << 8; in generate_fifo()
205 t = (d >> shift) + (((fs->xa_last[0] * f0) + in generate_fifo()
206 (fs->xa_last[1] * f1) + 32) >> 6); in generate_fifo()
207 if (t < -32768) { in generate_fifo()
208 t = -32768; in generate_fifo()
214 * CD-XA BRR generates 16-bit signed output, so convert to in generate_fifo()
215 * 8-bit before writing to buffer. Does real hardware do the in generate_fifo()
220 fs->xa_cnt++; in generate_fifo()
222 fs->xa_last[1] = fs->xa_last[0]; in generate_fifo()
223 fs->xa_last[0] = (int16_t)t; in generate_fifo()
225 if (fs->xa_cnt == 28) { in generate_fifo()
227 fs->xa_cnt = -1; in generate_fifo()
235 if (fs->cnt) { in generate_fifo()
255 * MacOS (un)helpfully leaves the FIFO engine running even when it has in generate_fifo()
256 * finished writing out samples, but still expects the FIFO empty in generate_fifo()
257 * interrupts to be generated for each FIFO cycle (without these interrupts in generate_fifo()
260 if (s->fifos[0].cnt == 0 && s->fifos[1].cnt == 0) { in generate_fifo()
261 if (!s->fifo_empty_ns) { in generate_fifo()
262 /* FIFO has completed first empty cycle */ in generate_fifo()
263 s->fifo_empty_ns = now; in generate_fifo()
264 } else if (now > (s->fifo_empty_ns + ASC_FIFO_CYCLE_TIME)) { in generate_fifo()
265 /* FIFO has completed entire cycle with no data */ in generate_fifo()
266 s->fifos[0].int_status |= ASC_FIFO_STATUS_HALF_FULL | in generate_fifo()
268 s->fifos[1].int_status |= ASC_FIFO_STATUS_HALF_FULL | in generate_fifo()
270 s->fifo_empty_ns = now; in generate_fifo()
274 /* FIFO contains data, reset empty time */ in generate_fifo()
275 s->fifo_empty_ns = 0; in generate_fifo()
283 uint8_t *buf = s->mixbuf; in generate_wavetable()
291 ASCFIFOState *fs = &s->fifos[channel >> 1]; in generate_wavetable()
295 phase = ldl_be_p(&s->regs[chanreg]); in generate_wavetable()
296 incr = ldl_be_p(&s->regs[chanreg + sizeof(uint32_t)]); in generate_wavetable()
300 sample = fs->fifo[0x200 * (channel >> 1) + offset]; in generate_wavetable()
302 stl_be_p(&s->regs[chanreg], phase); in generate_wavetable()
326 samples = MIN(s->samples, free_b >> s->shift); in asc_out_cb()
328 switch (s->regs[ASC_MODE] & 3) { in asc_out_cb()
334 /* FIFO mode */ in asc_out_cb()
346 int silent_samples = muldiv64(now - s->fifo_empty_ns, in asc_out_cb()
351 * No new FIFO data within half a cycle time (~23ms) so fill the in asc_out_cb()
354 * loop because the FIFO has run out of data, and the driver in asc_out_cb()
357 AUD_write(s->voice, s->silentbuf, samples << s->shift); in asc_out_cb()
362 AUD_write(s->voice, s->mixbuf, generated << s->shift); in asc_out_cb()
366 unsigned size) in asc_fifo_read() argument
370 trace_asc_read_fifo('A' + fs->index, addr, size, fs->fifo[addr]); in asc_fifo_read()
371 return fs->fifo[addr]; in asc_fifo_read()
375 unsigned size) in asc_fifo_write() argument
378 ASCState *s = container_of(fs, ASCState, fifos[fs->index]); in asc_fifo_write()
379 bool fifo_half_irq_enabled = fs->extregs[ASC_EXTREGS_INTCTRL] & 1; in asc_fifo_write()
381 trace_asc_write_fifo('A' + fs->index, addr, size, fs->wptr, fs->cnt, value); in asc_fifo_write()
383 if (s->regs[ASC_MODE] == 1) { in asc_fifo_write()
384 fs->fifo[fs->wptr++] = value; in asc_fifo_write()
385 fs->wptr &= 0x3ff; in asc_fifo_write()
386 fs->cnt++; in asc_fifo_write()
388 if (fs->cnt <= 0x1ff) { in asc_fifo_write()
389 /* FIFO less than half full */ in asc_fifo_write()
390 fs->int_status |= ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_write()
392 /* FIFO at least half full */ in asc_fifo_write()
393 fs->int_status &= ~ASC_FIFO_STATUS_HALF_FULL; in asc_fifo_write()
396 if (fs->cnt == 0x200 && fifo_half_irq_enabled) { in asc_fifo_write()
397 /* Raise FIFO half full interrupt */ in asc_fifo_write()
401 if (fs->cnt == 0x3ff) { in asc_fifo_write()
402 /* Raise FIFO full interrupt */ in asc_fifo_write()
403 fs->int_status |= ASC_FIFO_STATUS_FULL_EMPTY; in asc_fifo_write()
407 fs->fifo[addr] = value; in asc_fifo_write()
425 unsigned size) in asc_read() argument
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()
456 trace_asc_read_reg(addr, size, value); in asc_read()
461 unsigned size) in asc_write() argument
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()
497 trace_asc_write_reg(addr, size, value); in asc_write()
498 s->regs[addr] = value; in asc_write()
512 unsigned size) in asc_ext_read() argument
517 value = fs->extregs[addr]; in asc_ext_read()
519 trace_asc_read_extreg('A' + fs->index, addr, size, value); in asc_ext_read()
524 unsigned size) in asc_ext_write() argument
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",
559 VMSTATE_UINT8_ARRAY(fifo, ASCFIFOState, ASC_FIFO_SIZE),
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()
602 name = g_strdup_printf("asc.fifo%c", 'A' + 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()
625 /* FIFO half full IRQs enabled by default */ 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 s->shift = 1; in asc_realize()
658 s->samples = AUD_get_buffer_size_out(s->voice) >> s->shift; in asc_realize()
659 s->mixbuf = g_malloc0(s->samples << s->shift); in asc_realize()
661 s->silentbuf = g_malloc0(s->samples << s->shift); in asc_realize()
662 memset(s->silentbuf, 0x80, s->samples << s->shift); in asc_realize()
665 if (s->type == ASC_TYPE_EASC) { in asc_realize()
666 memory_region_add_subregion(&s->asc, ASC_EXTREG_OFFSET, in asc_realize()
667 &s->fifos[0].mem_extregs); in asc_realize()
668 memory_region_add_subregion(&s->asc, in asc_realize()
670 &s->fifos[1].mem_extregs); in asc_realize()
679 memory_region_init(&s->asc, OBJECT(obj), "asc", ASC_SIZE); in asc_init()
681 asc_fifo_init(&s->fifos[0], 0); in asc_init()
682 asc_fifo_init(&s->fifos[1], 1); in asc_init()
684 memory_region_add_subregion(&s->asc, ASC_FIFO_OFFSET, in asc_init()
685 &s->fifos[0].mem_fifo); in asc_init()
686 memory_region_add_subregion(&s->asc, in asc_init()
688 &s->fifos[1].mem_fifo); in asc_init()
690 memory_region_init_io(&s->mem_regs, OBJECT(obj), &asc_regs_ops, s, in asc_init()
692 memory_region_add_subregion(&s->asc, ASC_REG_OFFSET, &s->mem_regs); in asc_init()
694 sysbus_init_irq(sbd, &s->irq); in asc_init()
695 sysbus_init_mmio(sbd, &s->asc); in asc_init()
709 dc->realize = asc_realize; in asc_class_init()
710 dc->unrealize = asc_unrealize; in asc_class_init()
711 set_bit(DEVICE_CATEGORY_SOUND, dc->categories); in asc_class_init()
712 dc->vmsd = &vmstate_asc; in asc_class_init()
714 rc->phases.hold = asc_reset_hold; in asc_class_init()