📄 hwctxt.cpp
字号:
switch(SampleRate)
{
case 8000:
value = XLLP_AC97_U14_DR_8000;
break;
case 11025:
value = XLLP_AC97_U14_DR_11025;
break;
case 16000:
value = XLLP_AC97_U14_DR_16000;
break;
case 22050:
value = XLLP_AC97_U14_DR_22050;
break;
case 32000:
value = XLLP_AC97_U14_DR_32000;
break;
case 44100:
value = XLLP_AC97_U14_DR_44100;
break;
case 48000:
value = XLLP_AC97_U14_DR_48000;
break;
default:
DEBUGCHK(0); //we sent a bad rate
RetVal=FALSE;
return (RetVal);
}
if (apidir == WAPI_IN)
RetVal=SafeWriteAC97((XLLP_UINT16_T)AUDIO_ADC_RATE,value , DEV_AUDIO); //set the input sample rate
else
RetVal=SafeWriteAC97((XLLP_UINT16_T)AUDIO_DAC_RATE,value , DEV_AUDIO); //set the output sample rate
return (RetVal);
}
void HardwareContext::DumpDmacRegs()
{
int i;
DEBUGMSG(ZONE_ERROR, (TEXT( "gsr %x, posr %x, pocr %x, pisr %x, picr %x\r\n" ),
m_pAc97regs->GSR,
m_pAc97regs->POSR,
m_pAc97regs->POCR,
m_pAc97regs->PISR,
m_pAc97regs->PICR
) );
for (i=0; i< 16; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dcsr[%d] %x \r\n" ),i,m_pDMARegisters->dcsr[i] ) );
//skip rsvd section rsvd0[44];
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->dint %x \r\n" ),m_pDMARegisters->dint ) );
//skip rsvd seciton rsvd1[3];
for (i=0; i< 39; i++)
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->drcmr[%d] %x \r\n" ),i,m_pDMARegisters->drcmr[i] ) );
for (i=0; i<16; i++)
{
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].ddadr %x \r\n" ),i,m_pDMARegisters->ddg[i].ddadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dsadr %x \r\n" ),i,m_pDMARegisters->ddg[i].dsadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dtadr %x \r\n" ),i,m_pDMARegisters->ddg[i].dtadr ) );
DEBUGMSG(ZONE_ERROR, (TEXT( "m_pDMARegisters->ddg[%d].dcmd %x \r\n" ),i,m_pDMARegisters->ddg[i].dcmd ) );
}
}
void HardwareContext::InitCodec(void)
{
static DWORD VendorId=0;
unsigned short int VidTemp=0;
unsigned short int Ac97RegisterData=0;
unsigned short int FeatureCrs1Data=0;
DEBUGMSG(ZONE_INIT, (TEXT("HardwareContext::InitCodec\r\n")));
//Get vendor ID to identify chipset first
if(VendorId == 0)
{
SafeReadAC97(VENDOR_ID1, &VidTemp, DEV_AUDIO);
VendorId= (VidTemp <<16); //ffffffffssssssss // f=first ascii s = second ascii
SafeReadAC97(VENDOR_ID2, &VidTemp, DEV_AUDIO);
VendorId |=VidTemp; //ttttttttrrrrrrrr //t = third ascii, r=rev #
VendorId &= 0xfffffff0;//trim of version number
}
//vendor specific
switch (VendorId)
{
case 0x574D4C10: //For Wolfson WM9712L chipset
//
// 1. Configure GPIO pins for AC'97
//
//Pin 4 is output, active low, sticky (/AC97_AMPSD)
//Pin 1 is active low. (For Jack insert detection)
//Set GPIO pin direction
Ac97RegisterData = 0xFFEF;
SafeWriteAC97(AUGPIO_PIN_DIR,Ac97RegisterData, DEV_AUDIO);
//Set GPIO pin polarity
Ac97RegisterData = 0xFFED;
SafeWriteAC97(AUGPIO_PIN_POL,Ac97RegisterData, DEV_AUDIO);
//Set GPIO pins sticky
Ac97RegisterData = 0x10;
SafeWriteAC97(AUGPIO_PIN_STICK,Ac97RegisterData, DEV_AUDIO);
//
// 2. Configure Jack insertion and auto-switching between headphone and ear speaker
//
SafeReadAC97(AUADD_FUNC1,&Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData | 0x1000;
Ac97RegisterData = Ac97RegisterData & 0xF7FF;
SafeWriteAC97(AUADD_FUNC1, Ac97RegisterData, DEV_AUDIO);
//
// 3. Force VRA (variable rate audio) to be on
//
SafeWriteAC97(EXTENDED_AUDIO_CTRL, VRA_ENABLED_MASK, DEV_AUDIO);
//
// 4. Set Record selector and Record gain/volume(18dB w/20db Boost)
//
SafeWriteAC97(RECORD_SELECT, 0x7000, DEV_AUDIO); // 0x7000 for phone mic and 0x7707 for AEC mic
SafeWriteAC97(RECORD_GAIN, 0x0C0C, DEV_AUDIO);
//
// 4.5 Set inputs
//
SafeWriteAC97(MIC_VOLUME, 0x6008, DEV_AUDIO); // 0dB MICVOL, single ended mono (MIC1), 0x6040 for AEC mic
SafeWriteAC97(PHONE_VOLUME, 0xC008, DEV_AUDIO); //0dB PHONEVOL
SafeWriteAC97(LINE_IN_VOLUME,0xE006,DEV_AUDIO); // Line-in not used
//
//5. Mute every output that is not used
//
SafeWriteAC97(MASTER_VOLUME, 0x8000, DEV_AUDIO); // LOUT/ROUT - not used
//
//6. Open DAC path for headphone, speaker and phone mixer.
//
SafeWriteAC97(PCM_OUT_VOL, 0x0808, DEV_AUDIO); // 0dB DAC volume
//
//7. Set outputs: headphone, ear speaker and loudspeaker volume to max
//
SafeWriteAC97(HEADPHONE_VOLUME, 0x0000, DEV_AUDIO); // R/LHeadphone volume 0dB
SafeWriteAC97(AUX_VOLUME, 0x0000, DEV_AUDIO); // Set OUT3 (ear speaker) volume 0dB
SafeWriteAC97(MASTER_VOLUME_MONO, 0x0000, DEV_AUDIO); // PHONE output (loudspeaker thru AEC chip) volume 0dB
//
// 7.5 Tone control
//
SafeWriteAC97(MASTER_TONE_R_L, 0x9444, DEV_AUDIO); // Adaptive bassboost, -6db attn, bass & treble boost
//
//8. Power down everything except the ACLink and oscillator by default. Things will be turned on as needed
//
SafeWriteAC97(ADDTL_POWERDOWN_CTRL_STAT, 0x7FFF, DEV_AUDIO);
//
//9. Misc config
//
// Enable DAC auto-mute and ADC High Pass Filter
SafeReadAC97(AUADD_FUNC2, &Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData | 0x80; // DAC Auto-Mute
Ac97RegisterData = Ac97RegisterData | 0x08; // ADC High-Pass
Ac97RegisterData = Ac97RegisterData &= 0xFEFF;
SafeWriteAC97(AUADD_FUNC2, Ac97RegisterData, DEV_AUDIO);
// Disable AUXDAC for power conservation
SafeReadAC97(CD_VOLUME, &Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData & 0xFFFE;
SafeWriteAC97(CD_VOLUME, Ac97RegisterData, DEV_AUDIO);
break;
default:
DEBUGMSG(ZONE_ERROR, (TEXT( "Error: Unknown codec.\r\n")));
break;
}
return;
}
void HardwareContext::DeInitCodec(void)
{
DEBUGMSG(ZONE_INIT, (TEXT("HardwareContext::DeInitCodec\r\n")));
// Power down Codec
// SafeWriteAC97(XLLP_AC97_CR_POWERDOWN_CTRL_STAT, 0x1000, DEV_AUDIO);
return;
}
void HardwareContext::PowerDown()
{
m_Sleeping=TRUE;
DEBUGMSG(ZONE_FUNCTION | ZONE_VERBOSE, (TEXT("WaveDev2: PowerDown\r\n")));
// Power down Codec
SafeWriteAC97(AUADD_FUNC1, 0x0400, DEV_AUDIO); // set SVD=1 just to make sure VREF is off
SafeWriteAC97(ADDTL_POWERDOWN_CTRL_STAT, 0xFFFF, DEV_AUDIO);
SafeWriteAC97(POWERDOWN_CTRL_STAT, 0x7F00, DEV_AUDIO);
// Power down AC97 link
UnConfigureAC97Control();
} // PowerDown()
void HardwareContext::PowerUp()
{
// Initialize GPIO and power up AC97 link
ConfigureAC97Control();
// Initialize the codec
InitCodec();
//Initialize AEC chipset
AecAudioInit();
// Power up the AEC if it was previously powered
if (m_AECStatus)
{
PowerUpAEC();
}
// Clear DMA status
ClearDmac(m_RecordingChannel);
ClearDmac(m_PlaybackChannel);
InterruptDone(m_SysIntrAudioDMA);
if (TRUE == m_InPowerHandler)
{
m_Sleeping=FALSE;
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("Wavedev:HardwareContext::PowerUp: Done\r\n")));
}
// Control the hardware speaker enable
void HardwareContext::SetSpeakerEnable(BOOL bEnable)
{
unsigned short int Ac97RegisterData=0;
BOOL fAECStatus = FALSE;
// Switch the power on or off to the audio amp that controls the speaker
if (bEnable)
{
RETAILMSG(1,(TEXT("Turning speaker on...\r\n")));
// power up the buffers and the speaker mixer
SafeReadAC97(ADDTL_POWERDOWN_CTRL_STAT,&Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData & 0xFF3F;
SafeWriteAC97(ADDTL_POWERDOWN_CTRL_STAT, Ac97RegisterData, DEV_AUDIO);
// power up the amp
SafeReadAC97(AUGPIO_PIN_STATUS, &Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData | 0x20;
SafeWriteAC97(AUGPIO_PIN_STATUS, Ac97RegisterData, DEV_AUDIO);
// Speaker output comes through the AEC chip. So power it up!
fAECStatus = TRUE;
SetAECStatus(&fAECStatus);
}
else
{
RETAILMSG(1,(TEXT("Turning speaker off...\r\n")));
// power down the buffers and the speaker mixer
SafeReadAC97(ADDTL_POWERDOWN_CTRL_STAT,&Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData | 0x00C0;
SafeWriteAC97(ADDTL_POWERDOWN_CTRL_STAT, Ac97RegisterData, DEV_AUDIO);
//power down the amp
SafeReadAC97(AUGPIO_PIN_STATUS, &Ac97RegisterData, DEV_AUDIO);
Ac97RegisterData = Ac97RegisterData & 0xFFDF;
SafeWriteAC97(AUGPIO_PIN_STATUS, Ac97RegisterData, DEV_AUDIO);
// AEC is not needed if the speaker output is disabled. Power it down to reduce power consumption
fAECStatus = FALSE;
SetAECStatus(&fAECStatus);
}
return;
}
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// RecalcSpeakerEnable decides whether to enable the speaker or not.
// For now, it only looks at the m_bForceSpeaker variable, but it could
// also look at whether the headset is plugged in
// and/or whether we're in a voice call. Some mechanism would
// need to be implemented to inform the wave driver of changes in the state of
// these variables however.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
void HardwareContext::RecalcSpeakerEnable()
{
SetSpeakerEnable(m_NumForcedSpeaker);
}
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// SetForceSpeaker is called from the device context to update the state of the
// m_bForceSpeaker variable.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
DWORD HardwareContext::ForceSpeaker( BOOL bForceSpeaker )
{
// If m_NumForcedSpeaker is non-zero, audio should be routed to an
// external speaker (if hw permits).
if (bForceSpeaker)
{
m_NumForcedSpeaker++;
if (m_NumForcedSpeaker==1)
{
RecalcSpeakerEnable();
}
}
else
{
m_NumForcedSpeaker--;
if (m_NumForcedSpeaker==0)
{
RecalcSpeakerEnable();
}
}
return MMSYSERR_NOERROR;
}
void HardwareContext::SetAECStatus(LPVOID pvStatus)
{
if (m_AECStatus != *((BOOL*)pvStatus))
{
m_AECStatus = *((BOOL*)pvStatus);
if (m_AECStatus)
{
// turn on AEC
if (!PowerUpAEC())
{
DEBUGMSG(ZONE_ERROR, (TEXT( "Failed to power up the AEC chip.\r\n" )));
}
}
else
{
// turn off AEC
if (!PowerDownAEC())
{
DEBUGMSG(ZONE_ERROR, (TEXT( "Failed to power down the AEC chip.\r\n" )));
}
}
}
}
void HardwareContext::GetAECStatus(LPVOID pvStatus)
{
*((BOOL*)pvStatus) = m_AECStatus;
}
short int HardwareContext::MsgWriteAC97(DWORD dwParam1,DWORD dwParam2)
{
DEBUGMSG(ZONE_VERBOSE, (TEXT( "write %x %x \r\n" ),dwParam1,dwParam2));
SafeWriteAC97((BYTE)dwParam1,(unsigned short int)dwParam2, DEV_AUDIO );
return (MMSYSERR_NOERROR);
}
short int HardwareContext::MsgReadAC97(DWORD dwParam1,DWORD dwParam2)
{
unsigned short int MyData=0;
DEBUGMSG(ZONE_VERBOSE, (TEXT( "read %x %x \r\n" ),dwParam1,MyData ));
SafeReadAC97((BYTE)dwParam1, &MyData, DEV_AUDIO);
if (dwParam2 != (unsigned short int) NULL)
* (unsigned short int *) dwParam2 = MyData;
return (MMSYSERR_NOERROR);
}
//------------------------------------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -