Subversion Repositories Kolibri OS

Rev

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

  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. 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
  63. endp
  64.  
  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
  73. endp
  74.  
  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
  83. endp
  84.  
  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
  93. endp
  94.  
  95. ; destructor
  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
  103.  
  104. .next:
  105.         test    edx, edx
  106.         jz      .free_head
  107.  
  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
  131. endp
  132.  
  133.  
  134. ; add a new widget node and read its attributes
  135. proc add_new_node stdcall, nid:dword
  136.         push    ebx ecx edx edi esi
  137.  
  138.         mov     eax, HDA_GNODE.sizeof
  139.         invoke  Kmalloc
  140.         test    eax, eax
  141.         jz      .err_out   ; Not enough memory
  142.  
  143.         mov     edx, eax
  144. ;Asper+ [
  145.         mov     edi, edx
  146.         xor     eax, eax
  147.         mov     ecx, HDA_GNODE.sizeof
  148.         rep     stosb
  149. ;Asper+ ]
  150.  
  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
  158.  
  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
  164.  
  165.         test    ebx, AC_WCAP_CONN_LIST
  166.         jz      .no_conn_list
  167.  
  168.         stdcall snd_hda_get_connections, [nid], edi, HDA_MAX_CONNECTIONS
  169.         mov     ecx, eax
  170.         cmp     ecx, 0
  171.         jge     @f
  172.  
  173.         mov     eax, edx
  174.         pusha
  175.         invoke  Kfree      ;free node
  176.         popa
  177.         mov     eax, ecx
  178.         jmp     .out
  179. .no_conn_list:
  180.  
  181.         xor     ecx, ecx
  182. @@:
  183.         cmp     ecx, 2     ;nconns <= ARRAY_SIZE(node->slist) ?
  184.         jg      @f
  185.  
  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
  198.  
  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
  213.  
  214.  
  215.         mov     al, byte [edx + HDA_GNODE.type]
  216.         test    al, AC_WID_PIN
  217.         jz      @f
  218. ;Asper+ [
  219.         cmp     al, AC_WID_VENDOR
  220.         je      @f
  221. ;Asper+ ]
  222.  
  223.  
  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. @@:
  231.  
  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:
  245.  
  246. ;;Asper+: Beeper [
  247. ;        pusha
  248. ;        mov     bl, byte [edx + HDA_GNODE.type]
  249. ;        cmp     bl, AC_WID_BEEP
  250. ;        jne     .not_beeper
  251. ;
  252. ;        mov     ebx, [nid]
  253. ;        mov     [codec.beeper_nid], bx
  254. ;
  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
  270. ;
  271. ;        mov     esi, msgBeeperValue
  272. ;        invoke  SysMsgBoardStr
  273. ;        pop     eax
  274. ;        stdcall fdword2str, 2
  275. ;        invoke  SysMsgBoardStr
  276. ;
  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
  302. ;;Asper+: Beeper ]
  303.  
  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:
  317.  
  318.         mov     esi, [spec.nid_list]
  319.         test    esi, esi
  320.         jnz     @f
  321.         mov     [spec.nid_list], edx
  322.         jmp     .out
  323. @@:
  324.  
  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
  334.  
  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+ ]
  364.  
  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
  373.  
  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
  383. endp
  384.  
  385.  
  386.  
  387. ; build the AFG subtree
  388. proc build_afg_tree
  389.         push    ebx ecx edx
  390.  
  391.         mov     ebx, [codec.afg]
  392.         snd_hda_param_read  ebx, AC_PAR_AMP_OUT_CAP
  393.  
  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
  397.  
  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
  403.  
  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:
  419.  
  420.         ; parse all nodes belonging to the AFG
  421. .next_node:
  422.         test    ecx, ecx
  423.         jz      .build_done
  424.  
  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
  436. endp
  437.  
  438. ;Asper+[
  439. proc print_afg_tree_nodes
  440.         push    eax esi edi
  441.         mov     esi, msgNodeSeq
  442.         invoke  SysMsgBoardStr
  443.  
  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.  
  466. ; look for the node record for the given NID
  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
  473.  
  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
  483.  
  484. .not_found: ;Asper+
  485.         xor     esi, esi
  486. .out:
  487.         mov     eax, esi
  488.         pop     esi edx ebx
  489.         ret
  490. endp
  491.  
  492. ;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
  517. endp
  518. ;Asper+]
  519.  
  520. ; unmute (and set max vol) the output amplifier
  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
  535.  
  536.         stdcall set_eapd, esi ;Asper+: set EAPD if exist
  537.  
  538.         mov     ebx, eax
  539.         mov     eax, [esi + HDA_GNODE.amp_out_caps]
  540.         mov     ecx, eax
  541.  
  542.         and     eax, AC_AMPCAP_NUM_STEPS
  543.         shr     eax, AC_AMPCAP_NUM_STEPS_SHIFT
  544.  
  545.         stdcall snd_hda_codec_amp_stereo, ebx, HDA_OUTPUT, 0, 0xFF, eax
  546.  
  547.         and     ecx, AC_AMPCAP_STEP_SIZE
  548.         shr     ecx, AC_AMPCAP_STEP_SIZE_SHIFT
  549.  
  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
  558.  
  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
  576. endp
  577.  
  578. ; unmute (and set max vol) the input amplifier
  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
  599.  
  600.         mov     edx, [esi + HDA_GNODE.amp_in_caps]
  601.         mov     ecx, edx
  602.  
  603.         and     edx, AC_AMPCAP_NUM_STEPS
  604.         shr     edx, AC_AMPCAP_NUM_STEPS_SHIFT
  605.  
  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
  611. endp
  612.  
  613.  
  614. ; select the input connection of the given node.
  615. proc select_input_connection stdcall, node:dword, index:dword
  616.         push    ebx esi
  617.         mov     esi, [node]
  618.         movzx   eax, word [esi + HDA_GNODE.nid]
  619.         mov     ebx, [index]
  620. if DEBUG
  621.         mov     esi, msgConnect
  622.         invoke  SysMsgBoardStr
  623.         stdcall fdword2str, 3
  624.         invoke  SysMsgBoardStr
  625.  
  626.         mov     esi, msgIdx
  627.         invoke  SysMsgBoardStr
  628.         push    eax
  629.         mov     eax, ebx
  630.         stdcall fdword2str, 3
  631.         invoke  SysMsgBoardStr
  632.         pop     eax
  633. end if
  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
  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
  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. ;
  663. proc parse_output_path stdcall, node:dword, dac_idx:dword
  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
  680. if DEBUG
  681.         push    esi
  682.         mov     esi, msgSkipDigitalOutNode
  683.         invoke  SysMsgBoardStr
  684.         stdcall fdword2str, 3
  685.         invoke  SysMsgBoardStr
  686.         pop     esi
  687. end if
  688.         jmp     .ret_zero
  689. @@:
  690. if DEBUG
  691.         push    eax esi
  692.         mov     esi, msgAudOutFound
  693.         invoke  SysMsgBoardStr
  694.         stdcall fdword2str, 3
  695.         invoke  SysMsgBoardStr
  696.         pop     esi eax
  697. end if
  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
  713. @@:
  714.         mov     ecx, [dac_idx]
  715.         shl     ecx, 2
  716.         mov     [spec.dac_node+ecx], eax
  717.         jmp     .ret_one   ;found
  718. .not_wid_aud_out:
  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
  724. .next_node:
  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
  734. @@:
  735. ;UNSUPPORTED YET!        stdcall unmute_input, esi, ecx
  736.         stdcall unmute_output, esi
  737.         jmp     .ret_one
  738.  
  739. .continue:
  740.         add     edx, 2
  741.         inc     ecx
  742.         cmp     ecx, ebx
  743.         jl      .next_node
  744. .ret_zero:
  745.         xor     eax, eax
  746.         pop     esi edx ecx ebx
  747.         ret
  748. .ret_one:
  749.         xor     eax, eax
  750.         inc     eax
  751. .ret: ;Asper+
  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.
  760. proc parse_output_jack stdcall, jack_type:dword
  761.         push    edx esi
  762.  
  763.         mov     esi, [spec.nid_list]
  764.         test    esi, esi
  765.         jz      .ret_zero
  766. .next_pin:
  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
  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.  
  795. if DEBUG
  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
  810.  
  811.         mov     esi, msgPin_Ctl
  812.         invoke  SysMsgBoardStr
  813.         mov     eax, ebx
  814.         stdcall fdword2str, 2
  815.         invoke  SysMsgBoardStr
  816.  
  817.         mov     esi, msgPin_Caps
  818.         invoke  SysMsgBoardStr
  819.         mov     eax, ecx
  820.         stdcall fdword2str, 2
  821.         invoke  SysMsgBoardStr
  822.  
  823.         mov     esi, msgDef_Cfg
  824.         invoke  SysMsgBoardStr
  825.         mov    eax, edx
  826.         stdcall fdword2str, 2
  827.         invoke  SysMsgBoardStr
  828.  
  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
  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
  851. .use_dac1:
  852.         stdcall clear_check_flags
  853.         stdcall parse_output_path, esi, 1
  854. @@:
  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
  865. @@:
  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
  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:
  879.         xor     eax, eax
  880. .out:
  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
  897. @@:
  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
  903. .l1:
  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
  914. @@:
  915.         mov     [spec.out_pin_node+4], eax
  916. .l2:
  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
  927. if DEBUG
  928.         push    esi
  929.         mov     esi, emsgNoProperOutputPathFound
  930.         invoke  SysMsgBoardStr
  931.         pop     esi
  932. end if
  933. @@:
  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.  
  952. if  FDEBUG
  953.         stdcall print_afg_tree_nodes ;Asper+
  954. end if
  955.  
  956.         stdcall parse_output
  957.         xor     eax, eax
  958. .out:
  959.         ret
  960. .error:
  961.         stdcall snd_hda_generic_free
  962.         ret
  963. endp
  964.  
  965.  
  966. ; some data
  967. spec HDA_GSPEC
  968. volume VOLUME_CTL
  969.