📄 ac97codec.cpp
字号:
ULONG ulRGIS;
LARGE_INTEGER liStart, liCurrent;
BOOL b;
//
// How it is supposed to work is:
// - The ac97 controller sends out a read addr in slot 1.
// - In the next frame, the codec will echo that address back in slot 1
// and send the data in slot 2. SLOT2RXVALID will be set to 1.
//
// Read until SLOT2RXVALID goes to 1. Reading the data in AACS2DATA
// clears SLOT2RXVALID.
//
b = QueryPerformanceCounter(&liStart);
for(;;)
{
//
// Sleep for a little bit.
//
//Sleep(1);
b = QueryPerformanceCounter(&liCurrent);
//
// Check to see if there is any data in the receive fifo.
//
ulRGIS = *AC97I_RGIS;
if(ulRGIS & GIS_SLOT1TXCOMPLETE)
break;
if((liStart.QuadPart + TIMEOUT_AC97_READ) <liCurrent.QuadPart)
{
ERRMSG((L"PeekAC97 SLOT2TXVALID timed out. reg = 0x%02x.\r\n", ulCodecReg));
return MMSYSERR_ERROR;
}
}
//if( !(ulRGIS & GIS_SLOT2RXVALID) )
//{
// ERRMSG((L"PeekAC97: SLOT2RXVALID timed out, reg = 0x%02x..\n", ulCodecReg));
// return MMSYSERR_ERROR;
//}
//
// Write the address to AACS1DATA.
//
*AC97I_S1DATA = ulCodecReg;
b = QueryPerformanceCounter(&liStart);
for(;;)
{
//
// Sleep for a little bit.
//
// Sleep(1);
b = QueryPerformanceCounter(&liCurrent);
//
// Check to see if there is any data in the receive fifo.
//
ulRGIS = *AC97I_RGIS;
if((ulRGIS & (GIS_SLOT1TXCOMPLETE | GIS_SLOT2RXVALID)) ==
(GIS_SLOT1TXCOMPLETE | GIS_SLOT2RXVALID))
break;
if((liStart.QuadPart + TIMEOUT_AC97_READ) <liCurrent.QuadPart)
{
ERRMSG((L"PeekAC97 timed out reading reg = 0x%04x.\r\n", ulCodecReg));
return MMSYSERR_ERROR;
}
}
//
// Read in the value from S2Data
//
*pulValue = *AC97I_S2DATA;
AC97_MSG((L"PeekAC97: Reg = 0x%02x, Value = 0x%04x\r\n",ulCodecReg, *pulValue));
return MMSYSERR_NOERROR;
}
//****************************************************************************
// PokeAC97
//****************************************************************************
// Writes an AC97 codec Register.
//
// ulCodecReg - AC97 Codec Register
// ulValue - New Codec Register valuie.
//
// Return MMSYSERROR_NOERROR
// MMSYSERROR_ERROR
//
MMRESULT AC97Codec::PokeAC97(ULONG ulCodecReg, ULONG ulValue)
{
BOOL b;
ULONG ulRGIS;
LARGE_INTEGER liStart, liCurrent;
AC97_MSG((L"PokeAC97: Reg = 0x%02x, Value = 0x%04x\r\n",ulCodecReg, ulValue));
//
// Read AACS2DATA to be sure and clear the SLOT2RXVALID bit.
// May not be necessary, not sure.
//
// uiTemp = Ac97Global->AACS2DATA.Value;
//
// Write the data to AACS2DATA, then the address to AACS1DATA.
//
*AC97I_S2DATA = ulValue;
*AC97I_S1DATA = ulCodecReg;
b = QueryPerformanceCounter(&liStart);
for(;;)
{
//
// Sleep for a little bit.
//
// Sleep(1);
b = QueryPerformanceCounter(&liCurrent);
//
// Check to see if there is any data in the receive fifo.
//
ulRGIS = *AC97I_RGIS;
if(ulRGIS & GIS_SLOT2TXCOMPLETE)
break;
if((liStart.QuadPart + TIMEOUT_AC97_READ) <liCurrent.QuadPart)
{
ERRMSG((L"PokeAC97: SLOT2TXVALID timed out reg = 0x%02x.\r\n", ulCodecReg));
return MMSYSERR_ERROR;
}
}
return MMSYSERR_NOERROR;
}
static volatile ULONG ulJunk;
//****************************************************************************
// I2SCodec::ProducePIOTone
//****************************************************************************
// For Debug only.
//
// Uses I2S to produce a PIO tone.
//
//
void AC97Codec::ProducePIOTone(void)
{
ULONG ulCount;
volatile ULONG ulTemp;
volatile ULONG ulSR;
ULONG ulMax= 0x80008000, ulMin=0x7FFF7FFF;
//
// Enable the AC97 transmit channel 0.
//
m_puAC97Ch[AC97I_TXCR>>2] = m_ulTXCR | TXCR_TEN;
ulTemp = ulMax;
for(ulCount = 0; ;ulCount ++)
{
if(ulCount& 0x40)
{
ulTemp = ulMax;
}
else
{
ulTemp = ulMin;
}
do
{
ulSR = m_puAC97Ch[AC97I_SR >>2];
} while( ulSR & SR_TXFF);
m_puAC97Ch[AC97I_DR >>2] = ulTemp;
}
}
//****************************************************************************
// I2SCodec::CapturePIO
//****************************************************************************
// For Debug only.
//
// Uses I2S to produce a PIO tone.
//
//
void AC97Codec::CapturePIO(void)
{
ULONG ulCount;
volatile ULONG ulTemp[100];
volatile ULONG ulSR;
//
// Enable the AC97 capture channel 0.
//
m_puAC97Ch[AC97I_RXCR>>2] = m_ulRXCR | RXCR_REN;
for(;;)
{
for(ulCount = 0; ulCount <100;ulCount ++)
{
do
{
ulSR = m_puAC97Ch[AC97I_SR >>2];
} while( ulSR & SR_RXFE);
ulTemp[ulCount] = m_puAC97Ch[AC97I_DR >>2] ;
}
}
}
//****************************************************************************
// I2SCodec::CaptureNPlay
//****************************************************************************
// Play and capture to test the AC97 codec interface.
//
//
void AC97Codec::CaptureNPlay(void)
{
volatile ULONG ulTemp;
volatile ULONG ulSR;
//
// Enable the AC97 transmitt channel 0.
//
m_puAC97Ch[AC97I_RXCR>>2] = m_ulRXCR | RXCR_REN;
m_puAC97Ch[AC97I_TXCR>>2] = m_ulTXCR | TXCR_TEN;
for(;;)
{
do
{
ulSR = m_puAC97Ch[AC97I_SR >>2];
} while( ulSR & SR_RXFE);
ulTemp = m_puAC97Ch[AC97I_DR >>2] ;
ulSR = m_puAC97Ch[AC97I_SR >>2];
if(!( ulSR & SR_TXFF))
{
m_puAC97Ch[AC97I_DR >>2] = ulTemp;
}
}
}
#define ZONE_MIXER 1
DWORD AC97Codec:: MixerVolumeSettings( DWORD dwCode ,DWORD dwControl, DWORD dwSetting)
{
DWORD *pdwSetting=(DWORD *)dwSetting;
DWORD dwRet= MMSYSERR_NOERROR;
if( dwCode == WPDM_GETMIXERVAL )
{
switch (dwControl) {
case WPDMX_MASTER_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MASTER_VOL\r\n")));
*pdwSetting=m_VolumeSettings.dwMasterVolume;
break;
case WPDMX_MASTER_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MASTER_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fMasterMute;
break;
case WPDMX_LINEIN_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_LINEIN_VOL\r\n")));
*pdwSetting = m_VolumeSettings.dwLineInVolume;
break;
case WPDMX_LINEIN_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_LINEIN_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fLineInMute;
break;
case WPDMX_MIC_VOL:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MIC_VOL\r\n")));
*pdwSetting = m_VolumeSettings.dwMicVolume;
break;
case WPDMX_MIC_MUTE:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_MIC_MUTE\r\n")));
*pdwSetting = m_VolumeSettings.fMicMute;
break;
case WPDMX_INPUT_MUX:
RETAILMSG(ZONE_MIXER, (TEXT("WPDMX_INPUT_MUX\r\n")));
*pdwSetting = m_VolumeSettings.dwInputSelect;
break;
default:
RETAILMSG(1, (TEXT("private_GetMixerValue: unrecognized control %d"), dwControl));
dwRet= MMSYSERR_NOTSUPPORTED;
break;
}
RETAILMSG(1, (TEXT("private_GetMixerValue(%04x, %08x)\r\n"), dwControl, *pdwSetting));
}
else if( dwCode == WPDM_SETMIXERVAL )
{
//ULONG ulRight, ulLeft;
RETAILMSG(1, (TEXT("private_SetMixerValue(%04x, %08x)\r\n"), dwControl, dwSetting));
switch (dwControl) {
// volume controls
case WPDMX_MASTER_VOL:
m_VolumeSettings.dwMasterVolume =dwSetting;
UpdateMuteSettings( AC97_PCMOUT_VOLUME, m_VolumeSettings.dwLineInVolume, FALSE);
break;
case WPDMX_LINEIN_VOL:
m_VolumeSettings.dwLineInVolume = dwSetting;
UpdateMuteSettings( AC97_LINEIN_VOLUME, m_VolumeSettings.dwLineInVolume, FALSE);
break;
case WPDMX_MIC_VOL:
m_VolumeSettings.dwMicVolume = dwSetting;
UpdateMuteSettings( AC97_MIC_VOLUME, m_VolumeSettings.dwMicVolume, FALSE);
break;
// Mute controls
case WPDMX_MASTER_MUTE:
m_VolumeSettings.fMasterMute = dwSetting;
UpdateMuteSettings( AC97_MASTER_VOLUME, m_VolumeSettings.dwMasterVolume, dwSetting);
break;
case WPDMX_LINEIN_MUTE:
m_VolumeSettings.fLineInMute = dwSetting;
UpdateMuteSettings( AC97_LINEIN_VOLUME, m_VolumeSettings.dwLineInVolume, dwSetting);
break;
case WPDMX_MIC_MUTE:
m_VolumeSettings.fMicMute = dwSetting;
UpdateMuteSettings( AC97_MIC_VOLUME, m_VolumeSettings.dwMicVolume, dwSetting);
break;
case WPDMX_INPUT_MUX:
m_VolumeSettings.dwInputSelect = dwSetting;
switch( dwSetting )
{
default:
case WPDMX_LINE_MIC:
RETAILMSG(1, (TEXT("SetMixerValue: INPUT_MUX, MicroPhone selected %x\r\n"), dwSetting));
PokeAC97(AC97_RECORD_SELECT, 0x0); //microphone
break;
case WPDMX_LINE_IN:
RETAILMSG(1, (TEXT("SetMixerValue: INPUT_MUX, Linein selected %x\r\n"), dwSetting));
PokeAC97(AC97_RECORD_SELECT, AC97_RECMUX_LINE);
break;
}
break;
default:
RETAILMSG(1, (TEXT("private_SetMixerValue: unsupported control %d\r\n"), dwControl));
dwRet= MMSYSERR_NOTSUPPORTED;
break;
}
}
return dwRet;
}
DWORD AC97Codec::UpdateMuteSettings( DWORD dwRegister, DWORD dwVolumeValue, BOOL bMute)
{
if( bMute )
{
PokeAC97(dwRegister, 0xFFFF);
}
else
{
ULONG ulRight, ulLeft;
ulRight = 0x1F - ( ( 0x1F * ( dwVolumeValue>>16 )) / 0xFFFF );
ulLeft = 0x1F - ( ( 0x1F * ( dwVolumeValue&0xFFFF)) / 0xFFFF );
//PokeAC97( dwRegister ,(ulRight << 8) | ulLeft );
PokeAC97( dwRegister ,(ulRight << 8 ) | ulLeft |0x8000);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -