1657fae25SBALATON Zoltan /* 2657fae25SBALATON Zoltan * VIA south bridges sound support 3657fae25SBALATON Zoltan * 4eb604411SBALATON Zoltan * Copyright (c) 2022-2023 BALATON Zoltan 5eb604411SBALATON Zoltan * 6657fae25SBALATON Zoltan * This work is licensed under the GNU GPL license version 2 or later. 7657fae25SBALATON Zoltan */ 8657fae25SBALATON Zoltan 9657fae25SBALATON Zoltan /* 10eb604411SBALATON Zoltan * TODO: This is only a basic implementation of one audio playback channel 11eb604411SBALATON Zoltan * more functionality should be added here. 12657fae25SBALATON Zoltan */ 13657fae25SBALATON Zoltan 14657fae25SBALATON Zoltan #include "qemu/osdep.h" 15eb604411SBALATON Zoltan #include "qemu/log.h" 16657fae25SBALATON Zoltan #include "hw/isa/vt82c686.h" 17eb604411SBALATON Zoltan #include "ac97.h" 18eb604411SBALATON Zoltan #include "trace.h" 19eb604411SBALATON Zoltan 20eb604411SBALATON Zoltan #define CLEN_IS_EOL(x) ((x)->clen & BIT(31)) 21eb604411SBALATON Zoltan #define CLEN_IS_FLAG(x) ((x)->clen & BIT(30)) 22eb604411SBALATON Zoltan #define CLEN_IS_STOP(x) ((x)->clen & BIT(29)) 23eb604411SBALATON Zoltan #define CLEN_LEN(x) ((x)->clen & 0xffffff) 24eb604411SBALATON Zoltan 25eb604411SBALATON Zoltan #define STAT_ACTIVE BIT(7) 26eb604411SBALATON Zoltan #define STAT_PAUSED BIT(6) 27eb604411SBALATON Zoltan #define STAT_TRIG BIT(3) 28eb604411SBALATON Zoltan #define STAT_STOP BIT(2) 29eb604411SBALATON Zoltan #define STAT_EOL BIT(1) 30eb604411SBALATON Zoltan #define STAT_FLAG BIT(0) 31eb604411SBALATON Zoltan 32eb604411SBALATON Zoltan #define CNTL_START BIT(7) 33eb604411SBALATON Zoltan #define CNTL_TERM BIT(6) 34eb604411SBALATON Zoltan #define CNTL_PAUSE BIT(3) 35eb604411SBALATON Zoltan 36eb604411SBALATON Zoltan static void open_voice_out(ViaAC97State *s); 37eb604411SBALATON Zoltan 38eb604411SBALATON Zoltan static uint16_t codec_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, 39eb604411SBALATON Zoltan 48000 }; 40eb604411SBALATON Zoltan 41eb604411SBALATON Zoltan #define CODEC_REG(s, o) ((s)->codec_regs[(o) / 2]) 42eb604411SBALATON Zoltan #define CODEC_VOL(vol, mask) ((255 * ((vol) & mask)) / mask) 43eb604411SBALATON Zoltan 44eb604411SBALATON Zoltan static void codec_volume_set_out(ViaAC97State *s) 45eb604411SBALATON Zoltan { 46eb604411SBALATON Zoltan int lvol, rvol, mute; 47eb604411SBALATON Zoltan 48eb604411SBALATON Zoltan lvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f); 49eb604411SBALATON Zoltan lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f); 50eb604411SBALATON Zoltan lvol /= 255; 51eb604411SBALATON Zoltan rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f); 52eb604411SBALATON Zoltan rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f); 53eb604411SBALATON Zoltan rvol /= 255; 54eb604411SBALATON Zoltan mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT; 55eb604411SBALATON Zoltan mute |= CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT; 56eb604411SBALATON Zoltan AUD_set_volume_out(s->vo, mute, lvol, rvol); 57eb604411SBALATON Zoltan } 58eb604411SBALATON Zoltan 59eb604411SBALATON Zoltan static void codec_reset(ViaAC97State *s) 60eb604411SBALATON Zoltan { 61eb604411SBALATON Zoltan memset(s->codec_regs, 0, sizeof(s->codec_regs)); 62eb604411SBALATON Zoltan CODEC_REG(s, AC97_Reset) = 0x6a90; 63eb604411SBALATON Zoltan CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000; 64eb604411SBALATON Zoltan CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000; 65eb604411SBALATON Zoltan CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000; 66eb604411SBALATON Zoltan CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008; 67eb604411SBALATON Zoltan CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008; 68eb604411SBALATON Zoltan CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808; 69eb604411SBALATON Zoltan CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808; 70eb604411SBALATON Zoltan CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808; 71eb604411SBALATON Zoltan CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808; 72eb604411SBALATON Zoltan CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808; 73eb604411SBALATON Zoltan CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000; 74eb604411SBALATON Zoltan CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f; 75eb604411SBALATON Zoltan CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05; 76eb604411SBALATON Zoltan CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400; 77eb604411SBALATON Zoltan CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000; 78eb604411SBALATON Zoltan CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000; 79eb604411SBALATON Zoltan /* Sigmatel 9766 (STAC9766) */ 80eb604411SBALATON Zoltan CODEC_REG(s, AC97_Vendor_ID1) = 0x8384; 81eb604411SBALATON Zoltan CODEC_REG(s, AC97_Vendor_ID2) = 0x7666; 82eb604411SBALATON Zoltan } 83eb604411SBALATON Zoltan 84eb604411SBALATON Zoltan static uint16_t codec_read(ViaAC97State *s, uint8_t addr) 85eb604411SBALATON Zoltan { 86eb604411SBALATON Zoltan return CODEC_REG(s, addr); 87eb604411SBALATON Zoltan } 88eb604411SBALATON Zoltan 89eb604411SBALATON Zoltan static void codec_write(ViaAC97State *s, uint8_t addr, uint16_t val) 90eb604411SBALATON Zoltan { 91eb604411SBALATON Zoltan trace_via_ac97_codec_write(addr, val); 92eb604411SBALATON Zoltan switch (addr) { 93eb604411SBALATON Zoltan case AC97_Reset: 94eb604411SBALATON Zoltan codec_reset(s); 95eb604411SBALATON Zoltan return; 96eb604411SBALATON Zoltan case AC97_Master_Volume_Mute: 97eb604411SBALATON Zoltan case AC97_PCM_Out_Volume_Mute: 98eb604411SBALATON Zoltan if (addr == AC97_Master_Volume_Mute) { 99eb604411SBALATON Zoltan if (val & BIT(13)) { 100eb604411SBALATON Zoltan val |= 0x1f00; 101eb604411SBALATON Zoltan } 102eb604411SBALATON Zoltan if (val & BIT(5)) { 103eb604411SBALATON Zoltan val |= 0x1f; 104eb604411SBALATON Zoltan } 105eb604411SBALATON Zoltan } 106eb604411SBALATON Zoltan CODEC_REG(s, addr) = val & 0x9f1f; 107eb604411SBALATON Zoltan codec_volume_set_out(s); 108eb604411SBALATON Zoltan return; 109eb604411SBALATON Zoltan case AC97_Extended_Audio_Ctrl_Stat: 110eb604411SBALATON Zoltan CODEC_REG(s, addr) &= ~EACS_VRA; 111eb604411SBALATON Zoltan CODEC_REG(s, addr) |= val & EACS_VRA; 112eb604411SBALATON Zoltan if (!(val & EACS_VRA)) { 113eb604411SBALATON Zoltan CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000; 114eb604411SBALATON Zoltan CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000; 115eb604411SBALATON Zoltan open_voice_out(s); 116eb604411SBALATON Zoltan } 117eb604411SBALATON Zoltan return; 118eb604411SBALATON Zoltan case AC97_PCM_Front_DAC_Rate: 119eb604411SBALATON Zoltan case AC97_PCM_LR_ADC_Rate: 120eb604411SBALATON Zoltan if (CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) { 121eb604411SBALATON Zoltan int i; 122eb604411SBALATON Zoltan uint16_t rate = val; 123eb604411SBALATON Zoltan 124eb604411SBALATON Zoltan for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) { 125eb604411SBALATON Zoltan if (rate < codec_rates[i] + 126eb604411SBALATON Zoltan (codec_rates[i + 1] - codec_rates[i]) / 2) { 127eb604411SBALATON Zoltan rate = codec_rates[i]; 128eb604411SBALATON Zoltan break; 129eb604411SBALATON Zoltan } 130eb604411SBALATON Zoltan } 131eb604411SBALATON Zoltan if (rate > 48000) { 132eb604411SBALATON Zoltan rate = 48000; 133eb604411SBALATON Zoltan } 134eb604411SBALATON Zoltan CODEC_REG(s, addr) = rate; 135eb604411SBALATON Zoltan open_voice_out(s); 136eb604411SBALATON Zoltan } 137eb604411SBALATON Zoltan return; 138eb604411SBALATON Zoltan case AC97_Powerdown_Ctrl_Stat: 139eb604411SBALATON Zoltan CODEC_REG(s, addr) = (val & 0xff00) | (CODEC_REG(s, addr) & 0xff); 140eb604411SBALATON Zoltan return; 141eb604411SBALATON Zoltan case AC97_Extended_Audio_ID: 142eb604411SBALATON Zoltan case AC97_Vendor_ID1: 143eb604411SBALATON Zoltan case AC97_Vendor_ID2: 144eb604411SBALATON Zoltan /* Read only registers */ 145eb604411SBALATON Zoltan return; 146eb604411SBALATON Zoltan default: 147eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, 148eb604411SBALATON Zoltan "via-ac97: Unimplemented codec register 0x%x\n", addr); 149eb604411SBALATON Zoltan CODEC_REG(s, addr) = val; 150eb604411SBALATON Zoltan } 151eb604411SBALATON Zoltan } 152eb604411SBALATON Zoltan 153eb604411SBALATON Zoltan static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d) 154eb604411SBALATON Zoltan { 155eb604411SBALATON Zoltan uint32_t b[2]; 156eb604411SBALATON Zoltan 157eb604411SBALATON Zoltan if (c->curr < c->base) { 158eb604411SBALATON Zoltan c->curr = c->base; 159eb604411SBALATON Zoltan } 160eb604411SBALATON Zoltan if (unlikely(pci_dma_read(d, c->curr, b, sizeof(b)) != MEMTX_OK)) { 161eb604411SBALATON Zoltan qemu_log_mask(LOG_GUEST_ERROR, 162eb604411SBALATON Zoltan "via-ac97: DMA error reading SGD table\n"); 163eb604411SBALATON Zoltan return; 164eb604411SBALATON Zoltan } 165eb604411SBALATON Zoltan c->addr = le32_to_cpu(b[0]); 166eb604411SBALATON Zoltan c->clen = le32_to_cpu(b[1]); 167eb604411SBALATON Zoltan trace_via_ac97_sgd_fetch(c->curr, c->addr, CLEN_IS_STOP(c) ? 'S' : '-', 168eb604411SBALATON Zoltan CLEN_IS_EOL(c) ? 'E' : '-', 169eb604411SBALATON Zoltan CLEN_IS_FLAG(c) ? 'F' : '-', CLEN_LEN(c)); 170eb604411SBALATON Zoltan } 171eb604411SBALATON Zoltan 172eb604411SBALATON Zoltan static void out_cb(void *opaque, int avail) 173eb604411SBALATON Zoltan { 174eb604411SBALATON Zoltan ViaAC97State *s = opaque; 175eb604411SBALATON Zoltan ViaAC97SGDChannel *c = &s->aur; 176eb604411SBALATON Zoltan int temp, to_copy, copied; 177eb604411SBALATON Zoltan bool stop = false; 178eb604411SBALATON Zoltan uint8_t tmpbuf[4096]; 179eb604411SBALATON Zoltan 180eb604411SBALATON Zoltan if (c->stat & STAT_PAUSED) { 181eb604411SBALATON Zoltan return; 182eb604411SBALATON Zoltan } 183eb604411SBALATON Zoltan c->stat |= STAT_ACTIVE; 184eb604411SBALATON Zoltan while (avail && !stop) { 185eb604411SBALATON Zoltan if (!c->clen) { 186eb604411SBALATON Zoltan fetch_sgd(c, &s->dev); 187eb604411SBALATON Zoltan } 188eb604411SBALATON Zoltan temp = MIN(CLEN_LEN(c), avail); 189eb604411SBALATON Zoltan while (temp) { 190eb604411SBALATON Zoltan to_copy = MIN(temp, sizeof(tmpbuf)); 191eb604411SBALATON Zoltan pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy); 192eb604411SBALATON Zoltan copied = AUD_write(s->vo, tmpbuf, to_copy); 193eb604411SBALATON Zoltan if (!copied) { 194eb604411SBALATON Zoltan stop = true; 195eb604411SBALATON Zoltan break; 196eb604411SBALATON Zoltan } 197eb604411SBALATON Zoltan temp -= copied; 198eb604411SBALATON Zoltan avail -= copied; 199eb604411SBALATON Zoltan c->addr += copied; 200eb604411SBALATON Zoltan c->clen -= copied; 201eb604411SBALATON Zoltan } 202eb604411SBALATON Zoltan if (CLEN_LEN(c) == 0) { 203eb604411SBALATON Zoltan c->curr += 8; 204eb604411SBALATON Zoltan if (CLEN_IS_EOL(c)) { 205eb604411SBALATON Zoltan c->stat |= STAT_EOL; 206eb604411SBALATON Zoltan if (c->type & CNTL_START) { 207eb604411SBALATON Zoltan c->curr = c->base; 208eb604411SBALATON Zoltan c->stat |= STAT_PAUSED; 209eb604411SBALATON Zoltan } else { 210eb604411SBALATON Zoltan c->stat &= ~STAT_ACTIVE; 211eb604411SBALATON Zoltan AUD_set_active_out(s->vo, 0); 212eb604411SBALATON Zoltan } 213eb604411SBALATON Zoltan if (c->type & STAT_EOL) { 2140ed083a1SBALATON Zoltan via_isa_set_irq(&s->dev, 0, 1); 215eb604411SBALATON Zoltan } 216eb604411SBALATON Zoltan } 217eb604411SBALATON Zoltan if (CLEN_IS_FLAG(c)) { 218eb604411SBALATON Zoltan c->stat |= STAT_FLAG; 219eb604411SBALATON Zoltan c->stat |= STAT_PAUSED; 220eb604411SBALATON Zoltan if (c->type & STAT_FLAG) { 2210ed083a1SBALATON Zoltan via_isa_set_irq(&s->dev, 0, 1); 222eb604411SBALATON Zoltan } 223eb604411SBALATON Zoltan } 224eb604411SBALATON Zoltan if (CLEN_IS_STOP(c)) { 225eb604411SBALATON Zoltan c->stat |= STAT_STOP; 226eb604411SBALATON Zoltan c->stat |= STAT_PAUSED; 227eb604411SBALATON Zoltan } 228eb604411SBALATON Zoltan c->clen = 0; 229eb604411SBALATON Zoltan stop = true; 230eb604411SBALATON Zoltan } 231eb604411SBALATON Zoltan } 232eb604411SBALATON Zoltan } 233eb604411SBALATON Zoltan 234eb604411SBALATON Zoltan static void open_voice_out(ViaAC97State *s) 235eb604411SBALATON Zoltan { 236eb604411SBALATON Zoltan struct audsettings as = { 237eb604411SBALATON Zoltan .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate), 238eb604411SBALATON Zoltan .nchannels = s->aur.type & BIT(4) ? 2 : 1, 239eb604411SBALATON Zoltan .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8, 240eb604411SBALATON Zoltan .endianness = 0, 241eb604411SBALATON Zoltan }; 242eb604411SBALATON Zoltan s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as); 243eb604411SBALATON Zoltan } 244eb604411SBALATON Zoltan 245eb604411SBALATON Zoltan static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size) 246eb604411SBALATON Zoltan { 247eb604411SBALATON Zoltan ViaAC97State *s = opaque; 248eb604411SBALATON Zoltan uint64_t val = 0; 249eb604411SBALATON Zoltan 250eb604411SBALATON Zoltan switch (addr) { 251eb604411SBALATON Zoltan case 0: 252eb604411SBALATON Zoltan val = s->aur.stat; 253eb604411SBALATON Zoltan if (s->aur.type & CNTL_START) { 254eb604411SBALATON Zoltan val |= STAT_TRIG; 255eb604411SBALATON Zoltan } 256eb604411SBALATON Zoltan break; 257eb604411SBALATON Zoltan case 1: 258eb604411SBALATON Zoltan val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0; 259eb604411SBALATON Zoltan break; 260eb604411SBALATON Zoltan case 2: 261eb604411SBALATON Zoltan val = s->aur.type; 262eb604411SBALATON Zoltan break; 263eb604411SBALATON Zoltan case 4: 264eb604411SBALATON Zoltan val = s->aur.curr; 265eb604411SBALATON Zoltan break; 266eb604411SBALATON Zoltan case 0xc: 267eb604411SBALATON Zoltan val = CLEN_LEN(&s->aur); 268eb604411SBALATON Zoltan break; 269eb604411SBALATON Zoltan case 0x10: 270eb604411SBALATON Zoltan /* silence unimplemented log message that happens at every IRQ */ 271eb604411SBALATON Zoltan break; 272eb604411SBALATON Zoltan case 0x80: 273eb604411SBALATON Zoltan val = s->ac97_cmd; 274eb604411SBALATON Zoltan break; 275eb604411SBALATON Zoltan case 0x84: 276eb604411SBALATON Zoltan val = s->aur.stat & STAT_FLAG; 277eb604411SBALATON Zoltan if (s->aur.stat & STAT_EOL) { 278eb604411SBALATON Zoltan val |= BIT(4); 279eb604411SBALATON Zoltan } 280eb604411SBALATON Zoltan if (s->aur.stat & STAT_STOP) { 281eb604411SBALATON Zoltan val |= BIT(8); 282eb604411SBALATON Zoltan } 283eb604411SBALATON Zoltan if (s->aur.stat & STAT_ACTIVE) { 284eb604411SBALATON Zoltan val |= BIT(12); 285eb604411SBALATON Zoltan } 286eb604411SBALATON Zoltan break; 287eb604411SBALATON Zoltan default: 288eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register read 0x%" 289eb604411SBALATON Zoltan HWADDR_PRIx"\n", addr); 290eb604411SBALATON Zoltan } 291eb604411SBALATON Zoltan trace_via_ac97_sgd_read(addr, size, val); 292eb604411SBALATON Zoltan return val; 293eb604411SBALATON Zoltan } 294eb604411SBALATON Zoltan 295eb604411SBALATON Zoltan static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 296eb604411SBALATON Zoltan { 297eb604411SBALATON Zoltan ViaAC97State *s = opaque; 298eb604411SBALATON Zoltan 299eb604411SBALATON Zoltan trace_via_ac97_sgd_write(addr, size, val); 300eb604411SBALATON Zoltan switch (addr) { 301eb604411SBALATON Zoltan case 0: 302eb604411SBALATON Zoltan if (val & STAT_STOP) { 303eb604411SBALATON Zoltan s->aur.stat &= ~STAT_PAUSED; 304eb604411SBALATON Zoltan } 305eb604411SBALATON Zoltan if (val & STAT_EOL) { 306eb604411SBALATON Zoltan s->aur.stat &= ~(STAT_EOL | STAT_PAUSED); 307eb604411SBALATON Zoltan if (s->aur.type & STAT_EOL) { 3080ed083a1SBALATON Zoltan via_isa_set_irq(&s->dev, 0, 0); 309eb604411SBALATON Zoltan } 310eb604411SBALATON Zoltan } 311eb604411SBALATON Zoltan if (val & STAT_FLAG) { 312eb604411SBALATON Zoltan s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED); 313eb604411SBALATON Zoltan if (s->aur.type & STAT_FLAG) { 3140ed083a1SBALATON Zoltan via_isa_set_irq(&s->dev, 0, 0); 315eb604411SBALATON Zoltan } 316eb604411SBALATON Zoltan } 317eb604411SBALATON Zoltan break; 318eb604411SBALATON Zoltan case 1: 319eb604411SBALATON Zoltan if (val & CNTL_START) { 320eb604411SBALATON Zoltan AUD_set_active_out(s->vo, 1); 321eb604411SBALATON Zoltan s->aur.stat = STAT_ACTIVE; 322eb604411SBALATON Zoltan } 323eb604411SBALATON Zoltan if (val & CNTL_TERM) { 324eb604411SBALATON Zoltan AUD_set_active_out(s->vo, 0); 325eb604411SBALATON Zoltan s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED); 326eb604411SBALATON Zoltan s->aur.clen = 0; 327eb604411SBALATON Zoltan } 328eb604411SBALATON Zoltan if (val & CNTL_PAUSE) { 329eb604411SBALATON Zoltan AUD_set_active_out(s->vo, 0); 330eb604411SBALATON Zoltan s->aur.stat &= ~STAT_ACTIVE; 331eb604411SBALATON Zoltan s->aur.stat |= STAT_PAUSED; 332eb604411SBALATON Zoltan } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) { 333eb604411SBALATON Zoltan AUD_set_active_out(s->vo, 1); 334eb604411SBALATON Zoltan s->aur.stat |= STAT_ACTIVE; 335eb604411SBALATON Zoltan s->aur.stat &= ~STAT_PAUSED; 336eb604411SBALATON Zoltan } 337eb604411SBALATON Zoltan break; 338eb604411SBALATON Zoltan case 2: 339eb604411SBALATON Zoltan { 340eb604411SBALATON Zoltan uint32_t oldval = s->aur.type; 341eb604411SBALATON Zoltan s->aur.type = val; 342eb604411SBALATON Zoltan if ((oldval & 0x30) != (val & 0x30)) { 343eb604411SBALATON Zoltan open_voice_out(s); 344eb604411SBALATON Zoltan } 345eb604411SBALATON Zoltan break; 346eb604411SBALATON Zoltan } 347eb604411SBALATON Zoltan case 4: 348eb604411SBALATON Zoltan s->aur.base = val & ~1ULL; 349eb604411SBALATON Zoltan s->aur.curr = s->aur.base; 350eb604411SBALATON Zoltan break; 351eb604411SBALATON Zoltan case 0x80: 352eb604411SBALATON Zoltan if (val >> 30) { 353eb604411SBALATON Zoltan /* we only have primary codec */ 354eb604411SBALATON Zoltan break; 355eb604411SBALATON Zoltan } 356eb604411SBALATON Zoltan if (val & BIT(23)) { /* read reg */ 357eb604411SBALATON Zoltan s->ac97_cmd = val & 0xc0ff0000ULL; 358eb604411SBALATON Zoltan s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f); 359eb604411SBALATON Zoltan s->ac97_cmd |= BIT(25); /* data valid */ 360eb604411SBALATON Zoltan } else { 361eb604411SBALATON Zoltan s->ac97_cmd = val & 0xc0ffffffULL; 362eb604411SBALATON Zoltan codec_write(s, (val >> 16) & 0x7f, val); 363eb604411SBALATON Zoltan } 364eb604411SBALATON Zoltan break; 365eb604411SBALATON Zoltan case 0xc: 366eb604411SBALATON Zoltan case 0x84: 367eb604411SBALATON Zoltan /* Read only */ 368eb604411SBALATON Zoltan break; 369eb604411SBALATON Zoltan default: 370eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register write 0x%" 371eb604411SBALATON Zoltan HWADDR_PRIx"\n", addr); 372eb604411SBALATON Zoltan } 373eb604411SBALATON Zoltan } 374eb604411SBALATON Zoltan 375eb604411SBALATON Zoltan static const MemoryRegionOps sgd_ops = { 376eb604411SBALATON Zoltan .read = sgd_read, 377eb604411SBALATON Zoltan .write = sgd_write, 378eb604411SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 379eb604411SBALATON Zoltan }; 380eb604411SBALATON Zoltan 381eb604411SBALATON Zoltan static uint64_t fm_read(void *opaque, hwaddr addr, unsigned size) 382eb604411SBALATON Zoltan { 383eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size); 384eb604411SBALATON Zoltan return 0; 385eb604411SBALATON Zoltan } 386eb604411SBALATON Zoltan 387eb604411SBALATON Zoltan static void fm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 388eb604411SBALATON Zoltan { 389eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n", 390eb604411SBALATON Zoltan __func__, addr, size, val); 391eb604411SBALATON Zoltan } 392eb604411SBALATON Zoltan 393eb604411SBALATON Zoltan static const MemoryRegionOps fm_ops = { 394eb604411SBALATON Zoltan .read = fm_read, 395eb604411SBALATON Zoltan .write = fm_write, 396eb604411SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 397eb604411SBALATON Zoltan }; 398eb604411SBALATON Zoltan 399eb604411SBALATON Zoltan static uint64_t midi_read(void *opaque, hwaddr addr, unsigned size) 400eb604411SBALATON Zoltan { 401eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size); 402eb604411SBALATON Zoltan return 0; 403eb604411SBALATON Zoltan } 404eb604411SBALATON Zoltan 405eb604411SBALATON Zoltan static void midi_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) 406eb604411SBALATON Zoltan { 407eb604411SBALATON Zoltan qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n", 408eb604411SBALATON Zoltan __func__, addr, size, val); 409eb604411SBALATON Zoltan } 410eb604411SBALATON Zoltan 411eb604411SBALATON Zoltan static const MemoryRegionOps midi_ops = { 412eb604411SBALATON Zoltan .read = midi_read, 413eb604411SBALATON Zoltan .write = midi_write, 414eb604411SBALATON Zoltan .endianness = DEVICE_LITTLE_ENDIAN, 415eb604411SBALATON Zoltan }; 416eb604411SBALATON Zoltan 417eb604411SBALATON Zoltan static void via_ac97_reset(DeviceState *dev) 418eb604411SBALATON Zoltan { 419eb604411SBALATON Zoltan ViaAC97State *s = VIA_AC97(dev); 420eb604411SBALATON Zoltan 421eb604411SBALATON Zoltan codec_reset(s); 422eb604411SBALATON Zoltan } 423657fae25SBALATON Zoltan 424a250e1c6SBALATON Zoltan static void via_ac97_realize(PCIDevice *pci_dev, Error **errp) 425657fae25SBALATON Zoltan { 426eb604411SBALATON Zoltan ViaAC97State *s = VIA_AC97(pci_dev); 427eb604411SBALATON Zoltan Object *o = OBJECT(s); 428eb604411SBALATON Zoltan 429cb94ff5fSMartin Kletzander if (!AUD_register_card ("via-ac97", &s->card, errp)) { 430cb94ff5fSMartin Kletzander return; 431cb94ff5fSMartin Kletzander } 432cb94ff5fSMartin Kletzander 433eb604411SBALATON Zoltan /* 434eb604411SBALATON Zoltan * Command register Bus Master bit is documented to be fixed at 0 but it's 435eb604411SBALATON Zoltan * needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here 436eb604411SBALATON Zoltan * and the AmigaOS driver writes 1 only enabling IO bit which works on 437eb604411SBALATON Zoltan * real hardware. So set it here and fix it to 1 to allow DMA. 438eb604411SBALATON Zoltan */ 439eb604411SBALATON Zoltan pci_set_word(pci_dev->config + PCI_COMMAND, PCI_COMMAND_MASTER); 440eb604411SBALATON Zoltan pci_set_word(pci_dev->wmask + PCI_COMMAND, PCI_COMMAND_IO); 441a250e1c6SBALATON Zoltan pci_set_word(pci_dev->config + PCI_STATUS, 442a250e1c6SBALATON Zoltan PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM); 443a250e1c6SBALATON Zoltan pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03); 444eb604411SBALATON Zoltan pci_set_byte(pci_dev->config + 0x40, 1); /* codec ready */ 445eb604411SBALATON Zoltan 446eb604411SBALATON Zoltan memory_region_init_io(&s->sgd, o, &sgd_ops, s, "via-ac97.sgd", 256); 447eb604411SBALATON Zoltan pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->sgd); 448eb604411SBALATON Zoltan memory_region_init_io(&s->fm, o, &fm_ops, s, "via-ac97.fm", 4); 449eb604411SBALATON Zoltan pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm); 450eb604411SBALATON Zoltan memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4); 451eb604411SBALATON Zoltan pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi); 452657fae25SBALATON Zoltan } 453657fae25SBALATON Zoltan 454eb604411SBALATON Zoltan static void via_ac97_exit(PCIDevice *dev) 455eb604411SBALATON Zoltan { 456eb604411SBALATON Zoltan ViaAC97State *s = VIA_AC97(dev); 457eb604411SBALATON Zoltan 458eb604411SBALATON Zoltan AUD_close_out(&s->card, s->vo); 459eb604411SBALATON Zoltan AUD_remove_card(&s->card); 460eb604411SBALATON Zoltan } 461eb604411SBALATON Zoltan 462ed1e71daSRichard Henderson static const Property via_ac97_properties[] = { 463eb604411SBALATON Zoltan DEFINE_AUDIO_PROPERTIES(ViaAC97State, card), 464eb604411SBALATON Zoltan }; 465eb604411SBALATON Zoltan 466*12d1a768SPhilippe Mathieu-Daudé static void via_ac97_class_init(ObjectClass *klass, const void *data) 467657fae25SBALATON Zoltan { 468657fae25SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 469657fae25SBALATON Zoltan PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 470657fae25SBALATON Zoltan 471657fae25SBALATON Zoltan k->realize = via_ac97_realize; 472eb604411SBALATON Zoltan k->exit = via_ac97_exit; 473657fae25SBALATON Zoltan k->vendor_id = PCI_VENDOR_ID_VIA; 474657fae25SBALATON Zoltan k->device_id = PCI_DEVICE_ID_VIA_AC97; 475657fae25SBALATON Zoltan k->revision = 0x50; 476657fae25SBALATON Zoltan k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO; 477eb604411SBALATON Zoltan device_class_set_props(dc, via_ac97_properties); 478657fae25SBALATON Zoltan set_bit(DEVICE_CATEGORY_SOUND, dc->categories); 479a250e1c6SBALATON Zoltan dc->desc = "VIA AC97"; 480e3d08143SPeter Maydell device_class_set_legacy_reset(dc, via_ac97_reset); 481a250e1c6SBALATON Zoltan /* Reason: Part of a south bridge chip */ 482a250e1c6SBALATON Zoltan dc->user_creatable = false; 483657fae25SBALATON Zoltan } 484657fae25SBALATON Zoltan 485657fae25SBALATON Zoltan static const TypeInfo via_ac97_info = { 486657fae25SBALATON Zoltan .name = TYPE_VIA_AC97, 487657fae25SBALATON Zoltan .parent = TYPE_PCI_DEVICE, 488eb604411SBALATON Zoltan .instance_size = sizeof(ViaAC97State), 489657fae25SBALATON Zoltan .class_init = via_ac97_class_init, 490657fae25SBALATON Zoltan .interfaces = (InterfaceInfo[]) { 491657fae25SBALATON Zoltan { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 492657fae25SBALATON Zoltan { }, 493657fae25SBALATON Zoltan }, 494657fae25SBALATON Zoltan }; 495657fae25SBALATON Zoltan 496a250e1c6SBALATON Zoltan static void via_mc97_realize(PCIDevice *pci_dev, Error **errp) 497657fae25SBALATON Zoltan { 498a250e1c6SBALATON Zoltan pci_set_word(pci_dev->config + PCI_COMMAND, 499a250e1c6SBALATON Zoltan PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE); 500a250e1c6SBALATON Zoltan pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM); 501a250e1c6SBALATON Zoltan pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03); 502657fae25SBALATON Zoltan } 503657fae25SBALATON Zoltan 504*12d1a768SPhilippe Mathieu-Daudé static void via_mc97_class_init(ObjectClass *klass, const void *data) 505657fae25SBALATON Zoltan { 506657fae25SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass); 507657fae25SBALATON Zoltan PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 508657fae25SBALATON Zoltan 509657fae25SBALATON Zoltan k->realize = via_mc97_realize; 510657fae25SBALATON Zoltan k->vendor_id = PCI_VENDOR_ID_VIA; 511657fae25SBALATON Zoltan k->device_id = PCI_DEVICE_ID_VIA_MC97; 512657fae25SBALATON Zoltan k->class_id = PCI_CLASS_COMMUNICATION_OTHER; 513657fae25SBALATON Zoltan k->revision = 0x30; 514657fae25SBALATON Zoltan set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 515a250e1c6SBALATON Zoltan dc->desc = "VIA MC97"; 516a250e1c6SBALATON Zoltan /* Reason: Part of a south bridge chip */ 517a250e1c6SBALATON Zoltan dc->user_creatable = false; 518657fae25SBALATON Zoltan } 519657fae25SBALATON Zoltan 520657fae25SBALATON Zoltan static const TypeInfo via_mc97_info = { 521657fae25SBALATON Zoltan .name = TYPE_VIA_MC97, 522657fae25SBALATON Zoltan .parent = TYPE_PCI_DEVICE, 523a250e1c6SBALATON Zoltan .instance_size = sizeof(PCIDevice), 524657fae25SBALATON Zoltan .class_init = via_mc97_class_init, 525657fae25SBALATON Zoltan .interfaces = (InterfaceInfo[]) { 526657fae25SBALATON Zoltan { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 527657fae25SBALATON Zoltan { }, 528657fae25SBALATON Zoltan }, 529657fae25SBALATON Zoltan }; 530657fae25SBALATON Zoltan 531657fae25SBALATON Zoltan static void via_ac97_register_types(void) 532657fae25SBALATON Zoltan { 533657fae25SBALATON Zoltan type_register_static(&via_ac97_info); 534657fae25SBALATON Zoltan type_register_static(&via_mc97_info); 535657fae25SBALATON Zoltan } 536657fae25SBALATON Zoltan 537657fae25SBALATON Zoltan type_init(via_ac97_register_types) 538