[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playbac
From: |
Bernhard Beschow |
Subject: |
Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback |
Date: |
Fri, 24 Feb 2023 09:53:57 +0000 |
Am 23. Februar 2023 19:40:03 UTC schrieb "Volker Rümelin" <vr_qemu@t-online.de>:
>Am 21.02.23 um 19:44 schrieb BALATON Zoltan:
>> This adds basic implementation of the AC'97 sound part used in VIA
>> south bridge chips. Not all features of the device is emulated, only
>> one playback channel is supported but this is enough to get sound
>> output from some guests running on machines using this device such as
>> pegasos2.
>>
>> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
>> ---
>> hw/audio/trace-events | 6 +
>> hw/audio/via-ac97.c | 436 +++++++++++++++++++++++++++++++++++++-
>> hw/isa/vt82c686.c | 3 +-
>> include/hw/isa/vt82c686.h | 26 +++
>> 4 files changed, 466 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/audio/trace-events b/hw/audio/trace-events
>> index e0e71cd9b1..6eccdaa4b5 100644
>> --- a/hw/audio/trace-events
>> +++ b/hw/audio/trace-events
>> @@ -11,3 +11,9 @@ hda_audio_running(const char *stream, int nr, bool
>> running) "st %s, nr %d, run %
>> hda_audio_format(const char *stream, int chan, const char *fmt, int freq)
>> "st %s, %d x %s @ %d Hz"
>> hda_audio_adjust(const char *stream, int pos) "st %s, pos %d"
>> hda_audio_overrun(const char *stream) "st %s"
>> +
>> +#via-ac97.c
>> +via_ac97_codec_write(uint8_t addr, uint16_t val) "0x%x <- 0x%x"
>> +via_ac97_sgd_fetch(uint32_t addr, char stop, char eol, char flag, uint32_t
>> len) "addr=0x%x %c%c%c len=%d"
>> +via_ac97_sgd_read(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64"
>> %d -> 0x%"PRIx64
>> +via_ac97_sgd_write(uint64_t addr, unsigned size, uint64_t val) "0x%"PRIx64"
>> %d <- 0x%"PRIx64
>> diff --git a/hw/audio/via-ac97.c b/hw/audio/via-ac97.c
>> index d1a856f63d..cdac5bc14b 100644
>> --- a/hw/audio/via-ac97.c
>> +++ b/hw/audio/via-ac97.c
>> @@ -1,39 +1,467 @@
>> /*
>> * 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 entirely boiler plate just registering empty PCI devices
>> - * with the right ID guests expect, functionality should be added here.
>> + * 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 "hw/pci/pci_device.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 & 0xfff)
>
>Hi,
>
>the CLEN_LEN mask is 0xffffff instead of 0xfff. The SGD Table Base Count has
>24 bits.
This fixes sound for a x86 Linux guest on my pc-via branch.
Best regards,
Bernhard
>
>With best regards,
>Volker
>
>> +
>> +#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;
>> + }
>> + pci_dma_read(d, c->curr, b, sizeof(b));
>> + c->addr = le32_to_cpu(b[0]);
>> + c->clen = le32_to_cpu(b[1]);
>> + trace_via_ac97_sgd_fetch(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, VIA_IRQ_AC97, 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, VIA_IRQ_AC97, 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 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 %"
>> + 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, VIA_IRQ_AC97, 0);
>> + }
>> + }
>> + if (val & STAT_FLAG) {
>> + s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
>> + if (s->aur.type & STAT_FLAG) {
>> + via_isa_set_irq(&s->dev, VIA_IRQ_AC97, 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;
>> + 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 %"
>> + 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);
>> +
>> pci_set_word(pci_dev->config + PCI_COMMAND,
>> PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY);
>> 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);
>> +
>> + 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);
>> +
>> + AUD_register_card ("via-ac97", &s->card);
>> }
>> +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;
>> }
>> @@ -41,7 +469,7 @@ static void via_ac97_class_init(ObjectClass *klass, void
>> *data)
>> static const TypeInfo via_ac97_info = {
>> .name = TYPE_VIA_AC97,
>> .parent = TYPE_PCI_DEVICE,
>> - .instance_size = sizeof(PCIDevice),
>> + .instance_size = sizeof(ViaAC97State),
>> .class_init = via_ac97_class_init,
>> .interfaces = (InterfaceInfo[]) {
>> { INTERFACE_CONVENTIONAL_PCI_DEVICE },
>> diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
>> index f31b2fa7ca..b16620daf8 100644
>> --- a/hw/isa/vt82c686.c
>> +++ b/hw/isa/vt82c686.c
>> @@ -555,7 +555,7 @@ struct ViaISAState {
>> PCIIDEState ide;
>> UHCIState uhci[2];
>> ViaPMState pm;
>> - PCIDevice ac97;
>> + ViaAC97State ac97;
>> PCIDevice mc97;
>> };
>> @@ -610,6 +610,7 @@ void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit
>> n, int level)
>> break;
>> case VIA_IRQ_USB0:
>> case VIA_IRQ_USB1:
>> + case VIA_IRQ_AC97:
>> max_irq = 14;
>> isa_irq = d->config[PCI_INTERRUPT_LINE];
>> break;
>> diff --git a/include/hw/isa/vt82c686.h b/include/hw/isa/vt82c686.h
>> index e982c5fe26..f7258d01df 100644
>> --- a/include/hw/isa/vt82c686.h
>> +++ b/include/hw/isa/vt82c686.h
>> @@ -1,6 +1,8 @@
>> #ifndef HW_VT82C686_H
>> #define HW_VT82C686_H
>> +#include "hw/pci/pci_device.h"
>> +#include "audio/audio.h"
>> #define TYPE_VT82C686B_ISA "vt82c686b-isa"
>> #define TYPE_VT82C686B_USB_UHCI "vt82c686b-usb-uhci"
>> @@ -9,6 +11,29 @@
>> #define TYPE_VIA_IDE "via-ide"
>> #define TYPE_VIA_MC97 "via-mc97"
>> +typedef struct {
>> + uint8_t stat;
>> + uint8_t type;
>> + uint32_t base;
>> + uint32_t curr;
>> + uint32_t addr;
>> + uint32_t clen;
>> +} ViaAC97SGDChannel;
>> +
>> +OBJECT_DECLARE_SIMPLE_TYPE(ViaAC97State, VIA_AC97);
>> +
>> +struct ViaAC97State {
>> + PCIDevice dev;
>> + QEMUSoundCard card;
>> + MemoryRegion sgd;
>> + MemoryRegion fm;
>> + MemoryRegion midi;
>> + SWVoiceOut *vo;
>> + ViaAC97SGDChannel aur;
>> + uint16_t codec_regs[128];
>> + uint32_t ac97_cmd;
>> +};
>> +
>> typedef enum {
>> VIA_IRQ_IDE0 = 0,
>> VIA_IRQ_IDE1 = 1,
>> @@ -18,6 +43,7 @@ typedef enum {
>> VIA_IRQ_PIRQB = 5,
>> VIA_IRQ_PIRQC = 6,
>> VIA_IRQ_PIRQD = 7,
>> + VIA_IRQ_AC97 = 8,
>> } ViaISAIRQSourceBit;
>> void via_isa_set_irq(PCIDevice *d, ViaISAIRQSourceBit n, int level);
>
- Re: [PATCH 4/5] hw/audio/ac97: Split off some definitions to a header, (continued)
- [PATCH 1/5] hw/isa/vt82c686: Implement interrupt routing in via_isa_set_irq, BALATON Zoltan, 2023/02/21
- [PATCH 2/5] hw/isa/vt82c686: Implement PIRQ pins, BALATON Zoltan, 2023/02/21
- [PATCH 3/5] hw/ppc/pegasos2: Fix PCI interrupt routing, BALATON Zoltan, 2023/02/21
- [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, BALATON Zoltan, 2023/02/21
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, Volker Rümelin, 2023/02/23
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback,
Bernhard Beschow <=
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, BALATON Zoltan, 2023/02/24
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, BALATON Zoltan, 2023/02/24
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, Daniel Henrique Barboza, 2023/02/24
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, BALATON Zoltan, 2023/02/24
- Re: [PATCH 5/5] hw/audio/via-ac97: Basic implementation of audio playback, Daniel Henrique Barboza, 2023/02/25
Re: [PATCH 0/5] Pegasos2 fixes and audio output support, Bernhard Beschow, 2023/02/22