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

📄 hwctxt_8_1.cpp

📁 WM9715 driver for S3C2440.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

   
Module Name:	HWCTXT.CPP

Abstract:		Platform dependent code for the mixing audio driver.

Notes:			The following file contains all the hardware specific code
				for the mixing audio driver.  This code's primary responsibilities
				are:

					* Initialize audio hardware (including codec chip)
					* Schedule DMA operations (move data from/to buffers)
					* Handle audio interrupts

				All other tasks (mixing, volume control, etc.) are handled by the "upper"
				layers of this driver.

				****** IMPORTANT ******
				For the SC2440 CPU, DMA channel 2 can be used for both input and output.  In this,
				configuration, however, only one type operation (input or output) can execute.  In 
				order to implement simultaneous playback and recording, two things must be done:
 
					1) Input DMA should be moved to DMA Channel 1; Output DMA still uses DMA Channel 2.
					2) Step #3 in InterruptThread() needs to be implemented so that the DMA interrupt
					   source (input DMA or output DMA?) can be determined.  The interrupt source needs
					   to be determined so that the appropriate buffers can be copied (Steps #4,#5...etc.).

				Lastly, the m_OutputDMAStatus and m_InputDMAStatus variables shouldn't need to be modified.  
				The logic surrounding these drivers is simply used to determine which buffer (A or B) needs
				processing.

-*/
#include "wavemain.h"
#include <s3c2440a.h>
#include <bsp_cfg.h>			// Kingfish2
#include "ac97.h"				// Kingfish2
#include "s3c2440a_dmatransfer.h"
#include "hwctxt.h"
#include "DMA.h"
#include <ceddk.h>

#define AC97_RECORD_MICIN 0
#define DMA_FLAG	1		// Kingfish2	1:DMA, 0:Polling
#define WAIT_DMA_END 0

#define DMA_CH_MIC 2
#define DMA_CH_OUT 1

//#define AC97_READY_CHECK_METHOD		0	// Kingfish2
#define AC97_READY_CHECK_METHOD		1	// 2440A
#define AC97_DEBUG 0	
#define AC97_DEBUG1 0
#define AC97_DEBUG2 0
#define AC97_DEBUG3 0
#define AC97MSG(b)	RETAILMSG(AC97_DEBUG,b)

#define DELAY_COUNT	0x100000


//-------------------------------- Global Variables --------------------------------------
volatile S3C2440A_IOPORT_REG *v_pIOPregs		= NULL;		// GPIO registers (needed to enable AC97)
volatile S3C2440A_AC97_REG	 *v_pAC97regs		= NULL;		// AC97 control registers
volatile S3C2440A_DMA_REG    *v_pDMAregs		= NULL;		// DMA registers (needed for I/O on AC97)
volatile S3C2440A_CLKPWR_REG *v_pCLKPWRreg	= NULL;		// Clock power registers (needed to enable AC97)
volatile S3C2440A_INTR_REG *s2440INT 		= NULL;
				
HardwareContext *g_pHWContext		= NULL;

PHYSICAL_ADDRESS g_PhysDMABufferAddr;
unsigned int delay_count;

//----------------------------------------------------------------------------------------

#ifdef DEBUG
#if 0  //JEFF conflict with WaveMain
DBGPARAM dpCurSettings = {
    TEXT("WaveDriver"), {
		 TEXT("Test")           //  0   ZONE_TEST
		,TEXT("Params")         //  1   ZONE_PARAMS     
		,TEXT("Verbose")        //  2   ZONE_VERBOSE    
		,TEXT("Interrupt")      //  3   ZONE_INTERRUPT  
		,TEXT("WODM")           //  4   ZONE_WODM       
		,TEXT("WIDM")           //  5   ZONE_WIDM       
		,TEXT("PDD")            //  6   ZONE_PDD        
		,TEXT("MDD")            //  7   ZONE_MDD        
		,TEXT("Regs")           //  8   ZONE_REGS       
		,TEXT("Misc")           //  9   ZONE_MISC       
		,TEXT("Init")           // 10   ZONE_INIT       
		,TEXT("IOcontrol")      // 11   ZONE_IOCTL      
		,TEXT("Alloc")          // 12   ZONE_ALLOC      
		,TEXT("Function")       // 13   ZONE_FUNCTION   
		,TEXT("Warning")        // 14   ZONE_WARN       
		,TEXT("Error")          // 15   ZONE_ERROR      
	},
        (1 << 15)   // Errors
    |   (1 << 14)   // Warnings
}; 
#endif
#endif

// Kingfish2
volatile static int loop = S3C2440A_FCLK/100000;
static void Delay(USHORT count)
{
	volatile int i, j=0;
	
	for(;count > 0;count--)
		for(i=0;i < loop; i++) { j++; }
}

static void WriteCodecRegister(UCHAR Reg, USHORT Val)
{
	v_pAC97regs->AC_CODEC_CMD = (Reg << AC97_CMD_ADDR_SHIFT) | (Val << AC97_CMD_DATA_SHIFT);
	Delay(100);
	//Sleep(5);
	v_pAC97regs->AC_CODEC_CMD |= (AC97_READ_COMMAND);	//To receive SLOTREQ bits when VRA is '1'.
}

static USHORT ReadCodecRegister(UCHAR Reg)
{
	USHORT retval;
	
	v_pAC97regs->AC_CODEC_CMD = AC97_READ_COMMAND | (Reg << AC97_CMD_ADDR_SHIFT);
	
	Delay(100);
	//Sleep(5);
	
	retval = v_pAC97regs->AC_CODEC_STAT & AC97_STAT_DATA_READ_MASK;
	
	return retval;
}

//for Modem Voice Call path
HANDLE hVoiceCallEvent[2] = {NULL, NULL};   //hVoiceCallEvent[0]: start event, hVoiceCallEvent[1]:end event
HANDLE hVoiceCallThread = NULL;

static DWORD ModemVoiceCallThread(void)
{
	DWORD dwResult;
	while(1)
	{
	    __try {
		dwResult= WaitForMultipleObjects(2, hVoiceCallEvent,FALSE,  INFINITE);
		
		if(dwResult == WAIT_OBJECT_0)
		{
/*			WriteCodecRegister(AC97_AUX_VOL, 0xaaa0);
			WriteCodecRegister(AC97_VXDAC_VOL, 0xaaa0);
			WriteCodecRegister(AC97_REC_ROUTING, 0x8201);
			WriteCodecRegister(AC97_MIC_SELECT, 0x0f40);   // only MIC1 select
			WriteCodecRegister(AC97_MIC_VOL, 0x4040);          // Recording volume mute
			WriteCodecRegister(AC97_MIC_ROUTING, 0x00da);   //MICA:Mono mixer, MICB:headphonemixer.
			WriteCodecRegister(AC97_DAC_VOL,0xe808);	    //mute  DAC to all mixer
			WriteCodecRegister(AC97_MONO_VOL, 0xff00); // MonoVol Max*/
			RETAILMSG(1,(TEXT("RIL Event for Voice Call Start is received\r\n")));
		}
		else if(dwResult == WAIT_OBJECT_0+1)
		{
/*			WriteCodecRegister(AC97_MIC_SELECT, 0x0f60);   // only MIC1 select
			WriteCodecRegister(AC97_REC_ROUTING, 0xd640);
			WriteCodecRegister(AC97_MIC_VOL, 0x0808);          // Recording volume max
			WriteCodecRegister(AC97_MIC_ROUTING, 0x00da);   //mute mic to all mixer.
			WriteCodecRegister(AC97_DAC_VOL,0x6404);	    //For DAC control for headphone mixer , speaker and mono mute, +6db
			WriteCodecRegister(AC97_MONO_VOL, 0xc880); // MonoVol mute*/
			RETAILMSG(1,(TEXT("RIL Event for Voice Call End is received\r\n")));
		}
		else
		{
                RETAILMSG(1,(TEXT("RIL Event is received, but unknown\r\n")));
	    	}		
	
		}
	
	__except(EXCEPTION_EXECUTE_HANDLER){
			// do nothing
			RETAILMSG(1, (TEXT("an exception is raised in ModemVoiceCallThread... \r\n")));
		}


	}
		return 0;
}



static void Modem_VoiceCallThread_Initialize(void)
{
		DWORD        dwThreadID; 
		//VoiceCall Start Evevt
	    hVoiceCallEvent[0] = CreateEvent(NULL, FALSE, FALSE,TEXT("RIL_EVT_VOICECALL_START"));
	    
	    if (NULL == hVoiceCallEvent[0]) {
			RETAILMSG(1,(TEXT("Modem VoiceCall Start event Error1\r\n")));
	    }

		//VoiceCall End Evevt
	    hVoiceCallEvent[1] = CreateEvent(NULL, FALSE, FALSE,TEXT("RIL_EVT_VOICECALL_END"));
	    
	    if (NULL == hVoiceCallEvent[1]) {
			RETAILMSG(1,(TEXT("Modem VoiceCall End event Error1\r\n")));
	    }    	
         
	
	    hVoiceCallThread = CreateThread(NULL,
		                          			  0,
						 	         (LPTHREAD_START_ROUTINE)ModemVoiceCallThread,
		                           			  0,
		                             		  0,
		                                            &dwThreadID);
		
		if (NULL == hVoiceCallThread ) {
			RETAILMSG(1,(TEXT("Create Modem Voice Call Thread Fail\r\n")));
		}	
	   RETAILMSG(1,(TEXT("Initialization for Modem Voice Call Thread\r\n")));
}


// Sound Path interrupt Thread
DWORD g_HPinputIrq = IRQ_EINT8;
DWORD g_HPinputSysIrq = SYSINTR_UNDEFINED;
HANDLE AC97_SoundPathEvent = NULL;
HANDLE AC97_SoundPathThread = NULL;
DWORD g_SoundPath=0;     // 0: Speaker  1:Headphone

DWORD AC97SoundPathInterruptThread(void);
void ChangeSoundPath(DWORD dwSoundPath);

static DWORD AC97SoundPathInterruptThread(void)
{
      while(1)
	{
	    __try {
		WaitForSingleObject(AC97_SoundPathEvent, INFINITE);
		
		RETAILMSG(1,(_T("AC97SoundPathInterruptThread() !!\r\n")));
		Sleep(200);
/*		if(v_pIOPregs->GPGDAT & 1<<0)
		{
			g_SoundPath=SPEAKER;
                    RETAILMSG(1,(TEXT("Sound Path Change to Speaker\r\n")));
		}
		else*/
		{
			g_SoundPath=HEADPHONE;
                    RETAILMSG(1,(TEXT("Sound Path Change to HeadPhone\r\n")));
		}
		ChangeSoundPath(g_SoundPath);
              InterruptDone(g_HPinputSysIrq);
	    	} _except(EXCEPTION_EXECUTE_HANDLER) {
            RETAILMSG(1,(TEXT("!!! Ac97_WavePath EXCEPTION: 0x%X !!!\r\n"), GetExceptionCode() ));
	    		}
	}
	  return 0;
}

static void AC97_SoundPath_InterruptThread_Initialize(void)
{
	DWORD         threadID; 
	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_HPinputIrq, sizeof(UINT32), &g_HPinputSysIrq, sizeof(UINT32), NULL))
    	{
       	 RETAILMSG(1, (TEXT("ERROR: AC97Irq: Failed to request sysintr value for AC97 interrupt.\r\n")));
        }
	if (AC97_SoundPathEvent == NULL)
	{
	    AC97_SoundPathEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
	    
	    if (NULL == AC97_SoundPathEvent) {
			RETAILMSG(1,(TEXT("AC97 WavePath interrupt event Error1\r\n")));
	    }
    	
	    // initialize the card insertion interrupt event
	    if (!InterruptInitialize (g_HPinputSysIrq, AC97_SoundPathEvent, 0, 0)) {
			RETAILMSG(1,(TEXT("AC97 WavePath interrupt event Error2\r\n")));
	    }
	}

	if (AC97_SoundPathThread == NULL)
	{
		AC97_SoundPathThread = CreateThread(NULL,
		                          			  0,
						 	         (LPTHREAD_START_ROUTINE)AC97SoundPathInterruptThread,
		                           			  0,
		                             		  0,
		                                            &threadID);
		
		if (NULL == AC97_SoundPathThread ) {
			RETAILMSG(1,(TEXT("Create AC97 SoundPath Interrupt Thread Fail\r\n")));
		}	
	}
	RETAILMSG(1,(TEXT("Initialization for Ac97 Sound Path(SP/HP)\r\n")));	
}

BOOL HardwareContext::CreateHWContext(DWORD Index)
{
    if (g_pHWContext)
    {
        return(TRUE);
    }

    g_pHWContext = new HardwareContext;
    if (!g_pHWContext)
    {
        return(FALSE);
    }

    return(g_pHWContext->Init(Index));
}

HardwareContext::HardwareContext()
: m_InputDeviceContext(), m_OutputDeviceContext()
{
    InitializeCriticalSection(&m_Lock);
    m_Initialized=FALSE;
}

HardwareContext::~HardwareContext()
{
    DeleteCriticalSection(&m_Lock);
}



BOOL HardwareContext::Init(DWORD Index)
{
    UINT32 Irq;

	m_dwInputGain = 0xFFFF;
	m_dwOutputGain = 0xFFFF;
    m_fInputMute = FALSE;
    m_fOutputMute = FALSE;




    if (m_Initialized)
    {
        return(FALSE);
    }

    // Call the OAL to translate the audio IRQ into a SYSINTR value.
    //
    Irq = IRQ_DMA1;  // audio output DMA interrupt.
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &m_dwSysintrOutput, sizeof(UINT32), NULL))
    {
        RETAILMSG(TRUE, (TEXT("ERROR: HardwareContext::Init: Failed to obtain sysintr value for output interrupt.\r\n")));
        return FALSE;
    }

    Irq = IRQ_DMA2;  // audio input DMA interrupt.
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(UINT32), &m_dwSysintrInput, sizeof(UINT32), NULL))
    {
        RETAILMSG(TRUE, (TEXT("ERROR: HardwareContext::Init: Failed to obtain sysintr value for input interrupt.\r\n")));
        return FALSE;
    }

	//----- 1. Initialize the state/status variables -----
    m_DriverIndex		= Index;
    m_InPowerHandler    = FALSE;
    m_InputDMARunning   = FALSE;
    m_OutputDMARunning  = FALSE;
	m_InputDMAStatus	= DMA_CLEAR;				
	m_OutputDMAStatus	= DMA_CLEAR;				

    //----- 2. Map the necessary descriptory channel and control registers into the driver's virtual address space -----
	if(!MapRegisters())
	{
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to map config registers.\r\n")));
        goto Exit;
	}

    //----- 3. Map the DMA buffers into driver's virtual address space -----
    if(!MapDMABuffers())
    {
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to map DMA buffers.\r\n")));
        goto Exit;
    }
      
	//HP detect EINT8 
       v_pIOPregs->GPGCON = ( v_pIOPregs->GPGCON & ~(0x3)) | 0x2;
	v_pIOPregs->EXTINT1 &= ~(0x7 << 0 );
	v_pIOPregs->EXTINT1 |= (0x7 << 0 );
	
	RETAILMSG(1,(TEXT("v_pIOPregs->GPGDAT= 0x%x \r\n"),v_pIOPregs->GPGDAT));

	//AC97_SoundPath_InterruptThread_Initialize(); //JEFF 20060722

⌨️ 快捷键说明

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