📄 codec.c
字号:
ErrNum = AC97_PCM_OUT_VOLUME;
if (!AAC_WriteCODECIndexRegister (AacRegPtr, AC97_PCM_OUT_VOLUME, 0x0808)) {;
goto ErrorReturn;
}
//******************************************************************************
//* If no errors were found, exit gracefully.
//* Else, we've jumped to ErrorReturn:
//* Post a message and exit with a failure code.
//*
//******************************************************************************
DEBUGMSG(1, (TEXT("CodecInitializeRegisters: Success\r\n")));
return TRUE;
ErrorReturn:
DEBUGMSG(1, (TEXT("CodecInitializeRegisters: failed (0x%x)\r\n"), ErrNum));
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecInitialize
//
// Description:
// Initializes the codec.
//
// Parameters:
// None described
//
// Return Value:
// TRUE - Successful initialization.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN CodecInitialize(IN OUT PWAVE_DEVICE_INSTANCE WaveInstance)
{
BOOLEAN RoutineSuccess = FALSE;
BOOLEAN Success;
PCODEC_DEVICE NewDevice;
NewDevice = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(*NewDevice));
if(NewDevice == NULL)
{
DEBUGMSG(1, (TEXT("CodecInitialize: Failed to allocate codec structure\r\n")));
goto ErrorReturn;
}
NewDevice->AacRegPtr = WaveInstance->AacRegPtr;
Success = CodecInitializeRegisters(NewDevice);
if(Success == FALSE)
{
DEBUGMSG(1, ( TEXT("CodecInitialize: Failed to initialize registers\r\n")));
goto ErrorReturn;
}
DEBUGMSG(1, (TEXT("CodecInitialize: Success\r\n")));
RoutineSuccess = TRUE;
ErrorReturn:
WaveInstance->CodecDevice = NewDevice;
if(RoutineSuccess == FALSE)
{
CodecDeinitialize(WaveInstance);
}
return RoutineSuccess;
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecGetVolume
//
// Description:
// Return the current volume setting.
//
// Parameters:
// None described
//
// Return Value:
// ULONG - Current volume setting.
//
////////////////////////////////////////////////////////////////////////////////
ULONG CodecGetVolume(IN PCODEC_DEVICE CodecDevice)
{
return CodecDevice->Volume;
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: CodecSetVolume
//
// Description:
// Set a new volume setting.
//
// Parameters:
// Volume - New volume level desired.
//
// Return Value:
// TRUE - Successful volume setting.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN CodecSetVolume(IN OUT PCODEC_DEVICE CodecDevice, IN ULONG Volume)
{
APB_AAC_REGS* AacRegPtr;
ULONG Attenuation1;
ULONG Attenuation2;
ULONG tmp;
// int loop;
//******************************************************************************
//* Volume comes in from CE as one of 6 levels:
//* 0xFFFFFFFF - Max volume
//* 0xCCCCCCCC
//* 0x99999999
//* 0x66666666
//* 0x33333333
//* 0x00000000 - Min volume
//*
//******************************************************************************
AacRegPtr = CodecDevice->AacRegPtr;
CodecDevice->Volume = Volume;
Attenuation1 = (ULONG) ((MAX_VOLUME - (Volume & 0xFFFF)) & 0xF);
Attenuation2 = Attenuation1;
if(Attenuation2 >= 8)
{
Attenuation1 |= 0x10;
}
tmp = (Attenuation1 << 8) | Attenuation1;
DEBUGMSG(1, (TEXT("CodecSetVolume: Volume=0x%X Attenuation=0x%X (0x%X)\r\n"), Volume, tmp, Attenuation1));
AAC_WriteCODECIndexRegister(AacRegPtr, AC97_MASTER_VOLUME, tmp);
//*TSAT* 02-Jan-2003
// Cirrus CS4201 Data Sheet (CS4201_AudioCodec.pdf), Pg. 23.
// - Analog Mixer Output Volume Registers (Index 02h - 04h)
// - "If the HPCFG pin is tied 'low', register 02h controls the Headphone Volume and register 04h is a read-only register and
// always returns 0000h when 'read'."
// - On Aruba, HPCFG is tied to ground.
// AAC_WriteCODECIndexRegister (AacRegPtr, AC97_ALT_LINE_LEVEL_OUT_VOLUME, tmp);
return TRUE;
}
//******************************************************************************
//* POWER MANAGEMENT ROUTINES BELOW HERE.
//* THESE ROUTINES HAVE NOT BEEN ADAPTED FOR THE ARUBA PLATFORM. 02-Jan-2003
//*
//******************************************************************************
////////////////////////////////////////////////////////////////////////////////
//
// Name: Delay
//
// Description:
// Delay during STANDBY.
//
// Parameters:
// None
//
// Return Value:
// None
//
////////////////////////////////////////////////////////////////////////////////
void Delay()
{
PHYSICAL_ADDRESS PhysAddr;
ULONG TmpVal;
ULONG StartVal;
//******************************************************************************
//* This delay routine is used when the system is in STANDBY mode and all
//* the timer clocks are stopped at this point except the 1s RTC.
//* But the 1s resolution is too long for the delay and it will affect the
//* performance when the system goes from RUN to STANDBY and reverse. So
//* we have to implement the software loop for the delay. As result, the
//* constant value used here may need to adjust if the CPU speed changes.
//*
//******************************************************************************
if(RTCRegPtr == NULL) {
PhysAddr.QuadPart = APB_RTC_REGS_BASE;
RTCRegPtr = MmMapIoSpace(PhysAddr, sizeof(APB_RTC_REGS), FALSE);
if(RTCRegPtr == NULL) {
DEBUGMSG(1, (TEXT("CODEC.C:Delay: Unable to map RTC registers\r\n")));
return;
}
}
#if 1
//******************************************************************************
//* Do dummy read for the delay loop
//*
//******************************************************************************
for (TmpVal = 0; TmpVal < DELAY_VAL; TmpVal++) {
StartVal = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
StartVal++;
StartVal = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
}
#else
//******************************************************************************
//* Use the RTC
//*
//******************************************************************************
StartVal = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
TmpVal = StartVal;
StartVal += 1;
while(TmpVal <= StartVal) {
TmpVal = READ_REGISTER_ULONG(&RTCRegPtr->RTCDR);
}
#endif
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: AAC_Slot1Wait_Pmgt
// AAC_Slot2Wait_Pmgt
//
// Description:
// Wait for indicator bit to be set in AAC status register.
//
// Parameters:
// aacRegPtr - Pointer to AAC controller within the SOC.
//
// Return Value:
// TRUE - Success if bit was set by the AAC controller
//
////////////////////////////////////////////////////////////////////////////////
// Function to wait for the transmit on Slot 1
// to happen correctly.
// This prevents us from overwriting data while
// waiting to transmit
BOOLEAN AAC_Slot1Wait_Pmgt (APB_AAC_REGS* aacRegPtr)
{
int timeoutcounter;
volatile ULONG * pAACRGIS = &(aacRegPtr->AACRGIS);
Delay(); // Slowdown this routine because of HW bugs
timeoutcounter = 100;
while (!((*pAACRGIS) & AAC_RGIS_SLOT1TXCOMPLETE))
{
timeoutcounter--;
if (timeoutcounter == 0)
{
return FALSE;
}
}
return TRUE;
}
// Function to wait for the data requested from
// the AC97 to get into Slot 2
BOOLEAN AAC_Slot2Wait_Pmgt (APB_AAC_REGS* aacRegPtr)
{
int timeoutcounter;
volatile ULONG * pAACRGIS = &(aacRegPtr->AACRGIS);
Delay(); // Slowdown this routine because of HW bugs
timeoutcounter = 100;
while (!((*pAACRGIS) & AAC_RGIS_SLOT2RXVALID))
{
timeoutcounter--;
if (timeoutcounter == 0)
{
return FALSE;
}
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: AC97Write_Pmgt
//
// Description:
// Write data through the AAC controller to the codec.
//
// Parameters:
// aacRegPtr - Pointer to AAC controller within the SOC.
// AC97Reg - Index of codec register being written.
// AC97Data - Data to be loaded into the codec register.
//
// Return Value:
// TRUE - Success if register was written correctly.
//
////////////////////////////////////////////////////////////////////////////////
BOOLEAN AC97Write_Pmgt (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG AC97Data)
{
ULONG JNK, JNK2;
volatile ULONG * pAACS1DATA = &(aacRegPtr->AACS1DATA);
volatile ULONG * pAACS2DATA = &(aacRegPtr->AACS2DATA);
Delay(); // Slowdown this routine because of HW bugs
DEBUGMSG(1,(TEXT("AC97Write - aacRegPtr=0x%x, AC97Reg=0x%x, AC97Data=0x%x\r\n"),
(DWORD)aacRegPtr,AC97Reg,AC97Data));
*pAACS2DATA = AC97Data;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot1Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot1Wait\r\n")));
return FALSE;
}
if ((AAC_Slot2Wait_Pmgt(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot2Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait_Pmgt(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 3rd Slot1Wait\r\n")));
return FALSE;
}
if ((AAC_Slot2Wait_Pmgt(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot2Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
JNK2 = *pAACS1DATA;
if ((AC97Reg == 0) || // don't check data echo for reset cmd
(JNK == AC97Data)) // for other cmd's echo should equal data sent
{
return TRUE;
}
else
{
DEBUGMSG(1,(TEXT("AC97Write, failure on data echo: 0x%x != 0x%x\r\n"),JNK,AC97Data));
return FALSE;
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Name: AAC_WriteCODECIndexRegister_Pmgt
//
// Description:
// Pass-through routine.
//
// Parameters:
// aacRegPtr - Pointer to AAC controller within the SOC.
// AC97Reg - Index of codec register being written.
// Value - Data to be loaded into the codec register.
//
// Return Value:
// TRUE - Success if register was written correctly.
//
////////////////////////////////////////////////////////////////////////////////
// AAC_WriteCODECIndexRegister
BOOLEAN AAC_WriteCODECIndexRegister_Pmgt (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG Value)
{
return AC97Write_Pmgt (aacRegPtr, AC97Reg, Value);
}
//******************************************************************************
//* ORIGINAL CODEC ROUTINES.
//* OBSOLETE AS OF 31-DEC-2002
//*
//******************************************************************************
//*TSAT* 31-Dec-2002
#ifdef THE_ORIGINAL_CODEC_AC97WRITE_ROUTINE
// AC97 Write
BOOLEAN AC97Write (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg, ULONG AC97Data)
{
ULONG JNK, JNK2;
volatile ULONG * pAACS1DATA = &(aacRegPtr->AACS1DATA);
volatile ULONG * pAACS2DATA = &(aacRegPtr->AACS2DATA);
DEBUGMSG(1,(TEXT("AC97Write - aacRegPtr=0x%x, AC97Reg=0x%x, AC97Data=0x%x\r\n"),
(DWORD)aacRegPtr,AC97Reg,AC97Data));
*pAACS2DATA = AC97Data;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot1Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot1Wait\r\n")));
return FALSE;
}
if ((AAC_Slot2Wait(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 1st Slot2Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
if ((AAC_Slot1Wait(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 3rd Slot1Wait\r\n")));
return FALSE;
}
if ((AAC_Slot2Wait(aacRegPtr)) == FALSE)
{
DEBUGMSG(1,(TEXT("AC97Write, failure on 2nd Slot2Wait\r\n")));
return FALSE;
}
JNK = *pAACS2DATA;
JNK2 = *pAACS1DATA;
if ((AC97Reg == 0) || // don't check data echo for reset cmd
(JNK == AC97Data)) // for other cmd's echo should equal data sent
{
return TRUE;
}
else
{
DEBUGMSG(1,(TEXT("AC97Write, failure on data echo: 0x%x != 0x%x\r\n"),JNK,AC97Data));
return FALSE;
}
}
#endif //the_original_codec_ac97write_routine
//*TSAT* 31-Dec-2002
#ifdef THE_ORIGINAL_CODEC_AC97READ_ROUTINE
// AC97 Read
ULONG AC97Read (APB_AAC_REGS* aacRegPtr, ULONG AC97Reg)
{
ULONG Data, JNK2;
volatile ULONG * pAACS1DATA = &(aacRegPtr->AACS1DATA);
volatile ULONG * pAACS2DATA = &(aacRegPtr->AACS2DATA);
*pAACS2DATA = 0x5555;
Data = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
AAC_Slot1Wait(aacRegPtr);
AAC_Slot2Wait(aacRegPtr);
Data = *pAACS2DATA;
*pAACS1DATA = AC97Reg;
AAC_Slot1Wait(aacRegPtr);
AAC_Slot2Wait(aacRegPtr);
Data = *pAACS2DATA;
JNK2 = *pAACS1DATA;
return Data;
}
#endif //the_original_codec_ac97read_routine
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -