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

📄 ac97codec.cpp

📁 CIRRUS 93XX系列windows mobile 6.0 BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    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 + -