⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac97codec.cpp

📁 CIRRUS 93XX系列windows mobile 6.0 BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//**********************************************************************
//                                                                      
// Filename: ac97audio.cpp 
//                                                                      
// Description: interface for the AC97 codec.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to 
// use this source code. For a copy of the EULA, please see the 
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved 
//                                                                      
//**********************************************************************
#include "wavecommon.h"
#include "ac97regs.h"
#include <hwdefs.h>


//
// Set the codec read timeout to 1ms
//
#define TIMEOUT_AC97_READ           1000
#define TIMEOUT_AC97_RESET          20000



//****************************************************************************
// AC97Codec::AC97Codec
//****************************************************************************
// 
// 
//
AC97Codec::AC97Codec(void)
{
}

//****************************************************************************
// AC97Codec::~AC97Codec
//****************************************************************************
// 
// 
//
AC97Codec::~AC97Codec(void)
{
}

//****************************************************************************
// AC97Codec::Initialize
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::Initialize(void )
{
    ULONG   ulRawIntStatus, ulSR;
    BOOL    b;
    LARGE_INTEGER liStart, liCurrent;

    //
    // Write the following registers.
    //
    HalWriteCommonReg
    (
        CSC_DEVCFG, 
        DEVCFG_I2SONSSP | DEVCFG_I2SONAC97 | DEVCFG_A1ONG | DEVCFG_A2ONG,
        0 
    );

    
    //
    // Initialize the AC97 controller to use channel 1.
    //
    m_puAC97Ch = AC97I_CH1_BASE;
           
    //
    // Enable the AC97 controller internal loopback.  Override codec ready.
    //
    *AC97I_GCR = GCR_AC97IFE;

    //
    // Set the TIMEDRESET bit.  Will cause a > 1uSec reset of the ac-link.
    // This bit is self resetting.
    //
    *AC97I_RESET = RESET_TIMEDRESET;
    Sleep(1);    

    //
    // Wait for the codec ready signal from the AC97 codec.
    //
    b = QueryPerformanceCounter(&liStart);
    ASSERT(b);
    for(;;)
    {
        b = QueryPerformanceCounter(&liCurrent);

        //
        // Check to see if the codec is ready.
        //
        ulRawIntStatus = *AC97I_RGIS;
        if(ulRawIntStatus & GCR_OCODECREADY)
            break;

        //
        // See if we hit the timeout.
        //
        if(liStart.QuadPart + TIMEOUT_AC97_RESET <liCurrent.QuadPart)
        {
            ERRMSG((L"AAC: Codec interface Failed to Reset \r\n"));
            return MMSYSERR_NOTENABLED;
        }
    }

    //
    // Set up the rx and tx channels
    //
    m_puAC97Ch[AC97I_RXCR>>2] = (m_ulRXCR = RXCR_CM | RXCR_RSIZE_16 | RXCR_SLOT3 | RXCR_SLOT4) | RXCR_REN;
    m_puAC97Ch[AC97I_TXCR>>2] = (m_ulTXCR = TXCR_CM | TXCR_RSIZE_16 | TXCR_SLOT3 | TXCR_SLOT4) | TXCR_TEN;    

    //
    // Enable the interrupt incase we are using PIO instead of DMA.
    //
    m_puAC97Ch[AC97I_IE>>2]   = m_ulIE = 0;

    
    //
    // Wait until Rx fifo is no longer empty, which means that
    // the codec is pumping ADC data across the AC-link.
    //
    b = QueryPerformanceCounter(&liStart);
    ASSERT(b);
    for(;;)
    {
        Sleep(2);

        b = QueryPerformanceCounter(&liCurrent);

        // 
        // Check to see if there is any data in the receive fifo.
        //
        ulSR = m_puAC97Ch[AC97I_SR>>2];
        if(!(ulSR & SR_RXFE))
            break;

        if(liStart.QuadPart + TIMEOUT_AC97_RESET <liCurrent.QuadPart)
        {
            ERRMSG((L"AC97: Receive Interface Failed to Initialize.\r\n"));
            return MMSYSERR_NOTENABLED;
        }
    }

    //
    // Disable rx and txchannel
    //
    m_puAC97Ch[AC97I_RXCR>>2] = m_ulRXCR;
    m_puAC97Ch[AC97I_TXCR>>2] = m_ulTXCR;

    PokeAC97(AC97_MASTER_VOLUME, 0x0);

    PokeAC97(AC97_PCMOUT_VOLUME, 0x0);
	PokeAC97(AC97_HEADPHONE_VOLUME,0x0);

    //
    // Set up the codec so that variable sample rates are enabled.
    //
    PokeAC97(AC97_EXT_AUDIO_POWER, 0xF);
//    PokeAC97(AC97_EXT_AUDIO_POWER, EXT_AUDIO_POWER_VRA);

	//PokeAC97(AC97_RECORD_SELECT, AC97_RECMUX_LINE);
	PokeAC97(AC97_RECORD_SELECT, 0x0); //microphone

	PokeAC97(AC97_MISC_CRYSTAL_CONTROL,0x10);

//	PokeAC97(AC97_MIC_VOLUME, 0x8);
//	PokeAC97(AC97_LINEIN_VOLUME, 0x0808 );

	PokeAC97(AC97_RECORD_GAIN_MIC,0x0 );
	PokeAC97(AC97_RECORD_GAIN, 0x0);

	//PokeAC97(AC97_CD_VOLUME    , 0x0 );
//	PokeAC97(AC97_VIDEO_VOLUME , 0x0 );
//	PokeAC97(AC97_AUX_VOLUME   , 0x0 );
//	PokeAC97(AC97_PCMOUT_VOLUME, 0x0808 );

//	PokeAC97(AC97_PHONE_VOLUME, 0x0008);
//	PokeAC97(AC97_MASTER_VOLUME,0x0);

	//PokeAC97(AC97_GENERAL_PURPOSE,0x100); //select mic2

    //SetPlaybackSampleRate(44100,0);
    //SetRecordSampleRate(44100,0);
    //CaptureNPlay();

    return MMSYSERR_NOERROR;
}

//****************************************************************************
// AC97Codec::SetVolume
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::SetVolume
(
    ULONG ulRightVolume, 
    ULONG ulLeftVolume, 
    ULONG ulChannel
)
{
    ULONG   ulRight, ulLeft;
    //
    // Convert the volume to AC97 volume values.
    //
    // Input     Codec Value      db Value
    // 0xFFFF       0             12.5db 
    // 0            0x1F          -34.5db
    // 1.5 db steps
    //
    ulRight = 0x1F - ( ( 0x1F * ( ulRightVolume)) / 0xFFFF );
    ulLeft  = 0x1F - ( ( 0x1F * ( ulLeftVolume)) / 0xFFFF );

    //
    // Writ to the AC97 codec register.
    //

	m_VolumeSettings.dwMasterVolume= ulRightVolume<<16 | ulLeftVolume;

    PokeAC97(AC97_PCMOUT_VOLUME, (ulRight << 8) | ulLeft);

    return MMSYSERR_NOERROR;
}

//****************************************************************************
// AC97Codec::SetRecordSampleRate
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::SetRecordSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
    return PokeAC97(AC97_PCM_LR_ADC_RATE, ulFrequency);
}

//****************************************************************************
// AC97Codec::SetPlaybackSampleRate
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::SetPlaybackSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
    return PokeAC97(AC97_PCM_FRONT_DAC_RATE, ulFrequency);
}


//****************************************************************************
// AC97Codec::StartPlayback
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::StartPlayback(ULONG ulChannel)
{
    //
    // For PIO mode an interrupt is generated continously if the 
    // Transmit Interrupt is enabled, but transmit is disabled.
    //
    // Enabled Transmit then enable the interrupt.
    //
    m_puAC97Ch[AC97I_TXCR>>2] = m_ulTXCR | TXCR_TEN;
    m_puAC97Ch[AC97I_IE>>2]   = m_ulIE |= IE_TIE;
    return MMSYSERR_NOERROR;
}

//****************************************************************************
// AC97Codec::StopPlayback
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::StopPlayback(ULONG ulChannel)
{
    //
    // For PIO mode an interrupt is generated continously if the 
    // Transmit Interrupt is enabled, but transmit is disabled.
    //
    // Disable the Transmit Interrupt then disable transmit.
    //
	DWORD dwAC97Status;

	while(1)
	{

		dwAC97Status=m_puAC97Ch[AC97I_SR >>2];
		if( dwAC97Status & ( ( 0x1<<6) | (0x1<<1) ) )
			break;

		//RETAILMSG(1,(L"97data\r\n") );
	}

    m_puAC97Ch[AC97I_IE>>2]   = m_ulIE &= ~IE_TIE;
    m_puAC97Ch[AC97I_TXCR>>2] = m_ulTXCR ;
    return MMSYSERR_NOERROR;
}

//****************************************************************************
// AC97Codec::StartRecord
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::StartRecord(ULONG ulChannel)
{
    //
    // For PIO mode an interrupt is generated continously if the 
    // Receive Interrupt is enabled, but receive is disabled.
    //
    // Enabled Receive then enable the Receive Interrupt.
    //
    m_puAC97Ch[AC97I_RXCR>>2] = m_ulRXCR  | RXCR_REN;
    m_puAC97Ch[AC97I_IE>>2]   = m_ulIE |= IE_RIE;
    return MMSYSERR_NOERROR;
}

//****************************************************************************
// AC97Codec::StopRecord
//****************************************************************************
// 
// 
//
MMRESULT AC97Codec::StopRecord(ULONG ulChannel)
{
    //
    // For PIO mode an interrupt is generated continously if the 
    // Recieve Interrupt is enabled, but Receive is disabled.
    //
    // Disable the Recieve Interrupt then disable Recieve.
    //
    m_puAC97Ch[AC97I_IE>>2]   = m_ulIE &= ~IE_RIE;
    m_puAC97Ch[AC97I_RXCR>>2] = m_ulRXCR;
    return MMSYSERR_NOERROR;
}


//****************************************************************************
// AC97Codec::GetDmaPort
//****************************************************************************
// 
// 
//
ULONG  AC97Codec::GetDmaPort(void)
{
    return PRALLOC_AAC1;
}


//****************************************************************************
// PeekAC97
//****************************************************************************
// Read an AC97 codec Register.  
//
// ulCodecReg - AC97 Codec Register
// pulValue   - Codec Register value.
//
// Return MMSYSERROR_NOERROR
//        MMSYSERROR_ERROR
//
MMRESULT AC97Codec::PeekAC97(UINT ulCodecReg, PULONG pulValue)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -