📄 hwctxt.cpp
字号:
// Init MIC-IN configurations
// 20h
WriteCodecRegister( AC97_GENERAL_PURPOSE, 0x0000 ); //MIC1 Selected
// Now write High Pass Filter Bypass Control Register
// 78h
//WriteCodecRegister( AC97_HPF_BYPASS, AC97_HIPASS_DISABLE );
RETAILMSG(AC97_DEBUG, (TEXT("---InitCodec\r\n")));
#elif (BSP_TYPE == BSP_SMDK2450)
ULONG CodecVendorID0, CodecVendorID1;
RETAILMSG(TRUE, (TEXT("+++InitCodec\r\n"))); //RETAILMSG(AC97_DEBUG, (TEXT("+++InitCodec\r\n")));
WriteCodecRegister(WM9713_POWER_CONTROL, 0x0000);
WriteCodecRegister(WM9713_POWERDOWN1, 0x0000);
WriteCodecRegister(WM9713_POWERDOWN2, 0x0000);
WriteCodecRegister(WM9713_MCLK_PLL_CTRL0, 0x0b80);
WriteCodecRegister(WM9713_HEADPHONE_VOL, 0x0808); // Unmute HPL, HPR
WriteCodecRegister(WM9713_DAC_VOL_ROUTING, 0x6404); // Unmute DAC to HPMix, SPKMix, MONOMix, 0 dB
WriteCodecRegister(WM9713_OUTPUT_MUX, 0x00a0); // Output HPL, HPR is HPMix, All others is Vmid
WriteCodecRegister(WM9713_RECORD_ROUTING_MUX, 0xd652); // Record Mux Source is LineIn, +20dB
WriteCodecRegister(WM9713_RECORD_VOL, 0x0000); // Unmute ADC input
WriteCodecRegister(WM9713_ADDITIONAL_FUNC2, 0x0080); // AC97_ADDITIONAL_FUNC2 // Set DAC Auto-Mute, bit[1:0]=00, ADC Slot(L/R=3/4)
WriteCodecRegister(WM9713_EXTED_AUDIOCTRL, 0x0031); // bit[5:4]=11, SPDIF Output Slot(L/R=10/11), VRA Enabled
//------------------------------------------------------------------------------
// If using sampling rate other than 48KHz you must enable VRA before set sampling rate !!!!!
//------------------------------------------------------------------------------
WriteCodecRegister(WM9713_AUDIO_DAC_RATE, SAMPLERATE); // 2Ch DAC Sample rate
WriteCodecRegister(WM9713_AUDIO_ADC_RATE, SAMPLERATE); // 32h ADC Sample rate
WriteCodecRegister(WM9713_AUX_DAC_RATE, SAMPLERATE); // AC97_AUXDAC_RATE // 2Eh AUXDAC Sample rate
AudioMute((DMA_CH_OUT | DMA_CH_MIC), FALSE);
Codec_channel(); // ADC/DAC power down
CodecVendorID0 = ReadCodecRegister(WM9713_VENDOR_ID1);
CodecVendorID1 = ReadCodecRegister(WM9713_VENDOR_ID2);
if (CodecVendorID0 != 0x574d || CodecVendorID1 != 0x4c13)
{
// 0x574D4C13 is VenderID of WM9713 Codec
RETAILMSG(TRUE, (TEXT("[WAV:ERR] InitCodec() : VenderID Mismatch\n\r\r\n")));
}
RETAILMSG(TRUE, (TEXT("---InitCodec\r\n"))); //RETAILMSG(AC97_DEBUG, (TEXT("---InitCodec\r\n")));
#endif
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)
{
Lock();
m_fOutputMute = fMute;
WriteCodecRegister(0x02, 0x8000); // OUT2 volume Muted. Kingfish2
Unlock();
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);
}
v_pDMAregs->DISRC1 = (int)(g_PhysDMABufferAddr.LowPart);
v_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 -----
v_pDMAregs->DIDST1 = (int)(AC_PCMDATA_PHYS);
v_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
v_pDMAregs->DCON1 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT
#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
v_pDMAregs->DMAREQSEL1 = (DMAREQSEL_PCMOUT) + (1<<0);
//----- 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_DEBUG1,(_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);
//RETAILMSG(AC97_DEBUG,(_T("StartOutputDMA:OutputTransferred =>0x%x\n"), OutputTransferred));
//----- 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
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x2<<12); // 0x2 = DMA
#else
v_pAC97regs->AC_GLBCTRL = (v_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((v_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_DEBUG1,(_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
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x0<<12); // 0x0 = OFF
#if (BSP_TYPE == BSP_SMDK2443)
AudioMute(DMA_CH_OUT, TRUE);
#elif (BSP_TYPE == BSP_SMDK2450)
#endif
}
m_OutputDMARunning = FALSE;
#if (BSP_TYPE == BSP_SMDK2443)
#elif (BSP_TYPE == BSP_SMDK2450)
AudioMute(DMA_CH_OUT, TRUE);
#endif
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 SC2450
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);
}
//============================ Configure DMA Channel 1 ===========================
//------ On platforms with the revsion of the Samsung SC2450 CPU with the AC97 SLAVE bug fix, this -----
// code can be used to configure DMA channel 1 for input.
//----- 1. Initialize the DMA channel for input mode and use the first input DMA buffer -----
#if AC97_RECORD_MICIN
v_pDMAregs->DISRC2 = (int)AC_MICDATA_PHYS;
#else
v_pDMAregs->DISRC2 = (int)AC_PCMDATA_PHYS;
#endif
v_pDMAregs->DISRCC2 = (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
//----- 2. Initialize the DMA channel to receive data over the AC97 -----
v_pDMAregs->DIDST2 = (int)(RECORD_DMA_BUFFER_PHYS);
v_pDMAregs->DIDSTC2 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment 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
#if AC97_RECORD_MICIN
v_pDMAregs->DCON2 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT
#else
v_pDMAregs->DCON2 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT
#endif
#if DMA_FLAG
#if (INCHANNELS==2)
| TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4) );
#else
| TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
#endif
#else /* DMA_FLAG */
| NO_DMA_AUTO_RELOAD | TRANSFER_WORD | (AUDIO_DMA_PAGE_SIZE / 4) );
//| NO_DMA_AUTO_RELOAD | TRANSFER_HALF_WORD | (AUDIO_DMA_PAGE_SIZE / 2) );
#endif /* DMA_FLAG */
#if AC97_RECORD_MICIN
v_pDMAregs->DMAREQSEL2 = (DMAREQSEL_MICIN) + (1<<0);
#else
v_pDMAregs->DMAREQSEL2 = (DMAREQSEL_PCMIN) + (1<<0);
#endif
RETAILMSG(AC97_DEBUG1,(TEXT("---InitInputDMA\n")));
return(TRUE);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: StartInputDMA()
Description: Starts inputting the recorded sound data from the
audio codec chip via DMA.
Notes: ***** NOT IMPLEMENTED *****
The following routine is not implemented due to a
hardware bug in the revision of the Samsung SC2450
CPU this driver was developed on. See the header
at the top of this file for details.
Returns: Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::StartInputDMA()
{
DEBUGMSG(ZONE_FUNCTION,(TEXT("+++StartInputDMA\n")));
RETAILMSG(AC97_DEBUG1,(TEXT("+++StartInputDMA\n")));
// RETAILMSG(AC97_DEBUG1,(TEXT("m_InputDMARunning=%d\r\n"),m_InputDMARunning));
if(!m_InputDMARunning)
{
//----- 1. Initialize our buffer counters -----
m_InputDMARunning=TRUE;
Codec_channel(); // Turn On Input channel
m_InBytes[IN_BUFFER_A]=m_InBytes[IN_BUFFER_B]=0;
//----- 2. Prime the output buffer with sound data -----
m_InputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;
//----- 3. Configure the DMA channel for record -----
if(!InitInputDMA())
{
DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartInputDMA() - Unable to initialize input DMA channel!\r\n")));
goto START_ERROR;
}
// Kingfish2 AC97
#if AC97_RECORD_MICIN
#if DMA_FLAG
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<8)) | (0x2<<8); // 0x2 = DMA
#else
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<8)) | (0x1<<8); // 0x1 = PIO
#endif
#else // AC97_RECORD_MICIN
#if DMA_FLAG
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<10)) | (0x2<<10); // 0x2 = DMA
#else
v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3<<10)) | (0x1<<10); // 0x1 = PIO
#endif
#endif
//----- 4. Make sure the audio isn't muted -----
AudioMute(DMA_CH_MIC, FALSE);
//----- 5. Start the input DMA -----
AUDIO_RESET_RECORD_POINTER();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -