📄 common.cpp
字号:
WriteCodecRegister (AC97REG_POWERDOWN, 0x0700, -1);
break;
case PowerDeviceD2:
case PowerDeviceD3:
//
// This is a full hibernation state and is the longest latency sleep
// state. In this modes the power could be removed or reduced that
// much that the AC97 controller looses information, so we save
// whatever we have to save.
//
//
// Powerdown ADC, DAC, Mixer, Vref, HP amp, and Exernal Amp but not
// AC-link and Clk
//
WriteCodecRegister (AC97REG_POWERDOWN, 0xCF00, -1);
//
// Only in D3 mode we set the AD3 bit and evtl. shut off the AC link.
//
if (NewState.DeviceState == PowerDeviceD3)
{
//
// Set the AD3 bit.
//
ULONG ulReg = ReadBMControlRegister32 (GLOB_STA);
WriteBMControlRegister (GLOB_STA, ulReg | GLOB_STA_AD3);
//
// We check if the modem is sleeping. If it is, we can shut off the
// AC link also. We shut off the AC link also if the modem is not
// there.
//
if ((ulReg & GLOB_STA_MD3) || !(ulReg & GLOB_STA_SCR))
{
// Set Codec to super sleep
WriteCodecRegister (AC97REG_POWERDOWN, 0xFF00, -1);
// Disable the AC-link signals
ulReg = ReadBMControlRegister32 (GLOB_CNT);
WriteBMControlRegister (GLOB_CNT, (ulReg | GLOB_CNT_ACLOFF) & ~GLOB_CNT_COLD);
}
}
break;
}
//
// Save the new state. This local value is used to determine when to
// cache property accesses and when to permit the driver from accessing
// the hardware.
//
m_PowerState = NewState.DeviceState;
DOUT (DBG_POWER, ("Entering D%d", (ULONG)m_PowerState -
(ULONG)PowerDeviceD0));
}
/*****************************************************************************
* CAdapterCommon::QueryPowerChangeState
*****************************************************************************
* Query to see if the device can change to this power state
*/
STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryPowerChangeState
(
IN POWER_STATE NewState
)
{
PAGED_CODE ();
DOUT (DBG_PRINT, ("[CAdapterCommon::QueryPowerChangeState]"));
// Check here to see of a legitimate state is being requested
// based on the device state and fail the call if the device/driver
// cannot support the change requested. Otherwise, return STATUS_SUCCESS.
// Note: A QueryPowerChangeState() call is not guaranteed to always preceed
// a PowerChangeState() call.
// check the new state being requested
switch (NewState.DeviceState)
{
case PowerDeviceD0:
case PowerDeviceD1:
case PowerDeviceD2:
case PowerDeviceD3:
return STATUS_SUCCESS;
default:
DOUT (DBG_ERROR, ("Unknown device state: D%d.",
(ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
return STATUS_NOT_IMPLEMENTED;
}
}
/*****************************************************************************
* CAdapterCommon::QueryDeviceCapabilities
*****************************************************************************
* Called at startup to get the caps for the device. This structure provides
* the system with the mappings between system power state and device power
* state. This typically will not need modification by the driver.
* If the driver modifies these mappings then the driver is not allowed to
* change the mapping to a weaker power state (e.g. from S1->D3 to S1->D1).
*
*/
STDMETHODIMP_(NTSTATUS) CAdapterCommon::QueryDeviceCapabilities
(
IN PDEVICE_CAPABILITIES PowerDeviceCaps
)
{
PAGED_CODE ();
DOUT (DBG_PRINT, ("[CAdapterCommon::QueryDeviceCapabilities]"));
return STATUS_SUCCESS;
}
/*****************************************************************************
* CAdapterCommon::RestoreAC97Registers
*****************************************************************************
* Preset the AC97 registers with default values. The routine first checks if
* There are registry entries for the default values. If not, we have hard
* coded values too ;)
*/
NTSTATUS CAdapterCommon::SetAC97Default (void)
{
PAGED_CODE ();
PREGISTRYKEY DriverKey;
PREGISTRYKEY SettingsKey;
UNICODE_STRING sKeyName;
ULONG ulDisposition;
ULONG ulResultLength;
PVOID KeyInfo = NULL;
DOUT (DBG_PRINT, ("[CAdapterCommon::SetAC97Default]"));
// open the driver registry key
NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
NULL, // OuterUnknown
DriverRegistryKey, // Registry key type
KEY_READ, // Access flags
m_pDeviceObject, // Device object
NULL, // Subdevice
NULL, // ObjectAttributes
0, // Create options
NULL); // Disposition
if (NT_SUCCESS (ntStatus))
{
// make a unicode string for the subkey name
RtlInitUnicodeString (&sKeyName, L"Settings");
// open the settings subkey
ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
NULL, // OuterUnknown
KEY_READ, // Access flags
&sKeyName, // Subkey name
REG_OPTION_NON_VOLATILE, // Create options
&ulDisposition);
if (NT_SUCCESS (ntStatus))
{
// allocate data to hold key info
KeyInfo = ExAllocatePool (PagedPool,
sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
sizeof(WORD));
if (NULL != KeyInfo)
{
// loop through all mixer settings
for (AC97Register i = AC97REG_RESET; i <= AC97REG_RESERVED2;
i = (AC97Register)(i + 1))
{
if (m_stAC97Registers[i].wFlags & SHREG_INIT)
{
// init key name
RtlInitUnicodeString (&sKeyName,
m_stAC97Registers[i].sRegistryName);
// query the value key
ntStatus = SettingsKey->QueryValueKey (&sKeyName,
KeyValuePartialInformation,
KeyInfo,
sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
sizeof(WORD),
&ulResultLength);
if (NT_SUCCESS (ntStatus))
{
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
(PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
if (PartialInfo->DataLength == sizeof(WORD))
{
// set mixer register to registry value
WriteCodecRegister
(i, *(PWORD)PartialInfo->Data, -1);
}
else // write the hard coded default
{
// if key access failed, set to default
WriteCodecRegister
(i, m_stAC97Registers[i].wWantedDefault, -1);
}
}
else // write the hard coded default
{
// if key access failed, set to default
WriteCodecRegister
(i, m_stAC97Registers[i].wWantedDefault, -1);
}
}
}
// we want to return status success even if the last QueryValueKey
// failed.
ntStatus = STATUS_SUCCESS;
// free the key info
ExFreePool (KeyInfo);
}
// release the settings key
SettingsKey->Release ();
}
// release the driver key
DriverKey->Release ();
}
// in case we did not query the registry (cause of lack of resources)
// restore default values and return insufficient resources.
if (!NT_SUCCESS (ntStatus) || !KeyInfo)
{
// copy hard coded default settings
for (AC97Register i = AC97REG_RESET; i < AC97REG_RESERVED2;
i = (AC97Register)(i + 1))
{
if (m_stAC97Registers[i].wFlags & SHREG_INIT)
{
WriteCodecRegister (i, m_stAC97Registers[i].wWantedDefault, -1);
}
}
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
/*****************************************************************************
* CAdapterCommon::DisableAC97Pin
*****************************************************************************
* Returns TRUE when the HW vendor wants to disable the pin. A disabled pin is
* not shown to the user (means it is not included in the topology). The
* reason for doing this could be that some of the input lines like Aux or
* Video are not available to the user (to plug in something) but the codec
* can handle those lines.
*/
BOOL CAdapterCommon::DisableAC97Pin
(
IN TopoPinConfig pin
)
{
PAGED_CODE ();
PREGISTRYKEY DriverKey;
PREGISTRYKEY SettingsKey;
UNICODE_STRING sKeyName;
ULONG ulDisposition;
ULONG ulResultLength;
PVOID KeyInfo = NULL;
BOOL bDisable = FALSE;
DOUT (DBG_PRINT, ("[CAdapterCommon::DisableAC97Pin]"));
// open the driver registry key
NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
NULL, // OuterUnknown
DriverRegistryKey, // Registry key type
KEY_READ, // Access flags
m_pDeviceObject, // Device object
NULL, // Subdevice
NULL, // ObjectAttributes
0, // Create options
NULL); // Disposition
if (NT_SUCCESS (ntStatus))
{
// make a unicode string for the subkey name
RtlInitUnicodeString (&sKeyName, L"Settings");
// open the settings subkey
ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
NULL, // OuterUnknown
KEY_READ, // Access flags
&sKeyName, // Subkey name
REG_OPTION_NON_VOLATILE, // Create options
&ulDisposition);
if (NT_SUCCESS (ntStatus))
{
// allocate data to hold key info
KeyInfo = ExAllocatePool (PagedPool,
sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
sizeof(BYTE));
if (NULL != KeyInfo)
{
// init key name
RtlInitUnicodeString (&sKeyName, m_stHardwareConfig.
Pins[pin].sRegistryName);
// query the value key
ntStatus = SettingsKey->QueryValueKey (&sKeyName,
KeyValuePartialInformation,
KeyInfo,
sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
sizeof(BYTE),
&ulResultLength );
if (NT_SUCCESS (ntStatus))
{
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
(PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
if (PartialInfo->DataLength == sizeof(BYTE))
{
// store the value
if (*(PBYTE)PartialInfo->Data)
bDisable = TRUE;
else
bDisable = FALSE;
}
}
// free the key info
ExFreePool (KeyInfo);
}
// release the settings key
SettingsKey->Release ();
}
// release the driver key
DriverKey->Release ();
}
// if one of the stuff above fails we return the default, which is FALSE.
return bDisable;
}
/*****************************************************************************
* CAdapterCommon::RestoreCodecRegisters
*****************************************************************************
* write back cached mixer values to codec registers
*/
NTSTATUS CAdapterCommon::RestoreCodecRegisters (void)
{
PAGED_CODE ();
DOUT (DBG_PRINT, ("[CAdapterCommon::RestoreCodecRegisters]"));
//
// Initialize the AC97 codec.
//
NTSTATUS ntStatus = InitAC97 ();
if (!NT_SUCCESS (ntStatus))
return ntStatus;
//
// Restore all codec registers. Failure is not critical.
//
for (AC97Register i = AC97REG_MASTER_VOLUME; i < AC97REG_RESERVED2;
i = (AC97Register)(i + 1))
{
WriteCodecRegister (i, m_stAC97Registers[i].wCache, -1);
}
return STATUS_SUCCESS;
}
/*****************************************************************************
* CAdapterCommon::ReadChannelConfigDefault
*****************************************************************************
* This function reads the default channel config from the registry. The
* registry entry "ChannelConfig" is set every every time we get a
* KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
* In case the key doesn't exist we assume a channel config of stereo speakers,
* cause that is the default of DSOUND.
*/
STDMETHODIMP_(void) CAdapterCommon::ReadChannelConfigDefault
(
PDWORD pdwChannelConfig,
PWORD pwChannels
)
{
PAG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -