Subversion Repositories Kolibri OS

Rev

Rev 3083 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3083 leency 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
; Universal Interface for Intel High Definition Audio Codec  ;
3
;                                                            ;
4
; Generic widget tree parser                                 ;
5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
 
7
; widget node for parsing
8
struc HDA_GNODE
9
{
5048 Asper 10
	.nid		    dw ?    ;NID of this widget
11
	.nconns 	    dw ?    ;number of input connections
12
	.conn_list	    dd ?
13
	.slist		    dw ?    ;temporary list
14
			    dw ?
3083 leency 15
 
5048 Asper 16
	.wid_caps	    dd ?    ;widget capabilities
17
	.type		    db ?    ;widget type
18
	.pin_ctl	    db ?    ;pin controls
19
	.checked	    db ?    ;the flag indicates that the node is already parsed
20
	.pin_caps	    dd ?    ;pin widget capabilities
21
	.def_cfg	    dd ?    ;default configuration
22
	.amp_out_caps	    dd ?    ;AMP out capabilities
23
	.amp_in_caps	    dd ?    ;AMP in capabilities
24
	.next		    dd ? ;        struct list_head list
25
	.sizeof:
3083 leency 26
}
27
 
28
virtual at 0
5048 Asper 29
	HDA_GNODE  HDA_GNODE
3083 leency 30
end virtual
31
 
32
struc HDA_GSPEC
33
{
5048 Asper 34
	.dac_node	    dd ?    ;DAC node
35
			    dd ?
36
	.out_pin_node	    dd ?    ;Output pin (Line-Out) node
37
			    dd ?
3083 leency 38
 
5048 Asper 39
	.def_amp_in_caps    dd ?
40
	.def_amp_out_caps   dd ?
3083 leency 41
 
5048 Asper 42
;        .pcm_rec            dd ?    ;PCM information
43
	.nid_list	    dd 0    ;list of widgets
3083 leency 44
}
45
 
46
struc VOLUME_CTL
47
{
5048 Asper 48
	.out_amp_node	    dd 0    ;Asper+ : To get/set volume
49
	.num_steps	    db ?    ; num_steps=NumSteps+1
50
	.step_size	    db ?    ; step_size=StepSize+1
51
	.maxDb		    dd ?    ; Max volume in Db.   maxDb=(num_steps*step_size/4*100)
3083 leency 52
}
53
 
54
; retrieve the default device type from the default config value
5048 Asper 55
proc defcfg_type stdcall, node:dword
56
	push	 edx
57
	mov	 edx, [node]
58
	mov	 eax, [edx + HDA_GNODE.def_cfg]
59
	and	 eax, AC_DEFCFG_DEVICE
60
	shr	 eax, AC_DEFCFG_DEVICE_SHIFT
61
	pop	 edx
62
	ret
3083 leency 63
endp
64
 
5048 Asper 65
proc defcfg_location stdcall, node:dword
66
	push	 edx
67
	mov	 edx, [node]
68
	mov	 eax, [edx + HDA_GNODE.def_cfg]
69
	and	 eax, AC_DEFCFG_LOCATION
70
	shr	 eax, AC_DEFCFG_LOCATION_SHIFT
71
	pop	 edx
72
	ret
3083 leency 73
endp
74
 
5048 Asper 75
proc defcfg_port_conn stdcall, node:dword
76
	push	 edx
77
	mov	 edx, [node]
78
	mov	 eax, [edx + HDA_GNODE.def_cfg]
79
	and	 eax, AC_DEFCFG_PORT_CONN
80
	shr	 eax, AC_DEFCFG_PORT_CONN_SHIFT
81
	pop	 edx
82
	ret
3083 leency 83
endp
84
 
5048 Asper 85
proc defcfg_color stdcall, node:dword
86
	push	 edx
87
	mov	 edx, [node]
88
	mov	 eax, [edx + HDA_GNODE.def_cfg]
89
	and	 eax, AC_DEFCFG_COLOR
90
	shr	 eax, AC_DEFCFG_COLOR_SHIFT
91
	pop	 edx
92
	ret
3083 leency 93
endp
94
 
95
; destructor
5048 Asper 96
proc snd_hda_generic_free
97
	push	eax ebx edx edi
98
	; free all widgets
99
	mov	ebx, [spec.nid_list]  ; ebx = 1st node address
100
	test	ebx, ebx
101
	jz	.out
102
	mov	edx, [ebx + HDA_GNODE.next]  ;edx = 2nd node address
3083 leency 103
 
5048 Asper 104
.next:
105
	test	edx, edx
106
	jz	.free_head
3083 leency 107
 
5048 Asper 108
	mov	eax, [edx + HDA_GNODE.conn_list]
109
	lea	edi, [edx + HDA_GNODE.slist]
110
	cmp	eax, edi
111
	je	@f
