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