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.
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"
16 #include "hw/isa/vt82c686.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,
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
)
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);
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);
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
);
96 case AC97_Master_Volume_Mute
:
97 case AC97_PCM_Out_Volume_Mute
:
98 if (addr
== AC97_Master_Volume_Mute
) {
106 CODEC_REG(s
, addr
) = val
& 0x9f1f;
107 codec_volume_set_out(s
);
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;
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
) {
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
];
134 CODEC_REG(s
, addr
) = rate
;
138 case AC97_Powerdown_Ctrl_Stat
:
139 CODEC_REG(s
, addr
) = (val
& 0xff00) | (CODEC_REG(s
, addr
) & 0xff);
141 case AC97_Extended_Audio_ID
:
142 case AC97_Vendor_ID1
:
143 case AC97_Vendor_ID2
:
144 /* Read only registers */
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
)
157 if (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");
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
;
178 uint8_t tmpbuf
[4096];
180 if (c
->stat
& STAT_PAUSED
) {
183 c
->stat
|= STAT_ACTIVE
;
184 while (avail
&& !stop
) {
186 fetch_sgd(c
, &s
->dev
);
188 temp
= MIN(CLEN_LEN(c
), avail
);
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
);
202 if (CLEN_LEN(c
) == 0) {
204 if (CLEN_IS_EOL(c
)) {
206 if (c
->type
& CNTL_START
) {
208 c
->stat
|= STAT_PAUSED
;
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
;
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
,
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
;
253 if (s
->aur
.type
& CNTL_START
) {
258 val
= s
->aur
.stat
& STAT_PAUSED
? BIT(3) : 0;
267 val
= CLEN_LEN(&s
->aur
);
270 /* silence unimplemented log message that happens at every IRQ */
276 val
= s
->aur
.stat
& STAT_FLAG
;
277 if (s
->aur
.stat
& STAT_EOL
) {
280 if (s
->aur
.stat
& STAT_STOP
) {
283 if (s
->aur
.stat
& STAT_ACTIVE
) {
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
);
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
);
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);
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
);
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
;
340 uint32_t oldval
= s
->aur
.type
;
342 if ((oldval
& 0x30) != (val
& 0x30)) {
348 s
->aur
.base
= val
& ~1ULL;
349 s
->aur
.curr
= s
->aur
.base
;
353 /* we only have primary codec */
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 */
361 s
->ac97_cmd
= val
& 0xc0ffffffULL
;
362 codec_write(s
, (val
>> 16) & 0x7f, val
);
370 qemu_log_mask(LOG_UNIMP
, "via-ac97: Unimplemented register write 0x%"
371 HWADDR_PRIx
"\n", addr
);
375 static const MemoryRegionOps sgd_ops
= {
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
);
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
= {
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
);
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
= {
414 .endianness
= DEVICE_LITTLE_ENDIAN
,
417 static void via_ac97_reset(DeviceState
*dev
)
419 ViaAC97State
*s
= VIA_AC97(dev
);
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
;
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
},
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
;
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
},
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
)