;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; ;; Distributed under terms of the GNU General Public License ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; format PE DLL native 0.05 section '.flat' code readable writable executable DEBUG equ 1 FDEBUG equ 0 DEBUG_IRQ equ 0 USE_SINGLE_MODE equ 0 ; 1 = Single mode; 0 = Normal mode. USE_UNSOL_EV equ 1 ; 1 = Use unsolicited events; 0 = Do not use unsolicited events. TEST_VERSION_NUMBER equ '019a' ;Asper+ [ SDO_TAG equ 1 ;Output stream tag id (any number except 0) SDO_IDX equ 4 ;Output stream index ;According to "Intel� I/O Controller Hub 6 (ICH6) High Definition Audio / AC �97 Programmer�s Reference Manual (PRM) May 2005 Document" ;and "Intel� I/O Controller Hub 6 (ICH6) Family Datasheet" SDO0=4, ;but according to "High Definition Audio Specification Revision 1.0a June 17, 2010" SDO0 depends on the number of SDIs. SDO_INT equ 1 shl SDO_IDX ;Output stream interrupt (must be power of 2) SDO_OFS equ 0x80+(SDO_IDX*0x20) ;Output stream offset ;Asper+ ] CURRENT_API equ 0x0100 ;1.00 COMPATIBLE_API equ 0x0101 ;1.01 API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API IRQ_REMAP equ 0 IRQ_LINE equ 0 CPU_FREQ equ 2600d ; Vendors VID_INTEL equ 0x8086 VID_NVIDIA equ 0x10DE VID_ATI equ 0x1002 VID_AMD equ 0x1022 VID_VIA equ 0x1106 VID_SIS equ 0x1039 VID_ULI equ 0x10B9 VID_CREATIVE equ 0x1102 VID_TERA equ 0x6549 VID_RDC equ 0x17F3 VID_VMWARE equ 0x15AD ; Devices ; Intel CTRL_INTEL_SCH2 equ 0x080a CTRL_INTEL_HPT equ 0x0c0c CTRL_INTEL_0F04 equ 0x0F04 CTRL_INTEL_CPT equ 0x1c20 CTRL_INTEL_PGB equ 0x1d20 CTRL_INTEL_PPT1 equ 0x1e20 CTRL_INTEL_2284 equ 0x2284 CTRL_INTEL_ICH6 equ 0x2668 CTRL_INTEL_63XXESB equ 0x269a CTRL_INTEL_ICH7 equ 0x27d8 CTRL_INTEL_ICH8 equ 0x284b CTRL_INTEL_82801_UNK1 equ 0x2911 CTRL_INTEL_ICH9 equ 0x293e CTRL_INTEL_ICH9_2 equ 0x293f CTRL_INTEL_ICH10 equ 0x3a3e CTRL_INTEL_ICH10_2 equ 0x3a6e CTRL_INTEL_PCH equ 0x3b56 CTRL_INTEL_PCH2 equ 0x3b57 CTRL_INTEL_SCH equ 0x811b CTRL_INTEL_LPT equ 0x8c20 CTRL_INTEL_8ca0 equ 0x8cA0 CTRL_INTEL_8d20 equ 0x8d20 CTRL_INTEL_8d21 equ 0x8d21 CTRL_INTEL_A1F0 equ 0xA1F0 CTRL_INTEL_A270 equ 0xA270 CTRL_INTEL_9C20 equ 0x9c20 CTRL_INTEL_9C21 equ 0x9c21 CTRL_INTEL_9CA0 equ 0x9cA0 CTRL_INTEL_A170 equ 0xA170 CTRL_INTEL_9D70 equ 0x9D70 CTRL_INTEL_5A98 equ 0x5A98 ; Nvidia CTRL_NVIDIA_MCP51 equ 0x026c CTRL_NVIDIA_MCP55 equ 0x0371 CTRL_NVIDIA_MCP61_1 equ 0x03e4 CTRL_NVIDIA_MCP61_2 equ 0x03f0 CTRL_NVIDIA_MCP65_1 equ 0x044a CTRL_NVIDIA_MCP65_2 equ 0x044b CTRL_NVIDIA_MCP67_1 equ 0x055c CTRL_NVIDIA_MCP67_2 equ 0x055d CTRL_NVIDIA_MCP78_1 equ 0x0774 CTRL_NVIDIA_MCP78_2 equ 0x0775 CTRL_NVIDIA_MCP78_3 equ 0x0776 CTRL_NVIDIA_MCP78_4 equ 0x0777 CTRL_NVIDIA_MCP73_1 equ 0x07fc CTRL_NVIDIA_MCP73_2 equ 0x07fd CTRL_NVIDIA_MCP79_1 equ 0x0ac0 CTRL_NVIDIA_MCP79_2 equ 0x0ac1 CTRL_NVIDIA_MCP79_3 equ 0x0ac2 CTRL_NVIDIA_MCP79_4 equ 0x0ac3 CTRL_NVIDIA_0BE2 equ 0x0be2 CTRL_NVIDIA_0BE3 equ 0x0be3 CTRL_NVIDIA_0BE4 equ 0x0be4 CTRL_NVIDIA_GT100 equ 0x0be5 CTRL_NVIDIA_GT106 equ 0x0be9 CTRL_NVIDIA_GT108 equ 0x0bea CTRL_NVIDIA_GT104 equ 0x0beb CTRL_NVIDIA_GT116 equ 0x0bee CTRL_NVIDIA_MCP89_1 equ 0x0d94 CTRL_NVIDIA_MCP89_2 equ 0x0d95 CTRL_NVIDIA_MCP89_3 equ 0x0d96 CTRL_NVIDIA_MCP89_4 equ 0x0d97 CTRL_NVIDIA_GF119 equ 0x0e08 CTRL_NVIDIA_GF110_1 equ 0x0e09 CTRL_NVIDIA_GF110_2 equ 0x0e0c ; ATI CTRL_ATI_SB450 equ 0x437b CTRL_ATI_SB600 equ 0x4383 ; ATI HDMI CTRL_ATI_RS600 equ 0x793b CTRL_ATI_RS690 equ 0x7919 CTRL_ATI_RS780 equ 0x960f CTRL_ATI_RS_UNK1 equ 0x970f CTRL_ATI_R600 equ 0xaa00 CTRL_ATI_RV630 equ 0xaa08 CTRL_ATI_RV610 equ 0xaa10 CTRL_ATI_RV670 equ 0xaa18 CTRL_ATI_RV635 equ 0xaa20 CTRL_ATI_RV620 equ 0xaa28 CTRL_ATI_RV770 equ 0xaa30 CTRL_ATI_RV730 equ 0xaa38 CTRL_ATI_RV710 equ 0xaa40 CTRL_ATI_RV740 equ 0xaa48 ; AMD CTRL_AMD_HUDSON equ 0x780d CTRL_AMD_RAVEN_RIDGE equ 0x15e3 CTRL_AMD_MATISSE equ 0x1487 ; VIA CTRL_VIA_VT82XX equ 0x3288 CTRL_VIA_VT61XX equ 0x9140 CTRL_VIA_VT71XX equ 0x9170 ; SiS CTRL_SIS_966 equ 0x7502 ; ULI CTRL_ULI_M5461 equ 0x5461 ; Creative CTRL_CREATIVE_CA0110_IBG equ 0x0009 CTRL_CREATIVE_SOUND_CORE3D_1 equ 0x0010 CTRL_CREATIVE_SOUND_CORE3D_2 equ 0x0012 ; Teradici CTRL_TERA_UNK1 equ 0x1200 ; RDC Semiconductor CTRL_RDC_R3010 equ 0x3010 ;VMware CTRL_VMWARE_UNK1 equ 0x1977 ; driver types AZX_DRIVER_ICH equ 0 AZX_DRIVER_PCH equ 1 AZX_DRIVER_SCH equ 2 AZX_DRIVER_ATI equ 3 AZX_DRIVER_ATIHDMI equ 4 AZX_DRIVER_VIA equ 5 AZX_DRIVER_SIS equ 6 AZX_DRIVER_ULI equ 7 AZX_DRIVER_NVIDIA equ 8 AZX_DRIVER_TERA equ 9 AZX_DRIVER_CTX equ 10 AZX_DRIVER_GENERIC equ 11 AZX_NUM_DRIVERS equ 12 ; registers ICH6_REG_GCAP equ 0x00 ICH6_REG_VMIN equ 0x02 ICH6_REG_VMAJ equ 0x03 ICH6_REG_OUTPAY equ 0x04 ICH6_REG_INPAY equ 0x06 ICH6_REG_GCTL equ 0x08 ICH6_GCTL_RESET equ (1 shl 0) ; controller reset ICH6_GCTL_FCNTRL equ (1 shl 1) ; flush control ICH6_GCTL_UNSOL equ (1 shl 8) ; accept unsol. response enable ICH6_REG_WAKEEN equ 0x0c ICH6_REG_STATESTS equ 0x0e ICH6_REG_GSTS equ 0x10 ICH6_GSTS_FSTS equ (1 shl 1) ; flush status ICH6_REG_INTCTL equ 0x20 ICH6_REG_INTSTS equ 0x24 ICH6_REG_WALLCLK equ 0x30 ; 24Mhz source ICH6_REG_OLD_SSYNC equ 0x34 ; SSYNC for old ICH ICH6_REG_SSYNC equ 0x38 ICH6_REG_CORBLBASE equ 0x40 ICH6_REG_CORBUBASE equ 0x44 ICH6_REG_CORBWP equ 0x48 ICH6_REG_CORBRP equ 0x4A ICH6_CORBRP_RST equ (1 shl 15) ; read pointer reset ICH6_REG_CORBCTL equ 0x4c ICH6_CORBCTL_RUN equ (1 shl 1) ; enable DMA ICH6_CORBCTL_CMEIE equ (1 shl 0) ; enable memory error irq ICH6_REG_CORBSTS equ 0x4d ICH6_CORBSTS_CMEI equ (1 shl 0) ; memory error indication ICH6_REG_CORBSIZE equ 0x4e ICH6_REG_RIRBLBASE equ 0x50 ICH6_REG_RIRBUBASE equ 0x54 ICH6_REG_RIRBWP equ 0x58 ICH6_RIRBWP_RST equ (1 shl 15) ; write pointer reset ICH6_REG_RINTCNT equ 0x5a ICH6_REG_RIRBCTL equ 0x5c ICH6_RBCTL_IRQ_EN equ (1 shl 0) ; enable IRQ ICH6_RBCTL_DMA_EN equ (1 shl 1) ; enable DMA ICH6_RBCTL_OVERRUN_EN equ (1 shl 2) ; enable overrun irq ICH6_REG_RIRBSTS equ 0x5d ICH6_RBSTS_IRQ equ (1 shl 0) ; response irq ICH6_RBSTS_OVERRUN equ (1 shl 2) ; overrun irq ICH6_REG_RIRBSIZE equ 0x5e ICH6_REG_IC equ 0x60 ICH6_REG_IR equ 0x64 ICH6_REG_IRS equ 0x68 ICH6_IRS_VALID equ 2 ICH6_IRS_BUSY equ 1 ICH6_REG_DPLBASE equ 0x70 ICH6_REG_DPUBASE equ 0x74 ICH6_DPLBASE_ENABLE equ 1 ; Enable position buffer ; SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ SDI0_SD_OFFSET equ 0x80 SDI1_SD_OFFSET equ 0xA0 SDI2_SD_OFFSET equ 0xC0 SDI3_SD_OFFSET equ 0xE0 SDO0_SD_OFFSET equ 0x100 SDO1_SD_OFFSET equ 0x120 SDO2_SD_OFFSET equ 0X140 SDO3_SD_OFFSET equ 0x160 ; stream register offsets from stream base ICH6_REG_SD_CTL equ 0x00 ICH6_REG_SD_STS equ 0x03 ICH6_REG_SD_LPIB equ 0x04 ICH6_REG_SD_CBL equ 0x08 ICH6_REG_SD_LVI equ 0x0c ICH6_REG_SD_FIFOW equ 0x0e ICH6_REG_SD_FIFOSIZE equ 0x10 ICH6_REG_SD_FORMAT equ 0x12 ICH6_REG_SD_BDLPL equ 0x18 ICH6_REG_SD_BDLPU equ 0x1c ; PCI space ICH6_PCIREG_TCSEL equ 0x44 ; other constants ICH6_RIRB_EX_UNSOL_EV equ (1 shl 4) ; max number of SDs MAX_ICH6_DEV equ 8 ; max number of fragments - we may use more if allocating more pages for BDL AZX_MAX_FRAG equ (4096 / (MAX_ICH6_DEV * 16)) ; max buffer size - no h/w limit, you can increase as you like AZX_MAX_BUF_SIZE equ (1024*1024*1024) ; max number of PCM devices per card AZX_MAX_PCMS equ 8 ; RIRB int mask: overrun[2], response[0] RIRB_INT_RESPONSE equ 0x01 RIRB_INT_OVERRUN equ 0x04 RIRB_INT_MASK equ 0x05 ; STATESTS int mask: SD2,SD1,SD0 STATESTS_INT_MASK equ 0x07 AZX_MAX_CODECS equ 4 ; SD_CTL bits SD_CTL_STREAM_RESET equ 0x01 ; stream reset bit SD_CTL_DMA_START equ 0x02 ; stream DMA start bit SD_CTL_STREAM_TAG_MASK equ (0xf shl 20) SD_CTL_STREAM_TAG_SHIFT equ 20 ; SD_CTL and SD_STS SD_INT_DESC_ERR equ 0x10 ; descriptor error interrupt SD_INT_FIFO_ERR equ 0x08 ; FIFO error interrupt SD_INT_COMPLETE equ 0x04 ; completion interrupt SD_INT_MASK equ (SD_INT_DESC_ERR or SD_INT_FIFO_ERR or SD_INT_COMPLETE) ; SD_STS SD_STS_FIFO_READY equ 0x20 ; FIFO ready ; INTCTL and INTSTS ICH6_INT_ALL_STREAM equ 0xff ; all stream interrupts ICH6_INT_CTRL_EN equ 0x40000000 ; controller interrupt enable bit ICH6_INT_GLOBAL_EN equ 0x80000000 ; global interrupt enable bit ; GCTL reset bit ICH6_GCTL_RESET equ 1 ; CORB/RIRB control, read/write pointer ICH6_RBCTL_DMA_EN equ 0x02 ; enable DMA ICH6_RBCTL_IRQ_EN equ 0x01 ; enable IRQ ICH6_RBRWP_CLR equ 0x8000 ; read/write pointer clear ; below are so far hardcoded - should read registers in future ICH6_MAX_CORB_ENTRIES equ 256 ICH6_MAX_RIRB_ENTRIES equ 256 ; position fix mode POS_FIX_AUTO equ 0 POS_FIX_LPIB equ 1 POS_FIX_POSBUF equ 2 POS_FIX_VIACOMBO equ 4 POS_FIX_COMBO equ 8 ; Defines for ATI HD Audio support in SB450 south bridge ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR equ 0x42 ATI_SB450_HDAUDIO_ENABLE_SNOOP equ 0x02 ; Defines for Nvidia HDA support NVIDIA_HDA_TRANSREG_ADDR equ 0x4e NVIDIA_HDA_ENABLE_COHBITS equ 0x0f NVIDIA_HDA_ISTRM_COH equ 0x4d NVIDIA_HDA_OSTRM_COH equ 0x4c NVIDIA_HDA_ENABLE_COHBIT equ 0x01 ; Defines for Intel SCH HDA snoop control INTEL_SCH_HDA_DEVC equ 0x78 INTEL_SCH_HDA_DEVC_NOSNOOP equ (0x1 shl 11) ; Define IN stream 0 FIFO size offset in VIA controller VIA_IN_STREAM0_FIFO_SIZE_OFFSET equ 0x90 ; Define VIA HD Audio Device ID VIA_HDAC_DEVICE_ID equ 0x3288 ; HD Audio class code PCI_CLASS_MULTIMEDIA_HD_AUDIO equ 0x0403 SRV_GETVERSION equ 0 DEV_PLAY equ 1 DEV_STOP equ 2 DEV_CALLBACK equ 3 DEV_SET_BUFF equ 4 DEV_NOTIFY equ 5 DEV_SET_MASTERVOL equ 6 DEV_GET_MASTERVOL equ 7 DEV_GET_INFO equ 8 DEV_GET_POS equ 9 DEV_SET_CHANNEL_VOLUME equ 10 DEV_GET_CHANNEL_VOLUME equ 11 ;Asper: Non standard system service. For the tests only! [ DEV_EXEC_CODEC_CMD equ 100 ;Asper: Non standard system service. For the tests only! ] struc AC_CNTRL ;AC controller base class { .bus dd ? .devfn dd ? .vendor dw ? .dev_id dw ? .pci_cmd dd ? .pci_stat dd ? .ctrl_io_base dd ? .ctrl_mem_base dd ? .cfg_reg dd ? .int_line dd ? .vendor_ids dd ? ;vendor id string .ctrl_ids dd ? ;hub id string .buffer dd ? .notify_pos dd ? .notify_task dd ? .lvi_reg dd ? .civ_val dd 1 .user_callback dd ? .ctrl_read8 dd ? .ctrl_read16 dd ? .ctrl_read32 dd ? .ctrl_write8 dd ? .ctrl_write16 dd ? .ctrl_write32 dd ? .codec_mask dd ? .rb dd ? .rirb_rp dw 0 .rirb_wp dw 0 .corb_rp dw 0 .corb_wp dw 0 .rirb_cmd dd 0 .rirb_res dd 0 .rirb_error dd 0 .response_reset dd 0 .polling_mode db 0 .poll_count db 0 .posbuf dd ? .start_wallclk dd ? ; start + minimum wallclk .period_wallclk dd ? ; wallclk for period .position_fix db ? } struc CODEC ;Audio Chip base class { .addr dd ? ; codec slot index (codec address) .afg dd ? ; AFG node id .mfg dd ? ; MFG node id .function_id dd ? .subsystem_id dd ? .revision_id dd ? .chip_id dw ? .vendor_id dw ? ; widget capabilities cache .num_nodes dw ? .start_nid dw ? .wcaps dd ? .init_pins dd ? ; initial (BIOS) pin configurations .num_pins dd ? ;Asper + : word is enough, but for align... .beeper_nid dw ? .pad dw ? .ac_vendor_ids dd ? ;ac vendor id string .chip_ids dd ? ;chip model string } struc CTRL_INFO { .pci_cmd dd ? .irq dd ? .glob_cntrl dd ? .glob_sta dd ? .codec_io_base dd ? .ctrl_io_base dd ? .codec_mem_base dd ? .ctrl_mem_base dd ? .codec_id dd ? } struc IOCTL { .handle dd ? .io_code dd ? .input dd ? .inp_size dd ? .output dd ? .out_size dd ? } EVENT_NOTIFY equ 0x00000200 ; Macroses by CleverMouse ; The following macro assume that we are on uniprocessor machine. ; Serious work is needed for multiprocessor machines. macro spin_lock_irqsave spinlock { pushf cli } macro spin_unlock_irqrestore spinlock { popf } macro spin_lock_irq spinlock { cli } macro spin_unlock_irq spinlock { sti } SPINLOCK_BUSY = 1 SPINLOCK_FREE = 0 macro spin_lock { push eax ebx mov eax, aspinlock mov ebx, SPINLOCK_BUSY @@: lock xchg [eax], ebx cmp ebx, SPINLOCK_FREE jnz @b pop ebx eax } macro spin_unlock { push eax ebx mov eax, aspinlock mov eax, aspinlock mov ebx, SPINLOCK_FREE lock xchg [eax], ebx pop ebx eax } data fixups end data include '../../struct.inc' include '../../macros.inc' include '../../proc32.inc' include '../../peimport.inc' include 'CODEC_H.INC' entry START ;proc START c, reason:dword, cmdline:dword proc START push ebx esi ; save used registers to be stdcall virtual at esp rd 2 ; saved registers dd ? ; return address .reason dd ? ; DRV_ENTRY or DRV_EXIT .cmdline dd ? ; normally NULL end virtual ; 1. Check the reason for the call, do nothing unless initializing. cmp [.reason], DRV_ENTRY jne .stop if DEBUG mov esi, msgTV invoke SysMsgBoardStr mov esi, msgInit invoke SysMsgBoardStr end if call detect_controller test eax, eax jz .fail mov esi,[ctrl.vendor_ids] invoke SysMsgBoardStr mov esi, [ctrl.ctrl_ids] invoke SysMsgBoardStr call init_controller test eax, eax jz .fail ;Asper This part is from "azx_create" proc. [ mov [ctrl.position_fix], POS_FIX_LPIB cmp [driver_type], AZX_DRIVER_VIA je .set_via_patch cmp [driver_type], AZX_DRIVER_ATI jne .no_via_patch .set_via_patch: or [ctrl.position_fix], POS_FIX_VIACOMBO .no_via_patch: ; codec detection mov eax, [ctrl.codec_mask] test eax, eax jnz @f if DEBUG mov esi, msgNoCodecsFound jmp .fail_msg else jmp .fail end if @@: ;Asper ] mov esi, msgPrimBuff invoke SysMsgBoardStr call create_primary_buff mov esi, msgDone invoke SysMsgBoardStr if IRQ_REMAP pushf cli mov ebx, [ctrl.int_line] in al, 0xA1 mov ah, al in al, 0x21 test ebx, ebx jz .skip bts ax, bx ;mask old line .skip bts ax, IRQ_LINE ;mask new line out 0x21, al mov al, ah out 0xA1, al ;remap IRQ invoke PciWrite8, 0, 0xF8, 0x61, IRQ_LINE mov dx, 0x4d0 ;8259 ELCR1 in al, dx bts ax, IRQ_LINE out dx, al ;set level-triggered mode mov [ctrl.int_line], IRQ_LINE popf mov esi, msgRemap invoke SysMsgBoardStr end if mov ebx, [ctrl.int_line] invoke AttachIntHandler, ebx, hda_irq, dword 0 ;Asper This part is from "azx_probe" proc. [ call azx_codec_create cmp eax, 0 jl .fail call azx_codec_configure cmp eax, 0 jl .fail ;] Asper ; create PCM streams ;Asper+ [ mov eax, [spec.dac_node] if DEBUG ;- push eax esi mov esi, msgVal invoke SysMsgBoardStr stdcall fdword2str, 3 invoke SysMsgBoardStr pop esi eax end if test eax, eax jz .fail mov ebx, [spec.dac_node+4] if DEBUG ;- push eax esi mov esi, msgVal invoke SysMsgBoardStr mov eax, [spec.dac_node+4] stdcall fdword2str, 3 invoke SysMsgBoardStr pop esi eax end if test ebx, ebx jz @f cmp eax, ebx je @f stdcall hda_codec_setup_stream, ebx, SDO_TAG, 0, 0x11 ; Left & Right channels (Front panel) @@: stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel) ;Asper+ ] invoke TimerHS, 1, 0, snd_hda_automute, 0 if USE_SINGLE_MODE mov esi, msgSingleMode invoke SysMsgBoardStr else mov esi, msgNormalMode invoke SysMsgBoardStr end if .reg: invoke RegService, sz_sound_srv, service_proc pop esi ebx ret .fail: mov esi, msgFail .fail_msg: invoke SysMsgBoardStr pop esi ebx xor eax, eax ret .stop: call stop pop esi ebx xor eax, eax ret endp handle equ IOCTL.handle io_code equ IOCTL.io_code input equ IOCTL.input inp_size equ IOCTL.inp_size output equ IOCTL.output out_size equ IOCTL.out_size align 4 proc service_proc stdcall, ioctl:dword mov edi, [ioctl] mov eax, [edi+io_code] cmp eax, SRV_GETVERSION jne @F mov eax, [edi+output] cmp [edi+out_size], 4 jne .fail mov [eax], dword API_VERSION xor eax, eax ret @@: cmp eax, DEV_PLAY jne @F if DEBUG mov esi, msgPlay invoke SysMsgBoardStr end if call play xor eax, eax ret @@: cmp eax, DEV_STOP jne @F if DEBUG mov esi, msgStop invoke SysMsgBoardStr end if call stop xor eax, eax ret @@: cmp eax, DEV_CALLBACK jne @f mov ebx, [edi+input] stdcall set_callback, [ebx] xor eax, eax ret @@: cmp eax, DEV_SET_MASTERVOL jne @f mov eax, [edi+input] mov eax, [eax] call set_master_vol xor eax, eax ret @@: cmp eax, DEV_GET_MASTERVOL jne @f mov ebx, [edi+output] stdcall get_master_vol, ebx xor eax, eax ret ;@@: ; cmp eax, DEV_GET_INFO ; jne @f ; mov ebx, [edi+output] ; stdcall get_dev_info, ebx ; xor eax, eax ; ret @@: cmp eax, DEV_GET_POS jne @f stdcall azx_get_position shr eax, 2 mov ebx, [edi+output] mov [ebx], eax xor eax, eax ret @@: ; cmp eax, DEV_SET_CHANNEL_VOLUME ; jne @f ;if DEBUG ; mov esi, msgSetChannelVolume ; invoke SysMsgBoardStr ;end if ; mov ebx, [edi+input] ; mov cl, byte [ebx] ; cl=channel ; mov eax, dword [ebx+1] ; eax=volume in Db ;if DEBUG ; push eax esi ; mov esi, msgYAHOO1 ; invoke SysMsgBoardStr ; stdcall fdword2str, 1 ; invoke SysMsgBoardStr ; mov esi, strSemicolon ; invoke SysMsgBoardStr ; movzx eax, cl ; stdcall fdword2str, 3 ; invoke SysMsgBoardStr ; pop esi eax ;end if ; ; call set_channel_volume ; xor eax, eax ; ret ;@@: ; cmp eax, DEV_GET_CHANNEL_VOLUME ; jne @f ; mov cl, byte [edi+input] ; cl=channel ; call get_channel_volume ; mov ebx, [edi+output] ; mov [ebx], eax ; xor eax, eax ; ret ;@@: ;Asper: Non standard system service. For the tests only! [ @@: cmp eax, DEV_EXEC_CODEC_CMD jne @f mov eax, [edi+input] mov eax, [eax] stdcall codec_exec_verb, eax xor eax, eax ret @@: ;Asper: Non standard system service. For the tests only! ] .fail: or eax, -1 ret endp restore handle restore io_code restore input restore inp_size restore output restore out_size align 4 proc hda_irq ;+ spin_lock if DEBUG_IRQ push eax esi ;mov esi, msgIRQ ;invoke SysMsgBoardStr invoke GetTimerTicks stdcall fdword2str, 2 invoke SysMsgBoardStr pop esi eax end if mov edx, ICH6_REG_INTSTS call azx_readl test eax, eax jnz @f spin_unlock ret @@: mov ebx, eax ; status mov eax, SDO_INT test ebx, eax jz @f mov edx, ICH6_REG_SD_STS + SDO_OFS call azx_readb mov bl, al mov al, SD_INT_MASK mov edx, ICH6_REG_SD_STS + SDO_OFS call azx_writeb test bl, SD_INT_COMPLETE jz @f mov eax, [ctrl.civ_val] inc eax and eax, 4-1 ;2-1 mov [ctrl.civ_val], eax mov ebx, dword [buff_list+eax*4] cmp [ctrl.user_callback], 0 je @f stdcall [ctrl.user_callback], ebx @@: ; clear rirb int mov edx, ICH6_REG_RIRBSTS call azx_readb test al, RIRB_INT_MASK jz .l1 test al, RIRB_INT_RESPONSE jz .l2 cmp byte [driver_type], AZX_DRIVER_CTX jne @f mov eax, 80 ; wait 80 us call StallExec @@: call azx_update_rirb .l2: mov al, RIRB_INT_MASK mov edx, ICH6_REG_RIRBSTS call azx_writeb .l1: ;if 0 ; clear state status int mov edx, ICH6_REG_STATESTS call azx_readb test al, 0x04 jz @f mov al, 0x04 mov edx, ICH6_REG_STATESTS call azx_writeb @@: ;end if or eax, 1 spin_unlock ret endp align 4 proc create_primary_buff invoke KernelAlloc, 4096 mov [ctrl.posbuf], eax invoke KernelAlloc, 0x10000 ;0x8000 mov [ctrl.buffer], eax mov edi, eax mov ecx, 0x10000/4 ;0x8000/4 xor eax, eax cld rep stosd invoke KernelAlloc, 4096 mov [pcmout_bdl], eax mov edi, eax mov ecx, 4096/4 xor eax, eax cld rep stosd ; reset BDL address xor eax, eax mov edx, ICH6_REG_SD_BDLPL + SDO_OFS call azx_writel xor eax, eax mov edx, ICH6_REG_SD_BDLPU + SDO_OFS call azx_writel ; program the initial BDL entries mov eax, [ctrl.buffer] mov ebx, eax invoke GetPgAddr and ebx, 0xFFF add eax, ebx mov ebx, 0x4000 ;buffer size mov ecx, 8 ;number of periods mov edi, [pcmout_bdl] ;pcmout_bdl .next_period: push eax ecx mov ecx, 4 ;2 ;number of bdl in a period .next_bdl: ; program the address field of the BDL entry mov dword [edi], eax mov dword [edi+4], 0 ; program the size field of the BDL entry mov dword [edi+8], ebx ; program the IOC to enable interrupt when buffer completes mov dword [edi+12], 0x01 add eax, ebx add edi, 16 dec ecx jnz .next_bdl pop ecx eax dec ecx jnz .next_period mov edi, buff_list mov eax, [ctrl.buffer] mov ecx, 4 ;2 @@: mov [edi], eax mov [edi+8], eax mov [edi+16], eax mov [edi+24], eax mov [edi+32], eax mov [edi+40], eax mov [edi+48], eax mov [edi+56], eax add eax, ebx add edi, 4 loop @B ; wallclk has 24Mhz clock source mov [ctrl.period_wallclk], ((0x4000 * 24000) / 48000) * 1000 call azx_stream_reset call azx_setup_controller ret endp align 4 proc detect_controller locals last_bus dd ? bus dd ? devfn dd ? endl xor eax, eax mov [bus], eax inc eax invoke PciApi cmp eax, -1 je .err mov [last_bus], eax .next_bus: and [devfn], 0 .next_dev: invoke PciRead32, [bus], [devfn], dword 0 test eax, eax jz .next cmp eax, -1 je .next mov edi, devices @@: mov ebx, [edi] test ebx, ebx jz .next cmp eax, ebx je .found add edi, 12 jmp @b .next: inc [devfn] cmp [devfn], 256 jb .next_dev mov eax, [bus] inc eax mov [bus], eax cmp eax, [last_bus] jna .next_bus xor eax, eax ret .found: mov ebx, [bus] mov [ctrl.bus], ebx mov ecx, [devfn] mov [ctrl.devfn], ecx mov edx, eax and edx, 0xFFFF mov [ctrl.vendor], dx shr eax, 16 mov [ctrl.dev_id], ax mov ebx, [edi+4] mov [ctrl.ctrl_ids], ebx cmp edx, VID_INTEL jne @f mov [ctrl.vendor_ids], msg_Intel jmp .ok @@: cmp edx, VID_NVIDIA jne @f mov [ctrl.vendor_ids], msg_NVidia jmp .ok @@: cmp edx, VID_ATI jne @f cmp eax, 0x4383 jg .ati_hdmi mov [ctrl.vendor_ids], msg_ATI jmp .ok .ati_hdmi: mov [ctrl.vendor_ids], msg_ATI_HDMI jmp .ok @@: cmp edx, VID_AMD jne @f mov [ctrl.vendor_ids], msg_AMD jmp .ok @@: cmp edx, VID_VIA jne @f mov [ctrl.vendor_ids], msg_VIA jmp .ok @@: cmp edx, VID_SIS jne @f mov [ctrl.vendor_ids], msg_SIS jmp .ok @@: cmp edx, VID_ULI jne @f mov [ctrl.vendor_ids], msg_ULI jmp .ok @@: cmp edx, VID_TERA jne @f mov [ctrl.vendor_ids], msg_TERA jmp .ok @@: cmp edx, VID_CREATIVE jne @f mov [ctrl.vendor_ids], msg_CREATIVE jmp .ok @@: cmp edx, VID_RDC jne @f mov [ctrl.vendor_ids], msg_RDC jmp .ok @@: cmp edx, VID_VMWARE jne @f mov [ctrl.vendor_ids], msg_VMWARE jmp .ok @@: .err: xor eax, eax mov [ctrl.vendor_ids], eax ;something wrong ? mov [driver_type], -1 ret .ok: mov ebx, [edi+8] mov [driver_type], ebx ret endp align 4 proc init_controller invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 movi ebx, 0x6 and ebx, eax cmp ebx, 0x6 ; Test Master and Memory bits jz @f or eax, 0x6 ; Set Master and Memory bits invoke PciWrite32, [ctrl.bus], [ctrl.devfn], dword 4, eax invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 @@: mov ebx, eax and eax, 0xFFFF mov [ctrl.pci_cmd], eax shr ebx, 16 mov [ctrl.pci_stat], ebx mov esi, msgPciCmd invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr mov esi, msgPciStat invoke SysMsgBoardStr mov eax, [ctrl.pci_stat] stdcall fdword2str, 2 invoke SysMsgBoardStr mov esi, msgHDALowMMIo invoke SysMsgBoardStr invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 stdcall fdword2str, 2 invoke SysMsgBoardStr and eax, 0xFFFFC000 mov [ctrl.ctrl_mem_base], eax mov esi, msgHDAUpMMIo invoke SysMsgBoardStr invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 ;-mov [ctrl.hda_upper_mem_base], eax stdcall fdword2str, 2 invoke SysMsgBoardStr .default: invoke PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C and eax, 0xFF @@: mov [ctrl.int_line], eax mov [ctrl.user_callback], 0 call set_HDA ;Asper This is from "azx_create" proc. [ xor eax, eax mov edx, ICH6_REG_GCAP call azx_readw if DEBUG mov esi, msgGCap invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr end if ; allocate CORB/RIRB call azx_alloc_cmd_io ; initialize chip call azx_init_pci xor eax, eax call azx_init_chip ;] Asper xor eax, eax inc eax ret endp PG_SW equ 0x003 PG_NOCACHE equ 0x018 align 4 proc set_HDA invoke MapIoMem,[ctrl.ctrl_mem_base],0x1000,PG_SW+PG_NOCACHE mov [ctrl.ctrl_mem_base], eax ret endp ; in: eax - fullreset_flag ; ; reset codec link align 4 proc reset_controller locals counter dd ? endl test eax, eax jz .skip ; clear STATESTS mov eax, STATESTS_INT_MASK mov edx, ICH6_REG_STATESTS call azx_writeb ; reset controller mov edx, ICH6_REG_GCTL call azx_readl mov ebx, ICH6_GCTL_RESET xor ebx, -1 and eax, ebx mov edx, ICH6_REG_GCTL call azx_writel mov [counter], 50 ; total 50*100 us = 0.5s .wait0: mov edx, ICH6_REG_GCTL call azx_readb test eax, eax jz @f mov eax, 100 ; wait 100 us call StallExec dec [counter] jnz .wait0 @@: ; delay for >= 100us for codec PLL to settle per spec ; Rev 0.9 section 5.5.1 mov eax, 100 ; wait 100 us call StallExec ; Bring controller out of reset mov edx, ICH6_REG_GCTL call azx_readb or eax, ICH6_GCTL_RESET mov edx, ICH6_REG_GCTL call azx_writeb mov [counter], 50 ; total 50*100 us = 0.5s .wait1: mov edx, ICH6_REG_GCTL call azx_readb test eax, eax jnz @f mov eax, 100 ; wait 100 us call StallExec dec [counter] jnz .wait1 @@: ; Brent Chartrand said to wait >= 540us for codecs to intialize mov eax, 540 ; wait 540 us call StallExec .skip: ; check to see if controller is ready mov edx, ICH6_REG_GCTL call azx_readb test eax, eax jz .fail ; Accept unsolicited responses if USE_SINGLE_MODE else if USE_UNSOL_EV ;UNSUPPORTED YET! [ mov edx, ICH6_REG_GCTL call azx_readl or eax, ICH6_GCTL_UNSOL mov edx, ICH6_REG_GCTL call azx_writel ;UNSUPPORTED YET! ] end if ; detect codecs mov eax, [ctrl.codec_mask] test ax, ax jnz @f mov edx, ICH6_REG_STATESTS call azx_readw mov [ctrl.codec_mask], eax if DEBUG mov esi, msgCodecMask invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr end if @@: .ok: clc ret .fail: if DEBUG mov esi, msgHDARFail invoke SysMsgBoardStr end if stc ret endp align 4 play: spin_lock_irq mov edx, ICH6_REG_WALLCLK call azx_readl mov [ctrl.start_wallclk], eax call azx_stream_start xor eax, eax spin_unlock_irq ret align 4 stop: spin_lock_irq ;* call azx_stream_stop ;Asper: Hangs system ;R push ebx ecx edx ;R ; stop DMA ;R mov edx, ICH6_REG_SD_CTL ;R call azx_sd_readb ;R mov bl, SD_CTL_DMA_START or SD_INT_MASK ;R xor bl, -1 ;R and al, bl ;R mov edx, ICH6_REG_SD_CTL ;R call azx_sd_writeb ;R mov edx, ICH6_REG_SD_STS ;R mov al, SD_INT_MASK ;R call azx_sd_writeb ; to be sure ; disable SIE ;N mov edx, ICH6_REG_INTCTL ;N call azx_readb ;N mov bl, SDO_INT ;shl azx_dev->index ;N xor bl, -1 ;N and al, bl ;N mov edx, ICH6_REG_INTCTL ;N call azx_writeb ; int timeout = 5000; ; while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout) ; ;Asper: Hangs system [ ;* mov ecx, 5000 ;*.l1: ;* mov edx, ICH6_REG_SD_CTL ;* call azx_sd_readb ;* test al, SD_CTL_DMA_START ;* jz @f ;* dec ecx ;* jnz .l1 ;*@@: ;* ;* pop edx ecx ebx ;Asper ] xor eax, eax spin_unlock_irq ret ;align 4 ;proc get_dev_info stdcall, p_info:dword ;deprecated ;virtual at esi ; CTRL_INFO CTRL_INFO ;end virtual ; ; mov esi, [p_info] ; mov eax, [ctrl.int_line] ; mov bx, [ctrl.dev_id] ; shl ebx, 16 ; and bx, [ctrl.vendor] ; mov ecx, [ctrl.pci_cmd] ; mov edx, [ctrl.codec_mem_base] ;[ctrl.hda_lower_mem_base] ; mov edi, [ctrl.ctrl_mem_base] ;[ctrl.hda_upper_mem_base] ; ; mov [CTRL_INFO.irq], eax ; mov [CTRL_INFO.codec_id], ebx ; mov [CTRL_INFO.pci_cmd], ecx ; mov [CTRL_INFO.codec_mem_base], edx ; mov [CTRL_INFO.ctrl_mem_base], edi ; ; xor eax, eax ; mov [CTRL_INFO.codec_io_base], eax ; mov [CTRL_INFO.ctrl_io_base], eax ; mov [CTRL_INFO.glob_cntrl], eax ; mov [CTRL_INFO.glob_sta], eax ; ret ;endp align 4 proc set_callback stdcall, handler:dword mov eax, [handler] mov [ctrl.user_callback], eax ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interface for HD codec ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CORB / RIRB interface ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;; proc azx_alloc_cmd_io push eax ecx edx ; single page (at least 4096 bytes) must suffice for both ringbuffers invoke KernelAlloc, 4096 mov [ctrl.rb], eax mov edi, eax mov ecx, 4096/4 xor eax, eax cld rep stosd pop edx ecx eax ret endp proc azx_init_cmd_io spin_lock_irq pusha ; CORB set up mov eax, [ctrl.rb] mov ebx, eax invoke GetPgAddr and ebx, 0xFFF add eax, ebx push eax ; save corb address mov edx, ICH6_REG_CORBLBASE call azx_writel xor eax, eax mov edx, ICH6_REG_CORBUBASE call azx_writel ; set the corb size to 256 entries (ULI requires explicitly) mov al, 0x02 mov edx, ICH6_REG_CORBSIZE call azx_writeb ; set the corb write pointer to 0 xor ax, ax mov edx, ICH6_REG_CORBWP call azx_writew ; reset the corb hw read pointer mov ax, ICH6_CORBRP_RST mov edx, ICH6_REG_CORBRP call azx_writew ; enable corb dma mov al, ICH6_CORBCTL_RUN mov edx, ICH6_REG_CORBCTL call azx_writeb ; RIRB set up mov [ctrl.rirb_rp], 0 mov [ctrl.rirb_wp], 0 mov [ctrl.rirb_cmd], 0 pop eax ; restore corb address add eax, 2048 mov edx, ICH6_REG_RIRBLBASE call azx_writel xor eax, eax mov edx, ICH6_REG_RIRBUBASE call azx_writel ; set the rirb size to 256 entries (ULI requires explicitly) mov al, 0x02 mov edx, ICH6_REG_RIRBSIZE call azx_writeb ; reset the rirb hw write pointer mov ax, ICH6_RIRBWP_RST mov edx, ICH6_REG_RIRBWP call azx_writew ; set N=1, get RIRB response interrupt for new entry xor ax, ax cmp byte [driver_type], AZX_DRIVER_CTX jne @f mov ax, 0xC0-1 @@: inc ax mov edx, ICH6_REG_RINTCNT call azx_writew ; enable rirb dma and response irq mov al, ICH6_RBCTL_DMA_EN or ICH6_RBCTL_IRQ_EN mov edx, ICH6_REG_RIRBCTL call azx_writeb popa spin_unlock_irq ret endp proc azx_free_cmd_io spin_lock_irq push eax edx ; disable ringbuffer DMAs xor al, al mov edx, ICH6_REG_RIRBCTL call azx_writeb mov edx, ICH6_REG_CORBCTL call azx_writeb pop edx eax spin_unlock_irq ret endp ; send a command proc azx_corb_send_cmd stdcall, val:dword spin_lock_irq push edx edi xor eax, eax ; add command to corb mov edx, ICH6_REG_CORBWP call azx_readb inc al inc dword [ctrl.rirb_cmd] mov edi, dword [ctrl.rb] push eax shl eax, 2 ;wp=wp*sizeof(corb entry)=wp*4 add edi, eax mov eax, dword [val] stosd pop eax mov edx, ICH6_REG_CORBWP call azx_writel pop edi edx xor eax, eax ;Asper+ spin_unlock_irq ret endp ; retrieve RIRB entry - called from interrupt handler proc azx_update_rirb pusha xor eax, eax mov edx, ICH6_REG_RIRBWP call azx_readb ;call azx_readw cmp ax, [ctrl.rirb_wp] je .done mov [ctrl.rirb_wp], ax mov bx, [ctrl.rirb_rp] .l1: cmp bx, [ctrl.rirb_wp] je .l3 inc bl .l2: cmp bx, ICH6_MAX_RIRB_ENTRIES jl @f sub bx, ICH6_MAX_RIRB_ENTRIES jmp .l2 @@: movzx edx, bx shl edx, 1 + 2 ; an RIRB entry is 8-bytes mov esi, dword [ctrl.rb] add esi, 2048 add esi, edx lodsd ; res mov edx, eax lodsd ; res_ex test eax, ICH6_RIRB_EX_UNSOL_EV jz @f stdcall snd_hda_queue_unsol_event, edx, eax jmp .l1 @@: mov ecx, [ctrl.rirb_cmd] test ecx, ecx jz @f mov [ctrl.rirb_res], edx dec dword [ctrl.rirb_cmd] jmp .l1 @@: if DEBUG push esi mov esi, msgSpuriousResponce invoke SysMsgBoardStr pop esi end if jmp .l1 .l3: mov [ctrl.rirb_rp], bx .done: popa ret endp ; receive a response proc azx_rirb_get_response locals do_poll db 0 endl push ebx ecx edx .again: mov ecx, 1000;+1000 .next_try: mov al, [ctrl.polling_mode] test al, al jnz .poll mov ah, [do_poll] test ah, ah jz @f .poll: spin_lock_irq call azx_update_rirb spin_unlock_irq @@: mov eax, [ctrl.rirb_cmd] test eax, eax jnz .l1 mov [ctrl.rirb_error], 0 mov al, [do_poll] test al, al jnz @f mov [ctrl.poll_count], 0 @@: mov eax, [ctrl.rirb_res] ; the last value jmp .out .l1: push eax mov eax, 2000 ; temporary workaround call StallExec pop eax dec ecx jnz .next_try .no_next_try: mov al, [ctrl.polling_mode] test al, al jnz .no_poll mov al, [ctrl.poll_count] cmp al, 2 jge .poll_count_overflow if DEBUG push eax esi mov esi, msgGetResponceTimeout invoke SysMsgBoardStr mov esi, msgPollingCodecOnce invoke SysMsgBoardStr pop esi eax end if mov [do_poll], 1 inc [ctrl.poll_count] jmp .again .poll_count_overflow: if DEBUG push eax esi mov esi, msgGetResponceTimeout invoke SysMsgBoardStr mov esi, msgSwitchToPollMode invoke SysMsgBoardStr pop esi eax end if mov [ctrl.polling_mode], 1 jmp .again .no_poll: mov al, [ctrl.polling_mode] test al, al jz @f mov eax, -1 jmp .out @@: ; a fatal communication error; need either to reset or to fallback ; to the single_cmd mode mov [ctrl.rirb_error], 1 ;Asper~ -? [ mov [ctrl.response_reset], 1 mov eax, -1 ; give a chance to retry jmp .out ;Asper~ -? ] ;-? mov [ctrl.single_cmd], 1 mov [ctrl.response_reset], 0 ; release CORB/RIRB call azx_free_cmd_io ; disable unsolicited responses mov edx, ICH6_REG_GCTL call azx_readl mov ebx, ICH6_GCTL_UNSOL xor ebx, -1 and eax, ebx mov edx, ICH6_REG_GCTL call azx_writel mov eax, -1 .out: pop edx ecx ebx ret endp ; ; Use the single immediate command instead of CORB/RIRB for simplicity ; ; Note: according to Intel, this is not preferred use. The command was ; intended for the BIOS only, and may get confused with unsolicited ; responses. So, we shouldn't use it for normal operation from the ; driver. ; I left the codes, however, for debugging/testing purposes. ; ; receive a response proc azx_single_wait_for_response push ecx edx esi mov ecx, 50 .l1: test ecx, ecx jz .timeout ; check IRV busy bit mov edx, ICH6_REG_IRS call azx_readw test ax, ICH6_IRS_VALID jz @f ; reuse rirb.res as the response return value mov edx, ICH6_REG_IR call azx_readl mov [ctrl.rirb_res], eax pop esi edx ecx xor eax, eax ret @@: xor eax, eax inc eax call StallExec dec ecx jmp .l1 .timeout: if DEBUG xor eax, eax mov edx, ICH6_REG_IRS call azx_readw mov esi, msgGetResponceTimeout invoke SysMsgBoardStr mov esi, msgIRS invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr end if pop esi edx ecx mov eax, -1 mov [ctrl.rirb_res], eax ret endp ; send a command proc azx_single_send_cmd stdcall, val:dword push ecx edx esi mov ecx, 50 .l1: test ecx, ecx jz .timeout ; check ICB busy bit mov edx, ICH6_REG_IRS call azx_readw test ax, ICH6_IRS_BUSY jnz @f ; Clear IRV valid bit mov edx, ICH6_REG_IRS call azx_readw or ax, ICH6_IRS_VALID mov edx, ICH6_REG_IRS call azx_writew mov eax, dword [val] mov edx, ICH6_REG_IC call azx_writel mov edx, ICH6_REG_IRS call azx_readw or ax, ICH6_IRS_BUSY mov edx, ICH6_REG_IRS call azx_writew stdcall azx_single_wait_for_response pop esi edx ecx ret @@: dec ecx jmp .l1 .timeout: if DEBUG xor eax, eax mov edx, ICH6_REG_IRS call azx_readw mov esi, msgSendCmdTimeout invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr mov esi, msgVal invoke SysMsgBoardStr mov eax, dword [val] stdcall fdword2str, 2 invoke SysMsgBoardStr end if pop esi edx ecx mov eax, -1 ret endp ; receive a response proc azx_single_get_response mov eax, [ctrl.rirb_res] ret endp ; ; The below are the main callbacks from hda_codec. ; ; They are just the skeleton to call sub-callbacks according to the ; current setting of chip->single_cmd. ; ; send a command proc azx_send_cmd stdcall, val:dword if USE_SINGLE_MODE stdcall azx_single_send_cmd, [val] else stdcall azx_corb_send_cmd, [val] end if ret endp ; get a response proc azx_get_response if USE_SINGLE_MODE call azx_single_get_response else call azx_rirb_get_response end if ret endp ;;;;;;;;;;;;;;;;;;;;;;;; ;; Lowlevel interface ;; ;;;;;;;;;;;;;;;;;;;;;;;; ; enable interrupts proc azx_int_enable push eax edx ; enable controller CIE and GIE mov edx, ICH6_REG_INTCTL call azx_readl or eax, ICH6_INT_CTRL_EN or ICH6_INT_GLOBAL_EN mov edx, ICH6_REG_INTCTL call azx_writel pop edx eax ret endp ; disable interrupts proc azx_int_disable push eax ebx edx ; disable interrupts in stream descriptor mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb mov bl, SD_INT_MASK xor bl, -1 and al, bl mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writeb ; disable SIE for all streams xor al, al mov edx, ICH6_REG_INTCTL call azx_writeb ; disable controller CIE and GIE mov edx, ICH6_REG_INTCTL call azx_readl mov ebx, ICH6_INT_CTRL_EN or ICH6_INT_GLOBAL_EN xor ebx, -1 and eax, ebx call azx_writel pop edx ebx eax ret endp ; clear interrupts proc azx_int_clear push eax edx ; clear stream status mov al, SD_INT_MASK mov edx, ICH6_REG_SD_STS + SDO_OFS call azx_writeb ; clear STATESTS mov al, STATESTS_INT_MASK mov edx, ICH6_REG_STATESTS call azx_writeb ; clear rirb status mov al, RIRB_INT_MASK mov edx, ICH6_REG_RIRBSTS call azx_writeb ; clear int status mov eax, ICH6_INT_CTRL_EN or ICH6_INT_ALL_STREAM mov edx, ICH6_REG_INTSTS call azx_writel pop edx eax ret endp ; start a stream proc azx_stream_start push eax edx ; enable SIE mov edx, ICH6_REG_INTCTL call azx_readl or eax, 0xC0000000 ;Asper+ or eax, SDO_INT ; Asper: output stream interrupt index mov edx, ICH6_REG_INTCTL call azx_writel ; set DMA start and interrupt mask mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb or al, SD_CTL_DMA_START or SD_INT_MASK mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writeb pop edx eax ret endp ; stop DMA proc azx_stream_clear push eax ebx edx mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb mov bl, SD_CTL_DMA_START or SD_INT_MASK xor bl, -1 and al, bl mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writeb mov al, SD_INT_MASK mov edx, ICH6_REG_SD_STS + SDO_OFS call azx_writeb pop edx ebx eax ret endp ; stop a stream proc azx_stream_stop push eax ebx edx call azx_stream_clear ; disable SIE mov edx, ICH6_REG_INTCTL call azx_readl mov ebx, (SDO_INT) xor ebx, -1 and eax, ebx mov edx, ICH6_REG_INTCTL call azx_writel pop edx ebx eax ret endp ; ;in: eax = full_reset ; ; initialize the chip proc azx_init_chip push eax ; reset controller mov eax, 1 ;full reset call reset_controller ; initialize interrupts call azx_int_clear call azx_int_enable ; initialize the codec command I/O if USE_SINGLE_MODE else call azx_init_cmd_io end if ; program the position buffer mov eax, dword [ctrl.posbuf] mov ebx, eax invoke GetPgAddr and ebx, 0xFFF add eax, ebx mov edx, ICH6_REG_DPLBASE call azx_writel xor eax, eax mov edx, ICH6_REG_DPUBASE call azx_writel pop eax ret endp ; initialize the PCI registers ; update bits in a PCI register byte proc update_pci_byte stdcall, reg:dword, mask:dword, val:dword push ax bx invoke PciRead8, [ctrl.bus], [ctrl.devfn], [reg] mov bl, byte [mask] mov bh, bl xor bl, -1 and al, bl shr bx, 8 and bl, byte [val] or al, bl invoke PciWrite8, [ctrl.bus], [ctrl.devfn], [reg], eax pop bx ax ret endp proc azx_init_pci ; Clear bits 0-2 of PCI register TCSEL (at offset 0x44) ; TCSEL == Traffic Class Select Register, which sets PCI express QOS ; Ensuring these bits are 0 clears playback static on some HD Audio ; codecs push eax stdcall update_pci_byte, ICH6_PCIREG_TCSEL, 0x07, 0 mov eax, [driver_type] cmp eax, AZX_DRIVER_ATI jne @f ; For ATI SB450 azalia HD audio, we need to enable snoop stdcall update_pci_byte, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP jmp .done @@: cmp eax, AZX_DRIVER_NVIDIA jne @f ; For NVIDIA HDA, enable snoop stdcall update_pci_byte, NVIDIA_HDA_TRANSREG_ADDR, 0x0f, NVIDIA_HDA_ENABLE_COHBITS stdcall update_pci_byte, NVIDIA_HDA_ISTRM_COH, 0x01, NVIDIA_HDA_ENABLE_COHBIT stdcall update_pci_byte, NVIDIA_HDA_OSTRM_COH, 0x01, NVIDIA_HDA_ENABLE_COHBIT jmp .done @@: cmp eax, AZX_DRIVER_SCH je .l1 cmp eax, AZX_DRIVER_PCH jne @f .l1: invoke PciRead16, [ctrl.bus], [ctrl.devfn], dword INTEL_SCH_HDA_DEVC test ax, INTEL_SCH_HDA_DEVC_NOSNOOP jz @f push ebx mov ebx, INTEL_SCH_HDA_DEVC_NOSNOOP xor ebx, -1 and eax, ebx pop ebx invoke PciWrite16, [ctrl.bus], [ctrl.devfn], dword INTEL_SCH_HDA_DEVC, eax invoke PciRead16, [ctrl.bus], [ctrl.devfn], dword INTEL_SCH_HDA_DEVC if DEBUG push esi mov esi, msgHDASnoopDisabled invoke SysMsgBoardStr mov esi, msg_OK test ax, INTEL_SCH_HDA_DEVC_NOSNOOP jz .snoop_ok mov esi, msg_Fail .snoop_ok: invoke SysMsgBoardStr pop esi end if @@: .done: pop eax ret endp ; reset stream proc azx_stream_reset push eax ebx ecx edx call azx_stream_clear mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb or al, SD_CTL_STREAM_RESET mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writeb mov eax, 3 call StallExec mov ecx, 300 .l1: mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb test al, SD_CTL_STREAM_RESET jnz @f dec ecx jnz .l1 @@: mov bl, SD_CTL_STREAM_RESET xor bl, -1 and al, bl mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writeb mov eax, 3 call StallExec mov ecx, 300 ; waiting for hardware to report that the stream is out of reset .l2: mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readb test al, SD_CTL_STREAM_RESET jnz @f dec ecx jnz .l2 @@: ; reset first position - may not be synced with hw at this time mov edx, [ctrl.posbuf] mov dword [edx], 0 pop edx ecx ebx eax ret endp ; set up the SD for streaming proc azx_setup_controller push eax ebx ecx edx ; make sure the run bit is zero for SD call azx_stream_clear ; program the stream_tag mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readl mov ecx, SD_CTL_STREAM_TAG_MASK xor ecx, -1 and eax, ecx mov ecx, SDO_TAG shl ecx, SD_CTL_STREAM_TAG_SHIFT or eax, ecx ; Asper stream_tag = SDO_TAG mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writel ; program the length of samples in cyclic buffer mov eax, 0x4000*32 mov edx, ICH6_REG_SD_CBL + SDO_OFS call azx_writel ; program the stream format ; this value needs to be the same as the one programmed mov ax, 0x11 mov edx, ICH6_REG_SD_FORMAT + SDO_OFS call azx_writew ; program the stream LVI (last valid index) of the BDL mov eax, 32-1 ;4-1 ;2-1 mov [ctrl.lvi_reg], eax mov edx, ICH6_REG_SD_LVI + SDO_OFS call azx_writew ; program the BDL address ; lower BDL address mov eax, [pcmout_bdl] mov ebx, eax invoke GetPgAddr and ebx, 0xFFF add eax, ebx mov edx, ICH6_REG_SD_BDLPL + SDO_OFS call azx_writel ; upper BDL address xor eax, eax ;upper_32bit(azx_dev->bdl_addr) mov edx, ICH6_REG_SD_BDLPU + SDO_OFS call azx_writel ; enable the position buffer cmp [ctrl.position_fix], POS_FIX_LPIB jz @f mov edx, ICH6_REG_DPLBASE call azx_readl and eax, ICH6_DPLBASE_ENABLE jnz @f mov eax, dword [ctrl.posbuf] mov ebx, eax invoke GetPgAddr and ebx, 0xFFF add eax, ebx or eax, ICH6_DPLBASE_ENABLE mov edx, ICH6_REG_DPLBASE call azx_writel @@: ; set the interrupt enable bits in the descriptor control register mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_readl or eax, SD_INT_MASK mov edx, ICH6_REG_SD_CTL + SDO_OFS call azx_writel pop edx ecx ebx eax ret endp ;(...) ; Probe the given codec address proc probe_codec, addr:dword push edx mov eax, [addr] shl eax, 28 mov edx, (AC_NODE_ROOT shl 20) or (AC_VERB_PARAMETERS shl 8) or AC_PAR_VENDOR_ID or eax, edx stdcall azx_send_cmd, eax stdcall azx_get_response cmp eax, -1 je .out mov eax, [addr] mov [codec.addr], eax ;Asper+ if DEBUG push esi mov esi, msgCodecOK invoke SysMsgBoardStr mov esi, msgCAd invoke SysMsgBoardStr stdcall fdword2str, 3 invoke SysMsgBoardStr pop esi end if xor eax, eax .out: pop edx ret endp proc azx_bus_reset call azx_stop_chip call azx_init_chip ret endp ; Codec initialization proc azx_codec_create push ebx ecx edx ;(...) ; First try to probe all given codec slots ; Asper: We asume for now that max slots for codecs = 4 xor ecx, ecx xor edx, edx inc edx .next_slot: test edx, [ctrl.codec_mask] jz @f stdcall probe_codec, ecx test eax, eax jz .init ;@f ; Some BIOSen give you wrong codec addresses that don't exist if DEBUG mov esi, msgCodecError invoke SysMsgBoardStr end if mov ebx, edx xor ebx, -1 and [ctrl.codec_mask], ebx ; More badly, accessing to a non-existing ; codec often screws up the controller chip, ; and disturbs the further communications. ; Thus if an error occurs during probing, ; better to reset the controller chip to ; get back to the sanity state. ;call azx_bus_reset @@: shl edx, 1 inc ecx ;if USE_FIRST_CODEC ; cmp ecx, 1 ;else cmp ecx, 4 ;end if jl .next_slot mov eax, -1 jmp .out .init: push ecx edx stdcall snd_hda_codec_init pop edx ecx test eax, eax jnz @b .out: pop edx ecx ebx ret endp proc azx_codec_configure ;(...) call snd_hda_codec_configure ret endp proc azx_get_position test [ctrl.position_fix], POS_FIX_LPIB jz @f ; read LPIB mov edx, ICH6_REG_SD_LPIB + SDO_OFS call azx_readl jmp .out @@: test [ctrl.position_fix], POS_FIX_VIACOMBO jz @f ; call azx_get_via_position ; jmp .out @@: ; use the position buffer push edx mov edx, dword [ctrl.posbuf] mov eax, dword [edx] pop edx .out: cmp eax, 0x4000 ; bufsize jl @f xor eax, eax @@: ret endp proc azx_stop_chip push eax edx ; disable interrupts call azx_int_disable call azx_int_clear ; disable CORB/RIRB call azx_free_cmd_io ; disable position buffer xor eax, eax mov edx, ICH6_REG_DPLBASE call azx_writel mov edx, ICH6_REG_DPUBASE call azx_writel pop edx eax ret endp ; in: eax = volume (-10000 - 0) align 4 set_master_vol: mov ecx, 3 call set_channel_volume ret ; out: [pvol] = volume (-10000 - 0) align 4 proc get_master_vol stdcall, pvol:dword xor ecx, ecx call get_channel_volume mov ebx, [pvol] mov [ebx], eax xor eax, eax ret endp ; in: ecx = channel mask (1 - Left; 2 - Right; 3-Both) ; eax = volume (-10000 - 0) align 4 set_channel_volume: push eax ebx ecx edx mov ebx, [volume.maxDb] neg eax if DEBUG ;- push eax esi mov esi, msgNewVolume invoke SysMsgBoardStr stdcall fdword2str, 2 invoke SysMsgBoardStr mov esi, msgMinVolume invoke SysMsgBoardStr mov eax, ebx stdcall fdword2str, 2 invoke SysMsgBoardStr pop esi eax end if test ebx, ebx jz .err_out cmp eax, 0 jg @f xor eax, eax jmp .set @@: cmp eax, ebx jng .set mov eax, ebx .set: sub ebx, eax mov eax, ebx ;cdq xor edx, edx push eax movzx eax, [volume.step_size] imul eax, (100/4) mov ebx, eax pop eax xor edx, edx idiv ebx mov edx, [volume.out_amp_node] test edx, edx jz .out movzx ebx, [edx+HDA_GNODE.nid] test ecx, 1 ; Left channel ? jz @f stdcall put_volume_mute, ebx, 0, HDA_OUTPUT, 0, eax @@: test ecx, 2 ; Right channel ? jz .out stdcall put_volume_mute, ebx, 1, HDA_OUTPUT, 0, eax .out: pop edx ecx ebx eax ret .err_out: if DEBUG ;- push esi mov esi, emsgNoVolCtrl invoke SysMsgBoardStr pop esi end if jmp .out ; in: ecx = channel (1 - Left; 2 - Right) ; out: eax = volume (-10000 - 0) align 4 get_channel_volume: push ebx ecx edx cmp ecx, 2 jg .out dec cl xor eax, eax mov edx, [volume.out_amp_node] test edx, edx jz .out movzx ebx, [edx+HDA_GNODE.nid] stdcall get_volume_mute, ebx, ecx, HDA_OUTPUT, 0 and eax, 0x7F ;get gain mov cl, [volume.step_size] mul cl imul eax, (-100/4) .out: pop edx ecx ebx ret ; in: ecx = delay udelay: push eax ecx edx test ecx, ecx jnz @f inc ecx @@: mov eax, ecx mov cx, 500 mul cl mov ecx, edx shl ecx, 16 or ecx, eax @@: xor eax, eax cpuid dec ecx jz @b pop edx ecx eax ret align 4 proc StallExec push ecx edx ebx eax mov ecx, CPU_FREQ mul ecx mov ebx, eax ;low mov ecx, edx ;high rdtsc add ebx, eax adc ecx,edx @@: rdtsc sub eax, ebx sbb edx, ecx js @B pop eax ebx edx ecx ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEMORY MAPPED IO (os depended) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align 4 proc azx_readb add edx, [ctrl.ctrl_mem_base] mov al, [edx] ret endp align 4 proc azx_readw add edx, [ctrl.ctrl_mem_base] mov ax, [edx] ret endp align 4 proc azx_readl add edx, [ctrl.ctrl_mem_base] mov eax, [edx] ret endp align 4 proc azx_writeb add edx, [ctrl.ctrl_mem_base] mov [edx], al ret endp align 4 proc azx_writew add edx, [ctrl.ctrl_mem_base] mov [edx], ax ret endp align 4 proc azx_writel add edx, [ctrl.ctrl_mem_base] mov [edx], eax ret endp ;_______ proc snd_hda_automute stdcall, data:dword push eax ebx ecx edx esi mov esi, [spec.out_pin_node+4] mov ecx, [spec.out_pin_node] test esi, esi jnz @f xchg ecx, esi test esi, esi jz .out @@: movzx edx, word [esi + HDA_GNODE.nid] stdcall is_jack_detectable, edx test eax, eax jz .out stdcall snd_hda_read_pin_sense, edx, 1 test eax, AC_PINSENSE_PRESENCE jnz @f xchg ecx, esi @@: ; set PIN-Out enable test esi, esi jz .out xor edx, edx test [esi + HDA_GNODE.pin_caps], AC_PINCAP_HP_DRV jz @f mov edx, AC_PINCTL_HP_EN @@: or edx, AC_PINCTL_OUT_EN movzx eax, [esi + HDA_GNODE.nid] stdcall snd_hda_codec_write, eax, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, edx ; set PIN-Out disable test ecx, ecx jz .out xor edx, edx movzx eax, [ecx + HDA_GNODE.nid] stdcall snd_hda_codec_write, eax, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, edx .out: pop esi edx ecx ebx eax ret endp ;Asper remember to add this functions: proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword ;if DEBUG ; push esi ; mov esi, msgUnsolEvent ; invoke SysMsgBoardStr ; pop esi ;end if if USE_UNSOL_EV = 1 ;Test. Do not make queue, process immediately! ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword ;and then mute/unmute pin based on the results invoke TimerHS, 1, 0, snd_hda_automute, 0 end if ret endp ;... align 4 proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined push eax ebx ecx mov esi, hex_buff mov ecx, -8 push eax @@: rol eax, 4 mov ebx, eax and ebx, 0x0F mov bl, [ebx+hexletters] mov [8+esi+ecx], bl inc ecx jnz @b pop eax mov dword [esi+8], 0 test [flags], 0x2 ; new line ? jz .no_newline mov dword [esi+8], 0x00000A0D .no_newline: push eax test [flags], 0x1 ; skip zero bits ? jz .no_skipz mov ecx, 8 @@: test eax, 0xF0000000 jnz .skipz_done rol eax, 4 inc esi dec ecx jnz @b dec esi .skipz_done: .no_skipz: pop eax pop ecx ebx eax ret endp hexletters db '0123456789ABCDEF' hex_buff db 8 dup(0),13,10,0,0 include "CODEC.INC" include "hda_generic.inc" align 4 devices: ; Intel dd (CTRL_INTEL_SCH2 shl 16)+VID_INTEL,msg_INTEL_SCH2, AZX_DRIVER_SCH dd (CTRL_INTEL_HPT shl 16)+VID_INTEL,msg_INTEL_HPT, AZX_DRIVER_SCH dd (CTRL_INTEL_CPT shl 16)+VID_INTEL,msg_INTEL_CPT, AZX_DRIVER_PCH dd (CTRL_INTEL_PGB shl 16)+VID_INTEL,msg_INTEL_PGB, AZX_DRIVER_PCH dd (CTRL_INTEL_PPT1 shl 16)+VID_INTEL,msg_INTEL_PPT1, AZX_DRIVER_PCH dd (CTRL_INTEL_ICH6 shl 16)+VID_INTEL,msg_INTEL_ICH6, AZX_DRIVER_ICH dd (CTRL_INTEL_63XXESB shl 16)+VID_INTEL,msg_INTEL_63XXESB, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH7 shl 16)+VID_INTEL,msg_INTEL_ICH7, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH8 shl 16)+VID_INTEL,msg_INTEL_ICH8, AZX_DRIVER_ICH dd (CTRL_INTEL_82801_UNK1 shl 16)+VID_INTEL,msg_INTEL_82801_UNK1, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH9 shl 16)+VID_INTEL,msg_INTEL_ICH9, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH9_2 shl 16)+VID_INTEL,msg_INTEL_ICH9, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH10 shl 16)+VID_INTEL,msg_INTEL_ICH10, AZX_DRIVER_ICH dd (CTRL_INTEL_ICH10_2 shl 16)+VID_INTEL,msg_INTEL_ICH10, AZX_DRIVER_ICH dd (CTRL_INTEL_PCH shl 16)+VID_INTEL,msg_INTEL_PCH, AZX_DRIVER_PCH dd (CTRL_INTEL_PCH2 shl 16)+VID_INTEL,msg_INTEL_PCH2, AZX_DRIVER_PCH dd (CTRL_INTEL_SCH shl 16)+VID_INTEL,msg_INTEL_SCH, AZX_DRIVER_SCH dd (CTRL_INTEL_LPT shl 16)+VID_INTEL,msg_INTEL_LPT, AZX_DRIVER_PCH dd (CTRL_INTEL_0F04 shl 16)+VID_INTEL,msg_INTEL_BAYTRAIL, AZX_DRIVER_PCH dd (CTRL_INTEL_2284 shl 16)+VID_INTEL,msg_INTEL_BRASWELL, AZX_DRIVER_PCH dd (CTRL_INTEL_8ca0 shl 16)+VID_INTEL,msg_INTEL_9SERIES, AZX_DRIVER_PCH dd (CTRL_INTEL_8d20 shl 16)+VID_INTEL,msg_INTEL_WELLSBURG, AZX_DRIVER_PCH dd (CTRL_INTEL_8d21 shl 16)+VID_INTEL,msg_INTEL_WELLSBURG, AZX_DRIVER_PCH dd (CTRL_INTEL_A1F0 shl 16)+VID_INTEL,msg_INTEL_LEWISBURG, AZX_DRIVER_PCH dd (CTRL_INTEL_A270 shl 16)+VID_INTEL,msg_INTEL_LEWISBURG, AZX_DRIVER_PCH dd (CTRL_INTEL_9C20 shl 16)+VID_INTEL,msg_INTEL_LYNX_LP, AZX_DRIVER_PCH dd (CTRL_INTEL_9C21 shl 16)+VID_INTEL,msg_INTEL_LYNX_LP, AZX_DRIVER_PCH dd (CTRL_INTEL_9CA0 shl 16)+VID_INTEL,msg_INTEL_WILD_LP, AZX_DRIVER_PCH dd (CTRL_INTEL_A170 shl 16)+VID_INTEL,msg_INTEL_SUNRISE, AZX_DRIVER_PCH dd (CTRL_INTEL_9D70 shl 16)+VID_INTEL,msg_INTEL_SUN_LP, AZX_DRIVER_PCH dd (CTRL_INTEL_5A98 shl 16)+VID_INTEL,msg_INTEL_BROXTON, AZX_DRIVER_PCH ; Nvidia dd (CTRL_NVIDIA_MCP51 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP51, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP55 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP55, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP61_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP61, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP61_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP61, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP65_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP65, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP65_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP65, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP67_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP67, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP67_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP67, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP73_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP73, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP73_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP73, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP78_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP78, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP78_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP78, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP78_3 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP78, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP78_4 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP78, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP79_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP79, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP79_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP79, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP79_3 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP79, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP79_4 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP79, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_0BE2 shl 16)+VID_NVIDIA,msg_NVIDIA_0BE2, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_0BE3 shl 16)+VID_NVIDIA,msg_NVIDIA_0BE3, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_0BE4 shl 16)+VID_NVIDIA,msg_NVIDIA_0BE4, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GT100 shl 16)+VID_NVIDIA,msg_NVIDIA_GT100, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GT106 shl 16)+VID_NVIDIA,msg_NVIDIA_GT106, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GT108 shl 16)+VID_NVIDIA,msg_NVIDIA_GT108, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GT104 shl 16)+VID_NVIDIA,msg_NVIDIA_GT104, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GT116 shl 16)+VID_NVIDIA,msg_NVIDIA_GT116, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP89_1 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP89, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP89_2 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP89, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP89_3 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP89, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_MCP89_4 shl 16)+VID_NVIDIA,msg_NVIDIA_MCP89, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GF119 shl 16)+VID_NVIDIA,msg_NVIDIA_GF119, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GF110_1 shl 16)+VID_NVIDIA,msg_NVIDIA_GF110, AZX_DRIVER_NVIDIA dd (CTRL_NVIDIA_GF110_2 shl 16)+VID_NVIDIA,msg_NVIDIA_GF110, AZX_DRIVER_NVIDIA ; ATI dd (CTRL_ATI_SB450 shl 16)+VID_ATI,msg_ATI_SB450, AZX_DRIVER_ATI dd (CTRL_ATI_SB600 shl 16)+VID_ATI,msg_ATI_SB600, AZX_DRIVER_ATI dd (CTRL_ATI_RS600 shl 16)+VID_ATI,msg_ATI_RS600, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RS690 shl 16)+VID_ATI,msg_ATI_RS690, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RS780 shl 16)+VID_ATI,msg_ATI_RS780, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RS_UNK1 shl 16)+VID_ATI,msg_ATI_RS_UNK1, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_R600 shl 16)+VID_ATI,msg_ATI_R600, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV610 shl 16)+VID_ATI,msg_ATI_RV610, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV620 shl 16)+VID_ATI,msg_ATI_RV620, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV630 shl 16)+VID_ATI,msg_ATI_RV630, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV635 shl 16)+VID_ATI,msg_ATI_RV635, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV670 shl 16)+VID_ATI,msg_ATI_RV670, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV710 shl 16)+VID_ATI,msg_ATI_RV710, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV730 shl 16)+VID_ATI,msg_ATI_RV730, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV740 shl 16)+VID_ATI,msg_ATI_RV740, AZX_DRIVER_ATIHDMI dd (CTRL_ATI_RV770 shl 16)+VID_ATI,msg_ATI_RV770, AZX_DRIVER_ATIHDMI ; AMD dd (CTRL_AMD_HUDSON shl 16)+VID_AMD,msg_AMD_HUDSON, AZX_DRIVER_GENERIC dd (CTRL_AMD_RAVEN_RIDGE shl 16)+VID_AMD,msg_AMD_RAVEN_RIDGE, AZX_DRIVER_GENERIC dd (CTRL_AMD_MATISSE shl 16)+VID_AMD,msg_AMD_MATISSE, AZX_DRIVER_GENERIC ; VIA dd (CTRL_VIA_VT82XX shl 16)+VID_VIA,msg_VIA_VT82XX, AZX_DRIVER_VIA dd (CTRL_VIA_VT61XX shl 16)+VID_VIA,msg_VIA_VT61XX, AZX_DRIVER_GENERIC dd (CTRL_VIA_VT71XX shl 16)+VID_VIA,msg_VIA_VT71XX, AZX_DRIVER_GENERIC ; SiS dd (CTRL_SIS_966 shl 16)+VID_SIS,msg_SIS_966, AZX_DRIVER_SIS ; ULI dd (CTRL_ULI_M5461 shl 16)+VID_ULI,msg_ULI_M5461, AZX_DRIVER_ULI ; Teradici dd (CTRL_TERA_UNK1 shl 16)+VID_ULI,msg_TERA_UNK1, AZX_DRIVER_TERA ; Creative dd (CTRL_CREATIVE_CA0110_IBG shl 16)+VID_CREATIVE,msg_CREATIVE_CA0110_IBG, AZX_DRIVER_CTX dd (CTRL_CREATIVE_SOUND_CORE3D_1 shl 16)+VID_CREATIVE,msg_CREATIVE_SOUND_CORE3D, AZX_DRIVER_GENERIC dd (CTRL_CREATIVE_SOUND_CORE3D_2 shl 16)+VID_CREATIVE,msg_CREATIVE_SOUND_CORE3D, AZX_DRIVER_GENERIC ; RDC Semiconductor dd (CTRL_RDC_R3010 shl 16)+VID_RDC,msg_RDC_R3010, AZX_DRIVER_GENERIC ; VMware dd (CTRL_VMWARE_UNK1 shl 16)+VID_VMWARE,msg_VMWARE_UNK1, AZX_DRIVER_GENERIC dd 0 ;terminator version dd (5 shl 16) or (API_VERSION and 0xFFFF) msg_Intel db 'Intel ',0 msg_INTEL_CPT db 'Cougar Point',13,10,0 msg_INTEL_PGB db 'Patsburg',13,10,0 msg_INTEL_PPT1 db 'Panther Point',13,10,0 msg_INTEL_LPT db 'Lynx Point',13,10,0 msg_INTEL_HPT db 'Haswell',13,10,0 msg_INTEL_ICH6 db 'ICH6',13,10,0 msg_INTEL_63XXESB db '631x/632xESB',13,10,0 msg_INTEL_ICH7 db 'ICH7', 13,10,0 msg_INTEL_ICH8 db 'ICH8', 13,10,0 msg_INTEL_ICH9 db 'ICH9', 13,10,0 msg_INTEL_ICH10 db 'ICH10',13,10,0 msg_INTEL_PCH db 'PCH',13,10,0 msg_INTEL_PCH2 db 'PCH2',13,10,0 msg_INTEL_SCH db 'Poulsbo',13,10,0 msg_INTEL_SCH2 db 'Oaktrail',13,10,0 msg_INTEL_BAYTRAIL db 'BayTrail', 13,10,0 msg_INTEL_BRASWELL db 'Braswell', 13,10,0 msg_INTEL_9SERIES db '9 Series', 13,10,0 msg_INTEL_WELLSBURG db 'Wellsburg', 13,10,0 msg_INTEL_LEWISBURG db 'Lewisburg', 13,10,0 msg_INTEL_LYNX_LP db 'Lynx Point-LP',13,10,0 msg_INTEL_WILD_LP db 'Wildcat Point-LP',13,10,0 msg_INTEL_SUNRISE db 'Sunrise Point',13,10,0 msg_INTEL_SUN_LP db 'Sunrise Point-LP',13,10,0 msg_INTEL_BROXTON db 'Broxton-P',13,10,0 msg_INTEL_82801_UNK1 db '82801_UNK1', 13,10,0 msg_NVidia db 'NVidia ',0 msg_NVIDIA_MCP51 db 'MCP51', 13,10,0 msg_NVIDIA_MCP55 db 'MCP55', 13,10,0 msg_NVIDIA_MCP61 db 'MCP61', 13,10,0 msg_NVIDIA_MCP65 db 'MCP65', 13,10,0 msg_NVIDIA_MCP67 db 'MCP67', 13,10,0 msg_NVIDIA_MCP73 db 'MCP73', 13,10,0 msg_NVIDIA_MCP78 db 'MCP78', 13,10,0 msg_NVIDIA_MCP79 db 'MCP79', 13,10,0 msg_NVIDIA_MCP89 db 'MCP89', 13,10,0 msg_NVIDIA_0BE2 db '(0x0be2)', 13,10,0 msg_NVIDIA_0BE3 db '(0x0be3)', 13,10,0 msg_NVIDIA_0BE4 db '(0x0be4)', 13,10,0 msg_NVIDIA_GT100 db 'GT100', 13,10,0 msg_NVIDIA_GT104 db 'GT104', 13,10,0 msg_NVIDIA_GT106 db 'GT106', 13,10,0 msg_NVIDIA_GT108 db 'GT108', 13,10,0 msg_NVIDIA_GT116 db 'GT116', 13,10,0 msg_NVIDIA_GF119 db 'GF119', 13,10,0 msg_NVIDIA_GF110 db 'GF110', 13,10,0 msg_ATI db 'ATI ',0 msg_ATI_SB450 db 'SB450', 13,10,0 msg_ATI_SB600 db 'SB600', 13,10,0 msg_ATI_HDMI db 'ATI HDMI ',0 msg_ATI_RS600 db 'RS600', 13,10,0 msg_ATI_RS690 db 'RS690', 13,10,0 msg_ATI_RS780 db 'RS780', 13,10,0 msg_ATI_RS_UNK1 db 'RS_UNK1', 13,10,0 msg_ATI_R600 db 'R600', 13,10,0 msg_ATI_RV610 db 'RV610', 13,10,0 msg_ATI_RV620 db 'RV620', 13,10,0 msg_ATI_RV630 db 'RV630', 13,10,0 msg_ATI_RV635 db 'RV635', 13,10,0 msg_ATI_RV670 db 'RV670', 13,10,0 msg_ATI_RV710 db 'RV710', 13,10,0 msg_ATI_RV730 db 'RV730', 13,10,0 msg_ATI_RV740 db 'RV740', 13,10,0 msg_ATI_RV770 db 'RV770', 13,10,0 msg_AMD db 'AMD ',0 msg_AMD_HUDSON db 'Hudson', 13,10,0 msg_AMD_RAVEN_RIDGE db 'RavenRidge', 13,10,0 msg_AMD_MATISSE db 'Matisse', 13,10,0 msg_VIA db 'VIA ',0 msg_VIA_VT82XX db 'VT8251/8237A', 13,10,0 msg_VIA_VT61XX db 'GFX VT6122/VX11', 13,10,0 msg_VIA_VT71XX db 'GFX VT7122/VX900', 13,10,0 msg_SIS db 'SIS ',0 msg_SIS_966 db '966', 13,10,0 msg_ULI db 'ULI ',0 msg_ULI_M5461 db 'M5461', 13,10,0 msg_TERA db 'Teradici ',0 msg_TERA_UNK1 db 'UNK1', 13,10,0 msg_CREATIVE db 'Creative ',0 msg_CREATIVE_CA0110_IBG db 'CA0110-IBG',13,10,0 ;SB X-Fi Xtreme Audio msg_CREATIVE_SOUND_CORE3D db 'Sound Core3D' msg_RDC db 'RDC ',0 msg_RDC_R3010 db 'R3010', 13,10,0 msg_VMWARE db 'VMware ',0 msg_VMWARE_UNK1 db 'UNK1', 13,10,0 szKernel db 'KERNEL',0 sz_sound_srv db 'SOUND',0 msgInit db 'detect hardware...',13,10,0 msgFail db 'device not found',13,10,0 msgAttchIRQ db 'IRQ line not supported', 13,10,0 msgInvIRQ db 'IRQ line not assigned or invalid', 13,10,0 msgPlay db 'start play', 13,10,0 msgStop db 'stop play', 13,10,0 msgSetChannelVolume db 'Set Channel Volume', 13,10,0 msgIRQ db 'HDA IRQ', 13,10,0 msgInitCtrl db 'init controller',13,10,0 msgPrimBuff db 'create primary buffer ...',0 msgDone db 'done',13,10,0 msgRemap db 'Remap IRQ',13,10,0 msgOk db 'service installed',13,10,0 msgCold db 'cold reset',13,10,0 msgHDARFail db 'controller not ready',13,10,0 msgCFail db 'codec not ready',13,10,0 msgResetOk db 'reset complete',13,10,0 msgPciCmd db 'PCI command ',0 msgPciStat db 'PCI status ',0 msgHDALowMMIo db 'lower mmio base ',0 msgHDAUpMMIo db 'upper mmio base ',0 msgIrqMap db 'HDA irq map as ',0 ;msgUnsolEvent db 'Unsolicited event!',13,10,0 ;Asper [ if DEBUG msgCodecMask db 'codec_mask = ',0 msgNoCodecsFound db 'no codecs found!',13,10,0 msgHDASnoopDisabled db 'HDA snoop disabled, enabling ... ',0 msg_OK db 'OK',13,10,0 msg_Fail db 'Failed',13,10,0 msgSpuriousResponce db 'spurious responce ',0 emsgInvalidAFGSubtree db 'Invalid AFG subtree',13,10,0 emsgConnListNotAvailable db 'connection list not available for ',0 msgUnmuteOut db 'UNMUTE OUT: NID=',0 msgUnmuteIn db 'UNMUTE IN: NID=',0 msgGetResponceTimeout db 'get_response timeout: ',0 msgVal db ' val=',0 emsgBusResetFatalComm db 'resetting BUS due to fatal communication error',13,10,0 msgCodecOK db 'codec probed OK',13,10,0 msgCodecError db 'codec probe error disabling it...',13,10,0 emsgNoAFGorMFGFound db 'no AFG or MFG node found',13,10,0 msgNoAFGFound db 'no AFG node found, trying another codec',13,10,0 emsgNoMem db 'hda_codec: cannot malloc',13,10,0 msgConnect db 'CONNECT: NID=',0 msgIdx db ' IDX=',0 msgSkipDigitalOutNode db 'Skip Digital OUT node ',0 msgAudOutFound db 'AUD_OUT found ',0 emsgNoParserAvailable db 'No codec parser is available',13,10,0 emsgNoProperOutputPathFound db 'hda_generic: no proper output path found',13,10,0 emsgInvConnList db 'hda_codec: invalid CONNECT_LIST verb ',0 emsgInvDepRangeVal db 'hda_codec: invalid dep_range_val ',0 emsgTooManyConns db 'Too many connections',13,10,0 emsgNoVolCtrl db 'No volume control',13,10,0 msgHDACodecSetupStream db 'hda_codec_setup_stream: NID=',0 msgStream db 'stream=',0 msgChannel db 'channel=',0 msgFormat db 'format=',0 msgPollingCodecOnce db 'polling the codec once',13,10,0 ;Asper~ msgSwitchToPollMode db 'switching to polling mode',13,10,0 ;Asper~ strSemicolon db ':',0 msgSETUP_FG_NODES db 'Setup FG nodes = start_nid:total_nodes = ',0 msgFG_TYPE db 'FG type = ',0 msgPinCfgs db 'Pin configurations:',13,10,0 msgWCaps db 'Widget capabilities:',13,10,0 msgCAd db 'CAd = ',0 msgTCSEL db 'PCI TCSEL ',0 msgTV db 'HDA test version ',TEST_VERSION_NUMBER,13,10,0 msgGCap db 'GCAP = ',0 end if if USE_SINGLE_MODE msgSingleMode db 'Single mode !',13,10,0 msgIRS db 'IRS=',0 msgSendCmdTimeout db 'send_cmd timeout: IRS=',0 else msgNormalMode db 'Normal mode !',13,10,0 end if if DEBUG msgYAHOO2 db 'YAHOO2: ',0 msgMinVolume db 'MinVolume: ',0 msgNewVolume db 'NewVolume: ',0 msgVerbQuery db 'Q: ',0 msgVerbAnswer db 'A: ',0 msgPin_Nid db 'Pin Nid = ',0 msgPin_Ctl db 'Pin Control = ',0 msgPin_Caps db 'Pin Capabilities = ',0 msgDef_Cfg db 'Pin def_cfg = ',0 msgAmp_Out_Caps db 'Pin Amp Out caps = ',0 msgAmpVal db 'Amp val = ',0 msgEnableEAPD db 'Enable EAPD: NID=',0 msgBeeperNid db 'Beeper found: NID=',0 msgBeeperValue db 'Beeper initial value: ',0 msgBeepNow db 'Beep!',13,10,0 msgNodeSeq db 'Sequence of codec nodes:',13,10,0 msgNID db 'NID: 0x',0 end if ;] Asper aspinlock dd SPINLOCK_FREE codec CODEC ctrl AC_CNTRL ;Asper: BDL must be aligned to 128 according to HDA specification. pcmout_bdl rd 1 buff_list rd 32 driver_type rd 1