xref: /openbmc/qemu/hw/audio/via-ac97.c (revision 0ed083a1)
1 /*
2  * VIA south bridges sound support
3  *
4  * Copyright (c) 2022-2023 BALATON Zoltan
5  *
6  * This work is licensed under the GNU GPL license version 2 or later.
7  */
8 
9 /*
10  * TODO: This is only a basic implementation of one audio playback channel
11  *       more functionality should be added here.
12  */
13 
14 #include "qemu/osdep.h"
15 #include "qemu/log.h"
16 #include "hw/isa/vt82c686.h"
17 #include "ac97.h"
18 #include "trace.h"
19 
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)
24 
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)
31 
32 #define CNTL_START  BIT(7)
33 #define CNTL_TERM   BIT(6)
34 #define CNTL_PAUSE  BIT(3)
35 
36 static void open_voice_out(ViaAC97State *s);
37 
38 static uint16_t codec_rates[] = { 8000, 11025, 16000, 22050, 32000, 44100,
39                                   48000 };
40 
41 #define CODEC_REG(s, o)  ((s)->codec_regs[(o) / 2])
42 #define CODEC_VOL(vol, mask)  ((255 * ((vol) & mask)) / mask)
43 
codec_volume_set_out(ViaAC97State * s)44 static void codec_volume_set_out(ViaAC97State *s)
45 {
46     int lvol, rvol, mute;
47 
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);
57 }
58 
codec_reset(ViaAC97State * s)59 static void codec_reset(ViaAC97State *s)
60 {
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;
82 }
83 
codec_read(ViaAC97State * s,uint8_t addr)84 static uint16_t codec_read(ViaAC97State *s, uint8_t addr)
85 {
86     return CODEC_REG(s, addr);
87 }
88 
codec_write(ViaAC97State * s,uint8_t addr,uint16_t val)89 static void codec_write(ViaAC97State *s, uint8_t addr, uint16_t val)
90 {
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;
101             }
102             if (val & BIT(5)) {
103                 val |= 0x1f;
104             }
105         }
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);
116         }
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;
123 
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;
129                 }
130             }
131             if (rate > 48000) {
132                 rate = 48000;
133             }
134             CODEC_REG(s, addr) = rate;
135             open_voice_out(s);
136         }
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;
150     }
151 }
152 
fetch_sgd(ViaAC97SGDChannel * c,PCIDevice * d)153 static void fetch_sgd(ViaAC97SGDChannel *c, PCIDevice *d)
154 {
155     uint32_t b[2];
156 
157     if (c->curr < c->base) {
158         c->curr = c->base;
159     }
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;
164     }
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));
170 }
171 
out_cb(void * opaque,int avail)172 static void out_cb(void *opaque, int avail)
173 {
174     ViaAC97State *s = opaque;
175     ViaAC97SGDChannel *c = &s->aur;
176     int temp, to_copy, copied;
177     bool stop = false;
178     uint8_t tmpbuf[4096];
179 
180     if (c->stat & STAT_PAUSED) {
181         return;
182     }
183     c->stat |= STAT_ACTIVE;
184     while (avail && !stop) {
185         if (!c->clen) {
186             fetch_sgd(c, &s->dev);
187         }
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;
196             }
197             temp -= copied;
198             avail -= copied;
199             c->addr += copied;
200             c->clen -= copied;
201         }
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);
212                 }
213                 if (c->type & STAT_EOL) {
214                     via_isa_set_irq(&s->dev, 0, 1);
215                 }
216             }
217             if (CLEN_IS_FLAG(c)) {
218                 c->stat |= STAT_FLAG;
219                 c->stat |= STAT_PAUSED;
220                 if (c->type & STAT_FLAG) {
221                     via_isa_set_irq(&s->dev, 0, 1);
222                 }
223             }
224             if (CLEN_IS_STOP(c)) {
225                 c->stat |= STAT_STOP;
226                 c->stat |= STAT_PAUSED;
227             }
228             c->clen = 0;
229             stop = true;
230         }
231     }
232 }
233 
open_voice_out(ViaAC97State * s)234 static void open_voice_out(ViaAC97State *s)
235 {
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,
241     };
242     s->vo = AUD_open_out(&s->card, s->vo, "via-ac97.out", s, out_cb, &as);
243 }
244 
sgd_read(void * opaque,hwaddr addr,unsigned size)245 static uint64_t sgd_read(void *opaque, hwaddr addr, unsigned size)
246 {
247     ViaAC97State *s = opaque;
248     uint64_t val = 0;
249 
250     switch (addr) {
251     case 0:
252         val = s->aur.stat;
253         if (s->aur.type & CNTL_START) {
254             val |= STAT_TRIG;
255         }
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);
279         }
280         if (s->aur.stat & STAT_STOP) {
281             val |= BIT(8);
282         }
283         if (s->aur.stat & STAT_ACTIVE) {
284             val |= BIT(12);
285         }
286         break;
287     default:
288         qemu_log_mask(LOG_UNIMP, "via-ac97: Unimplemented register read 0x%"
289                       HWADDR_PRIx"\n", addr);
290     }
291     trace_via_ac97_sgd_read(addr, size, val);
292     return val;
293 }
294 
sgd_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)295 static void sgd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
296 {
297     ViaAC97State *s = opaque;
298 
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;
304         }
305         if (val & STAT_EOL) {
306             s->aur.stat &= ~(STAT_EOL | STAT_PAUSED);
307             if (s->aur.type & STAT_EOL) {
308                 via_isa_set_irq(&s->dev, 0, 0);
309             }
310         }
311         if (val & STAT_FLAG) {
312             s->aur.stat &= ~(STAT_FLAG | STAT_PAUSED);
313             if (s->aur.type & STAT_FLAG) {
314                 via_isa_set_irq(&s->dev, 0, 0);
315             }
316         }
317         break;
318     case 1:
319         if (val & CNTL_START) {
320             AUD_set_active_out(s->vo, 1);
321             s->aur.stat = STAT_ACTIVE;
322         }
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;
327         }
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;
336         }
337         break;
338     case 2:
339     {
340         uint32_t oldval = s->aur.type;
341         s->aur.type = val;
342         if ((oldval & 0x30) != (val & 0x30)) {
343             open_voice_out(s);
344         }
345         break;
346     }
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;
355         }
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);
363         }
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);
372     }
373 }
374 
375 static const MemoryRegionOps sgd_ops = {
376     .read = sgd_read,
377     .write = sgd_write,
378     .endianness = DEVICE_LITTLE_ENDIAN,
379 };
380 
fm_read(void * opaque,hwaddr addr,unsigned size)381 static uint64_t fm_read(void *opaque, hwaddr addr, unsigned size)
382 {
383     qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
384     return 0;
385 }
386 
fm_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)387 static void fm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
388 {
389     qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
390                   __func__, addr, size, val);
391 }
392 
393 static const MemoryRegionOps fm_ops = {
394     .read = fm_read,
395     .write = fm_write,
396     .endianness = DEVICE_LITTLE_ENDIAN,
397 };
398 
midi_read(void * opaque,hwaddr addr,unsigned size)399 static uint64_t midi_read(void *opaque, hwaddr addr, unsigned size)
400 {
401     qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d\n", __func__, addr, size);
402     return 0;
403 }
404 
midi_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)405 static void midi_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
406 {
407     qemu_log_mask(LOG_UNIMP, "%s: 0x%"HWADDR_PRIx" %d <= 0x%"PRIX64"\n",
408                   __func__, addr, size, val);
409 }
410 
411 static const MemoryRegionOps midi_ops = {
412     .read = midi_read,
413     .write = midi_write,
414     .endianness = DEVICE_LITTLE_ENDIAN,
415 };
416 
via_ac97_reset(DeviceState * dev)417 static void via_ac97_reset(DeviceState *dev)
418 {
419     ViaAC97State *s = VIA_AC97(dev);
420 
421     codec_reset(s);
422 }
423 
via_ac97_realize(PCIDevice * pci_dev,Error ** errp)424 static void via_ac97_realize(PCIDevice *pci_dev, Error **errp)
425 {
426     ViaAC97State *s = VIA_AC97(pci_dev);
427     Object *o = OBJECT(s);
428 
429     if (!AUD_register_card ("via-ac97", &s->card, errp)) {
430         return;
431     }
432 
433     /*
434      * Command register Bus Master bit is documented to be fixed at 0 but it's
435      * needed for PCI DMA to work in QEMU. The pegasos2 firmware writes 0 here
436      * and the AmigaOS driver writes 1 only enabling IO bit which works on
437      * real hardware. So set it here and fix it to 1 to allow DMA.
438      */
439     pci_set_word(pci_dev->config + PCI_COMMAND, PCI_COMMAND_MASTER);
440     pci_set_word(pci_dev->wmask + PCI_COMMAND, PCI_COMMAND_IO);
441     pci_set_word(pci_dev->config + PCI_STATUS,
442                  PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_MEDIUM);
443     pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
444     pci_set_byte(pci_dev->config + 0x40, 1); /* codec ready */
445 
446     memory_region_init_io(&s->sgd, o, &sgd_ops, s, "via-ac97.sgd", 256);
447     pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->sgd);
448     memory_region_init_io(&s->fm, o, &fm_ops, s, "via-ac97.fm", 4);
449     pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->fm);
450     memory_region_init_io(&s->midi, o, &midi_ops, s, "via-ac97.midi", 4);
451     pci_register_bar(pci_dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->midi);
452 }
453 
via_ac97_exit(PCIDevice * dev)454 static void via_ac97_exit(PCIDevice *dev)
455 {
456     ViaAC97State *s = VIA_AC97(dev);
457 
458     AUD_close_out(&s->card, s->vo);
459     AUD_remove_card(&s->card);
460 }
461 
462 static Property via_ac97_properties[] = {
463     DEFINE_AUDIO_PROPERTIES(ViaAC97State, card),
464     DEFINE_PROP_END_OF_LIST(),
465 };
466 
via_ac97_class_init(ObjectClass * klass,void * data)467 static void via_ac97_class_init(ObjectClass *klass, void *data)
468 {
469     DeviceClass *dc = DEVICE_CLASS(klass);
470     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
471 
472     k->realize = via_ac97_realize;
473     k->exit = via_ac97_exit;
474     k->vendor_id = PCI_VENDOR_ID_VIA;
475     k->device_id = PCI_DEVICE_ID_VIA_AC97;
476     k->revision = 0x50;
477     k->class_id = PCI_CLASS_MULTIMEDIA_AUDIO;
478     device_class_set_props(dc, via_ac97_properties);
479     set_bit(DEVICE_CATEGORY_SOUND, dc->categories);
480     dc->desc = "VIA AC97";
481     dc->reset = via_ac97_reset;
482     /* Reason: Part of a south bridge chip */
483     dc->user_creatable = false;
484 }
485 
486 static const TypeInfo via_ac97_info = {
487     .name          = TYPE_VIA_AC97,
488     .parent        = TYPE_PCI_DEVICE,
489     .instance_size = sizeof(ViaAC97State),
490     .class_init    = via_ac97_class_init,
491     .interfaces = (InterfaceInfo[]) {
492         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
493         { },
494     },
495 };
496 
via_mc97_realize(PCIDevice * pci_dev,Error ** errp)497 static void via_mc97_realize(PCIDevice *pci_dev, Error **errp)
498 {
499     pci_set_word(pci_dev->config + PCI_COMMAND,
500                  PCI_COMMAND_INVALIDATE | PCI_COMMAND_VGA_PALETTE);
501     pci_set_word(pci_dev->config + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM);
502     pci_set_long(pci_dev->config + PCI_INTERRUPT_PIN, 0x03);
503 }
504 
via_mc97_class_init(ObjectClass * klass,void * data)505 static void via_mc97_class_init(ObjectClass *klass, void *data)
506 {
507     DeviceClass *dc = DEVICE_CLASS(klass);
508     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
509 
510     k->realize = via_mc97_realize;
511     k->vendor_id = PCI_VENDOR_ID_VIA;
512     k->device_id = PCI_DEVICE_ID_VIA_MC97;
513     k->class_id = PCI_CLASS_COMMUNICATION_OTHER;
514     k->revision = 0x30;
515     set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
516     dc->desc = "VIA MC97";
517     /* Reason: Part of a south bridge chip */
518     dc->user_creatable = false;
519 }
520 
521 static const TypeInfo via_mc97_info = {
522     .name          = TYPE_VIA_MC97,
523     .parent        = TYPE_PCI_DEVICE,
524     .instance_size = sizeof(PCIDevice),
525     .class_init    = via_mc97_class_init,
526     .interfaces = (InterfaceInfo[]) {
527         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
528         { },
529     },
530 };
531 
via_ac97_register_types(void)532 static void via_ac97_register_types(void)
533 {
534     type_register_static(&via_ac97_info);
535     type_register_static(&via_mc97_info);
536 }
537 
538 type_init(via_ac97_register_types)
539