qapi/qdev: Tidy up device_add documentation
[qemu/armbru.git] / hw / audio / via-ac97.c
blob676254b7a406641c0f5249566cfa89d2e24454bf
1 /*
2 * VIA south bridges sound support
4 * Copyright (c) 2022-2023 BALATON Zoltan
6 * This work is licensed under the GNU GPL license version 2 or later.
7 */
9 /*
10 * TODO: This is only a basic implementation of one audio playback channel
11 * more functionality should be added here.
14 #include "qemu/osdep.h"
15 #include "qemu/log.h"
16 #include "hw/isa/vt82c686.h"
17 #include "ac97.h"
18 #include "trace.h"
20 #define CLEN_IS_EOL(x) ((x)->clen & BIT(31))
21 #define CLEN_IS_FLAG(x) ((x)->clen & BIT(30))
22 #define CLEN_IS_STOP(x) ((x)->clen & BIT(29))
23 #define CLEN_LEN(x) ((x)->clen & 0xffffff)
25 #define STAT_ACTIVE BIT(7)
26 #define STAT_PAUSED BIT(6)
27 #define STAT_TRIG BIT(3)
28 #define STAT_STOP BIT(2)
29 #define STAT_EOL BIT(1)
30 #define STAT_FLAG BIT(0)
32 #define CNTL_START BIT(7)
33 #define CNTL_TERM BIT(6)
34 #define CNTL_PAUSE BIT(3)
36 static void open_voice_out(ViaAC97State *s);
38 static uint16_t codec_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100,
39 48000 };
41 #define CODEC_REG(s, o) ((s)->codec_regs[(o) / 2])
42 #define CODEC_VOL(vol, mask) ((255 * ((vol) & mask)) / mask)
44 static void codec_volume_set_out(ViaAC97State *s)
46 int lvol, rvol, mute;
48 lvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute) >> 8, 0x1f);
49 lvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> 8, 0x1f);
50 lvol /= 255;
51 rvol = 255 - CODEC_VOL(CODEC_REG(s, AC97_Master_Volume_Mute), 0x1f);
52 rvol *= 255 - CODEC_VOL(CODEC_REG(s, AC97_PCM_Out_Volume_Mute), 0x1f);
53 rvol /= 255;
54 mute = CODEC_REG(s, AC97_Master_Volume_Mute) >> MUTE_SHIFT;
55 mute |= CODEC_REG(s, AC97_PCM_Out_Volume_Mute) >> MUTE_SHIFT;
56 AUD_set_volume_out(s->vo, mute, lvol, rvol);
59 static void codec_reset(ViaAC97State *s)
61 memset(s->codec_regs, 0, sizeof(s->codec_regs));
62 CODEC_REG(s, AC97_Reset) = 0x6a90;
63 CODEC_REG(s, AC97_Master_Volume_Mute) = 0x8000;
64 CODEC_REG(s, AC97_Headphone_Volume_Mute) = 0x8000;
65 CODEC_REG(s, AC97_Master_Volume_Mono_Mute) = 0x8000;
66 CODEC_REG(s, AC97_Phone_Volume_Mute) = 0x8008;
67 CODEC_REG(s, AC97_Mic_Volume_Mute) = 0x8008;
68 CODEC_REG(s, AC97_Line_In_Volume_Mute) = 0x8808;
69 CODEC_REG(s, AC97_CD_Volume_Mute) = 0x8808;
70 CODEC_REG(s, AC97_Video_Volume_Mute) = 0x8808;
71 CODEC_REG(s, AC97_Aux_Volume_Mute) = 0x8808;
72 CODEC_REG(s, AC97_PCM_Out_Volume_Mute) = 0x8808;
73 CODEC_REG(s, AC97_Record_Gain_Mute) = 0x8000;
74 CODEC_REG(s, AC97_Powerdown_Ctrl_Stat) = 0x000f;
75 CODEC_REG(s, AC97_Extended_Audio_ID) = 0x0a05;
76 CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) = 0x0400;
77 CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
78 CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
79 /* Sigmatel 9766 (STAC9766) */
80 CODEC_REG(s, AC97_Vendor_ID1) = 0x8384;
81 CODEC_REG(s, AC97_Vendor_ID2) = 0x7666;
84 static uint16_t codec_read(ViaAC97State *s, uint8_t addr)
86 return CODEC_REG(s, addr);
89 static void codec_write(ViaAC97State *s, uint8_t addr, uint16_t val)
91 trace_via_ac97_codec_write(addr, val);
92 switch (addr) {
93 case AC97_Reset:
94 codec_reset(s);
95 return;
96 case AC97_Master_Volume_Mute:
97 case AC97_PCM_Out_Volume_Mute:
98 if (addr == AC97_Master_Volume_Mute) {
99 if (val & BIT(13)) {
100 val |= 0x1f00;
102 if (val & BIT(5)) {
103 val |= 0x1f;
106 CODEC_REG(s, addr) = val & 0x9f1f;
107 codec_volume_set_out(s);
108 return;
109 case AC97_Extended_Audio_Ctrl_Stat:
110 CODEC_REG(s, addr) &= ~EACS_VRA;
111 CODEC_REG(s, addr) |= val & EACS_VRA;
112 if (!(val & EACS_VRA)) {
113 CODEC_REG(s, AC97_PCM_Front_DAC_Rate) = 48000;
114 CODEC_REG(s, AC97_PCM_LR_ADC_Rate) = 48000;
115 open_voice_out(s);
117 return;
118 case AC97_PCM_Front_DAC_Rate:
119 case AC97_PCM_LR_ADC_Rate:
120 if (CODEC_REG(s, AC97_Extended_Audio_Ctrl_Stat) & EACS_VRA) {
121 int i;
122 uint16_t rate = val;
124 for (i = 0; i < ARRAY_SIZE(codec_rates) - 1; i++) {
125 if (rate < codec_rates[i] +
126 (codec_rates[i + 1] - codec_rates[i]) / 2) {
127 rate = codec_rates[i];
128 break;
131 if (rate > 48000) {
132 rate = 48000;
134 CODEC_REG(s, addr) = rate;
135 open_voice_out(s);
137 return;
138 case AC97_Powerdown_Ctrl_Stat:
139 CODEC_REG(s, addr) = (val & 0xff00) | (CODEC_REG(s, addr) & 0xff);
140 return;
141 case AC97_Extended_Audio_ID:
142 case AC97_Vendor_ID1:
143 case AC97_Vendor_ID2:
144 /* Read only registers */
145 return;
146 default:
147 qemu_log_mask(LOG_UNIMP,
148 "via-ac97: Unimplemented codec register 0x%x\n", addr);
149 CODEC_REG(s, addr) = val;
153 static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
155 uint32_t b[2];
157 if (c->curr < c->base) {
158 c->curr = c->base;
160 if (unlikely(pci_dma_read(d, c->curr, b, sizeof(b)) != MEMTX_OK)) {
161 qemu_log_mask(LOG_GUEST_ERROR,
162 "via-ac97: DMA error reading SGD table\n");
163 return;
165 c->addr = le32_to_cpu(b[0]);
166 c->clen = le32_to_cpu(b[1]);
167 trace_via_ac97_sgd_fetch(c->curr, c->addr, CLEN_IS_STOP(c) ? 'S' : '-',
168 CLEN_IS_EOL(c) ? 'E' : '-',
169 CLEN_IS_FLAG(c) ? 'F' : '-', CLEN_LEN(c));
172 static void out_cb(void *opaque, int avail)
174 ViaAC97State *s = opaque;
175 ViaAC97SGDChannel *c = &s->aur;
176 int temp, to_copy, copied;
177 bool stop = false;
178 uint8_t tmpbuf[4096];
180 if (c->stat & STAT_PAUSED) {
181 return;
183 c->stat |= STAT_ACTIVE;
184 while (avail && !stop) {
185 if (!c->clen) {
186 fetch_sgd(c, &s->dev);
188 temp = MIN(CLEN_LEN(c), avail);
189 while (temp) {
190 to_copy = MIN(temp, sizeof(tmpbuf));
191 pci_dma_read(&s->dev, c->addr, tmpbuf, to_copy);
192 copied = AUD_write(s->vo, tmpbuf, to_copy);
193 if (!copied) {
194 stop = true;
195 break;
197 temp -= copied;
198 avail -= copied;
199 c->addr += copied;
200 c->clen -= copied;
202 if (CLEN_LEN(c) == 0) {
203 c->curr += 8;
204 if (CLEN_IS_EOL(c)) {
205 c->stat |= STAT_EOL;
206 if (c->type & CNTL_START) {
207 c->curr = c->base;
208 c->stat |= STAT_PAUSED;
209 } else {
210 c->stat &= ~STAT_ACTIVE;
211 AUD_set_active_out(s->vo, 0);
213 if (c->type & STAT_EOL) {
214 pci_set_irq(&s->dev, 1);
217 if (CLEN_IS_FLAG(c)) {
218 c->stat |= STAT_FLAG;
219 c->stat |= STAT_PAUSED;
220 if (c->type & STAT_FLAG) {
221 pci_set_irq(&s->dev, 1);
224 if (CLEN_IS_STOP(c)) {
225 c->stat |= STAT_STOP;
226 c->stat |= STAT_PAUSED;
228 c->clen = 0;
229 stop = true;
234 static void open_voice_out(ViaAC97State *s)
236 struct audsettings as = {
237 .freq = CODEC_REG(s, AC97_PCM_Front_DAC_Rate),
238 .nchannels = s->aur.type & BIT(4) ? 2 : 1,
239 .fmt = s->aur.type & BIT(5) ? AUDIO_FORMAT_S16 : AUDIO_FORMAT_S8,
240 .endianness = 0,
242 s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as);
245 static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size)
247 ViaAC97State *s = opaque;
248 uint64_t val = 0;
250 switch (addr) {
251 case 0:
252 val = s->aur.stat;
253 if (s->aur.type & CNTL_START) {
254 val |= STAT_TRIG;
256 break;
257 case 1:
258 val = s->aur.stat & STAT_PAUSED ? BIT(3) : 0;
259 break;
260 case 2:
261 val = s->aur.type;
262 break;
263 case 4:
264 val = s->aur.curr;
265 break;
266 case 0xc:
267 val = CLEN_LEN(&s->aur);
268 break;
269 case 0x10:
270 /* silence unimplemented log message that happens at every IRQ */
271 break;
272 case 0x80:
273 val = s->ac97_cmd;
274 break;
275 case 0x84:
276 val = s->aur.stat & STAT_FLAG;
277 if (s->aur.stat & STAT_EOL) {
278 val |= BIT(4);
280 if (s->aur.stat & STAT_STOP) {
281 val |= BIT(8);
283 if (s->aur.stat & STAT_ACTIVE) {
284 val |= BIT(12);
286 break;
287 default:
288 qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register read 0x%"
289 HWADDR_PRIx"\n", addr);
291 trace_via_ac97_sgd_read(addr, size, val);
292 return val;
295 static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
297 ViaAC97State *s = opaque;
299 trace_via_ac97_sgd_write(addr, size, val);
300 switch (addr) {
301 case 0:
302 if (val & STAT_STOP) {
303 s->aur.stat &= ~STAT_PAUSED;
305 if (val & STAT_EOL) {
306 s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
307 if (s->aur.type & STAT_EOL) {
308 pci_set_irq(&s->dev, 0);
311 if (val & STAT_FLAG) {
312 s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
313 if (s->aur.type & STAT_FLAG) {
314 pci_set_irq(&s->dev, 0);
317 break;
318 case 1:
319 if (val & CNTL_START) {
320 AUD_set_active_out(s->vo, 1);
321 s->aur.stat = STAT_ACTIVE;
323 if (val & CNTL_TERM) {
324 AUD_set_active_out(s->vo, 0);
325 s->aur.stat &= ~(STAT_ACTIVE | STAT_PAUSED);
326 s->aur.clen = 0;
328 if (val & CNTL_PAUSE) {
329 AUD_set_active_out(s->vo, 0);
330 s->aur.stat &= ~STAT_ACTIVE;
331 s->aur.stat |= STAT_PAUSED;
332 } else if (!(val & CNTL_PAUSE) && (s->aur.stat & STAT_PAUSED)) {
333 AUD_set_active_out(s->vo, 1);
334 s->aur.stat |= STAT_ACTIVE;
335 s->aur.stat &= ~STAT_PAUSED;
337 break;
338 case 2:
340 uint32_t oldval = s->aur.type;
341 s->aur.type = val;
342 if ((oldval & 0x30) != (val & 0x30)) {
343 open_voice_out(s);
345 break;
347 case 4:
348 s->aur.base = val & ~1ULL;
349 s->aur.curr = s->aur.base;
350 break;
351 case 0x80:
352 if (val >> 30) {
353 /* we only have primary codec */
354 break;
356 if (val & BIT(23)) { /* read reg */
357 s->ac97_cmd = val & 0xc0ff0000ULL;
358 s->ac97_cmd |= codec_read(s, (val >> 16) & 0x7f);
359 s->ac97_cmd |= BIT(25); /* data valid */
360 } else {
361 s->ac97_cmd = val & 0xc0ffffffULL;
362 codec_write(s, (val >> 16) & 0x7f, val);
364 break;
365 case 0xc:
366 case 0x84:
367 /* Read only */
368 break;
369 default:
370 qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register write 0x%"
371 HWADDR_PRIx"\n", addr);
375 static const MemoryRegionOps sgd_ops = {
376 .read = sgd_read,
377 .write = sgd_write,
378 .endianness = DEVICE_LITTLE_ENDIAN,
381 static uint64_t fm_read(void *opaque, hwaddr addr, unsigned size)
383 qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
384 return 0;
387 static void fm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
389 qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
390 __func__, addr, size, val);
393 static const MemoryRegionOps fm_ops = {
394 .read = fm_read,
395 .write = fm_write,
396 .endianness = DEVICE_LITTLE_ENDIAN,
399 static uint64_t midi_read(void *opaque, hwaddr addr, unsigned size)
401 qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
402 return 0;
405 static void midi_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
407 qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
408 __func__, addr, size, val);
411 static const MemoryRegionOps midi_ops = {
412 .read = midi_read,
413 .write = midi_write,
414 .endianness = DEVICE_LITTLE_ENDIAN,
417 static void via_ac97_reset(DeviceState *dev)
419 ViaAC97State *s = VIA_AC97(dev);
421 codec_reset(s);
424 static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
426 ViaAC97State *s = VIA_AC97(pci_dev);
427 Object *o = OBJECT(s);
430 * Command register Bus Master bit is documented to be fixed at 0 but it's
431 * needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here
432 * and the AmigaOS driver writes 1 only enabling IO bit which works on
433 * real hardware. So set it here and fix it to 1 to allow DMA.
435 pci_set_word(pci_dev->config + PCI_COMMAND, PCI_COMMAND_MASTER);
436 pci_set_word(pci_dev->wmask + PCI_COMMAND, PCI_COMMAND_IO);
437 pci_set_word(pci_dev->config + PCI_STATUS,
438 PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM);
439 pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
440 pci_set_byte(pci_dev->config + 0x40, 1); /* codec ready */
442 memory_region_init_io(&s->sgd, o, &sgd_ops, s, "via-ac97.sgd", 256);
443 pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->sgd);
444 memory_region_init_io(&s->fm, o, &fm_ops, s, "via-ac97.fm", 4);
445 pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm);
446 memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4);
447 pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi);
449 AUD_register_card ("via-ac97", &s->card);
452 static void via_ac97_exit(PCIDevice *dev)
454 ViaAC97State *s = VIA_AC97(dev);
456 AUD_close_out(&s->card, s->vo);
457 AUD_remove_card(&s->card);
460 static Property via_ac97_properties[] = {
461 DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
462 DEFINE_PROP_END_OF_LIST(),
465 static void via_ac97_class_init(ObjectClass *klass, void *data)
467 DeviceClass *dc = DEVICE_CLASS(klass);
468 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
470 k->realize = via_ac97_realize;
471 k->exit = via_ac97_exit;
472 k->vendor_id = PCI_VENDOR_ID_VIA;
473 k->device_id = PCI_DEVICE_ID_VIA_AC97;
474 k->revision = 0x50;
475 k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
476 device_class_set_props(dc, via_ac97_properties);
477 set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
478 dc->desc = "VIA AC97";
479 dc->reset = via_ac97_reset;
480 /* Reason: Part of a south bridge chip */
481 dc->user_creatable = false;
484 static const TypeInfo via_ac97_info = {
485 .name = TYPE_VIA_AC97,
486 .parent = TYPE_PCI_DEVICE,
487 .instance_size = sizeof(ViaAC97State),
488 .class_init = via_ac97_class_init,
489 .interfaces = (InterfaceInfo[]) {
490 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
491 { },
495 static void via_mc97_realize(PCIDevice *pci_dev, Error **errp)
497 pci_set_word(pci_dev->config + PCI_COMMAND,
498 PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE);
499 pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
500 pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
503 static void via_mc97_class_init(ObjectClass *klass, void *data)
505 DeviceClass *dc = DEVICE_CLASS(klass);
506 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
508 k->realize = via_mc97_realize;
509 k->vendor_id = PCI_VENDOR_ID_VIA;
510 k->device_id = PCI_DEVICE_ID_VIA_MC97;
511 k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
512 k->revision = 0x30;
513 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
514 dc->desc = "VIA MC97";
515 /* Reason: Part of a south bridge chip */
516 dc->user_creatable = false;
519 static const TypeInfo via_mc97_info = {
520 .name = TYPE_VIA_MC97,
521 .parent = TYPE_PCI_DEVICE,
522 .instance_size = sizeof(PCIDevice),
523 .class_init = via_mc97_class_init,
524 .interfaces = (InterfaceInfo[]) {
525 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
526 { },
530 static void via_ac97_register_types(void)
532 type_register_static(&via_ac97_info);
533 type_register_static(&via_mc97_info);
536 type_init(via_ac97_register_types)