-
Notifications
You must be signed in to change notification settings - Fork 1
/
ac97.asm
751 lines (613 loc) · 17 KB
/
ac97.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
; 19/05/2024
; 12/11/2023
; 11/11/2023
; 06/11/2023
; 05/11/2023
; 04/11/2023
; 03/11/2023
; PCI and AC97 codec functions for wav player
; Erdogan Tan (17/02/2017)
; ----------------------------------------------------------------------------
; PCI.ASM
; ----------------------------------------------------------------------------
; PCI device register reader/writers.
; NASM version: Erdogan Tan (29/11/2016)
; Last Update: 17/02/2017
;===============================================================
; 8/16/32bit PCI reader
;
; Entry: EAX=PCI Bus/Device/fn/register number
; BIT30 set if 32 bit access requested
; BIT29 set if 16 bit access requested
; otherwise defaults to 8 bit read
;
; Exit: DL,DX,EDX register data depending on requested read size
;
; Note: this routine is meant to be called via pciRegRead8, pciRegread16,
; or pciRegRead32, listed below.
;
; Note2: don't attempt to read 32bits of data from a non dword aligned reg
; number. Likewise, don't do 16bit reads from non word aligned reg #
;
pciRegRead:
push ebx
push cx
mov ebx, eax ; save eax, dh
mov cl, dh
and eax, (~PCI32)+PCI16 ; clear out data size request
or eax, BIT31 ; make a PCI access request
and al, ~3 ; NOT 3 ; force index to be dword
mov dx, PCI_INDEX_PORT
out dx, eax ; write PCI selector
mov dx, PCI_DATA_PORT
mov al, bl
and al, 3 ; figure out which port to
add dl, al ; read to
in eax, dx ; do 32bit read
test ebx, PCI32
jz short _pregr1
mov edx, eax ; return 32bits of data
_pregr1:
mov dx, ax ; return 16bits of data
test ebx, PCI32+PCI16
jnz short _pregr2
mov dh, cl ; restore dh for 8 bit read
_pregr2:
mov eax, ebx ; restore eax
and eax, (~PCI32)+PCI16 ; clear out data size request
pop cx
pop ebx
retn
pciRegRead8:
and eax, (~PCI16)+PCI32 ; set up 8 bit read size
jmp short pciRegRead ; call generic PCI access
pciRegRead16:
and eax, (~PCI16)+PCI32 ; set up 16 bit read size
or eax, PCI16 ; call generic PCI access
jmp short pciRegRead
pciRegRead32:
and eax, (~PCI16)+PCI32 ; set up 32 bit read size
or eax, PCI32 ; call generic PCI access
jmp short pciRegRead
;===============================================================
; 8/16/32bit PCI writer
;
; Entry: EAX=PCI Bus/Device/fn/register number
; BIT31 set if 32 bit access requested
; BIT30 set if 16 bit access requested
; otherwise defaults to 8bit read
; DL/DX/EDX data to write depending on size
;
;
; note: this routine is meant to be called via pciRegWrite8, pciRegWrite16,
; or pciRegWrite32 as detailed below.
;
; Note2: don't attempt to write 32bits of data from a non dword aligned reg
; number. Likewise, don't do 16bit writes from non word aligned reg #
;
pciRegWrite:
push ebx
push cx
mov ebx, eax ; save eax, dx
mov cx, dx
or eax, BIT31 ; make a PCI access request
and eax, ~PCI16 ; NOT PCI16 ; clear out data size request
and al, ~3 ; NOT 3 ; force index to be dword
mov dx, PCI_INDEX_PORT
out dx, eax ; write PCI selector
mov dx, PCI_DATA_PORT
mov al, bl
and al, 3 ; figure out which port to
add dl, al ; write to
mov eax, edx ; put data into eax
mov ax, cx
out dx, al
test ebx, PCI16+PCI32 ; only 8bit access? bail
jz short _pregw1
out dx, ax ; write 16 bit value
test ebx, PCI16 ; 16bit requested? bail
jnz short _pregw1
out dx, eax ; write full 32bit
_pregw1:
mov eax, ebx ; restore eax
and eax, (~PCI32)+PCI16 ; clear out data size request
mov dx, cx ; restore dx
pop cx
pop ebx
ret
pciRegWrite8:
and eax, (~PCI16)+PCI32 ; set up 8 bit write size
jmp short pciRegWrite ; call generic PCI access
pciRegWrite16:
and eax, (~PCI16)+PCI32 ; set up 16 bit write size
or eax, PCI16 ; call generic PCI access
jmp short pciRegWrite
pciRegWrite32:
and eax, (~PCI16)+PCI32 ; set up 32 bit write size
or eax, PCI32 ; call generic PCI access
jmp short pciRegWrite
; 17/02/2017 (Modifed by Erdogan Tan for various ICH device IDs)
;===============================================================
; PCIFindDevice: scan through PCI space looking for a device+vendor ID
;
; ENTRY: none
;; Entry: EAX=Device+Vendor ID
;
; Exit: EAX=PCI address if device found
; EDX=Device+Vendor ID
; CY clear if found, set if not found. EAX invalid if CY set.
;
; [old stackless] Destroys: ebx, esi, edi, cl
;
pciFindDevice:
;push cx
;push eax ; *
;push esi
;push edi
;mov esi, eax ; save off vend+device ID
; 17/02/2017
mov si, valid_ids ; address of Valid ICH (AC97) Device IDs
mov cx, valid_id_count
pfd_0:
mov edi, (80000000h - 100h) ; start with bus 0, dev 0 func 0
nextPCIdevice:
add edi, 100h
cmp edi, 80FFF800h ; scanned all devices?
;stc
;je short PCIScanExit ; not found
jb short pfd_1
mov edi, 80000000h
add si, 4 ; scan for next device ID
loop pfd_1
stc
;jmp short PCIScanExit
retn
pfd_1:
mov eax, edi ; read PCI registers
call pciRegRead32
;cmp edx, esi ; found device?
cmp edx, dword [si]
jne short nextPCIdevice
;clc
PCIScanExit:
;pushf
mov eax, BIT31
not eax
and eax, edi ; return only bus/dev/fn #
;popf
;pop edi
;pop esi
;pop edx ; *
;pop cx
retn
; ----------------------------------------------------------------------------
; CODEC.ASM
; ----------------------------------------------------------------------------
; codec configuration code. Not much here really.
; NASM version: Erdogan Tan (29/11/2016)
; enable codec, unmute stuff, set output rate to 44.1
; entry: ax = desired sample rate
; 19/05/2024
; 11/11/2023
; 06/11/2023
%if 1
codecConfig:
; 19/05/2024
; 04/11/2023
; 17/02/2017
; 07/11/2016 (Erdogan Tan)
;PORT_NABM_GLB_CTRL_STAT equ 60h
; 03/11/2023 (MPXPLAY, 'SC_ICH.C', ac97_init)
; 'AC97_DEF.H'
;AC97_EXTENDED_STATUS equ 002Ah
AC97_EA_SPDIF equ 0002h
AC97_EA_VRA equ 0001h
; 04/11/2023
ICH_PO_CR_RESET equ 0002h ; reset codec
ICH_PCM_20BIT equ 400000h ; 20-bit samples (ICH4)
ICH_PCM_246_MASK equ 300000h ; 6 channels
; 04/11/2023
init_ac97_controller:
mov eax, [bus_dev_fn]
mov al, PCI_CMD_REG
call pciRegRead16 ; read PCI command register
or dl, IO_ENA+BM_ENA ; enable IO and bus master
call pciRegWrite16
call delay_100ms
; 19/05/2024
; ('PLAYMOD3.ASM', Erdogan Tan, 18/05/2024)
init_ac97_codec:
; 19/05/2024
mov bp, 40
_initc_1:
; 11/11/2023
; (TRDOS 386 v2.0.5, 'audio.s')
mov dx, GLOB_CNT_REG ; 2Ch
add dx, [NABMBAR]
in eax, dx
; 19/05/2024
call delay1_4ms
; ?
mov dx, GLOB_STS_REG ; 30h
add dx, [NABMBAR]
in eax, dx
; 19/05/2024
call delay1_4ms
cmp eax, 0FFFFFFFFh ; -1
jne short _initc_3
_initc_2:
dec bp
jz short _ac97_codec_ready
call delay_100ms
jmp short _initc_1
_initc_3:
; 19/05/2024
test eax, CTRL_ST_CREADY
jnz short _ac97_codec_ready
call reset_ac97_codec
jmp short _initc_2
_ac97_codec_ready:
mov dx, [NAMBAR]
;add dx, 0 ; ac_reg_0 ; reset register
out dx, ax
call delay_100ms
; 19/05/2024
or bp, bp
jnz short _ac97_codec_init_ok
xor eax, eax ; 0
mov dx, [NAMBAR]
add dx, CODEC_REG_POWERDOWN
out dx, ax
; wait for 1 second
;mov ecx, 1000 ; 1000*0.25ms = 1s
; 19/05/2024
mov cx, 40
_ac97_codec_rloop:
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
call delay_100ms
;mov dx, [NAMBAR]
;add dx, CODEC_REG_POWERDOWN
in ax, dx
call delay1_4ms
and ax, 0Fh
cmp al, 0Fh
je short _ac97_codec_init_ok
loop _ac97_codec_rloop
init_ac97_codec_err1:
;stc ; cf = 1 ; 19/05/2024
init_ac97_codec_err2:
retn
_ac97_codec_init_ok:
; 11/11/2023
;mov al, 2 ; force set 16-bit 2-channel PCM
;mov dx, GLOB_CNT_REG ; 2Ch
;add dx, [NABMBAR]
;out dx, eax
;;call delay1_4ms
call reset_ac97_controller
; 11/11/2023
;call delay1_4ms
; 19/05/2024
call delay_100ms
;call setup_ac97_codec
setup_ac97_codec:
; 12/11/2023
cmp word [sample_rate], 48000
je short skip_rate
; 11/11/2023
; 05/11/2023
;%if 1
AC97_EA_VRA equ BIT0 ; 11/11/2023
; 19/05/2024
call delay1_4ms
;; 19/05/2024
;;mov dx, [NAMBAR]
;;add dx, CODEC_EXT_AUDIO_REG ; 28h
;;in ax, dx
;
;; 19/05/2024
;;test al, 1 ; BIT0 ; Variable Rate Audio bit
;;jz short vra_not_supported
;
;; 19/05/2024
;;call delay1_4ms
; 11/11/2023
mov dx, [NAMBAR]
add dx, CODEC_EXT_AUDIO_CTRL_REG ; 2Ah
in ax, dx
; 19/05/2024
call delay1_4ms
and al, ~BIT1 ; Clear DRA
or al, AC97_EA_VRA ; 1 ; 04/11/2023
out dx, ax ; Enable variable rate audio
mov cx, 10
check_vra:
call delay_100ms
; 11/11/2023
in ax, dx
test al, AC97_EA_VRA ; 1
jnz short set_rate
; 11/11/2023
loop check_vra
; 19/05/2024
vra_not_supported:
; 12/11/2023
pop ax ; discard return address to the caller
mov dx, msg_no_vra
jmp vra_err
set_rate:
mov ax, [sample_rate] ; 17/02/2017 (Erdogan Tan)
mov dx, [NAMBAR]
add dx, CODEC_PCM_FRONT_DACRATE_REG ; 2Ch
out dx, ax ; PCM Front/Center Output Sample Rate
call delay_100ms
; 12/11/2023
skip_rate:
; 11/11/2023 (temporary)
;mov dx, [NAMBAR]
;add dx, CODEC_PCM_SURND_DACRATE_REG ; 2Eh
;out dx, ax ; PCM Surround Output Sample Rate
;call delay_100ms
;mov dx, [NAMBAR]
;add dx, CODEC_PCM_LFE_DACRATE_REG ; 30h
;out dx, ax ; PCM LFE Output Sample Rate
;call delay_100ms
; 05/11/2023 (temporary)
;mov dx, [NAMBAR]
;add dx, CODEC_LR_ADCRATE_REG ; 32h
;out dx, ax ; PCM Input Sample Rate
;
;call delay_100ms
mov ax, 0202h
mov dx, [NAMBAR]
add dx, CODEC_MASTER_VOL_REG ;02h
out dx, ax
; 11/11/2023
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;
;mov dx, [NAMBAR]
;add dx, CODEC_MASTER_MONO_VOL_REG ;06h
;out dx, ax
; 11/11/2023
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;
;mov ax, 02h
;mov dx, [NAMBAR]
;add dx, CODEC_PCBEEP_VOL_REG ;0Ah
;out dx, ax
call delay1_4ms
call delay1_4ms
call delay1_4ms
call delay1_4ms
;mov ax, 0202h
mov dx, [NAMBAR]
add dx, CODEC_PCM_OUT_REG ;18h
out dx, ax
call delay1_4ms
call delay1_4ms
call delay1_4ms
call delay1_4ms
; 11/11/2023
;mov ax, 8008h ; Mute
;mov dx, [NAMBAR]
;add dx, CODEC_PHONE_VOL_REG ;0Ch
; ; AC97_PHONE_VOL ; TAD Input (Mono)
;out dx, ax
;
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;mov ax, 0808h
;mov dx, [NAMBAR]
;add dx, CODEC_LINE_IN_VOL_REG ;10h ; Line Input (Stereo)
;out dx, ax
;
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;mov dx, [NAMBAR]
;add dx, CODEC_CD_VOL_REG ;12h ; CD Input (Stereo)
;out dx, ax
;
;mov dx, [NAMBAR]
;add dx, CODEC_AUX_VOL_REG ;16h ; Aux Input (Stereo)
;out dx, ax
;
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
;call delay1_4ms
; 19/05/2024
clc
;detect_ac97_codec:
retn
reset_ac97_controller:
; 19/05/2024
; 11/11/2023
; 10/06/2017
; 29/05/2017
; 28/05/2017
; reset AC97 audio controller registers
xor ax, ax
mov dx, PI_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
mov dx, PO_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
mov dx, MC_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
mov al, RR
mov dx, PI_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
mov dx, PO_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
mov dx, MC_CR_REG
add dx, [NABMBAR]
out dx, al
; 19/05/2024
call delay1_4ms
retn
reset_ac97_codec:
; 11/11/2023
; 28/05/2017 - Erdogan Tan (Ref: KolibriOS, intelac97.asm)
mov dx, GLOB_CNT_REG ; 2Ch
add dx, [NABMBAR]
in eax, dx
;test eax, 2
; 06/08/2022
test al, 2
jz short _r_ac97codec_cold
call warm_ac97codec_reset
jnc short _r_ac97codec_ok
_r_ac97codec_cold:
call cold_ac97codec_reset
jnc short _r_ac97codec_ok
; 16/04/2017
;xor eax, eax ; timeout error
;stc
retn
_r_ac97codec_ok:
xor eax, eax
;mov al, VIA_ACLINK_C00_READY ; 1
inc al
retn
warm_ac97codec_reset:
; 11/11/2023
; 06/08/2022 - TRDOS 386 v2.0.5
; 28/05/2017 - Erdogan Tan (Ref: KolibriOS, intelac97.asm)
mov eax, 6
mov dx, GLOB_CNT_REG ; 2Ch
add dx, [NABMBAR]
out dx, eax
mov cx, 10 ; total 1s
_warm_ac97c_rst_wait:
call delay_100ms
mov dx, GLOB_STS_REG ; 30h
add dx, [NABMBAR]
in eax, dx
test eax, CTRL_ST_CREADY
jnz short _warm_ac97c_rst_ok
dec cx
jnz short _warm_ac97c_rst_wait
_warm_ac97c_rst_fail:
stc
_warm_ac97c_rst_ok:
retn
cold_ac97codec_reset:
; 11/11/2023
; 06/08/2022 - TRDOS 386 v2.0.5
; 28/05/2017 - Erdogan Tan (Ref: KolibriOS, intelac97.asm)
mov eax, 2
mov dx, GLOB_CNT_REG ; 2Ch
add dx, [NABMBAR]
out dx, eax
call delay_100ms ; wait 100 ms
call delay_100ms ; wait 100 ms
call delay_100ms ; wait 100 ms
call delay_100ms ; wait 100 ms
mov cx, 16 ; total 20*100 ms = 2s
_cold_ac97c_rst_wait:
mov dx, GLOB_STS_REG ; 30h
add dx, [NABMBAR]
in eax, dx
test eax, CTRL_ST_CREADY
jnz short _cold_ac97c_rst_ok
call delay_100ms
dec cx
jnz short _cold_ac97c_rst_wait
_cold_ac97c_rst_fail:
stc
_cold_ac97c_rst_ok:
retn
delay_100ms:
; 11/11/2023
; 29/05/2017
; 24/03/2017 ('codec.asm')
; wait 100 ms
push cx
mov cx, 400 ; 400*0.25ms
_delay_x_ms:
call delay1_4ms
loop _delay_x_ms
pop cx
retn
%endif
; 11/11/2023
%if 0
codecConfig:
; 06/11/2023
; TUNELOOP version (playing without interrupt)
; 04/11/2023
; 17/02/2017
; 07/11/2016 (Erdogan Tan)
mov ax, [sample_rate] ; 17/02/2017 (Erdogan Tan)
mov dx, [NAMBAR]
add dx, CODEC_PCM_FRONT_DACRATE_REG ; 2Ch
out dx, ax ; out sample rate
; 05/11/2023 temp
;mov dx, [NAMBAR]
;add dx, CODEC_LR_ADCRATE_REG ; 32h
;out dx, ax
call delay1_4ms
call delay1_4ms
call delay1_4ms
call delay1_4ms
mov eax, [dev_vendor]
cmp eax, (SI7012_DID<<16)+SIS_VID
jne short cConfig1
; Unmute quirk specifically for the SiS7012
CUSTOM_SIS_7012_REG equ 4Ch ; SiS7012-specific register
mov dx, [NABMBAR]
add dx, CUSTOM_SIS_7012_REG
in ax, dx
or al, 1
out dx, ax
cConfig1:
; 03/11/2023 (MPXPLAY, 'SC_ICH.C', ac97_init)
; initial ac97 volumes (and clear mute flag)
mov dx, [NAMBAR]
add dx, CODEC_MASTER_VOL_REG ;02h ; STEREO
;xor ax, ax ; volume attenuation = 0 (max. volume)
; 03/11/2023
mov ax, 0202h
out dx, ax
call delay1_4ms ; delays because codecs are slow
call delay1_4ms
call delay1_4ms
call delay1_4ms
mov dx, [NAMBAR]
add dx, CODEC_PCM_OUT_REG ;18h
;;xor ax, ax
;mov ax, 0202h
out dx, ax
call delay1_4ms
call delay1_4ms
call delay1_4ms
call delay1_4ms
retn
%endif