Subversion Repositories Kolibri OS

Rev

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