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

📄 hwctxt_kingfish2.cpp

📁 WM9715 driver for S3C2440.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	//============================ Configure DMA Channel 1 ===========================
	//------ On platforms with the revsion of the Samsung SC2440 CPU with the AC97 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 -----
#if AC97_RECORD_MICIN
	g_pDMAregs->DISRC2	= (int)AC_MICDATA_PHYS;	
#else
	g_pDMAregs->DISRC2	= (int)AC_PCMDATA_PHYS;	
#endif    
	g_pDMAregs->DISRCC2 = (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS);				// Source is periperal bus, fixed addr

    //----- 2. Initialize the DMA channel to receive data over the AC97 -----
    g_pDMAregs->DIDST2	= (int)(RECORD_DMA_BUFFER_PHYS); 
    g_pDMAregs->DIDSTC2 &= ~(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, AC97 request, no auto-reload, half-word, tx count
#if AC97_RECORD_MICIN	
	g_pDMAregs->DCON2	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97MICIN_DMA2 | DMA_TRIGGERED_BY_HARDWARE 
#else
	g_pDMAregs->DCON2	= (  HANDSHAKE_MODE | GENERATE_INTERRUPT | AC97PCMIN_DMA2 | DMA_TRIGGERED_BY_HARDWARE 
#endif
#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 */
RETAILMSG(AC97_DEBUG1,(TEXT("---InitInputDMA\n")));
	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
				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::StartInputDMA()
{
	
	DEBUGMSG(ZONE_FUNCTION,(TEXT("+++StartInputDMA\n")));
   	RETAILMSG(AC97_DEBUG1,(TEXT("+++StartInoutDMA\n")));
	RETAILMSG(AC97_DEBUG1,(TEXT("m_InputDMARunning=%d\r\n"),m_InputDMARunning));
	if(!m_InputDMARunning)
    {
        //----- 1. Initialize our buffer counters -----
        m_InputDMARunning=TRUE;
		Codec_channel();        // Turn On Input channel
        m_InBytes[IN_BUFFER_A]=m_InBytes[IN_BUFFER_B]=0;

        //----- 2. Prime the output buffer with sound data -----
		m_InputDMAStatus = (DMA_DONEA | DMA_DONEB) & ~DMA_BIU;	

		//----- 3. Configure the DMA channel for record -----
		if(!InitInputDMA())
		{
			DEBUGMSG(ZONE_ERROR, (TEXT("HardwareContext::StartInputDMA() - Unable to initialize input DMA channel!\r\n")));
			goto START_ERROR;
		}
		// Kingfish2 AC97
#if AC97_RECORD_MICIN
#if	DMA_FLAG
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<8)) | (0x2<<8);	// 0x2 = DMA
#else
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<8)) | (0x1<<8);	// 0x1 = PIO
#endif	

#else // AC97_RECORD_MICIN

#if	DMA_FLAG
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<10)) | (0x2<<10);	// 0x2 = DMA
#else
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<10)) | (0x1<<10);	// 0x1 = PIO
#endif	

#endif

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

		//----- 5. Start the input DMA -----
		AUDIO_RESET_RECORD_POINTER();
		SELECT_AUDIO_DMA_INPUT_BUFFER_A();

		Codec_channel();        // Turn On Input channel
		g_pDMAregs->DMASKTRIG2 = ENABLE_DMA_CHANNEL;

	
#if DMA_FLAG			
        // wait for DMA to start.
        delay_count = 0;
        while((g_pDMAregs->DSTAT2&0xfffff)==0){
#if WAIT_DMA_END
			Sleep(1);
#else
        	if( delay_count++ > DELAY_COUNT )	break;
#endif
        } 

        // change the buffer pointer
        SELECT_AUDIO_DMA_INPUT_BUFFER_B();
#endif				
    }
    DEBUGMSG(ZONE_FUNCTION,(TEXT("---StartInputDMA\n")));
	RETAILMSG(AC97_DEBUG1,(TEXT("---StartInputDMA\n")));
	return(TRUE);

START_ERROR:
	return(FALSE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		StopInputDMA()

Description:	Stops any DMA activity on the input channel.

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
-------------------------------------------------------------------*/
void HardwareContext::StopInputDMA()
{

	//----- 1. If the output DMA is running, stop it -----
	RETAILMSG(AC97_DEBUG1,(TEXT("+++StopInputDMA\n")));
    if (m_InputDMARunning)
	{
		AUDIO_IN_DMA_DISABLE(); // jylee
		AUDIO_IN_CLEAR_INTERRUPTS();	
		
		m_InputDMAStatus = DMA_CLEAR;				
		
		// Kingfish2 AC97
#if AC97_RECORD_MICIN		
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<8)) | (0x0<<8);	// 0x0 = DMA OFF
#else
		g_pAC97regs->AC_GLBCTRL = (g_pAC97regs->AC_GLBCTRL & ~(0x3<<10)) | (0x0<<10);	// 0x0 = DMA OFF
#endif

		AudioMute(DMA_CH_MIC, TRUE);		
    }

	m_InputDMARunning = FALSE;
	Codec_channel();
	RETAILMSG(AC97_DEBUG1,(TEXT("---StopInputDMA\n")));
}


DWORD HardwareContext::GetInterruptThreadPriority()
{
    HKEY hDevKey;
    DWORD dwValType;
    DWORD dwValLen;
    DWORD dwPrio = 249; // Default priority

    hDevKey = OpenDeviceKey((LPWSTR)m_DriverIndex);
    if (hDevKey)
    {
        dwValLen = sizeof(DWORD);
        RegQueryValueEx(
            hDevKey,
            TEXT("Priority256"),
            NULL,
            &dwValType,
            (PUCHAR)&dwPrio,
            &dwValLen);
        RegCloseKey(hDevKey);
    }

    return dwPrio;
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// SetForceSpeaker is called from the device context to update the state of the
// m_bForceSpeaker variable.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

DWORD HardwareContext::ForceSpeaker( BOOL bForceSpeaker )
{
    // If m_NumForcedSpeaker is non-zero, audio should be routed to an
    // external speaker (if hw permits).
    if (bForceSpeaker)
    {
        m_NumForcedSpeaker++;
        if (m_NumForcedSpeaker==1)
        {
            RecalcSpeakerEnable();
        }
    }
    else
    {
        m_NumForcedSpeaker--;
        if (m_NumForcedSpeaker==0)
        {
            RecalcSpeakerEnable();
        }
    }

    return MMSYSERR_NOERROR;
}

// Control the hardware speaker enable
void HardwareContext::SetSpeakerEnable(BOOL bEnable)
{
    // Code to turn speaker on/off here
    return;
}

/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
// RecalcSpeakerEnable decides whether to enable the speaker or not.
// For now, it only looks at the m_bForceSpeaker variable, but it could
// also look at whether the headset is plugged in
// and/or whether we're in a voice call. Some mechanism would
// need to be implemented to inform the wave driver of changes in the state of
// these variables however.
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8

void HardwareContext::RecalcSpeakerEnable()
{
    SetSpeakerEnable(m_NumForcedSpeaker);
}



/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		InitInterruptThread()

Description:	Initializes the IST for handling DMA interrupts.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::InitInterruptThread()
{
    m_hAudioInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!m_hAudioInterrupt)
    {
        ERRMSG("Unable to create interrupt event");
        return(FALSE);
    }

    if (! InterruptInitialize(m_dwSysintrOutput, m_hAudioInterrupt, NULL, 0)) {
        ERRMSG("Unable to initialize output interrupt");
        return FALSE;
    }
    if (! InterruptInitialize(m_dwSysintrInput, m_hAudioInterrupt, NULL, 0)) {
        ERRMSG("Unable to initialize input interrupt");
        return FALSE;
    }

    m_hAudioInterruptThread  = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                            0,
                                            (LPTHREAD_START_ROUTINE)CallInterruptThread,
                                            this,
                                            0,
                                            NULL);
    if (!m_hAudioInterruptThread)
    {
        ERRMSG("Unable to create interrupt thread");
        return FALSE;
    }

    // Bump up the priority since the interrupt must be serviced immediately.
	CeSetThreadPriority(m_hAudioInterruptThread, GetInterruptThreadPriority());

    return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		PowerUp()

Description:	Powers up the audio codec chip.

Notes:			Currently, this function is unimplemented because
				the audio codec chip is ONLY powered up when the 
				user wishes to play or record.  The AudioMute() function
				handles the powerup sequence.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::PowerUp()
{
	AC97MSG((TEXT("AC97 Power UP \r\n")));

	AC97_Init();		// Kingfish2

       InitCodec();
	
      // AudioMute((DMA_CH_OUT | DMA_CH_MIC), FALSE);
      AudioMute((DMA_CH_OUT), FALSE);  //2005.7.1 junkim
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		PowerDown()

Description:	Powers down the audio codec chip.

Notes:			Even if the input/output channels are muted, this
				function powers down the audio codec chip in order
				to conserve battery power.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
void HardwareContext::PowerDown()
{
       AC97MSG((TEXT("AC97:PowerDown\r\n")));
/*	   
	StopOutputDMA();
	AudioMute((DMA_CH_OUT | DMA_CH_MIC), TRUE);
*/
       m_OutputDMAStatus = DMA_CLEAR;

	AUDIO_OUT_DMA_DISABLE();

	AUDIO_OUT_CLEAR_INTERRUPTS();

	g_pAC97regs->AC_GLBCTRL = ( g_pAC97regs->AC_GLBCTRL & ~(0x3<<12)) | (0x0 << 12);

	m_OutputDMARunning = FALSE;
	m_InputDMARunning = FALSE;

	AudioMute((DMA_CH_OUT | DMA_CH_MIC), TRUE);
	

}


//############################################ Helper Functions #############################################

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferOutputBuffer()

Description:	Retrieves the next "mixed" audio buffer of data to
				DMA into the output channel.

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

    PBYTE pBufferStart = m_Output_pbDMA_PAGES[NumBuf];
    PBYTE pBufferEnd = pBufferStart + AUDIO_DMA_PAGE_SIZE;
    PBYTE pBufferLast;
	
	RETAILMSG(AC97_DEBUG2,(_T("TransferOutputBuffer:%d\r\n"),NumBuf));	
	__try
	{
		pBufferLast = m_OutputDeviceContext.TransferBuffer(pBufferStart, pBufferEnd,NULL);
		BytesTransferred = m_OutBytes[NumBuf] = pBufferLast-pBufferStart;

		// Enable if you need to clear the rest of the DMA buffer
		StreamContext::ClearBuffer(pBufferLast,pBufferEnd);
		if(NumBuf == OUT_BUFFER_A)			// Output Buffer A
		{
			m_OutputDMAStatus &= ~DMA_DONEA;
			m_OutputDMAStatus |= DMA_STRTA;
		}
		else								// Output Buffer B
		{
			m_OutputDMAStatus &= ~DMA_DONEB;
			m_OutputDMAStatus |= DMA_STRTB;
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVDEV2.DLL:TransferOutputBuffer() - EXCEPTION: %d"), GetExceptionCode()));
	}

    return BytesTransferred;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		TransferOutputBuffers()

Description:	Determines which output buffer (A or B) needs to 
				be filled with sound data.  The correct buffer is
				then populated with data and ready to DMA to the 
				output channel.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
ULONG HardwareContext::TransferOutputBuffers(DWORD dwDCSR)

⌨️ 快捷键说明

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