📄 hwctxt_kingfish2.cpp
字号:
BOOL HardwareContext::Codec_channel()
{
// Kingfish2 AC97
if( m_InputDMARunning & m_OutputDMARunning )
{
RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - In & Out\r\n")));
WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_D0); // ADC, DAC power up
if(g_SoundPath == SPEAKER)
{
// WriteCodecRegister(AC97_POWER_DOWN1, 0xa90d); // Speaker
// WriteCodecRegister(AC97_POWER_DOWN2, 0xa670); // Speaker
}
else if(g_SoundPath == HEADPHONE)
{
// WriteCodecRegister(AC97_POWER_DOWN1, 0xa903); // HeadPhone
// WriteCodecRegister(AC97_POWER_DOWN2, 0xb9f0); // Headphone
}
}
else if( m_InputDMARunning )
{
RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - In\r\n")));
WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1); // DAC power down
//WriteCodecRegister(AC97_POWER_DOWN1, 0xb9cf);
//WriteCodecRegister(AC97_POWER_DOWN2, 0xbff0);
}
else if( m_OutputDMARunning )
{
RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - Out\r\n")));
WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR0); // ADC power down
if(g_SoundPath == SPEAKER)
{
//WriteCodecRegister(AC97_POWER_DOWN1, 0xf933); //all mixer power down except of headphone mixer
//WriteCodecRegister(AC97_POWER_DOWN2, 0xa67f); // speaker
}
else if(g_SoundPath == HEADPHONE)
{
//WriteCodecRegister(AC97_POWER_DOWN1, 0xf933); // headphone
//WriteCodecRegister(AC97_POWER_DOWN2, 0xb9ff); // headphone //Out3.4 disable
}
}
else
{
RETAILMSG(AC97_DEBUG1,(_T("Codec_channel() - none\r\n")));
WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1|AC97_PWR_PR0); // ADC/DAC power down
}
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitCodec()
Description: Initializes the audio codec chip.
Notes: The audio codec chip is intialized for output mode
but powered down. To conserve battery life, the chip
is only powered up when the user starts playing a
file.
Specifically, the powerup/powerdown logic is done
in the AudioMute() function. If either of the
audio channels are unmuted, then the chip is powered
up; otherwise the chip is powered own.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitCodec()
{
// USHORT CodecRead;
// ULONG CodecVendorID, CodecRevision, Output_Volume;
AC97MSG( (TEXT("+++InitCodec\r\n")));
// write the Codec software reset
// 00h
WriteCodecRegister(AC97_RESET, 0x683F); // it should be expected to muting all analog sources.
g_pAC97regs->AC_GLBCTRL |= AC97_ACLINK_ON; //sync enable
Delay(100);
WriteCodecRegister(AC97_POWER_CONTROL, 0x0); // all power on
//WriteCodecRegister(AC97_POWER_CONTROL, (1<<8)); // all power on except ADC blcok
WriteCodecRegister(AC97_POWER_DOWN1,0); //for power management 0xe933 headphone
WriteCodecRegister(AC97_POWER_DOWN2, 0); // enable Mic bias 0xb9ff
// mute all analog mixer input
WriteCodecRegister(AC97_LOUDSPK_VOL, 0x8080); // Speaker volume Muted
WriteCodecRegister(AC97_HEADPHONE_VOL, 0x8080); // Headphone volume Muted
WriteCodecRegister(AC97_OUT34_VOL, 0x8080); // OUT34(receiver) Muted
WriteCodecRegister(AC97_LINEIN_VOL, 0xE808); // (PhoneIN)LineIn to all mixer Muted
WriteCodecRegister(AC97_PCBEEP_VOL, 0xaaa0); // PCBEEP Muted
WriteCodecRegister(AC97_VXDAC_VOL, 0xaaa0); // VxDACMuted
WriteCodecRegister(AC97_AUX_VOL, 0xaaa0); // AUXDAC Muted
WriteCodecRegister(AC97_MONO_VOL, 0xc880); // MonoVol Muted
WriteCodecRegister(AC97_EXT_AUDIO_CONTROL,AC97_ENABLE_VRA); //variable rate enable
WriteCodecRegister(AC97_PCM_DAC_RATE,AC97_PCM_DAC_RATE_44KHZ); //PCM DAC 44.1Khz
WriteCodecRegister(AC97_PCM_ADC_RATE,AC97_PCM_DAC_RATE_44KHZ); //PCM ADC 44.1Khz
WriteCodecRegister(AC97_ADD_FUNC2,0x2); //select ADC slot6/9
WriteCodecRegister(AC97_MIC_SELECT, 0x0f7f); //Only MIC1/MICA(external) +30db, Mic bias en 0.75AVDD
WriteCodecRegister(AC97_DACTONE_CONTROL,0x9213); //DAC Tone control
WriteCodecRegister(AC97_VXDAC_VOL,0xaaa0); //For Voice DAC control for Speaker, speaker mixer no mute and 0db gain
WriteCodecRegister(AC97_DAC_VOL,0x6404); //For DAC control for headphone mixer , speaker and mono mute, +6db
if(g_pIOPregs->GPGDAT & 1<<0)
{
RETAILMSG(1,(TEXT("CodecInit:: Initial Sound Path Speaker, GPGDAT=%x \r\n"),g_pIOPregs->GPGDAT));
g_SoundPath = SPEAKER;
WriteCodecRegister(AC97_HEADPHONE_VOL, 0x0); // HP out volume 0db
WriteCodecRegister(AC97_OUT34_VOL,0x0); //for OUT3, OUT4 volume control
WriteCodecRegister(AC97_OUTPUT_SELECT,0x920a); //0x5b0a OUT3, OUT4 input source out3:INV1, Out4:INV4, HPL,HPR:unused
WriteCodecRegister(AC97_3D_CONTROL,0x8b00); // // INV1(HeadphoneR)INVV2(HeadPhoneL) low frq cutoff high frq cut off, 3d effect 0%
WriteCodecRegister(AC97_LOUDSPK_VOL,0x0); // Speaker volume on
WriteCodecRegister(AC97_MIC_SELECT, 0x1f60); // only MIC2A select
// WriteCodecRegister(AC97_POWER_DOWN1,0xc); //Power down control for Speaker out
// WriteCodecRegister(AC97_POWER_DOWN2,0x6f0);
}
else
{
g_SoundPath = HEADPHONE;
RETAILMSG(1,(TEXT("CodecInit:: Initial Sound Path HeadPhone, GPGDAT=%x \r\n"),g_pIOPregs->GPGDAT));
WriteCodecRegister(AC97_HEADPHONE_VOL, 0x0909); // HP out volume -13.5db
WriteCodecRegister(AC97_OUT34_VOL,0x8080); //for OUT3, OUT4 volume control:mute
WriteCodecRegister(AC97_LOUDSPK_VOL,0x8080); // Speaker volume on
WriteCodecRegister(AC97_OUTPUT_SELECT,0x80a0); // OUT3, OUT4 : vmid, Only HPLR mixer selected
WriteCodecRegister(AC97_3D_CONTROL,0x0); // INV1,INV2:Zh low frq cutoff high frq cut off, 3d effect 0%
WriteCodecRegister(AC97_MIC_SELECT, 0x0f60); // only MIC1 0x0f7f
}
WriteCodecRegister(AC97_MIC_ROUTING, 0x00da); //mute mic to all mixer.
WriteCodecRegister(AC97_REC_ROUTING, 0xd640); //0x0140 0x4347
WriteCodecRegister(AC97_REC_VOL, 0x0808); // Recording volume max
WriteCodecRegister(AC97_MIC_VOL, 0x0); // MIC volume max
AC97MSG( (TEXT("---InitCodec\r\n")));
WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1|AC97_PWR_PR0);
return(TRUE);
}
MMRESULT HardwareContext::SetOutputGain (DWORD dwGain)
{
m_dwOutputGain = dwGain & 0xffff; // save off so we can return this from GetGain - but only MONO
// convert 16-bit gain to 5-bit attenuation
UCHAR ucGain;
if (m_dwOutputGain == 0) {
ucGain = 0x3F; // mute: set maximum attenuation
}
else {
ucGain = (UCHAR) ((0xffff - m_dwOutputGain) >> 11); // codec supports 64dB attenuation, we'll only use 32
}
ASSERT((ucGain & 0xC0) == 0); // bits 6,7 clear indicate DATA0 in Volume mode.
// Kingfish2. I can't find output gain of CODEC
// WriteCodecRegister( AC97_RECORD_GAIN, AC97_RECORD_GAIN_VAL );
return MMSYSERR_NOERROR;
}
MMRESULT HardwareContext::SetOutputMute (BOOL fMute)
{
m_fOutputMute = fMute;
WriteCodecRegister(0x02, 0x8000); // OUT2 volume Muted. Kingfish2
return MMSYSERR_NOERROR;
}
BOOL HardwareContext::GetOutputMute (void)
{
return m_fOutputMute;
}
DWORD HardwareContext::GetOutputGain (void)
{
return m_dwOutputGain;
}
BOOL HardwareContext::GetInputMute (void)
{
return m_fInputMute;
}
MMRESULT HardwareContext::SetInputMute (BOOL fMute)
{
m_fInputMute = fMute;
return m_InputDeviceContext.SetGain(fMute ? 0: m_dwInputGain);
}
DWORD HardwareContext::GetInputGain (void)
{
return m_dwInputGain;
}
MMRESULT HardwareContext::SetInputGain (DWORD dwGain)
{
m_dwInputGain = dwGain;
if (! m_fInputMute) {
m_InputDeviceContext.SetGain(dwGain);
}
return MMSYSERR_NOERROR;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitOutputDMA()
Description: Initializes the DMA channel for output.
Notes: DMA Channel 2 is used for transmitting output sound
data from system memory to the AC97 controller.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitOutputDMA()
{
RETAILMSG(AC97_DEBUG,(_T("+++InitOutputDMA\r\n")));
//----- 1. Initialize the DMA channel for output mode and use the first output DMA buffer -----
if (!g_PhysDMABufferAddr.LowPart)
{
DEBUGMSG(TRUE, (TEXT("ERROR:HardwareContext::InitOutputDMA: Invalid DMA buffer physical address.\r\n")));
return(FALSE);
}
g_pDMAregs->DISRC1 = (int)(g_PhysDMABufferAddr.LowPart);
g_pDMAregs->DISRCC1 &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is system bus, increment addr
//----- 2. Initialize the DMA channel to send data over the AC97 -----
g_pDMAregs->DIDST1 = (int)(AC_PCMDATA_PHYS);
g_pDMAregs->DIDSTC1 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Dest is periperal bus, fixed addr
//----- 3. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single tx, single service, AC97 request, no auto-reload, half-word, tx count
g_pDMAregs->DCON1 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97PCMOUT_DMA1 | DMA_TRIGGERED_BY_HARDWARE
#if DMA_FLAG // Kingfish2 AC97
// | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2 ) );
| TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4 ) );
#else
// | NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
| NO_DMA_AUTO_RELOAD | TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4 ) );
#endif
//----- 4. Reset the playback pointers -----
AUDIO_RESET_PLAYBACK_POINTER();
DEBUGMSG(ZONE_FUNCTION,(TEXT("---InitOutputDMA\n")));
RETAILMSG(AC97_DEBUG,(_T("---InitOutputDMA\r\n")));
return TRUE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StartOutputDMA()
Description: Starts outputting the sound data to the audio codec
chip via DMA.
Notes: Currently, both playback and record share the same
DMA channel. Consequently, we can only start this
operation if the input channel isn't using DMA.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartOutputDMA()
{
RETAILMSG(AC97_DEBUG,(_T("+++StartOutputDMA\r\n")));
if(!m_OutputDMARunning && (m_Dx == D0) )
{
//----- 1. Initialize our buffer counters -----
m_OutputDMARunning=TRUE;
m_OutBytes[OUT_BUFFER_A]=m_OutBytes[OUT_BUFFER_B]=0;
//----- 2. Prime the output buffer with sound data -----
m_OutputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;
ULONG OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);
//----- 3. If we did transfer any data to the DMA buffers, go ahead and enable DMA -----
if(OutputTransferred)
{
//----- 4. Configure the DMA channel for playback -----
if(!InitOutputDMA())
{
DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartOutputDMA() - Unable to initialize output DMA channel!\r\n")));
goto START_ERROR;
}
// Kingfish2. AC97
#if DMA_FLAG
g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x2<<12); // 0x2 = DMA
#else
g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x1<<12); // 0x1 = PIO
#endif
//----- 5. Make sure the audio isn't muted -----
AudioMute(DMA_CH_OUT, FALSE);
RETAILMSG(AC97_DEBUG,(_T("Start DMA Controller\r\n")));
//----- 6. Start the DMA controller -----
AUDIO_RESET_PLAYBACK_POINTER();
SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();
Codec_channel(); // Turn ON output channel
// charlie, start A buffer
AUDIO_OUT_DMA_ENABLE();
#if DMA_FLAG
// wait for DMA to start.
delay_count = 0;
while((g_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
Sleep(1);
#else
if( delay_count++ > DELAY_COUNT ) break;
#endif
}
// change the buffer pointer
SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();
// Set DMA for B Buffer
#endif
}
else // We didn't transfer any data, so DMA wasn't enabled
{
m_OutputDMARunning=FALSE;
}
}
RETAILMSG(AC97_DEBUG,(_T("---StartOutputDMA\r\n")));
return TRUE;
START_ERROR:
return FALSE;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StopOutputDMA()
Description: Stops any DMA activity on the output channel.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::StopOutputDMA()
{
RETAILMSG(AC97_DEBUG,(_T("StopOutputDMA:%d\r\n"),m_OutputDMARunning));
//----- 1. If the output DMA is running, stop it -----
if (m_OutputDMARunning)
{
m_OutputDMAStatus = DMA_CLEAR;
AUDIO_OUT_DMA_DISABLE();
AUDIO_OUT_CLEAR_INTERRUPTS();
// Kingfish2 AC97
g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x0<<12); // 0x0 = OFF
AudioMute(DMA_CH_OUT, TRUE);
}
m_OutputDMARunning = FALSE;
Codec_channel();
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: InitInputDMA()
Description: Initializes the DMA channel for input.
Notes: ***** NOT IMPLEMENTED *****
The following routine is not implemented due to a
hardware bug in the revision of the Samsung SC2440
CPU this driver was developed on. See the header
at the top of this file for details.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInputDMA()
{
DEBUGMSG(ZONE_FUNCTION,(TEXT("+++InitInputDMA\n")));
RETAILMSG(AC97_DEBUG1,(TEXT("+++InitInputDMA\n")));
if (!g_PhysDMABufferAddr.LowPart)
{
DEBUGMSG(TRUE, (TEXT("ERROR:HardwareContext::InitInputDMA: Invalid DMA buffer physical address.\r\n")));
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -