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

📄 hwctxt_kingfish2.cpp

📁 WM9715 driver for S3C2440.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
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 + -