112
	pusha
113
	invoke	Kfree  ;free conn_list
114
	popa
115
@@:
116
	mov	eax, edx
117
	mov	edx, [edx + HDA_GNODE.next]
118
	pusha
119
	invoke	Kfree  ;free node
120
	popa
121
	jmp	.next
122
.free_head:
123
	mov	eax, [spec.nid_list]
124
	pusha
125
	invoke	Kfree  ;free the very 1st node in the list
126
	popa
127
	mov	[spec.nid_list], 0
128
.out:
129
	pop	edi edx ebx eax
130
	ret
3083 leency 131
endp
132
 
133
 
134
; add a new widget node and read its attributes
5048 Asper 135
proc add_new_node stdcall, nid:dword
136
	push	ebx ecx edx edi esi
3083 leency 137
 
5048 Asper 138
	mov	eax, HDA_GNODE.sizeof
139
	invoke	Kmalloc
140
	test	eax, eax
141
	jz	.err_out   ; Not enough memory
3083 leency 142
 
5048 Asper 143
	mov	edx, eax
3083 leency 144
;Asper+ [
5048 Asper 145
	mov	edi, edx
146
	xor	eax, eax
147
	mov	ecx, HDA_GNODE.sizeof
148
	rep	stosb
3083 leency 149
;Asper+ ]
150
 
5048 Asper 151
	mov	eax, [nid]
152
	mov	word [edx + HDA_GNODE.nid], ax
153
	stdcall get_wcaps, eax
154
	mov	[edx + HDA_GNODE.wid_caps], eax
155
	mov	ebx, eax
156
	stdcall get_wcaps_type, eax
157
	mov	byte [edx + HDA_GNODE.type], al
3083 leency 158
 
5048 Asper 159
	mov	eax, HDA_MAX_CONNECTIONS*2  ;HDA_MAX_CONNECTIONS * sizeof(word)
160
	push	ebx ecx edx
161
	invoke	Kmalloc    ;malloc temporary conn_list
162
	pop	edx ecx ebx
163
	mov	edi, eax
3083 leency 164
 
5048 Asper 165
	test	ebx, AC_WCAP_CONN_LIST
166
	jz	.no_conn_list
3083 leency 167
 
5048 Asper 168
	stdcall snd_hda_get_connections, [nid], edi, HDA_MAX_CONNECTIONS
169
	mov	ecx, eax
170
	cmp	ecx, 0
171
	jge	@f
3083 leency 172
 
5048 Asper 173
	mov	eax, edx
174
	pusha
175
	invoke	Kfree	   ;free node
176
	popa
177
	mov	eax, ecx
178
	jmp	.out
179
.no_conn_list:
3083 leency 180
 
5048 Asper 181
	xor	ecx, ecx
182
@@:
183
	cmp	ecx, 2	   ;nconns <= ARRAY_SIZE(node->slist) ?
184
	jg	@f
3083 leency 185
 
5048 Asper 186
	lea	eax, [edx + HDA_GNODE.slist]
187
	mov	[edx + HDA_GNODE.conn_list], eax
188
	jmp	.set_conn_list
189
@@:
190
	mov	eax, ecx
191
	shl	ecx, 1
192
	push	ebx ecx edx edi
193
	invoke	Kmalloc    ;malloc conn_list
194
	pop	edi edx ecx ebx
195
	shr	ecx, 1
196
	test	eax, eax
197
	jnz	@f
3083 leency 198
 
5048 Asper 199
	mov	eax, edi
200
	pusha
201
	invoke	Kfree	   ;free temporary conn_list
202
	popa
203
	jmp	.err_out
204
@@:
205
	mov	[edx + HDA_GNODE.conn_list], eax
206
.set_conn_list:
207
	mov	[edx + HDA_GNODE.nconns], cx
208
	push	edi
209
	mov	esi, edi
210
	mov	edi, eax
211
	rep	movsw
212
	pop	edi
3083 leency 213
 
214
 
5048 Asper 215
	mov	al, byte [edx + HDA_GNODE.type]
216
	test	al, AC_WID_PIN
217
	jz	@f
3083 leency 218
;Asper+ [
5048 Asper 219
	cmp	al, AC_WID_VENDOR
220
	je	@f
3083 leency 221
;Asper+ ]
222
 
223
 
5048 Asper 224
	stdcall read_pin_cap, [nid]
225
	mov	[edx + HDA_GNODE.pin_caps], eax
226
	stdcall snd_hda_codec_read, [nid], 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0
227
	mov	byte [edx + HDA_GNODE.pin_ctl], al
228
	stdcall snd_hda_codec_get_pincfg, [nid]
229
	mov	[edx + HDA_GNODE.def_cfg], eax
230
@@:
3083 leency 231
 
5048 Asper 232
	xor	eax, eax
233
	test	ebx, AC_WCAP_OUT_AMP
234
	jz	.no_out_amp
235
	test	ebx, AC_WCAP_AMP_OVRD
236
	jz	@f
237
	snd_hda_param_read [nid], AC_PAR_AMP_OUT_CAP
238
@@:
239
	test	eax, eax
240
	jnz	@f
241
	mov	eax, [spec.def_amp_out_caps]
242
@@:
243
	mov	[edx + HDA_GNODE.amp_out_caps], eax
244
.no_out_amp:
3083 leency 245
 
246
;;Asper+: Beeper [
5048 Asper 247
;        pusha
248
;        mov     bl, byte [edx + HDA_GNODE.type]
249
;        cmp     bl, AC_WID_BEEP
250
;        jne     .not_beeper
3083 leency 251
;
5048 Asper 252
;        mov     ebx, [nid]
253
;        mov     [codec.beeper_nid], bx
3083 leency 254
;
5048 Asper 255
;        test    eax, eax
256
;        jz      .no_beeper_amp
257
;        ;set beep amplifier here
258
;        stdcall unmute_output, edx
259
;.no_beeper_amp:
260
;        ;try to beep here
261
;        stdcall snd_hda_codec_read, [nid], 0, AC_VERB_GET_BEEP_CONTROL, 0 ;eax
262
;if DEBUG
263
;        push    eax esi
264
;        mov     esi, msgBeeperNid
265
;        invoke  SysMsgBoardStr
266
;        push    eax
267
;        mov     eax, [nid]
268
;        stdcall fdword2str, 2
269
;        invoke  SysMsgBoardStr
3083 leency 270
;
5048 Asper 271
;        mov     esi, msgBeeperValue
272
;        invoke  SysMsgBoardStr
273
;        pop     eax
274
;        stdcall fdword2str, 2
275
;        invoke  SysMsgBoardStr
3083 leency 276
;
5048 Asper 277
;        mov     esi, msgBeepNow
278
;        invoke  SysMsgBoardStr
279
;        pop     esi eax
280
;end if
281
;        mov     ecx, 256*1
282
;.next_tone:
283
;        dec     ecx
284
;        movzx   ebx, [esi + HDA_GNODE.nid]
285
;        stdcall snd_hda_codec_write, [nid], 0, AC_VERB_SET_BEEP_CONTROL, ecx
286
;        ;mov     eax, 0x8000
287
;        ;stdcall StallExec
288
;        test    ecx, ecx
289
;        jnz     .next_tone
290
;.end_beep:
291
;        stdcall snd_hda_codec_read, [nid], 0, AC_VERB_GET_BEEP_CONTROL, 0 ;eax
292
;if DEBUG
293
;        ;push    eax esi
294
;        mov     esi, msgBeeperValue
295
;        invoke  SysMsgBoardStr
296
;        stdcall  fdword2str, 2
297
;        invoke   SysMsgBoardStr
298
;        ;pop      esi eax
299
;end if
300
;.not_beeper:
301
;        popa
3083 leency 302
;;Asper+: Beeper ]
303
 
5048 Asper 304
	xor	eax, eax
305
	test	ebx, AC_WCAP_IN_AMP
306
	jz	.no_in_amp
307
	test	ebx, AC_WCAP_AMP_OVRD
308
	jz	@f
309
	snd_hda_param_read [nid], AC_PAR_AMP_IN_CAP
310
@@:
311
	test	eax, eax
312
	jnz	@f
313
	mov	eax, [spec.def_amp_in_caps]
314
@@:
315
	mov	[edx + HDA_GNODE.amp_in_caps], eax
316
.no_in_amp:
3083 leency 317
 
5048 Asper 318
	mov	esi, [spec.nid_list]
319
	test	esi, esi
320
	jnz	@f
321
	mov	[spec.nid_list], edx
322
	jmp	.out
323
@@:
3083 leency 324
 
5048 Asper 325
	;Asper+: Sort pins by DA:Sequence during tree building [
326
	mov	ecx, esi
327
	movzx	ebx, byte [edx + HDA_GNODE.def_cfg]
328
	push	edi
329
.next_node:
330
	cmp	[esi + HDA_GNODE.type], AC_WID_PIN
331
	jne	@f
332
	cmp	[edx + HDA_GNODE.type], AC_WID_PIN
333
	je	.pin
3083 leency 334
 
5048 Asper 335
	mov	edi, [spec.nid_list]
336
	cmp	[edi + HDA_GNODE.type], AC_WID_PIN
337
	jne	.not_pin
338
	mov	[edx + HDA_GNODE.next], edi
339
.head:						   ;CleverMouse+
340
	mov	[spec.nid_list], edx
341
	pop	edi
342
	jmp	.out
343
.pin:
344
	movzx	edi, byte [esi + HDA_GNODE.def_cfg]
345
	cmp	edi, ebx
346
	jle	@f
347
.not_pin:
348
	mov	[edx + HDA_GNODE.next], esi
349
	cmp	esi, [spec.nid_list]			;CleverMouse+
350
	jz	.head					;CleverMouse+
351
	mov	esi, ecx
352
	jmp	.insert
353
@@:
354
	mov	eax, [esi + HDA_GNODE.next]
355
	test	eax, eax
356
	jz	.insert
357
	mov	ecx, esi
358
	mov	esi, eax
359
	jmp	.next_node
360
.insert:
361
	mov	[esi + HDA_GNODE.next], edx
362
	pop	edi
363
	;Asper+ ]
3083 leency 364
 
5048 Asper 365
.out:
366
	mov	eax, edi
367
	pusha
368
	invoke	Kfree	  ;free temporary conn_list
369
	popa
370
	xor	eax, eax
371
	pop	esi edi edx ecx ebx
372
	ret
3083 leency 373
 
5048 Asper 374
.err_out:
375
	mov	eax, edx
376
	pusha
377
	invoke	Kfree	  ;free node
378
	popa
379
	xor	eax, eax
380
	dec	eax
381
	pop	esi edi edx ecx ebx
382
	ret
3083 leency 383
endp
384
 
385
 
386
 
387
; build the AFG subtree
5048 Asper 388
proc build_afg_tree
389
	push	ebx ecx edx
3083 leency 390
 
5048 Asper 391
	mov	ebx, [codec.afg]
392
	snd_hda_param_read  ebx, AC_PAR_AMP_OUT_CAP
3083 leency 393
 
5048 Asper 394
	mov	[spec.def_amp_out_caps], eax
395
	snd_hda_param_read  ebx, AC_PAR_AMP_IN_CAP
396
	mov	[spec.def_amp_in_caps], eax
3083 leency 397
 
5048 Asper 398
	stdcall snd_hda_get_sub_nodes, ebx
399
	mov	ecx, eax
400
	and	ecx, 0xFFFF    ;ecx = nodes number
401
	mov	edx, eax
402
	shr	edx, 16        ;eax = address of the first nid
3083 leency 403
 
5048 Asper 404
	test	edx, edx
405
	jz	@f
406
	cmp	ecx, 0
407
	jge	.nid_ok
408
@@:
409
if  FDEBUG
410
	push	esi
411
	mov	esi, emsgInvalidAFGSubtree
412
	invoke	SysMsgBoardStr
413
	pop	esi
414
end if
415
	xor	eax, eax
416
	dec	eax
417
	jmp	.out
418
.nid_ok:
3083 leency 419
 
5048 Asper 420
	; parse all nodes belonging to the AFG
421
.next_node:
422
	test	ecx, ecx
423
	jz	.build_done
3083 leency 424
 
5048 Asper 425
	stdcall add_new_node, edx
426
	test	eax, eax
427
	jnz	.out
428
	inc	edx
429
	dec	ecx
430
	jmp	.next_node
431
.build_done:
432
	xor	eax, eax
433
.out:
434
	pop	edx ecx ebx
435
	ret
3083 leency 436
endp
437
 
5048 Asper 438
;Asper+[
439
proc print_afg_tree_nodes
440
	push	eax esi edi
441
	mov	esi, msgNodeSeq
442
	invoke	SysMsgBoardStr
3083 leency 443
 
5048 Asper 444
	mov	edi, [spec.nid_list]
445
	test	edi, edi
446
	jz	.out
447
.next_node:
448
	movzx	eax, word [edi + HDA_GNODE.nid]
449
	mov	esi, msgNID
450
	invoke	SysMsgBoardStr
451
	stdcall fdword2str, 3
452
	invoke	SysMsgBoardStr
453
 
454
	mov	eax, [edi + HDA_GNODE.next]
455
	test	eax, eax
456
	jz	.out
457
 
458
	mov	edi, eax
459
	jmp	.next_node
460
.out:
461
	pop	edi esi eax
462
	ret
463
endp
464
;Asper+]
465
 
3083 leency 466
; look for the node record for the given NID
5048 Asper 467
proc hda_get_node stdcall, nid:dword
468
	push	ebx edx esi
469
	movzx	ebx, word [nid]
470
	mov	esi, [spec.nid_list]
471
	test	esi, esi
472
	jz	.out
3083 leency 473
 
5048 Asper 474
.next_node:
475
	mov	edx, [esi + HDA_GNODE.next]
476
	test	edx, edx   ;Asper+
477
	jz	.not_found ;Asper+
478
	mov	ax, word [esi + HDA_GNODE.nid]
479
	cmp	ax, bx
480
	je	.out
481
	mov	esi, edx
482
	jmp	.next_node
3083 leency 483
 
5048 Asper 484
.not_found: ;Asper+
485
	xor	esi, esi
486
.out:
487
	mov	eax, esi
488
	pop	esi edx ebx
489
	ret
3083 leency 490
endp
491
 
492
;Asper+[
5048 Asper 493
proc set_eapd stdcall, node:dword ;nid:dword, on:dword
494
	push	eax ebx esi
495
	mov	esi, [node]
496
	cmp	[esi + HDA_GNODE.type], AC_WID_PIN
497
	jne	.out
498
	; eapd capable?
499
	test	[esi + HDA_GNODE.pin_caps], AC_PINCAP_EAPD
500
	jz	.out
501
	;stdcall snd_hda_codec_read, ebx, 0, AC_VERB_GET_EAPD_BTLENABLE, AC_EAPDBTL_EAPD
502
	;or      eax, AC_EAPDBTL_EAPD
503
	movzx	ebx, [esi + HDA_GNODE.nid]
504
	stdcall snd_hda_codec_write, ebx, 0, AC_VERB_SET_EAPD_BTLENABLE, AC_EAPDBTL_EAPD ;eax
505
if  DEBUG
506
	push	eax esi
507
	mov	esi, msgEnableEAPD
508
	invoke	SysMsgBoardStr
509
	mov	eax, ebx
510
	stdcall fdword2str, 3
511
	invoke	SysMsgBoardStr
512
	pop	esi eax
513
      end if
514
.out:
515
	pop	esi ebx eax
516
	ret
3083 leency 517
endp
518
;Asper+]
519
 
520
; unmute (and set max vol) the output amplifier
5048 Asper 521
proc unmute_output stdcall, node:dword
522
	push	ebx ecx edx esi
523
	mov	esi, [node]
524
	test	[esi + HDA_GNODE.wid_caps], AC_WCAP_OUT_AMP
525
	jz	.out
526
	movzx	eax, word [esi + HDA_GNODE.nid]
527
if  DEBUG
528
	push	esi
529
	mov	esi, msgUnmuteOut
530
	invoke	SysMsgBoardStr
531
	stdcall fdword2str, 3
532
	invoke	SysMsgBoardStr
533
	pop	esi
534
end if
3083 leency 535
 
5048 Asper 536
	stdcall set_eapd, esi ;Asper+: set EAPD if exist
3083 leency 537
 
5048 Asper 538
	mov	ebx, eax
539
	mov	eax, [esi + HDA_GNODE.amp_out_caps]
540
	mov	ecx, eax
3083 leency 541
 
5048 Asper 542
	and	eax, AC_AMPCAP_NUM_STEPS
543
	shr	eax, AC_AMPCAP_NUM_STEPS_SHIFT
3083 leency 544
 
5048 Asper 545
	stdcall snd_hda_codec_amp_stereo, ebx, HDA_OUTPUT, 0, 0xFF, eax
3083 leency 546
 
5048 Asper 547
	and	ecx, AC_AMPCAP_STEP_SIZE
548
	shr	ecx, AC_AMPCAP_STEP_SIZE_SHIFT
3083 leency 549
 
5048 Asper 550
	test	al, al
551
	jz	.out
552
if  DEBUG
553
	push	eax esi
554
	mov	esi, msgAmpVal
555
	invoke	SysMsgBoardStr
556
	stdcall fdword2str, 1
557
	invoke	SysMsgBoardStr
3083 leency 558
 
5048 Asper 559
	mov	esi, strSemicolon
560
	invoke	SysMsgBoardStr
561
	mov	eax, ecx
562
	stdcall fdword2str, 3
563
	invoke	SysMsgBoardStr
564
	pop	esi eax
565
end if
566
	mov	[volume.out_amp_node], esi
567
	mov	[volume.num_steps], al
568
	mov	[volume.step_size], cl
569
	mul	cl
570
	imul	eax, (100/4)
571
	mov	[volume.maxDb], eax
572
.out:
573
	xor	eax, eax
574
	pop	esi edx ecx ebx
575
	ret
3083 leency 576
endp
577
 
578
; unmute (and set max vol) the input amplifier
5048 Asper 579
proc unmute_input stdcall, node:dword, index:dword
580
	push	ecx edx esi
581
	test	[esi + HDA_GNODE.wid_caps], AC_WCAP_IN_AMP
582
	jz	.out
583
	and	[index], 0xF ;Asper+ : Ranger
584
	mov	esi, [node]
585
	movzx	eax, word [esi + HDA_GNODE.nid]
586
if  DEBUG
587
	push	eax esi
588
	mov	esi, msgUnmuteIn
589
	invoke	SysMsgBoardStr
590
	stdcall fdword2str, 3
591
	invoke	SysMsgBoardStr
592
	mov	esi, msgIdx
593
	invoke	SysMsgBoardStr
594
	mov	eax, [index]
595
	stdcall fdword2str, 3
596
	invoke	SysMsgBoardStr
597
	pop	esi eax
598
end if
3083 leency 599
 
5048 Asper 600
	mov	edx, [esi + HDA_GNODE.amp_in_caps]
601
	mov	ecx, edx
3083 leency 602
 
5048 Asper 603
	and	edx, AC_AMPCAP_NUM_STEPS
604
	shr	edx, AC_AMPCAP_NUM_STEPS_SHIFT
3083 leency 605
 
5048 Asper 606
	stdcall snd_hda_codec_amp_stereo, eax, HDA_INPUT, [index], 0xFF, edx
607
.out:
608
	xor	eax, eax
609
	pop	esi edx ecx
610
	ret
3083 leency 611
endp
612
 
613
 
614
; select the input connection of the given node.
5048 Asper 615
proc select_input_connection stdcall, node:dword, index:dword
3083 leency 616
	push	ebx esi
617
	mov	esi, [node]
618
	movzx	eax, word [esi + HDA_GNODE.nid]
619
	mov	ebx, [index]
5048 Asper 620
if DEBUG
3083 leency 621
	mov	esi, msgConnect
5048 Asper 622
	invoke	SysMsgBoardStr
3083 leency 623
	stdcall fdword2str, 3
5048 Asper 624
	invoke	SysMsgBoardStr
3083 leency 625
 
626
	mov	esi, msgIdx
5048 Asper 627
	invoke	SysMsgBoardStr
3083 leency 628
	push	eax
629
	mov	eax, ebx
630
	stdcall fdword2str, 3
5048 Asper 631
	invoke	SysMsgBoardStr
3083 leency 632
	pop	eax
5048 Asper 633
end if
3083 leency 634
	stdcall snd_hda_codec_write, eax, 0, AC_VERB_SET_CONNECT_SEL, ebx
635
	pop	esi ebx
636
	ret
637
endp
638
 
639
 
640
; clear checked flag of each node in the node list
5048 Asper 641
proc clear_check_flags
642
	push	eax esi
643
	mov	esi, [spec.nid_list]
644
	test	esi, esi
645
	jz	.out
646
.next_node:
647
	mov	byte [esi + HDA_GNODE.checked], 0
648
	mov	eax, [esi + HDA_GNODE.next]
649
	test	eax, eax
650
	jz	.out
651
	mov	esi, eax
652
	jmp	.next_node
653
.out:
654
	pop	esi eax
655
	ret
3083 leency 656
endp
657
 
658
;
659
; parse the output path recursively until reach to an audio output widget
660
;
661
; returns 0 if not found, 1 if found, or a negative error code.
662
;
5048 Asper 663
proc parse_output_path stdcall, node:dword, dac_idx:dword
3083 leency 664
	push	ebx ecx edx esi
665
	mov	esi, [node]
666
	mov	al, byte [esi + HDA_GNODE.checked]
667
	test	al, al
668
	jnz	.ret_zero
669
 
670
	mov	byte [esi + HDA_GNODE.checked], 1
671
 
672
	mov	al, byte [esi + HDA_GNODE.type]
673
	cmp	al, AC_WID_AUD_OUT
674
	jne	.not_wid_aud_out
675
 
676
	movzx	eax, word [esi + HDA_GNODE.nid]
677
	mov	ebx, [esi + HDA_GNODE.wid_caps]
678
	test	ebx, AC_WCAP_DIGITAL
679
	jz	@f
5048 Asper 680
if DEBUG
3083 leency 681
	push	esi
682
	mov	esi, msgSkipDigitalOutNode
5048 Asper 683
	invoke	SysMsgBoardStr
3083 leency 684
	stdcall fdword2str, 3
5048 Asper 685
	invoke	SysMsgBoardStr
3083 leency 686
	pop	esi
5048 Asper 687
end if
3083 leency 688
	jmp	.ret_zero
5048 Asper 689
@@:
690
if DEBUG
3083 leency 691
	push	eax esi
692
	mov	esi, msgAudOutFound
5048 Asper 693
	invoke	SysMsgBoardStr
3083 leency 694
	stdcall fdword2str, 3
5048 Asper 695
	invoke	SysMsgBoardStr
3083 leency 696
	pop	esi eax
5048 Asper 697
end if
3083 leency 698
 
699
	push	eax
700
	stdcall unmute_output, esi ;Asper+
701
	pop	eax
702
	mov	ecx, [dac_idx]
703
	shl	ecx, 2
704
	push	eax
705
	mov	eax, [spec.dac_node+ecx]
706
	test	eax, eax
707
	pop	eax
708
	jz	@f
709
	; already DAC node is assigned, just unmute & connect
710
	cmp	eax, [node]
711
	je	.ret_one
712
	jmp	.ret_zero
5048 Asper 713
@@:
3083 leency 714
	mov	ecx, [dac_idx]
715
	shl	ecx, 2
716
	mov	[spec.dac_node+ecx], eax
717
	jmp	.ret_one   ;found
5048 Asper 718
.not_wid_aud_out:
3083 leency 719
	movzx	ebx, [esi + HDA_GNODE.nconns]
720
	xor	ecx, ecx
721
	mov	edx, [esi + HDA_GNODE.conn_list]
722
	test	ebx, ebx
723
	jz	.ret_zero
5048 Asper 724
.next_node:
3083 leency 725
	stdcall hda_get_node, [edx]
726
	test	eax, eax
727
	jz	.continue
728
 
729
	stdcall parse_output_path, eax, [dac_idx]
730
 
731
	cmp	[esi + HDA_GNODE.nconns], 1
732
	jle	@f
733
	stdcall select_input_connection, esi, ecx
5048 Asper 734
@@:
3083 leency 735
;UNSUPPORTED YET!        stdcall unmute_input, esi, ecx
736
	stdcall unmute_output, esi
737
	jmp	.ret_one
738
 
5048 Asper 739
.continue:
3083 leency 740
	add	edx, 2
741
	inc	ecx
742
	cmp	ecx, ebx
743
	jl	.next_node
5048 Asper 744
.ret_zero:
3083 leency 745
	xor	eax, eax
746
	pop	esi edx ecx ebx
747
	ret
5048 Asper 748
.ret_one:
3083 leency 749
	xor	eax, eax
750
	inc	eax
5048 Asper 751
.ret: ;Asper+
3083 leency 752
	pop	esi edx ecx ebx
753
	ret
754
endp
755
 
756
; Look for the output PIN widget with the given jack type
757
; and parse the output path to that PIN.
758
;
759
; Returns the PIN node when the path to DAC is established.
5048 Asper 760
proc parse_output_jack stdcall, jack_type:dword
3083 leency 761
	push	edx esi
762
 
763
	mov	esi, [spec.nid_list]
764
	test	esi, esi
765
	jz	.ret_zero
5048 Asper 766
.next_pin:
3083 leency 767
	cmp	[esi + HDA_GNODE.type], AC_WID_PIN
768
	jne	.continue
769
 
770
	; output capable?
771
	mov	eax, [esi + HDA_GNODE.pin_caps]
772
	test	eax, AC_PINCAP_OUT
773
	jz	.continue
774
 
775
	stdcall defcfg_port_conn, esi
776
	cmp	eax, AC_JACK_PORT_NONE
777
	je	.continue  ;unconnected
778
 
779
	mov	edx, [jack_type]
780
	cmp	edx, 0
781
	jl	@f
782
 
783
	stdcall defcfg_type, esi
784
	cmp	edx, eax
785
	jne	.continue
786
 
787
	test	[esi + HDA_GNODE.wid_caps], AC_WCAP_DIGITAL
788
	jnz	.continue ; skip SPDIF
5048 Asper 789
@@:
790
	push	eax
791
	movzx	eax, [esi + HDA_GNODE.nid]
792
	stdcall snd_hda_enable_pin_sense, eax, eax	;Asper+: enable unsolicited events for the output pin
793
	pop	eax
794
 
3083 leency 795
if DEBUG
5048 Asper 796
	pusha
797
;        push    esi
798
;        mov     esi, msgPin_Nid
799
;        invoke  SysMsgBoardStr
800
;        pop     esi
801
	movzx	eax, [esi + HDA_GNODE.nid]
802
	movzx	ebx, [esi + HDA_GNODE.pin_ctl]
803
	mov	ecx, [esi + HDA_GNODE.pin_caps]
804
	mov	edx, [esi + HDA_GNODE.def_cfg]
805
	mov	edi, [esi + HDA_GNODE.amp_out_caps]
806
	mov	esi, msgPin_Nid
807
	invoke	SysMsgBoardStr
808
	stdcall fdword2str, 3
809
	invoke	SysMsgBoardStr
3083 leency 810
 
5048 Asper 811
	mov	esi, msgPin_Ctl
812
	invoke	SysMsgBoardStr
813
	mov	eax, ebx
814
	stdcall fdword2str, 2
815
	invoke	SysMsgBoardStr
3083 leency 816
 
5048 Asper 817
	mov	esi, msgPin_Caps
818
	invoke	SysMsgBoardStr
819
	mov	eax, ecx
820
	stdcall fdword2str, 2
821
	invoke	SysMsgBoardStr
3083 leency 822
 
5048 Asper 823
	mov	esi, msgDef_Cfg
824
	invoke	SysMsgBoardStr
825
	mov    eax, edx
826
	stdcall fdword2str, 2
827
	invoke	SysMsgBoardStr
3083 leency 828
 
5048 Asper 829
	mov    esi, msgAmp_Out_Caps
830
	invoke	SysMsgBoardStr
831
	mov    eax, edi
832
	stdcall fdword2str, 2
833
	invoke	SysMsgBoardStr
834
	popa
835
end if
836
	; output as default?
837
;        test    [esi + HDA_GNODE.pin_ctl], AC_PINCTL_OUT_EN
838
;        jz      .continue
839
.use_dac0:
840
	cmp	[spec.dac_node], 0
841
	jne	.use_dac1
3083 leency 842
 
843
	stdcall clear_check_flags
844
	stdcall parse_output_path, esi, 0
845
 
846
	test	eax, eax
847
	jnz	@f
848
	mov	edx, [spec.out_pin_node]
849
	test	edx, edx
850
	jz	@f
5048 Asper 851
.use_dac1:
3083 leency 852
	stdcall clear_check_flags
853
	stdcall parse_output_path, esi, 1
5048 Asper 854
@@:
3083 leency 855
	cmp	eax, 0
856
	jle	.l1
857
 
858
	; unmute the PIN output
859
	stdcall unmute_output, esi
860
	; set PIN-Out enable
861
	xor	edx, edx
862
	test	[esi + HDA_GNODE.pin_caps], AC_PINCAP_HP_DRV
863
	jz	@f
864
	mov	edx, AC_PINCTL_HP_EN
5048 Asper 865
@@:
3083 leency 866
	or	edx, AC_PINCTL_OUT_EN
867
	movzx	eax, [esi + HDA_GNODE.nid]
868
	stdcall snd_hda_codec_write, eax, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, edx
869
	mov	eax, esi
870
	jmp	.out
5048 Asper 871
.l1:
872
.continue:
873
	mov	edx, [esi + HDA_GNODE.next]
874
	test	edx, edx
875
	jz	.ret_zero
876
	mov	esi, edx
877
	jmp	.next_pin
878
.ret_zero:
3083 leency 879
	xor	eax, eax
5048 Asper 880
.out:
3083 leency 881
	pop	esi edx
882
	ret
883
endp
884
 
885
 
886
; parse outputs
887
proc parse_output
888
	push	edx
889
	; Look for the output PIN widget
890
	;
891
	; first, look for the line-out pin
892
	stdcall parse_output_jack, AC_JACK_LINE_OUT
893
	test	eax, eax
894
	jz	@f
895
	mov	[spec.out_pin_node], eax   ; found, remember the PIN node
896
	jmp	.l1
5048 Asper 897
@@:
3083 leency 898
	; if no line-out is found, try speaker out
899
	stdcall parse_output_jack, AC_JACK_SPEAKER
900
	test	eax, eax
901
	jz	.l1
902
	mov	[spec.out_pin_node], eax   ; found, remember the PIN node
5048 Asper 903
.l1:
3083 leency 904
	; look for the HP-out pin
905
	stdcall parse_output_jack, AC_JACK_HP_OUT
906
	test	eax, eax
907
	jz	.l2
908
 
909
	mov	edx, [spec.out_pin_node]
910
	test	edx, edx
911
	jnz	@f
912
	mov	[spec.out_pin_node], eax
913
	jmp	.l2
5048 Asper 914
@@:
3083 leency 915
	mov	[spec.out_pin_node+4], eax
5048 Asper 916
.l2:
3083 leency 917
	mov	edx, [spec.out_pin_node]
918
	test	edx, edx
919
	jnz	@f
920
	; no line-out or HP pins found,
921
	; then choose for the first output pin
922
	stdcall parse_output_jack, -1
923
 
924
	mov	[spec.out_pin_node], eax
925
	test	eax, eax
926
	jnz	@f
5048 Asper 927
if DEBUG
3083 leency 928
	push	esi
929
	mov	esi, emsgNoProperOutputPathFound
5048 Asper 930
	invoke	SysMsgBoardStr
3083 leency 931
	pop	esi
5048 Asper 932
end if
933
@@:
3083 leency 934
	pop	edx
935
	xor	eax, eax
936
	ret
937
endp
938
 
939
 
940
;(...)  Skip functions for the input (capture is not supported).
941
 
942
; the generic parser
943
proc snd_hda_parse_generic_codec
944
	mov	eax, [codec.afg]
945
	test	eax, eax
946
	jz	.out
947
 
948
	stdcall build_afg_tree
949
	cmp	eax, 0
950
	jl	.error
951
 
5048 Asper 952
if  FDEBUG
953
	stdcall print_afg_tree_nodes ;Asper+
954
end if
955
 
3083 leency 956
	stdcall parse_output
957
	xor	eax, eax
5048 Asper 958
.out:
3083 leency 959
	ret
5048 Asper 960
.error:
3083 leency 961
	stdcall snd_hda_generic_free
962
	ret
963
endp
964
 
965
 
966
; some data
967
spec HDA_GSPEC
968
volume VOLUME_CTL