Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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.  
  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
  937.