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

📄 hwctxt_kingfish2.cpp

📁 WM9715 driver for S3C2440.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
    ULONG BytesTransferred = 0;

    ULONG BytesTotal;
    DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);

	RETAILMSG(AC97_DEBUG2,(_T("TransferOutputBuffers:%d\r\n"),Bits));	
	switch (Bits)
    {
    case 0:
    case DMA_BIU:
        // No done bits set- must not be my interrupt
        return 0;
    case DMA_DONEA|DMA_DONEB|DMA_BIU:
        // Load B, then A
        BytesTransferred = TransferOutputBuffer(OUT_BUFFER_B);
        // fall through
    case DMA_DONEA: // This should never happen!
    case DMA_DONEA|DMA_BIU:
		BytesTransferred += TransferOutputBuffer(OUT_BUFFER_A);		// charlie, A => B
        break;
    case DMA_DONEA|DMA_DONEB:
        // Load A, then B
        BytesTransferred = TransferOutputBuffer(OUT_BUFFER_A);
        // charlie
        BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B);
        break;		// charlie
        // fall through
    case DMA_DONEB|DMA_BIU: // This should never happen!
    case DMA_DONEB:
        // Load B
        BytesTransferred += TransferOutputBuffer(OUT_BUFFER_B);		// charlie, B => A
        break;
    }

    // If it was our interrupt, but we weren't able to transfer any bytes
    // (e.g. no full buffers ready to be emptied)
    // and all the output DMA buffers are now empty, then stop the output DMA
    BytesTotal = m_OutBytes[OUT_BUFFER_A]+m_OutBytes[OUT_BUFFER_B];

	if (BytesTotal==0)
    {
		StopOutputDMA();
    }
    return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferInputBuffer()

Description:	Retrieves the chunk of recorded sound data and inputs
				it into an audio buffer for potential "mixing".

Returns:		Number of bytes needing to be transferred.
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffer(ULONG NumBuf)
{
    ULONG BytesTransferred = 0;

    PBYTE pBufferStart = m_Input_pbDMA_PAGES[NumBuf];
    PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
    PBYTE pBufferLast;

	RETAILMSG(AC97_DEBUG3,(_T("TransferInputBuffer:%d\r\n"),NumBuf));
	__try
	{
		pBufferLast = m_InputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
		BytesTransferred = m_InBytes[NumBuf] = pBufferLast-pBufferStart;

		if(NumBuf == IN_BUFFER_A)			// Input Buffer A
		{
			m_InputDMAStatus &= ~DMA_DONEA;
			m_InputDMAStatus |= DMA_STRTA;
		}
		else								// Input Buffer B
		{
			m_InputDMAStatus &= ~DMA_DONEB;
			m_InputDMAStatus |= DMA_STRTB;
		}

	}
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferInputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
	}

    return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferInputBuffers()

Description:	Determines which input buffer (A or B) needs to 
				be filled with recorded sound data.  The correct 
				buffer is then populated with recorded sound data
				from the input channel.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferInputBuffers(DWORD dwDCSR)
{
    ULONG BytesTransferred=0;
    DWORD Bits = dwDCSR & (DMA_DONEA|DMA_DONEB|DMA_BIU);

	RETAILMSG(AC97_DEBUG3,(_T("TransferInputBuffers:%d\r\n"),Bits));
    switch (Bits)
    {
    case 0:
    case DMA_BIU:
        // No done bits set- must not be my interrupt
        return 0;
    case DMA_DONEA|DMA_DONEB|DMA_BIU:
        // Load B, then A
        BytesTransferred = TransferInputBuffer(IN_BUFFER_B);
        // fall through
    case DMA_DONEA: // This should never happen!
    case DMA_DONEA|DMA_BIU:
        // Load A
        BytesTransferred += TransferInputBuffer(IN_BUFFER_A);
        break;
    case DMA_DONEA|DMA_DONEB:
        // Load A, then B
        BytesTransferred = TransferInputBuffer(IN_BUFFER_A);
		BytesTransferred += TransferInputBuffer(IN_BUFFER_B);
		break;
        // fall through
    case DMA_DONEB|DMA_BIU: // This should never happen!
    case DMA_DONEB:
        // Load B
        BytesTransferred += TransferInputBuffer(IN_BUFFER_B);
        break;
    }

    // If it was our interrupt, but we weren't able to transfer any bytes
    // (e.g. no empty buffers ready to be filled)
    // Then stop the input DMA
    if (BytesTransferred==0)
    {
        StopInputDMA();
    }
    return BytesTransferred;
}


void HardwareContext::InterruptThread()
{
    ULONG InputTransferred, OutputTransferred;
	BOOL dmaInterruptSource = 0;

    // Fast way to access embedded pointers in wave headers in other processes.
	SetProcPermissions((DWORD)-1);

    while(TRUE)
    {
		WaitForSingleObject(m_hAudioInterrupt, INFINITE);
		dmaInterruptSource = 0;
		//----- 1. Grab the lock -----
		Lock();

		__try
		{

			//----- 3. Determine the interrupt source (input DMA operation or output DMA operation?) -----
			//----- NOTE:	Often, platforms use two separate DMA channels for input/output operations but
			//				have the OAL return SYSINTR_AUDIO as the interrupt source.  If this is the case,
			//				then the interrupt source (input or output DMA channel) must be determined in
			//				this step.

			if( s2440INT->INTMSK & (1 << IRQ_DMA2) ){
				dmaInterruptSource |= DMA_CH_MIC; // Input DMA is supported...
			    //----- 2. Acknowledge the DMA interrupt -----
			    InterruptDone(m_dwSysintrInput);
			}
			
			if( s2440INT->INTMSK & (1 << IRQ_DMA1) ){
				dmaInterruptSource |= DMA_CH_OUT;
				// Output DMA is supported...
			    //----- 2. Acknowledge the DMA interrupt -----
			    InterruptDone(m_dwSysintrOutput);
			}

			if ( m_Dx != D0 ) continue;
						
           
            //----- 4. Handle any interrupts on the input source -----
			//		   NOTE: The InterruptDone() call below automatically clears the interrupt.
			if ((dmaInterruptSource & DMA_CH_MIC) != 0)
			{
				//----- Determine which buffer just completed the DMA transfer -----
				if(m_InputDMAStatus & DMA_BIU)
				{
					m_InputDMAStatus &= ~DMA_STRTB;							// Buffer B just completed...
					m_InputDMAStatus |= DMA_DONEB;

					m_InputDMAStatus &= ~DMA_BIU;							// Buffer A is in use
#if DMA_FLAG					
					SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#else					
					SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#endif
					RETAILMSG(AC97_DEBUG,(_T("In1\r\n")));	
				}else
				{
					m_InputDMAStatus &= ~DMA_STRTA;							// Buffer A just completed...
					m_InputDMAStatus |= DMA_DONEA;

					m_InputDMAStatus |= DMA_BIU;							// Buffer B is in use
#if DMA_FLAG
					SELECT_AUDIO_DMA_INPUT_BUFFER_A();
#else										
					SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#endif	
					RETAILMSG(AC97_DEBUG,(_T("In2\r\n")));	
				}
#if !DMA_FLAG		
				//----- 5. Schedule the next DMA transfer -----
				AUDIO_IN_DMA_ENABLE();
#endif					
				//----- 6. Retrieve the next chunk of recorded data from the non-playing buffer -----
				InputTransferred = TransferInputBuffers(m_InputDMAStatus);			
			}

			//----- 7. Handle any interrupts on the output source -----
			//		   NOTE: The InterruptDone() call below automatically clears the interrupt.
			if ((dmaInterruptSource & DMA_CH_OUT) != 0)
			{	
				//----- Determine which buffer just completed the DMA transfer -----
				if(m_OutputDMAStatus & DMA_BIU)
				{
					m_OutputDMAStatus &= ~DMA_STRTB;						// Buffer A just completed...
					m_OutputDMAStatus |= DMA_DONEB;

					m_OutputDMAStatus &= ~DMA_BIU;							// Buffer B is in use
					
					delay_count = 0;
					while((g_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
						Sleep(1);
#else						
	        			if( delay_count++ > DELAY_COUNT )	break;
#endif						
	        		} 						
					RETAILMSG(AC97_DEBUG2,(_T("Out1\r\n")));	
#if DMA_FLAG		
					SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();		// charlie. B => A
#else				
					SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();		// charlie. B => A	
#endif	
				}else
				{
					m_OutputDMAStatus &= ~DMA_STRTA;						// Buffer B just completed...
					m_OutputDMAStatus |= DMA_DONEA;

					m_OutputDMAStatus |= DMA_BIU;							// Buffer A is in use
			
					delay_count = 0;			
					while((g_pDMAregs->DSTAT1&0xfffff)==0){
#if WAIT_DMA_END
						Sleep(1);
#else						
	        			if( delay_count++ > DELAY_COUNT )	break;
#endif						
	        		}						
					RETAILMSG(AC97_DEBUG2,(_T("Out2\r\n")));	
#if DMA_FLAG					
					SELECT_AUDIO_DMA_OUTPUT_BUFFER_A();		// charlie. B => A
#else				
					SELECT_AUDIO_DMA_OUTPUT_BUFFER_B();		// charlie. B => A	
#endif	
				}
#if !DMA_FLAG		
				//----- 8. Schedule the next DMA transfer -----
				AUDIO_OUT_DMA_ENABLE();
#endif
				//----- 9. Fill the non-playing buffer with the next chunk of audio data to play -----
				OutputTransferred = TransferOutputBuffers(m_OutputDMAStatus);			
			}

		}
		__except(EXCEPTION_EXECUTE_HANDLER) 
		{
			DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:InterruptThread() - EXCEPTION: %d"), GetExceptionCode()));
		}

		//----- 10. Give up the lock ----- 
		Unlock();
	}  
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		AudioMute()

Description:	Mutes/unmutes the specified audio channel.

Notes:			If both audio channels are MUTED, then the chip 
				is powered down to conserve battery life.  
				Alternatively, if either audio channel is unMUTED, 
				the chip is powered up.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::AudioMute(DWORD channel, BOOL bMute)
{
	static DWORD dwActiveChannel = 0;
	USHORT volume;


	// 
	// Turn off/on mute bit in volume control register.
	// 
	if( (channel & DMA_CH_OUT ) && !m_OutputDMARunning )		// 030711
	{
		if(g_SoundPath == HEADPHONE)
		{
			if(bMute)
			{
				volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
     			WriteCodecRegister(AC97_HEADPHONE_VOL, volume | 0x8080);
			}
			else
			{
				volume = ReadCodecRegister(AC97_HEADPHONE_VOL);
     			WriteCodecRegister(AC97_HEADPHONE_VOL, volume & ~0x8080);
			}
		}
		else
		{
			if(bMute)
			{
				volume = ReadCodecRegister(AC97_LOUDSPK_VOL);
     			WriteCodecRegister(AC97_LOUDSPK_VOL, volume | 0x8080);
			}
			else
			{
				volume = ReadCodecRegister(AC97_LOUDSPK_VOL);
     			WriteCodecRegister(AC97_LOUDSPK_VOL, volume & ~0x8080);
			}
		}
	}		

#if AC97_RECORD_MICIN
	if( (channel & DMA_CH_MIC ) && !m_InputDMARunning )
	{
		if(bMute)
		{
			volume = ReadCodecRegister(AC97_REC_VOL);
     		WriteCodecRegister(AC97_REC_VOL, volume | 0x8000);
		}
		else
		{
			volume = ReadCodecRegister(AC97_REC_VOL);
     		WriteCodecRegister(AC97_REC_VOL, volume & ~0x8000);
		}
	}		
#else
	if( (channel & DMA_CH_MIC ) && !m_InputDMARunning )
	{
		if(bMute)
		{
			volume = ReadCodecRegister(AC97_LINEIN_VOL);
     		WriteCodecRegister(AC97_LINEIN_VOL, volume | 0xe000);
		}
		else
		{
			volume = ReadCodecRegister(AC97_LINEIN_VOL);
     		WriteCodecRegister(AC97_LINEIN_VOL, volume & ~0xe000);
		}
	}
#endif

	return(TRUE);
}


void CallInterruptThread(HardwareContext *pHWContext)
{
    pHWContext->InterruptThread();
}

DWORD 
HardwareContext::Open(
    void
    )
{
    DWORD mmErr = MMSYSERR_NOERROR;
    
    // Don't allow play when not on, if there is a power constraint upon us.
    if ( D0 != m_Dx )
    {
        // Tell the Power Manager we need to power up.
        // If there is a power constraint then fail.
        DWORD dwErr = DevicePowerNotify(_T("WAV1:"), D0, POWER_NAME);
        if ( ERROR_SUCCESS !=  dwErr ) {
            RETAILMSG(1, (TEXT("WAVEDEV::Open:DevicePowerNotify ERROR: %u\r\n"), dwErr ));
            mmErr = MMSYSERR_ERROR;
        }
    }
    
    retu

⌨️ 快捷键说明

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