📄 audio.c
字号:
/*++
Copyright (c) 2001, 2002 BSQUARE Corporation. All rights reserved.
Module Name:
Audio.c
Module Description:
This module contains the implementation of PDD interface routines for
the platform wave device driver.
Author:
Benny Ng 25-June-2001
Revision History:
Yuqun Cao 16-Jan-2002
1. Add critical section protection in WaveProc(). It is called from
different threads. The MDD layer does not synchronize the access.
Thomas Satagaj 22-Apr-2002
1. Add InitializeAacPower() to cycle codec power.
--*/
#include "bceddk.h"
#include "chip.h"
#include "audio.h"
#include "ac97.h"
//#pragma optimize("", off)
//*TSAT* 27-Dec-2002 Turn on debug messages
//#undef DEBUGMSG
//#define DEBUGMSG(cond, msg) RETAILMSG(1, msg)
#define WORD_ALIGNMENT 4
#define SLEEP_VAL 3
//
// Required global for MDD.
//
ULONG gIntrAudio = SYSINTR_NOP;
static const PHYSICAL_ADDRESS HighestPhysAddr = PHYSICAL_ADDRESS_MAXIMUM;
static PWAVE_DEVICE_INSTANCE WaveDevice = NULL;
static PWAVE_RESOURCE WaveInResource = NULL;
static PWAVE_RESOURCE WaveOutResource = NULL;
PWAVE_DEVICE_INSTANCE
getWaveDevice( VOID )
{
return WaveDevice;
}
//
// Private Routines.
//
static
BOOLEAN
InitializePlatformRegisters(
IN PWAVE_DEVICE_INSTANCE WaveDevice
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
BOOLEAN RoutineSuccess = TRUE;
DEBUGMSG(1, (TEXT("InitializePlatformRegisters:\r\n")));
return RoutineSuccess;
}
static
BOOLEAN
InitializeAacPower(
IN BOOLEAN PwrOn
)
/*++
Routine Description:
This routine is used to modify the write-only I/O Board Control Register.
Only the kernel routine can be used since it maintains the software shadow
register to track the BCR's contents.
What this routine does is turn on/turn off power to the AC97 codec.
Arguments:
PwrOn - TRUE - Set nAC97_PWR_EN = LO to enable codec power.
- FALSE - Set nAC97_PWR_EN = HI to disable codec power.
Return Value:
TRUE if power was set as requested.
--*/
{
BOOL bSuccess; //Status
USHORT_MODIFY usModify; //Struct to pass to the bcr routine.
ULONG ulBytsRet; //Bytes returned.
//*************************************************************************
//* The I/O board has a (74LVC273PW) control latch to control power of
//* various I/O board peripherals (pc card, ethernet, audio, etc.)
//* This latch is loaded with a write only control register through the
//* processor board CPLD.
//* Since this register is write only and is required to control devices
//* that will exist in unknown process spaces, we use the IOCTL mechanism
//* to change and maintain the BCR in a single location.
//*
//* This routine will make the IOCTL call to enable/disable power to the
//* AC97 audio codec.
//*
//* BitMask tells the kernel routine which bit in the BCR will be altered.
//* BitValu tells the kernel routine how to set that bit.
//* 0 = power on.
//* 1 = power off.
//*
//*************************************************************************
if(PwrOn == TRUE)
{
usModify.Value = 0;
}
else
{
usModify.Value = CPLD_W_BDCTL_AC97_EN;
}
usModify.Address = 0;
usModify.Mask = CPLD_W_BDCTL_AC97_EN;
bSuccess = KernelIoControl(IOCTL_HAL_BCR_MODIFY,
&usModify,
sizeof(usModify),
NULL,
0,
&ulBytsRet);
DEBUGMSG((bSuccess == FALSE), (TEXT("InitializeAacPower: Failed BCR modify.\r\n")));
return(bSuccess);
}
static
BOOLEAN
InitializeAacRegisters(
IN PWAVE_DEVICE_INSTANCE WaveDevice
)
/*++
Routine Description:
Initializes the AAC registers.
Arguments:
WaveDevice - Pointer to the wave device configuration structure whose
corresponding AAC registers are to be initialized.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
long timeoutcounter;
ULONG tmp;
DEBUGMSG(1, (TEXT("InitializeAacRegisters:\r\n")));
// InitializeAacPower(FALSE);
// Sleep(500);
// InitializeAacPower(TRUE);
// Sleep(500);
//
// Enable the AAC block
// ***NOTE*** This call drives PH6 HI which releases the codec from reset.
//
WRITE_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACGCR, AAC_GCR_AACIFE);
Sleep(30);
WRITE_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACRESET, 0x3);
Sleep(500);
// WRITE_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACRESET, 0x00);
// Sleep(500);
//
// Wait for the AC97 Codec Ready signal
//
timeoutcounter = 9999999;
while ((READ_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACRGIS) & AAC_RGIS_CODECREADY)==0) {
timeoutcounter--;
// if (timeoutcounter == 0) {
// return FALSE;
// }
} // endwhile
//
// Setup the TX FIFO
//
tmp = (AAC_TXCR_TEN | AAC_TXCR_TX3 | AAC_TXCR_TX4);
#ifndef NOAUDIODMA
//
// DMA uses Compact Mode.
//
tmp |= AAC_TXCR_CM;
#endif
WRITE_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACTXCR1, tmp);
Drv_AHBBus_ExtraWrite();
if (READ_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACTXCR1) != tmp) {
DEBUGMSG(1, (TEXT("InitializeAacRegisters: Initialize AACTXCR1 failed\r\n")));
return FALSE;
}
if ((READ_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACSR1) & AAC_SR_TXFE) != AAC_SR_TXFE) {
DEBUGMSG(1, (TEXT("InitializeAacRegisters: AACSR1 failed\r\n")));
return FALSE;
}
//
// Setup the RX FIFO
//
tmp = (AAC_RXCR_REN | AAC_RXCR_RX3 | AAC_RXCR_RX4);
#ifndef NOAUDIODMA
//
// DMA uses Compact Mode.
//
tmp |= AAC_RXCR_CM;
#endif
WRITE_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACRXCR1, tmp);
if (READ_REGISTER_ULONG(&WaveDevice->AacRegPtr->AACRXCR1) != tmp) {
DEBUGMSG(1, (TEXT("InitializeAacRegisters: Initialize AACRXCR1 failed\r\n")));
return FALSE;
}
DEBUGMSG(1, (TEXT("InitializeAacRegisters: Sucessfull\r\n")));
return TRUE;
}
static
BOOLEAN
InitializeDmaResources(
IN OUT PWAVE_DEVICE_INSTANCE WaveDevice
)
/*++
Routine Description:
Arguments:
WaveDevice - Pointer to the wave device configuration structure for which
DMA resources are to be allocated and initialized.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
BOOLEAN RoutineSuccess;
BOOLEAN Success;
ULONG TotalDmaBufferSize;
PVOID DmaBuffersBase;
PHYSICAL_ADDRESS DmaBuffersPhysAddr;
PMDL DmaBuffersMdl;
DEVICE_DESCRIPTION DeviceDescription;
ULONG NumMapRegisters;
PADAPTER_OBJECT AdapterObject;
PVOID MapRegistersBase;
RoutineSuccess = FALSE;
DEBUGMSG(1, (TEXT("InitializeDmaResources:\r\n")));
//
// Allocate the memory for DMA buffers from the physical memory pool.
// This will guarantee virtually and physically contiguous memory.
//
TotalDmaBufferSize = WaveDevice->DmaBufferSize * 4;
DEBUGMSG(1,(TEXT("TotalDmaBufferSize = %d\r\n"),TotalDmaBufferSize));
DmaBuffersBase = MmAllocatePhysicalMemory(TotalDmaBufferSize,
HighestPhysAddr,
WORD_ALIGNMENT,
&DmaBuffersPhysAddr);
DEBUGMSG(1, (TEXT("InitializeDmaResources: DmaBuffersPhysAddr=0x%x TotalDmaBufferSize=0x%x CurrentProcessID=%X\r\n"),
DmaBuffersPhysAddr.LowPart,
TotalDmaBufferSize,GetCurrentProcessId()));
if (DmaBuffersBase == NULL) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Physical memory allocation failed\r\n")));
goto ErrorReturn;
}
WaveDevice->DmaBuffersBase = DmaBuffersBase;
//
// Create a MDL for the above. This is passed to the HalMapTransfer
// routine. Note that we could just use the physical and virtual
// addresses returned by MmAllocatePhysicalMemory, but that would kind of
// violate the driver model.
//
DmaBuffersMdl = MmCreateMdl(NULL,
DmaBuffersBase,
TotalDmaBufferSize);
if (DmaBuffersMdl == NULL) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Failed to create MDL\r\n")));
goto ErrorReturn;
}
DEBUGMSG(1,(TEXT("MDL Created\r\n")));
WaveDevice->DmaBuffersMdl = DmaBuffersMdl;
//
// Initialize the device description structure's relevant fields.
// Note that most are don't cares and are left uninitialized. With
// the device description, get the adapter.
//
DeviceDescription.DmaChannel = WaveDevice->DmaChannelOutput;
NumMapRegisters = 0;
//
// Get the adapter object for output.
//
AdapterObject = HalGetAdapter(&DeviceDescription, &NumMapRegisters);
if (AdapterObject == NULL) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Failed to get adapter for output\r\n")));
goto ErrorReturn;
}
DEBUGMSG(1,(TEXT("Output Adapter Object Created\r\n")));
WaveDevice->AdapterObjectOutput = AdapterObject;
//
// Allocate the DMA channel for output.
//
Success = HalAllocateAdapterChannel((PDMA_ADAPTER_OBJECT)(AdapterObject),
0,
&MapRegistersBase);
if (Success == FALSE) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Failed to allocate DMA channel for output\r\n")));
goto ErrorReturn;
}
WaveDevice->MapRegsBaseOutput = MapRegistersBase;
DEBUGMSG(1,(TEXT("Output DMA Channel Allocated\r\n")));
//
// Get the adapter object for input.
//
DeviceDescription.DmaChannel = WaveDevice->DmaChannelInput;
NumMapRegisters = 0;
AdapterObject = HalGetAdapter(&DeviceDescription,
&NumMapRegisters);
if (AdapterObject == NULL) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Failed to get adapter for input\r\n")));
goto ErrorReturn;
}
DEBUGMSG(1,(TEXT("Input Adapter Created\r\n")));
WaveDevice->AdapterObjectInput = AdapterObject;
//
// Allocate the DMA channel for input.
//
Success = HalAllocateAdapterChannel((PDMA_ADAPTER_OBJECT)(AdapterObject),
0,
&MapRegistersBase);
if (Success == FALSE) {
DEBUGMSG(1, (TEXT("InitializeDmaResources: Failed to allocate DMA channel for input\r\n")));
goto ErrorReturn;
}
WaveDevice->MapRegsBaseInput = MapRegistersBase;
DEBUGMSG(1, (TEXT("-InitializeDmaResources: success\r\n")));
RoutineSuccess = TRUE;
ErrorReturn:
return RoutineSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -