📄 common.cpp
字号:
SetPinConfig (PINC_VIDEO_PRESENT, FALSE);
//
// Test for Aux support.
//
ntStatus = ReadCodecRegister (AC97REG_AUX_VOLUME, &wCodecReg);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// Default is 0x8808.
SetPinConfig (PINC_AUX_PRESENT, (wCodecReg == 0x8808));
// Check if OEM wants to disable aux input.
if (DisableAC97Pin (PINC_AUX_PRESENT))
SetPinConfig (PINC_AUX_PRESENT, FALSE);
//
// Test for Mic2 source.
//
ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// Test for Mic2 select bit.
if (wCodecReg & 0x0100)
SetPinConfig (PINC_MIC2_PRESENT, TRUE);
else
{
// Select Mic2 as source.
ntStatus = WriteCodecRegister (AC97REG_GENERAL, 0x0100, 0x0100);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// Read back.
ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
if (wCodecReg & 0x0100)
{
// Yep, we have support so set it to the default value.
SetPinConfig (PINC_MIC2_PRESENT, TRUE);
// reset to default value.
WriteCodecRegister (AC97REG_GENERAL, 0, 0x0100);
}
else
SetPinConfig (PINC_MIC2_PRESENT, FALSE);
}
// Check if OEM wants to disable mic2 input.
if (DisableAC97Pin (PINC_MIC2_PRESENT))
SetPinConfig (PINC_MIC2_PRESENT, FALSE);
//
// Test the 3D controls.
//
if (GetNodeConfig (NODEC_3D_PRESENT))
{
//
// First test for fixed 3D controls. Write default value ...
//
ntStatus = WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
// Read 3D register. Default is 0 when adjustable, otherwise it is
// a fixed value.
ntStatus = ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
//
// Check center and depth separately.
//
// For center
SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, !(wCodecReg & 0x0F00));
// For depth
SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, !(wCodecReg & 0x000F));
//
// Test for adjustable controls.
//
WriteCodecRegister (AC97REG_3D_CONTROL, 0x0A0A, -1);
// Read 3D register. Now it should be 0x0A0A for adjustable controls,
// otherwise it is a fixed control or simply not there.
ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
// Restore the default value
WriteCodecRegister (AC97REG_3D_CONTROL, 0, -1);
// Check the center control for beeing adjustable
if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
(wCodecReg & 0x0F00) != 0x0A00)
{
SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, FALSE);
}
// Check the depth control for beeing adjustable
if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
(wCodecReg & 0x000F) != 0x000A)
{
SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, FALSE);
}
}
//
// Check for 6th bit support in volume controls. To check the 6th bit,
// we first have to write a value (with 6th bit set) and then read it
// back. After that, we should restore the register to its default value.
//
//
// Start with the master volume.
//
Check6thBitSupport (AC97REG_MASTER_VOLUME, NODEC_6BIT_MASTER_VOLUME);
//
// Check for a headphone volume control.
//
if (GetPinConfig (PINC_HPOUT_PRESENT))
{
Check6thBitSupport (AC97REG_HPHONE_VOLUME, NODEC_6BIT_HPOUT_VOLUME);
}
//
// Mono out there?
//
if (GetPinConfig (PINC_MONOOUT_PRESENT))
{
Check6thBitSupport (AC97REG_MMONO_VOLUME, NODEC_6BIT_MONOOUT_VOLUME);
}
//
// Get extended AC97 V2.0 information
//
ntStatus = ReadCodecRegister (AC97REG_EXT_AUDIO_ID, &wCodecReg);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
//
// Store the information
//
SetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED, wCodecReg & 0x0001);
SetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED, wCodecReg & 0x0002);
SetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED, wCodecReg & 0x0008);
SetNodeConfig (NODEC_CENTER_DAC_PRESENT, wCodecReg & 0x0040);
SetNodeConfig (NODEC_SURROUND_DAC_PRESENT, wCodecReg & 0x0080);
SetNodeConfig (NODEC_LFE_DAC_PRESENT, wCodecReg & 0x0100);
//
// In case we have some features get some more information and program
// the codec.
//
if (wCodecReg)
{
//
// Enable variable sample rate in the control register and disable
// double rate. Also enable all DACs.
//
WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, wCodecReg & 0x0009, 0x380B);
//
// Check for codecs that have only one sample rate converter. These
// codecs will stick registers AC97REG_FRONT_SAMPLERATE and
// AC97REG_RECORD_SAMPLERATE together.
//
if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
{
// The default of the sample rate registers should be 0xBB80.
WriteCodecRegister (AC97REG_FRONT_SAMPLERATE, 0xBB80, 0xFFFF);
// Write 44.1KHz into record VSR, then check playback again.
WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xAC44, 0xFFFF);
ntStatus = ReadCodecRegister (AC97REG_FRONT_SAMPLERATE, &wCodecReg);
WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xBB80, 0xFFFF);
if (!NT_SUCCESS (ntStatus))
return ntStatus;
//
// Set the flag accordingly
//
SetNodeConfig (NODEC_PCM_VSR_INDEPENDENT_RATES, (wCodecReg == 0xBB80));
}
//
// Check multichanel support on the ICH.
//
if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
{
dwGlobalStatus = ReadBMControlRegister32 (GLOB_STA);
//
// Codec supports >2 chanel, does ICH too?
//
if ((GetNodeConfig (NODEC_CENTER_DAC_PRESENT) ||
GetNodeConfig (NODEC_LFE_DAC_PRESENT)) &&
(dwGlobalStatus & GLOB_STA_MC6))
{
SetPinConfig (PINC_CENTER_LFE_PRESENT, TRUE);
}
else
{
SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
}
//
// Do we support at least 4 channels?
//
SetPinConfig (PINC_SURROUND_PRESENT, (dwGlobalStatus & GLOB_STA_MC4));
}
else
{
//
// Only 2 channel (stereo) support.
//
SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
}
}
// Check if OEM wants to disable surround output.
if (DisableAC97Pin (PINC_SURROUND_PRESENT))
SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
// Check if OEM wants to disable center and LFE output.
if (DisableAC97Pin (PINC_CENTER_LFE_PRESENT))
SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
//
// Check the 6th bit support for the additional channels.
//
if (GetPinConfig (PINC_SURROUND_PRESENT))
Check6thBitSupport (AC97REG_SURROUND_VOLUME, NODEC_6BIT_SURROUND_VOLUME);
if (GetPinConfig (PINC_CENTER_LFE_PRESENT))
Check6thBitSupport (AC97REG_CENTER_LFE_VOLUME, NODEC_6BIT_CENTER_LFE_VOLUME);
//
// We read these registers because they are dependent on the codec.
//
ReadCodecRegister (AC97REG_VENDOR_ID1, &wCodecReg);
ReadCodecRegister (AC97REG_VENDOR_ID2, &wCodecReg);
return STATUS_SUCCESS;
}
/*****************************************************************************
* CAdapterCommon::AcquireCodecSemiphore
*****************************************************************************
* Acquires the AC97 semiphore. This can not be called at dispatch level
* because it can timeout if a lower IRQL thread has the semaphore.
*/
NTSTATUS CAdapterCommon::AcquireCodecSemiphore ()
{
PAGED_CODE ();
DOUT (DBG_PRINT, ("[CAdapterCommon::AcquireCodecSemiphore]"));
ULONG ulCount = 0;
while (READ_PORT_UCHAR (m_pBusMasterBase + CAS) & CAS_CAS)
{
//
// Do we want to give up??
//
if (ulCount++ > 100)
{
DOUT (DBG_ERROR, ("Cannot acquire semaphore."));
return STATUS_IO_TIMEOUT;
}
//
// Let's wait a little, 40us and then try again.
//
KeStallExecutionProcessor (40L);
}
return STATUS_SUCCESS;
}
/*****************************************************************************
* CAdapterCommon::ReadCodecRegister
*****************************************************************************
* Reads a AC97 register. Don't call at PASSIVE_LEVEL.
*/
STDMETHODIMP_(NTSTATUS) CAdapterCommon::ReadCodecRegister
(
IN AC97Register reg,
OUT PWORD wData
)
{
PAGED_CODE ();
ASSERT (wData);
ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
NTSTATUS ntStatus;
ULONG Status;
DOUT (DBG_PRINT, ("[CAdapterCommon::ReadCodecRegister]"));
//
// Check if we have to access the HW directly.
//
if (m_bDirectRead || (m_stAC97Registers[reg].wFlags & SHREG_INVALID) ||
(m_stAC97Registers[reg].wFlags & SHREG_NOCACHE))
{
//
// Grab the codec access semiphore.
//
ntStatus = AcquireCodecSemiphore ();
if (!NT_SUCCESS (ntStatus))
{
DOUT (DBG_ERROR, ("ReadCodecRegister couldn't acquire the semiphore"
" for reg. %s", reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
"REG_INVALID"));
return ntStatus;
}
//
// Read the data.
//
*wData = READ_PORT_USHORT (m_pCodecBase + reg);
//
// Check to see if the read was successful.
//
Status = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA));
if (Status & GLOB_STA_RCS)
{
//
// clear the timeout bit
//
WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA), Status);
*wData = 0;
DOUT (DBG_ERROR, ("ReadCodecRegister timed out for register %s",
reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
"REG_INVALID"));
return STATUS_IO_TIMEOUT;
}
//
// Clear invalid flag
//
m_stAC97Registers[reg].wCache = *wData;
m_stAC97Registers[reg].wFlags &= ~SHREG_INVALID;
DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (HW)",
reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
"REG_INVALID", *wData));
}
else
{
//
// Otherwise, use the value in the cache.
//
*wData = m_stAC97Registers[reg].wCache;
DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (C)",
reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
"REG_INVALID", *wData));
}
return STATUS_SUCCESS;
}
/*****************************************************************************
* CAdapterCommon::WriteCodecRegister
*****************************************************************************
* Writes to a AC97 register. This can only be done at passive level because
* the AcquireCodecSemiphore call could fail!
*/
STDMETHODIMP_(NTSTATUS) CAdapterCommon::WriteCodecRegister
(
IN AC97Register reg,
IN WORD wData,
IN WORD wMask
)
{
PAGED_CODE ();
ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
WORD TempData = 0;
NTSTATUS ntStatus = STATUS_SUCCESS;
DOUT (DBG_PRINT, ("[CAdapterCommon::WriteCodecRegister]"));
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -