📄 wavepdd.c
字号:
/*++
Copyright (c) 2001-2005 BSQUARE Corporation. All rights reserved.
Module Name:
wavepdd.c
Module Description:
This module contains the pdd code of AC97 audio driver
Author:
Jun Li, July 2001
Revision History:
--*/
#include <windows.h>
#include <bceddk.h>
#include <wavedbg.h>
#include "ac97.h"
#include "au1kac97.h"
#include "ac97aud.h"
#define DIR_STR(x) \
(((x) == WAPI_IN) ? TEXT("WAPI_IN") : TEXT("WAPI_OUT"))
extern HANDLE hAudioInterrupt;
//static
PWAVE_DEVICE_INSTANCE WaveDevice = NULL;
PWAVE_RESOURCE WaveInResource = NULL;
PWAVE_RESOURCE WaveOutResource = NULL;
static
MMRESULT
WaveGetDeviceCapabilities(
IN WAPI_INOUT ApiDirection,
OUT PVOID DeviceCapabilities,
IN UINT Size
)
/*++
Routine Description:
Called to determine audio device capabilities.
Arguments:
ApiDirection - Audio direction (input or output).
DeviceCapabilites - Pointer to device capabilities structure or NULL.
Size - Size of device capabilities structure.
Return Value:
Returns the appropriate MMSYSERR condition code.
--*/
{
MMRESULT ReturnValue;
PWAVEINCAPS InputCapabilities;
PWAVEOUTCAPS OutputCapabilities;
DEBUGMSG(ZONE_PDD, (TEXT("+Audio WaveGetDeviceCapabilities.\r\n")));
ReturnValue = MMSYSERR_NOTSUPPORTED;
InputCapabilities = DeviceCapabilities;
OutputCapabilities = DeviceCapabilities;
//
// If DeviceCapabilities is NULL, we are asking if the driver PDD is
// capable of this mode at all. In other words, if the API direction is
// input, we return no MMSYSERR_NOERROR if input is supported, and
// MMSYSERR_NOTSUPPORTED otherwise.
//
if (DeviceCapabilities == NULL) {
ReturnValue = MMSYSERR_NOERROR;
goto ErrorReturn;
}
//
// Fill in the device capabilities structure here. Note that the input
// and output capabilities structure is identical except for the the
// dwSupport field which is present in the output structure but absent in
// the input structure.
//
if (ApiDirection == WAPI_OUT) {
OutputCapabilities->wMid = MM_MICROSOFT;
OutputCapabilities->wPid = MM_MSFT_GENERIC_WAVEOUT;
OutputCapabilities->vDriverVersion = MAKEWORD(0, 1); // v1.0
_stprintf(OutputCapabilities->szPname,
TEXT("BSQUARE: Au1000 AC97"));
//
// 11.025 kHz, 22.05 kHz, 44.1 kHz, mono and stereo, 8-bit and
// 16-bit, all combinations thereof.
//
// Note that 8 kHz is also supported, but not listed here.
//
// NOTE: Early Au1000 did not support variable sample rate audio, rather
// NOTE: audio had to be fixed at 48kHz. This driver does not support
// NOTE: early Au1000 anymore, but if it is needed, then only the 44.1khz
// NOTE: capabilities should be returned to the MDD, and the calls to
// NOTE: CodecSetSampleRate() and CodecSetADCSampleRate() should be
// NOTE: fixed to 48khz instead. This has the side effect of playing
// NOTE: sound faster than it should, but at least it plays...
OutputCapabilities->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |
WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |
WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |
WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16;
OutputCapabilities->wChannels = 2;
OutputCapabilities->dwSupport = WAVECAPS_VOLUME;
}
else {
InputCapabilities->wMid = MM_MICROSOFT;
InputCapabilities->wPid = MM_MSFT_GENERIC_WAVEIN;
InputCapabilities->vDriverVersion = MAKEWORD(0, 1); // v1.0
_stprintf(InputCapabilities->szPname,
TEXT("BSQUARE: Au1000 AC97"));
//
// 11.025 kHz, 22.05 kHz, 44.1 kHz, Monoaural and Stereo, 8-bit and
// 16-bit, all combinations thereof.
//
InputCapabilities->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |
WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |
WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
WAVE_FORMAT_4M08 | WAVE_FORMAT_4M16 |
WAVE_FORMAT_4S08 | WAVE_FORMAT_4S16;
InputCapabilities->wChannels = 2;
}
ReturnValue = MMSYSERR_NOERROR;
ErrorReturn:
DEBUGMSG(ZONE_PDD, (TEXT("-Audio WaveGetDeviceCapabilities.\r\n")));
return ReturnValue;
}
static
MMRESULT
WaveOpen(
IN LPWAVEFORMATEX WaveFormat,
IN BOOL QueryFormatOnly,
IN OUT PWAVE_RESOURCE WaveResource
)
/*++
Routine Description:
Opens the specified stream or returns information about valid stream
formats.
Arguments:
WaveFormat - Pointer to stream format description.
QueryFormatOnly - Flag for querying device only.
WaveResource - Pointer to the wave stream resource structure to update.
Return Value:
Returns the appropriate MMSYSERR condition code.
--*/
{
MMRESULT ReturnValue;
LONG OldValue;
DEBUGMSG(ZONE_PDD, (TEXT("+Audio WaveOpen.\r\n")));
ReturnValue = MMSYSERR_ERROR;
//
// Verify that a valid stream is being opened by checking the format
// parameters. If any of the parameters indicate an unsupported stream
// type, return an error.
//
//
// Wave stream format. Only PCM is supported.
//
if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveOpen: WAVE_FORMAT_PCM is supported.\r\n")));
ReturnValue = WAVERR_BADFORMAT;
goto ErrorReturn;
}
//
// Number of channels. Only 1 (mono) or 2 (stereo) are supported.
//
if (WaveFormat->nChannels != 1 &&
WaveFormat->nChannels != 2) {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveOpen: 1 or 2 channels is supported.\r\n")));
ReturnValue = WAVERR_BADFORMAT;
goto ErrorReturn;
}
//
// Sampling frequency. Only 8000, 11025, 22050, and 44100 Hz sample
// rates are supported. Note that the 8000 Hz rate is not listed as a
// supported sample rate in WaveGetDeviceCapabilities because there are
// no defines for that sample rate. Nevertheless, 8 khz is a popular
// sampling rate and is thus supported.
//
if (WaveFormat->nSamplesPerSec != 8000 &&
WaveFormat->nSamplesPerSec != 11025 &&
WaveFormat->nSamplesPerSec != 22050 &&
WaveFormat->nSamplesPerSec != 44100 &&
WaveFormat->nSamplesPerSec != 48000) {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveOpen: 8.0 kHz, 11.025, 22.05, 44.1 and 48 kHz are")
TEXT(" supported.\r\n")));
ReturnValue = WAVERR_BADFORMAT;
goto ErrorReturn;
}
//
// Number of bits per sample. Only 8-bit (signed) and 16-bit (unsigned)
// are supported.
//
if (WaveFormat->wBitsPerSample != 8 &&
WaveFormat->wBitsPerSample != 16) {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveOpen: 8 or 16 bit samples are supported.\r\n")));
ReturnValue = WAVERR_BADFORMAT;
goto ErrorReturn;
}
//
// Check if this routine is being called to just query for support of a
// particular format. If it is, we're done. The format is supported.
//
if (QueryFormatOnly == TRUE) {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveOpen: QueryFormatOnly.\r\n")));
ReturnValue = MMSYSERR_NOERROR;
goto ErrorReturn;
}
//
// Attempt to allocate the stream. If we fail, it's currently in use, and
// an error is returned saying that the stream is allocated. The
// interlocked test exchange guarantees that only one thread opens the
// wave device, regardless if the MDD performs any locking.
//
OldValue = InterlockedTestExchange(&WaveResource->InUse,
FALSE,
TRUE);
if (OldValue == TRUE) {
ReturnValue = MMSYSERR_ALLOCATED;
goto ErrorReturn;
}
// Update the resource structure with the new format.
//
memcpy(&WaveResource->WaveFormat,
WaveFormat,
sizeof(*WaveFormat));
// Ensure channel not muted
//
CodecClrMasterMute(WaveDevice->AC97Ctrl);
// Find a mic volume
//
WaveDevice->MicVolume = FindMicVolume(WaveDevice);
// Set Mic Volume
//
AC97WriteReg(WaveDevice->AC97Ctrl,AC97_MIC_VOLUME,WaveDevice->MicVolume);
#ifdef PLATFORM_MIRAGE
if (!CodecSetSampleRate(WaveDevice->AC97Ctrl, WaveFormat->nSamplesPerSec) )
DEBUGMSG(ZONE_PDD, (TEXT("-Audio Could not set sample rate\r\n")));
#else
if (WaveResource->WaveDirection==WAPI_OUT && !CodecSetSampleRate(WaveDevice->AC97Ctrl, WaveFormat->nSamplesPerSec) ) {
DEBUGMSG(ZONE_PDD, (TEXT("-Audio Could not set DAC sample rate\r\n")));
} else if (WaveResource->WaveDirection==WAPI_IN && !CodecSetADCSampleRate(WaveDevice->AC97Ctrl, WaveFormat->nSamplesPerSec) ) {
DEBUGMSG(ZONE_PDD, (TEXT("-Audio Could not set ADC sample rate\r\n")));
}
#endif
ReturnValue = MMSYSERR_NOERROR;
ErrorReturn:
DEBUGMSG(ZONE_PDD, (TEXT("-Audio WaveOpen.\r\n")));
return ReturnValue;
}
static
MMRESULT
WaveClose(
IN OUT PWAVE_RESOURCE WaveResource
)
/*++
Routine Description:
Closes a wave stream. This routine is dispatched by PDD_WaveProc. It is
expected that for every call to WaveOpen that succeeds, there will be one
and only one call to this routine.
Arguments:
WaveResource - Pointer to the wave resources structure corresponding to
the stream to be closed.
Return Value:
Returns an MMRESULT. MMSYSERR_NOERROR is returned on success.
--*/
{
MMRESULT ReturnValue;
ReturnValue = MMSYSERR_ERROR;
DEBUGMSG(ZONE_PDD, (TEXT("+Audio WaveClose.\r\n")));
//
// Verify that the resource was allocated and deallocate it by marking it
// as unused.
//
if (WaveResource->InUse == TRUE) {
WaveResource->MoreData = FALSE;
WaveResource->InUse = FALSE;
}
else {
DEBUGMSG(ZONE_PDD, (
TEXT(" WaveClose: Tried to close unallocated stream.\r\n")));
goto ErrorReturn;
}
//
// Mute channel
//
CodecClrMasterMute(WaveDevice->AC97Ctrl);
ReturnValue = MMSYSERR_NOERROR;
ErrorReturn:
DEBUGMSG(ZONE_PDD, (TEXT("-Audio WaveClose.\r\n")));
return ReturnValue;
}
static
VOID
WaveStandby(
IN OUT PWAVE_RESOURCE WaveResource
)
/*++
Routine Description:
Powers down the devices associated with the specified direction. This is
dispatched by PDD_WaveProc. The MDD will call into PDD_WaveProc to have
this routine run when either of the AUDIO_STATE_OUT_STOPPED or
AUDIO_STATE_IN_STOPPED flags are returned.
Arguments:
WaveResource - Pointer to the wave resouces structure corresponding to the
wave stream that is to be placed in standby.
Return Value:
None.
--*/
{
DEBUGMSG(ZONE_PDD, (TEXT("+Audio WaveStandby.\r\n")));
ShutdownDma(WaveResource);
DEBUGMSG(ZONE_PDD, (TEXT("-Audio WaveStandby.\r\n")));
}
DWORD
PDD_AudioMessage(
UINT Message,
ULONG Param1,
ULONG Param2
)
{
DEBUGMSG(ZONE_PDD, (TEXT("+Audio PDD_AudioMessage\r\n")));
switch (Message)
{
case IOCTL_POWER_CAPABILITIES:
//
// Support all states except for D3
//
((PPOWER_CAPABILITIES)Param1)->DeviceDx = 0x17;
WaveDevice->CurrentPowerState = D0;
break;
case IOCTL_POWER_GET:
*((PCEDEVICE_POWER_STATE)Param1) = WaveDevice->CurrentPowerState;
break;
case IOCTL_POWER_SET:
switch (Param1)
{
//
// Shut down DMA for a full power off (D4) and then shut down
// the codec for both power off and standby (D4 & D2)
//
case D4:
ShutdownDma(WaveInResource);
ShutdownDma(WaveOutResource);
WaveInResource->DmaRunning = FALSE;
WaveOutResource->DmaRunning = FALSE;
// Stop the Rx/Tx Controllers.
WRITE_REGISTER_ULONG((PULONG)&WaveDevice->AC97Ctrl->pcr,
(PSC_AC97_PCR_RP | PSC_AC97_PCR_TP));
case D2:
// Power down the amplifier if your platform has one
#ifdef PLATFORM_AMPLIFIER_POWERDOWN
PLATFORM_AMPLIFIER_POWERDOWN
#endif
if (!CodecPowerDown(WaveDevice->AC97Ctrl))
{
DEBUGMSG(ZONE_PDD,(TEXT("Codec did not power down\r\n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -