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
codec_volume_set_out(ViaAC97State * s)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
codec_reset(ViaAC97State * s)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
codec_read(ViaAC97State * s,uint8_t addr)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
codec_write(ViaAC97State * s,uint8_t addr,uint16_t val)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
fetch_sgd(ViaAC97SGDChannel * c,PCIDevice * d)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
out_cb(void * opaque,int avail)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
open_voice_out(ViaAC97State * s)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
sgd_read(void * opaque,hwaddr addr,unsigned size)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
sgd_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)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
fm_read(void * opaque,hwaddr addr,unsigned size)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
fm_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)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
midi_read(void * opaque,hwaddr addr,unsigned size)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
midi_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)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
via_ac97_reset(DeviceState * dev)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
via_ac97_realize(PCIDevice * pci_dev,Error ** errp)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
via_ac97_exit(PCIDevice * dev)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
462eb604411SBALATON Zoltan static Property via_ac97_properties[] = {
463eb604411SBALATON Zoltan DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
464eb604411SBALATON Zoltan DEFINE_PROP_END_OF_LIST(),
465eb604411SBALATON Zoltan };
466eb604411SBALATON Zoltan
via_ac97_class_init(ObjectClass * klass,void * data)467657fae25SBALATON Zoltan static void via_ac97_class_init(ObjectClass *klass, void *data)
468657fae25SBALATON Zoltan {
469657fae25SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass);
470657fae25SBALATON Zoltan PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
471657fae25SBALATON Zoltan
472657fae25SBALATON Zoltan k->realize = via_ac97_realize;
473eb604411SBALATON Zoltan k->exit = via_ac97_exit;
474657fae25SBALATON Zoltan k->vendor_id = PCI_VENDOR_ID_VIA;
475657fae25SBALATON Zoltan k->device_id = PCI_DEVICE_ID_VIA_AC97;
476657fae25SBALATON Zoltan k->revision = 0x50;
477657fae25SBALATON Zoltan k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
478eb604411SBALATON Zoltan device_class_set_props(dc, via_ac97_properties);
479657fae25SBALATON Zoltan set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
480a250e1c6SBALATON Zoltan dc->desc = "VIA AC97";
481*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, via_ac97_reset);
482a250e1c6SBALATON Zoltan /* Reason: Part of a south bridge chip */
483a250e1c6SBALATON Zoltan dc->user_creatable = false;
484657fae25SBALATON Zoltan }
485657fae25SBALATON Zoltan
486657fae25SBALATON Zoltan static const TypeInfo via_ac97_info = {
487657fae25SBALATON Zoltan .name = TYPE_VIA_AC97,
488657fae25SBALATON Zoltan .parent = TYPE_PCI_DEVICE,
489eb604411SBALATON Zoltan .instance_size = sizeof(ViaAC97State),
490657fae25SBALATON Zoltan .class_init = via_ac97_class_init,
491657fae25SBALATON Zoltan .interfaces = (InterfaceInfo[]) {
492657fae25SBALATON Zoltan { INTERFACE_CONVENTIONAL_PCI_DEVICE },
493657fae25SBALATON Zoltan { },
494657fae25SBALATON Zoltan },
495657fae25SBALATON Zoltan };
496657fae25SBALATON Zoltan
via_mc97_realize(PCIDevice * pci_dev,Error ** errp)497a250e1c6SBALATON Zoltan static void via_mc97_realize(PCIDevice *pci_dev, Error **errp)
498657fae25SBALATON Zoltan {
499a250e1c6SBALATON Zoltan pci_set_word(pci_dev->config + PCI_COMMAND,
500a250e1c6SBALATON Zoltan PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE);
501a250e1c6SBALATON Zoltan pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
502a250e1c6SBALATON Zoltan pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
503657fae25SBALATON Zoltan }
504657fae25SBALATON Zoltan
via_mc97_class_init(ObjectClass * klass,void * data)505657fae25SBALATON Zoltan static void via_mc97_class_init(ObjectClass *klass, void *data)
506657fae25SBALATON Zoltan {
507657fae25SBALATON Zoltan DeviceClass *dc = DEVICE_CLASS(klass);
508657fae25SBALATON Zoltan PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
509657fae25SBALATON Zoltan
510657fae25SBALATON Zoltan k->realize = via_mc97_realize;
511657fae25SBALATON Zoltan k->vendor_id = PCI_VENDOR_ID_VIA;
512657fae25SBALATON Zoltan k->device_id = PCI_DEVICE_ID_VIA_MC97;
513657fae25SBALATON Zoltan k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
514657fae25SBALATON Zoltan k->revision = 0x30;
515657fae25SBALATON Zoltan set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
516a250e1c6SBALATON Zoltan dc->desc = "VIA MC97";
517a250e1c6SBALATON Zoltan /* Reason: Part of a south bridge chip */
518a250e1c6SBALATON Zoltan dc->user_creatable = false;
519657fae25SBALATON Zoltan }
520657fae25SBALATON Zoltan
521657fae25SBALATON Zoltan static const TypeInfo via_mc97_info = {
522657fae25SBALATON Zoltan .name = TYPE_VIA_MC97,
523657fae25SBALATON Zoltan .parent = TYPE_PCI_DEVICE,
524a250e1c6SBALATON Zoltan .instance_size = sizeof(PCIDevice),
525657fae25SBALATON Zoltan .class_init = via_mc97_class_init,
526657fae25SBALATON Zoltan .interfaces = (InterfaceInfo[]) {
527657fae25SBALATON Zoltan { INTERFACE_CONVENTIONAL_PCI_DEVICE },
528657fae25SBALATON Zoltan { },
529657fae25SBALATON Zoltan },
530657fae25SBALATON Zoltan };
531657fae25SBALATON Zoltan
via_ac97_register_types(void)532657fae25SBALATON Zoltan static void via_ac97_register_types(void)
533657fae25SBALATON Zoltan {
534657fae25SBALATON Zoltan type_register_static(&via_ac97_info);
535657fae25SBALATON Zoltan type_register_static(&via_mc97_info);
536657fae25SBALATON Zoltan }
537657fae25SBALATON Zoltan
538657fae25SBALATON Zoltan type_init(via_ac97_register_types)
539