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

📄 hwctxt.cpp

📁 s3c2443的Wavedev代码,觉对好用.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// 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.

-2005.11.12 - DonGo.

-*/

#include "wavemain.h"
#include <s3c2443.h>
#include "I2S.h"
#include "hwctxt.h"
#include <p2.h>
#include <bsp.h>
#include <S3C2443REF_GPIO.h>

#define DMA_FLAG 1
#define DMA_CH_MIC 1
#define DMA_CH_OUT 2
#define DBG_WAV 0
#define UDA1341_ADDR_DATA0  0x14    // 00010100 | 00  (ID | data0)
#define UDA1341_ADDR_DATA1  0x15    // 00010100 | 01  (ID | data1)
#define UDA1341_ADDR_STATUS	0x16    // 00010100 | 10  (ID | status)

#define L3C (1<<2)	// GPG2 = L3CLOCK
#define L3D (1<<1)	// GPG1 = L3DATA 
#define L3M (1<<0)	// GPG0 = L3MODE


// debug message
#define DBG_ON		0	// Debug message on/off
#define DBG_AUDIO 	0

unsigned int delay_count;
#define DELAY_COUNT (100000)

//----- Macro used to send commands to the audio codec chip over the SPI bus -----
//		NOTE: The command format is 16 bits:		bits[15-9]	= register
//													bits[8-0]	= data command
//
//		Refer to the TILV320AC reference guide for details.
//
//#define SEND_CODEC_COMMAND(reg, dat)	{ SPI_SendWord((reg | dat));  }

int rec_mode=0;
//-------------------------------- Global Variables --------------------------------------
volatile S3C2443_IISBUS_REG 	*g_pIISregs		= NULL;		// I2S control registers
volatile S3C2443_IOPORT_REG 	*g_pIOPregs		= NULL;		// GPIO registers (needed to enable I2S and SPI)

volatile S3C2443_DMA_REG 		*g_pDMAregs	= NULL;		// DMA1 registers audio in (needed for I/O on I2S bus)

volatile S3C2443_CLKPWR_REG 	*g_pCLKPWRreg	= NULL;		// Clock power registers (needed to enable I2S and SPI clocks)
volatile S3C2443_INTR_REG 		*s2443INT 		= NULL;

				
//UTL_FASTCALL	g_tblFastCall;							// Needed for fast driver->driver calling mechanism
HANDLE		  g_hUTLObject		= INVALID_HANDLE_VALUE;

HardwareContext *g_pHWContext		= NULL;
PHYSICAL_ADDRESS g_PhysDMABufferAddr;
UINT32		g_ForCount=1;
int 	TransferCount;

extern int g_NeedtoSleep;
//----------------------------------------------------------------------------------------

DBGPARAM dpCurSettings = {
	TEXT("CONSOLE"), {
		TEXT("0"),TEXT("1"),TEXT("2"),TEXT("3"),
		TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),
		TEXT("8"),TEXT("9"),TEXT("10"),TEXT("11"),
		TEXT("12"),TEXT("Function"),TEXT("Init"),TEXT("Error")},
	0x8000  // Errors only, by default
}; 



void _WrL3Addr(unsigned char data)
{
 	volatile int i,j;

		g_pIOPregs->GPGDAT  = g_pIOPregs->GPGDAT & ~(L3D | L3M | L3C) | L3C;	//L3D=L, L3M=L(in address mode), L3C=H

		for(j=0;j<4;j++);	 //tsu(L3) > 190ns

	//GPG[2:0]=L3C:L3D:L3M
		for(i=0;i<8;i++)	//LSB first
		{
	  	if(data & 0x1)	//If data's LSB is 'H'
	  	{
			g_pIOPregs->GPGDAT &= ~L3C;	 //L3C=L
			g_pIOPregs->GPGDAT |= L3D;		 //L3D=H		 
			for(j=0;j<4;j++);			//tcy(L3) > 500ns
			g_pIOPregs->GPGDAT |= L3C;		 //L3C=H
			g_pIOPregs->GPGDAT |= L3D;		 //L3D=H
			for(j=0;j<4;j++);			//tcy(L3) > 500ns
	  	}
	  	else		//If data's LSB is 'L'
	  	{
			g_pIOPregs->GPGDAT &= ~L3C;	//L3C=L
			g_pIOPregs->GPGDAT &= ~L3D;	//L3D=L
			for(j=0;j<4;j++);		   //tcy(L3) > 500ns
			g_pIOPregs->GPGDAT |= L3C;		   //L3C=H
			g_pIOPregs->GPGDAT &= ~L3D;	//L3D=L
			for(j=0;j<4;j++);		   //tcy(L3) > 500ns
	  	}
	  	data >>= 1;
		}

		g_pIOPregs->GPGDAT  = g_pIOPregs->GPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M);	 //L3M=H,L3C=H   
}


void _WrL3Data(unsigned char data,int halt)
{
	
 	volatile int i,j;

		if(halt)
		{
	  	g_pIOPregs->GPGDAT  = g_pIOPregs->GPGDAT & ~(L3D | L3M | L3C) | L3C;   //L3C=H(while tstp, L3 interface halt condition)	  
	  	for(j=0;j<4;j++);		//tstp(L3) > 190ns
		}

		g_pIOPregs->GPGDAT  = g_pIOPregs->GPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M);   //L3M=H(in data transfer mode)	  
		for(j=0;j<4;j++);		//tsu(L3)D > 190ns

	//GPG[2:0]=L3C:L3D:L3M
		for(i=0;i<8;i++)
		{
	  	if(data & 0x1)	//if data's LSB is 'H'
	  	{
		 		g_pIOPregs->GPGDAT &= ~L3C;		//L3C=L
		 		g_pIOPregs->GPGDAT |= L3D;			//L3D=H

		 		for(j=0;j<4;j++);			//tcy(L3) > 500ns
		 		g_pIOPregs->GPGDAT |= (L3C | L3D);	//L3C=H,L3D=H
		 		for(j=0;j<4;j++);		 	//tcy(L3) > 500ns
	  	}
	  	else		//If data's LSB is 'L'
	  	{
		 		g_pIOPregs->GPGDAT &= ~L3C;	//L3C=L
		 		g_pIOPregs->GPGDAT &= ~L3D;	//L3D=L
		 		for(j=0;j<4;j++);		//tcy(L3) > 500ns
		 		g_pIOPregs->GPGDAT |= L3C;		//L3C=H
		 		g_pIOPregs->GPGDAT &= ~L3D;	//L3D=L
		 		for(j=0;j<4;j++);		//tcy(L3) > 500ns
	  	}
		data >>= 1;		//For check next bit
		}

		g_pIOPregs->GPGDAT  = g_pIOPregs->GPGDAT & ~(L3D | L3M | L3C) | (L3C | L3M);	//L3M=H,L3C=H
}

BOOL Codec_channel111()
{
	//RETAILMSG(DBG_ON, (TEXT("+Codec_channel\r\n")));

		//******  L3 I/F (GPIO) Initialize *****
   	//----------------------------------------------------------
	//PORT G GROUP
	//Ports  :   GPG0       GPG1        GPG2  
	//Signal :  L3MODE     L3DATA      L3CLK
	//Setting:  OUTPUT     OUTPUT      OUTPUT 
	//	        [1:0]      [3:2]       [5:4]
	//Binary :  01          01           01 
	//----------------------------------------------------------   
		g_pIOPregs->GPGDAT = g_pIOPregs->GPGDAT & ~(L3M|L3C|L3D) |(L3M|L3C);  //Start condition : L3M=H, L3C=H

		g_pIOPregs->GPGDAT = g_pIOPregs->GPGDAT & ~(0x3f); 
		g_pIOPregs->GPGDAT |= ((0x1<<4) |(0x1<<2) |(0x1<<0)); 
#ifdef EVT1		
		g_pIOPregs->EXTINT1 = READEXTINT1(g_pIOPregs->EXTINT1) | (1<<11)|(1<<7)|(1<<3);
#else 
		g_pIOPregs->GPGUDP  = g_pIOPregs->GPGUDP & ~(0x3f<<0) | (2<<4)|(2<<2)|(2<<0);	// 1:Pull-Down disable
#endif		

		g_pIOPregs->GPGDAT = g_pIOPregs->GPGDAT & ~(L3M|L3C|L3D) |(L3M|L3C);  //Start condition : L3M=H, L3C=H
#if 0
	_WrL3Addr(0x14+2); 		//STATUS (000101xx+10)	
	if( m_InputDMARunning & m_OutputDMARunning )
		_WrL3Data(0xa3,0); 	// 1010 0011	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDon
	else if( m_InputDMARunning ) 
		_WrL3Data(0xa2,0); 	// 1010 0010	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDoff		
	else if( m_OutputDMARunning )
		_WrL3Data(0xa1,0); 	// 1010 0001	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AoffDon
	else
		_WrL3Data(0xa0,0); 	// 1010 0000	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AoffDoff
#else
	_WrL3Addr(0x14+2); 		//STATUS (000101xx+10)	
	_WrL3Data(0xa1,0); 	// 1010 0011	: OGS=0,IGS=6db,ADC_NI,DAC_NI,sngl speed,AonDon
#endif	
	//RETAILMSG(DBG_ON, (TEXT("-Codec_channel\r\n")));
	return(TRUE);
}

//Sub-Routines  
//Setting Port related to IIS  
void IIS_Port_Init(void)
{
   	//----------------------------------------------------------
	//PORT G GROUP
	//Ports  :   GPG0       GPG1        GPG2  
	//Signal :  L3MODE     L3DATA      L3CLK
	//Setting:  OUTPUT     OUTPUT      OUTPUT 
	//	        [1:0]      [3:2]       [5:4]
	//Binary :  01          01           01 
	//----------------------------------------------------------    
    	g_pIOPregs->GPGCON = g_pIOPregs->GPGCON & ~((0x3<<4)|(0x3<<2)|(0x3)); 
   	g_pIOPregs->GPGCON |= ((0x1<<4)|(0x1<<2)|(0x1)); // output setting
#ifdef EVT1
	g_pIOPregs->EXTINT1 = READEXTINT1(g_pIOPregs->EXTINT1) | (1<<11)|(1<<7)|(1<<3);
#else
	g_pIOPregs->GPGUDP  = g_pIOPregs->GPGUDP & ~(0x3f<<0) | (2<<4)|(2<<2)|(2<<0);	// 1:Pull-Down disable
#endif

	
   	//-------------------------------------------------------------------------------
	//PORT E GROUP
	//Ports  :   GPE4  			GPE3           GPE2         GPE1           GPE0 
	//Signal :   I2S DO         I2S DI         CDCLK        I2S CLK        I2S LRCLK
	//Binary :   10,            10,            10,          10,            10  
	//-------------------------------------------------------------------------------
	g_pIOPregs->GPECON = g_pIOPregs->GPECON & ~(0x3ff) | 0x2aa;   
#ifdef EVT1	
	g_pIOPregs->GPEUDP = g_pIOPregs->GPEUDP  & ~(0x3ff)  | 0x155; 
#else
	g_pIOPregs->GPEUDP = g_pIOPregs->GPEUDP  & ~(0x3ff)  | 0x2AA; 
#endif	
}

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;
	
	if (m_Initialized)
	{
			return(FALSE);
	}
	m_IntrAudio = SYSINTR_NOP;	

	//RETAILMSG(1, (TEXT("AUDIO sysintr is %d\r\n"), m_IntrAudio));
	//----- 1. Initialize the state/status variables -----
	m_DriverIndex		= Index;
	m_IntrAudio		 = IRQ_AUDIO;	// Just init data...
	m_InPowerHandler	= FALSE;
	m_InputDMARunning   = FALSE;
	m_OutputDMARunning  = FALSE;
	m_InputDMAStatus	= DMA_CLEAR;
	m_OutputDMAStatus	= DMA_CLEAR;
	
	bIdlePwrDown		= TRUE;			// TRUE = Codec Power Turned off	
		//----- 2. Map the necessary descriptory channel and control registers into the driver's virtual address space -----
	if(!MapRegisters())
	{
		RETAILMSG(DBG_AUDIO, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to map config registers.\r\n")));
			goto Exit;
	}

	// 3.5 Init the GPIO ports
	IIS_Port_Init();
	
	//----- 3. Map the DMA buffers into driver's virtual address space -----
	if(!MapDMABuffers())
	{
		RETAILMSG(DBG_AUDIO, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to map DMA buffers.\r\n")));
			goto Exit;
	}

	// Call the OAL to translate the audio IRQ into a SYSINTR value.
	//
	Irq = IRQ_DMA1;  // 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;
	}
	RETAILMSG(1, (TEXT("Audio Input IRQ(DMA1) mapping: [IRQ:%d->sysIRQ:%d].\r\n"), Irq, m_dwSysintrInput));

	Irq = IRQ_DMA2;  // 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;
	}
	RETAILMSG(1, (TEXT("Audio Output IRQ(DMA2) mapping: [IRQ:%d->sysIRQ:%d].\r\n"), Irq, m_dwSysintrOutput));


	//Initialize the IIS registers
	I2S_Init();

	//----- 4. Configure the Codec -----
	InitCodec();
	//----- 5. Initialize the interrupt thread -----
	if (!InitInterruptThread())
	{
		RETAILMSG(DBG_AUDIO, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to initialize interrupt thread.\r\n")));
			goto Exit;
	}
//	Codec_channel111();
	m_Initialized=TRUE;
	
Exit:
	return(m_Initialized);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		MapRegisters()

Description:	Maps the config registers used by both the SPI and
				I2S controllers.

Notes:			The SPI and I2S controllers both use the GPIO config
				registers, so these MUST be initialized FIRST.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::MapRegisters()
{
	// IIS registers.
	//
		g_pIISregs = (volatile S3C2443_IISBUS_REG*)VirtualAlloc(0, sizeof(S3C2443_IISBUS_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!g_pIISregs)
	{
		RETAILMSG(1, (TEXT("S3C2443_IISBUS_REG: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)g_pIISregs, (PVOID)(S3C2443_BASE_REG_PA_IISBUS>>8), sizeof(S3C2443_IISBUS_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
	{
		RETAILMSG(1, (TEXT("S3C2443_IISBUS_REG: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	g_pIOPregs = (volatile S3C2443_IOPORT_REG*)VirtualAlloc(0, sizeof(S3C2443_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!g_pIOPregs)
	{
		RETAILMSG(1, (TEXT("S3C2443_IOPORT_REG: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)g_pIOPregs, (PVOID)(S3C2443_BASE_REG_PA_IOPORT>>8), sizeof(S3C2443_IOPORT_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
	{
		RETAILMSG(1, (TEXT("S3C2443_IOPORT_REG: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	g_pDMAregs = (volatile S3C2443_DMA_REG*)VirtualAlloc(0, sizeof(S3C2443_DMA_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!g_pDMAregs)
	{
		RETAILMSG(1, (TEXT("S3C2443_DMA_REG1: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)g_pDMAregs, (PVOID)(S3C2443_BASE_REG_PA_DMA>>8), sizeof(S3C2443_DMA_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
	{
		RETAILMSG(1, (TEXT("S3C2443_DMA_REG1: VirtualCopy failed!\r\n")));
		return(FALSE);
	}


	s2443INT = (volatile S3C2443_INTR_REG*)VirtualAlloc(0, sizeof(S3C2443_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!s2443INT)
	{
		RETAILMSG(1, (TEXT("S3C2443_INTR_REG: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)s2443INT, (PVOID)(S3C2443_BASE_REG_PA_INTR>>8), sizeof(S3C2443_INTR_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
	{
		RETAILMSG(1, (TEXT("S3C2443_INTR_REG: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	g_pCLKPWRreg = (volatile S3C2443_CLKPWR_REG *)VirtualAlloc(0, sizeof(S3C2443_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!g_pCLKPWRreg)
	{
		RETAILMSG(1, (TEXT("S3C2443_CLKPWR_REG: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)g_pCLKPWRreg, (PVOID)(S3C2443_BASE_REG_PA_CLOCK_POWER>>8), sizeof(S3C2443_CLKPWR_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
	{
		RETAILMSG(1, (TEXT("S3C2443_CLKPWR_REG: VirtualCopy failed!\r\n")));
		return(FALSE);
	}
	

   
	//PowerUp();

	return(TRUE);
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		Deinit()

Description:	Deinitializest the hardware: disables DMA channel(s), 
				clears any pending interrupts, powers down the audio
				codec chip, etc.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::Deinit()
{
	//----- 1. Disable the input/output channels -----
	//	AUDIO_IN_DMA_DISABLE();
	AUDIO_OUT_DMA_DISABLE();

	//----- 2. Disable/clear DMA input/output interrupts -----
	AUDIO_IN_CLEAR_INTERRUPTS();
	AUDIO_OUT_CLEAR_INTERRUPTS();

	//----- 3. Turn the audio hardware off -----
	AudioMute(DMA_CH_OUT | DMA_CH_MIC, TRUE);

	//----- 4. Unmap the control registers and DMA buffers -----
	UnmapRegisters();
	UnmapDMABuffers();

	return TRUE;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

⌨️ 快捷键说明

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