0,0 → 1,3062 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; 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 |
; 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 |
; 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_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 |