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=> |