forked from KolibriOS/kolibrios
11bd59473f
* sound driver selector: revert r5071 and fix the problem properly * sis: integrate changes from drivers/audio/sisnbook, add to autobuild * intelac97: fix clicks during play on VBox * intel_hda: fix problems at shutdown git-svn-id: svn://kolibrios.org@5077 a494cfbc-eb01-0410-851d-a64ba20cac60
2976 lines
66 KiB
NASM
2976 lines
66 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; ;;
|
||
;; Copyright (C) KolibriOS team 2004-2012. 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 '019'
|
||
|
||
;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_CPT equ 0x1c20
|
||
CTRL_INTEL_PGB equ 0x1d20
|
||
CTRL_INTEL_PPT1 equ 0x1e20
|
||
CTRL_INTEL_82801F equ 0x2668
|
||
CTRL_INTEL_63XXESB equ 0x269a
|
||
CTRL_INTEL_82801G equ 0x27d8
|
||
CTRL_INTEL_82801H equ 0x284b
|
||
CTRL_INTEL_82801_UNK1 equ 0x2911
|
||
CTRL_INTEL_82801I equ 0x293e
|
||
CTRL_INTEL_82801_UNK2 equ 0x293f
|
||
CTRL_INTEL_82801JI equ 0x3a3e
|
||
CTRL_INTEL_82801JD equ 0x3a6e
|
||
CTRL_INTEL_PCH equ 0x3b56
|
||
CTRL_INTEL_PCH2 equ 0x3b57
|
||
CTRL_INTEL_SCH equ 0x811b
|
||
CTRL_INTEL_LPT equ 0x8c20
|
||
; 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
|
||
; 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+ ]
|
||
|
||
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
|
||
call 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
|
||
test eax, 0x4 ; Test Master bit
|
||
jnz @f
|
||
or eax, 0x4 ; Set Master bit
|
||
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
|
||
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
|
||
|
||
;_______
|
||
|
||
|
||
;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 = 0
|
||
;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
|
||
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_82801F shl 16)+VID_INTEL,msg_INTEL_82801F, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_63XXESB shl 16)+VID_INTEL,msg_INTEL_63XXESB, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801G shl 16)+VID_INTEL,msg_INTEL_82801G, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801H shl 16)+VID_INTEL,msg_INTEL_82801H, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801_UNK1 shl 16)+VID_INTEL,msg_INTEL_82801_UNK1, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801I shl 16)+VID_INTEL,msg_INTEL_82801I, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801_UNK2 shl 16)+VID_INTEL,msg_INTEL_82801_UNK2, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801JI shl 16)+VID_INTEL,msg_INTEL_82801JI, AZX_DRIVER_ICH
|
||
dd (CTRL_INTEL_82801JD shl 16)+VID_INTEL,msg_INTEL_82801JD, 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
|
||
; 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
|
||
; 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_82801F db '82801F',13,10,0
|
||
msg_INTEL_63XXESB db '631x/632xESB',13,10,0
|
||
msg_INTEL_82801G db '82801G', 13,10,0
|
||
msg_INTEL_82801H db '82801H', 13,10,0
|
||
msg_INTEL_82801I db '82801I', 13,10,0
|
||
msg_INTEL_82801JI db '82801JI',13,10,0
|
||
msg_INTEL_82801JD db '82801JD',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_82801_UNK1 db '82801_UNK1', 13,10,0
|
||
msg_INTEL_82801_UNK2 db '82801_UNK2', 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_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
|
||
|
||
;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~
|
||
|
||
msgUnsolEvent db 'Unsolicited event!',13,10,0
|
||
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
|