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

📄 hwctxt.cpp

📁 wince5.0 BSP包
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	//		   AC_SDATA_OUT	- GPE4
	//		   AC_SDATA_IN	- GPE3
	//		   AC_nRESET	- GPE2
	//		   AC_BIT_CLK	- GPE1
	//		   AC_SYNC		- GPE0
	//
	// Port Init for AC97
	//PG[4:0]=AC_SDATA_OUT:AC_SDATA_IN:AC_nRESET:AC_BIT_CLK:AC_SYNC
	v_pIOPregs->rGPECON = ((v_pIOPregs->rGPECON & 0xfffffc00) | 0x3ff);
	v_pIOPregs->rGPEUP = (v_pIOPregs->rGPEUP & ~(0x1f)) | 0x1f;
	//Delay(10);
	//Sleep(5);
}

BOOL HardwareContext::AC97_Init()
{

	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()++\r\n")));
	
	//----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
	//					  we must first enable it.
	g_pCLKPWRreg->rCLKCON |= AC97_INTERNAL_CLOCK_ENABLE;		// Enable the CPU clock to the AC97 controller

	AC97_GPIO_Init();

	v_pAC97regs->rAC_GLBCTRL = 0;
	Delay(10); //Sleep(5);
		
	// Write into the AC97 Global Control Register
	
	//Cold Reset 
	v_pAC97regs->rAC_GLBCTRL = 0x1; 
	Delay(10); //Sleep(5);
	v_pAC97regs->rAC_GLBCTRL = 0x0;
	Delay(10); //Sleep(5);

	//AC-link On
	v_pAC97regs->rAC_GLBCTRL = (1<<2);
	Delay(10); //Sleep(5);

	//Transfer data enable using AC-link
	v_pAC97regs->rAC_GLBCTRL = v_pAC97regs->rAC_GLBCTRL | (1<<3);
	Delay(10); //Sleep(5);


	// Disable the Codec ready Interrupt
	v_pAC97regs->rAC_GLBCTRL = v_pAC97regs->rAC_GLBCTRL | (1<<22);
	Delay(10); //Sleep(5);

	//while (!(v_pAC97regs->rAC_GLBSTAT& 0x400000));

	RETAILMSG(AC97_DEBUG,(_T("WAVEDEV_AC97::AC97 Codec Ready!\r\n")));	
	
	v_pAC97regs->rAC_GLBCTRL &= ~(0x400000);	// codec ready interrupt disable

	Delay(10); //Sleep(5);

	v_pAC97regs->rAC_GLBCTRL = (v_pAC97regs->rAC_GLBCTRL & ~(0x3f<<8)) | 0x0000; // PCM_OUT=OFF,PCM_IN=OFF,MIC=OFF;
	//v_pAC97regs->rAC_GLBCTRL = (v_pAC97regs->rAC_GLBCTRL & ~(0x3f<<8)) | 0x2200; // PCM_OUT=DMA,PCM_IN=OFF,MIC=DMA;

	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()--\r\n")));

	return TRUE;
	
}


BOOL HardwareContext::Codec_channel()
{
	if( m_InputDMARunning & m_OutputDMARunning )
	{
		RETAILMSG(AC97_DEBUG,(_T("Codec_channel() - In & Out\r\n")));
	    WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_D0);		// ADC, DAC power up
	}	   
	else if( m_InputDMARunning )
	{
		RETAILMSG(AC97_DEBUG,(_T("Codec_channel() - In\r\n")));
	    WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR1);		// DAC power down
	}
	else if( m_OutputDMARunning )
	{
		RETAILMSG(AC97_DEBUG,(_T("Codec_channel() - Out\r\n")));
	    WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_PR0);		// ADC power down
	}
	else
	{
		RETAILMSG(AC97_DEBUG,(_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 power_up/down 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;           

	AC97MSG(1, (TEXT("+++InitCodec\r\n")));
 	                                             
	// write the Codec software reset
	// 00h
	WriteCodecRegister(AC97_RESET, 0x683F);   
	
	// Enable the VRA
	// 2Ah
	WriteCodecRegister(AC97_EXT_AUDIO_CONTROL, AC97_ENABLE_VRA);

	WriteCodecRegister(AC97_PCM_DAC_RATE, 44100); // Write default Sample rate for DAC
	WriteCodecRegister(AC97_PCM_ADC_RATE, 44100); // Write default Sample rate for DAC
  
	// get the Vendor ID and revision 
	// 7Ch            
	CodecVendorID = ULONG(ReadCodecRegister( AC97_VENDOR_ID1 )) << 16;
	
	// 7E
	CodecRead = ReadCodecRegister( AC97_VENDOR_ID2 );
	
	CodecVendorID |= ULONG(CodecRead) & 0x0000ff00;
	CodecRevision = ULONG(CodecRead) & 0x000000ff;

/*
	RETAILMSG(AC97_DEBUG, (TEXT("STAC9766 Codec Vendor ID: %08x \r\n"), CodecVendorID));
	RETAILMSG(AC97_DEBUG, (TEXT("STAC9766 Codec Revision:  %02x\r\n"), CodecRevision));

	if ( !( CodecVendorID == AC97_VENDOR_SIGMATEL && CodecRevision == 0x66)) 
	{
		// now power down the Analog section of the AC97
		// and power it back up.  This forces the Sigmatel
		// to calibrate it's analog levels
		// 26h 
		WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_ANLOFF );
		Delay(10); //Sleep(5);
		RETAILMSG(AC97_DEBUG,(_T("WriteCodecRegister(AC97_POWER_CONTROL, AC97_PWR_ANLOFF)\r\n")));
	}
*/
	// Turn Power on for sections
	// 26h
	WriteCodecRegister( AC97_POWER_CONTROL, AC97_PWR_D0 );
	
	// Write the Analog reg
	// 6Eh
	//WriteCodecRegister( AC97_ANALOG_SPEC, 0x0000 );
	
	// write HP Out Value
	// 04h
	WriteCodecRegister( AC97_HEADPHONE_VOL, 0x0404 ); //0x0202); //0x0404 );

	
	// Mute unusing analog source except -------------------------------	
	// PCBEEP_VOL - 0ah
	WriteCodecRegister( AC97_PCBEEP_VOL, 0x8000 );
	// PHONE_VOL - 0ch
	WriteCodecRegister( AC97_PHONE_VOL, 0x8000 );
	// LINEIN_VOL - 10h
	WriteCodecRegister( AC97_LINEIN_VOL, 0x8000 );
	// CD_VOL - 12h
	WriteCodecRegister( AC97_CD_VOL, 0x8000 );
	// VIDEO_VOL - 14h
	WriteCodecRegister( AC97_VIDEO_VOL, 0x8000 );
	// AUX_VOL - 16h
	WriteCodecRegister( AC97_AUX_VOL, 0x8000 );
	
	// write the wave out volume
	// 18h
	WriteCodecRegister( AC97_PCMOUT_VOL, 0x0505 ); //0x0000 ); //0x0606 );
	

	// Init MIC-IN configurations

	// 20h
	WriteCodecRegister( AC97_GENERAL_PURPOSE, 0x0000 );	//MIC1 Selected

	// ADC Gain Control, 30dB
	//BOOSTEN =1
//	tmp = ReadCodecRegister(AC97_MIC_VOL) & ~(0x1<<6);
//	WriteCodecRegister(AC97_MIC_VOL, tmp | (0x1<<6));
	WriteCodecRegister( AC97_MIC_VOL, (1<<15)|(1<<6) ); // Mute & BOOTEN
	
	//ADC Input Slot => left slot6, right slot9, MIC GAIN VAL=1
	WriteCodecRegister( AC97_INTR_PAGE, 0x0 );
	WriteCodecRegister( AC97_ANALOG_SPEC, 0x0024 );
	
	//Left, Right => MIC
	WriteCodecRegister( AC97_RECORD_SELECT, AC97_RECMUX_MIC );

	// set up a default record gain
	// 1Ch
	WriteCodecRegister( AC97_RECORD_GAIN, AC97_RECORD_GAIN_VAL );
	
	// Now write High Pass Filter Bypass Control Register
	// 78h
	WriteCodecRegister( AC97_HPF_BYPASS, AC97_HIPASS_DISABLE );

	AC97MSG(1, (TEXT("---InitCodec\r\n")));
	
	return(TRUE);
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 I2S controller.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitOutputDMA()
{

	//----- 1. Initialize the DMA channel for output mode and use the first output DMA buffer -----
    v_pDMAregs->rDISRC1	= (int)(PLAY_DMA_BUFFER_PHYS); 
    v_pDMAregs->rDISRCC1 &= ~(SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);				// Source is system bus, increment addr

    //----- 2. Initialize the DMA channel to send data over the I2S bus -----
    v_pDMAregs->rDIDST1	= (int)AC_PCMDATA_PHYS; 
    //v_pDMAregs->rDIDSTC1 |= (DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS);	// Dest is  periperal bus, fixed addr
    v_pDMAregs->rDIDSTC1 = (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, I2SSDO, I2S request, no auto-reload, half-word, tx count
	v_pDMAregs->rDCON1	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97PCMOUT_DMA1 | DMA_TRIGGERED_BY_HARDWARE 
#if	DMA_FLAG
//					| 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();
	
	AC97MSG(1,(TEXT("---InitOutputDMA\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()
{
	ULONG OutputTransferred;
	AC97MSG(1,(TEXT("+++StartOutputDMA\n")));
	
	if(!m_OutputDMARunning && (m_Dx == D0) )
//	if(!m_OutputDMARunning)
    {
        //----- 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;	
		//RETAILMSG(1,(_T("dmastat = %x\r\n"), m_OutputDMAStatus));
		m_OutputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;	
		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;
			}

#if	DMA_FLAG
			v_pAC97regs->rAC_GLBCTRL = (v_pAC97regs->rAC_GLBCTRL & ~(0x3<<12)) | (0x2<<12);	// 0x2 = DMA
#else
			v_pAC97regs->rAC_GLBCTRL = (v_pAC97regs->rAC_GLBCTRL & ~(0x3<<12)) | (0x1<<12);	// 0x1 = PIO
#endif	

			//----- 5. Make sure the audio isn't muted -----
			AudioMute(DMA_CH_OUT, FALSE);					

			//----- 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->rDSTAT1&0xfffff)==0){
	        	RETAILMSG(1,(_T("1")));
#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;
        }
    }
    
    AC97MSG(1,(TEXT("---StartOutputDMA\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()
{
	AC97MSG(1,(_T("StopOutputDMA()++\r\n")));

	// jylee,040220
	// you should do this sleep operation for AC-Link operation.
	Sleep(1);
	
	//----- 1. If the output DMA is running, stop it -----
    if (m_OutputDMARunning)
	{
		m_OutputDMAStatus = DMA_CLEAR;				
		AUDIO_OUT_DMA_DISABLE();
		AUDIO_OUT_CLEAR_INTERRUPTS();

		v_pAC97regs->rAC_GLBCTRL = (v_pAC97regs->rAC_GLBCTRL & ~(0x3<<12)) | (0x0<<12);	// 0x0 = OFF

		AudioMute(DMA_CH_OUT, TRUE);		
    }

	m_OutputDMARunning = FALSE;
	
	Codec_channel();

/*
	// jylee, 040220
	// Clear AC97 PCMDATA FIFO.
	for (int i=0; i<AC97_PCMDATA_FIFO_LENGTH;i++)
	{
		v_pAC97regs->rAC_PCMDATA = 0x00000000;
	}
*/
	AC97MSG(1,(_T("StopOutputDMA()--\r\n")));
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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()
{

//goto INIT_ERROR;
	AC97MSG(1,(TEXT("+++InitInputDMA\n")));
	//============================ Configure DMA Channel 1 ===========================
	//------ On platforms with the revsion of the Samsung SC2440 CPU with the IIS 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 -----
	v_pDMAregs->rDISRC2	= (int)AC_MICDATA_PHYS;	
	v_pDMAregs->rDISRCC2 = (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);				// Source is periperal bus, fixed addr
    
    //----- 2. Initialize the DMA channel to receive data over the I2S bus -----
    v_pDMAregs->rDIDST2	= (int)(RECORD_DMA_BUFFER_PHYS); //(AUDIO_DMA_BUFFER_PHYS); 
    v_pDMAregs->rDIDSTC2 &= ~(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, I2SSDI, I2S request, no auto-reload, half-word, tx count
	v_pDMAregs->rDCON2	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97MICIN_DMA2 | DMA_TRIGGERED_BY_HARDWARE 
#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 */

	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

⌨️ 快捷键说明

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