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

📄 hwctxt_8_1.cpp

📁 WM9715 driver for S3C2440.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	ChangeSoundPath(HEADPHONE);

	Modem_VoiceCallThread_Initialize();
	
    //----4.  Configure the AC97 Controller
    // Confiure GPIO for AC97 
    	v_pIOPregs->GPECON = (v_pIOPregs->GPECON & ~(0x3ff)) | 0x3ff;   //GPE[4:0]=AC_SDATA_OUT   AC_SDATA_IN   AC_nRESET   AC_BIT_CLK   AC_SYNC
	v_pIOPregs->GPEUP  = (v_pIOPregs->GPEUP  & ~(0x1f))  | 0x1f;    //The pull up function is disabled GPE[4:0] 1 1111
	v_pIOPregs->GPEDAT  = v_pIOPregs->GPEDAT  & ~(0x1f);    //The pull up function is disabled GPE[4:0] 1 1111
	AC97_Init();


    //----- 5. Configure the Codec -----
    InitCodec();
    
	//-----65. Initialize the interrupt thread -----
    if (!InitInterruptThread())
    {
		DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - Failed to initialize interrupt thread.\r\n")));
        goto Exit;
    }
    m_Initialized=TRUE;
    
    //
    // Power Manager expects us to init in D0.
    // We are normally in D4 unless we are opened for play.
    // Inform the PM.
    //
    m_Dx = D0;
    DevicePowerNotify(_T("WAV1:"),(_CEDEVICE_POWER_STATE)D4, POWER_NAME);    

Exit:
    return(m_Initialized);
}


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

Description:	Maps the config registers

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

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::MapRegisters()
{
	v_pIOPregs = (volatile S3C2440A_IOPORT_REG*)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!v_pIOPregs)
	{
		DEBUGMSG(1, (TEXT("IOPreg: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
	{
		DEBUGMSG(1, (TEXT("IOPreg: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	v_pDMAregs = (volatile S3C2440A_DMA_REG*)VirtualAlloc(0, sizeof(S3C2440A_DMA_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!v_pDMAregs)
	{
		DEBUGMSG(1, (TEXT("DMAreg: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)v_pDMAregs, (PVOID)(S3C2440A_BASE_REG_PA_DMA >> 8), sizeof(S3C2440A_DMA_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
	{
		DEBUGMSG(1, (TEXT("DMAreg: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	s2440INT = (volatile S3C2440A_INTR_REG*)VirtualAlloc(0, sizeof(S3C2440A_INTR_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!s2440INT)
	{
		DEBUGMSG(1, (TEXT("INTreg: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)s2440INT, (PVOID)(S3C2440A_BASE_REG_PA_INTR >> 8), sizeof(S3C2440A_INTR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
	{
		DEBUGMSG(1, (TEXT("INTreg: VirtualCopy failed!\r\n")));
		return(FALSE);
	}

	v_pCLKPWRreg = (volatile S3C2440A_CLKPWR_REG*)VirtualAlloc(0, sizeof(S3C2440A_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!v_pCLKPWRreg)
	{
		DEBUGMSG(1, (TEXT("DMAreg: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)v_pCLKPWRreg, (PVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER >> 8), sizeof(S3C2440A_CLKPWR_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
	{
		DEBUGMSG(1, (TEXT("DMAreg: VirtualCopy failed!\r\n")));
		return(FALSE);
	}
	
	v_pAC97regs = (volatile S3C2440A_AC97_REG*)VirtualAlloc(0, sizeof(S3C2440A_AC97_REG), MEM_RESERVE, PAGE_NOACCESS);
	if (!v_pAC97regs)
	{
		DEBUGMSG(1, (TEXT("AC97reg: VirtualAlloc failed!\r\n")));
		return(FALSE);
	}
	if (!VirtualCopy((PVOID)v_pAC97regs, (PVOID)(S3C2440A_BASE_REG_PA_AC97 >> 8), sizeof(S3C2440A_AC97_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))
	{
		DEBUGMSG(1, (TEXT("AC97reg: 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;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		UnmapRegisters()

Description:	Unmaps the config registers used by both the SPI and
				AC97 controllers.

Notes:			The SPI and AC97 controllers both use the GPIO config
				registers, so these MUST be deinitialized LAST.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::UnmapRegisters()
{
	return TRUE;
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		MapDMABuffers()

Description:	Maps the DMA buffers used for audio input/output
				on the AC97 bus.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::MapDMABuffers()
{
    PBYTE pVirtDMABufferAddr = NULL;
    DMA_ADAPTER_OBJECT Adapter;


    memset(&Adapter, 0, sizeof(DMA_ADAPTER_OBJECT));
    Adapter.InterfaceType = Internal;
    Adapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);

    // Allocate a block of virtual memory (physically contiguous) for the DMA buffers.
    //
    pVirtDMABufferAddr = (PBYTE)HalAllocateCommonBuffer(&Adapter, (AUDIO_DMA_PAGE_SIZE * 4), &g_PhysDMABufferAddr, FALSE);
    if (pVirtDMABufferAddr == NULL)
    {
        RETAILMSG(TRUE, (TEXT("WAVEDEV.DLL:HardwareContext::MapDMABuffers() - Failed to allocate DMA buffer.\r\n")));
        return(FALSE);
    }

    // Setup the DMA page pointers.
    // NOTE: Currently, input and output each have two DMA pages: these pages are used in a round-robin
    // fashion so that the OS can read/write one buffer while the audio codec chip read/writes the other buffer.
    //
    m_Output_pbDMA_PAGES[0] = pVirtDMABufferAddr;
    m_Output_pbDMA_PAGES[1] = pVirtDMABufferAddr + AUDIO_DMA_PAGE_SIZE;
    m_Input_pbDMA_PAGES[0]  = pVirtDMABufferAddr + (2 * AUDIO_DMA_PAGE_SIZE);
    m_Input_pbDMA_PAGES[1]  = pVirtDMABufferAddr + (3 * AUDIO_DMA_PAGE_SIZE);

    return(TRUE);
	
}


/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:		UnmapDMABuffers()

Description:	Unmaps the DMA buffers used for audio input/output
				on the AC97 bus.

Returns:		Boolean indicating success
-------------------------------------------------------------------*/
BOOL HardwareContext::UnmapDMABuffers()
{
	if(m_Output_pbDMA_PAGES[0])
	{
		VirtualFree((PVOID)m_Output_pbDMA_PAGES[0], 0, MEM_RELEASE);
	}

	return TRUE;
}

#if (AC97_READY_CHECK_METHOD == 1) // AC97 Interrupt Thread

HANDLE AC97_InterruptEvent = NULL;
HANDLE AC97_Thread = NULL;
DWORD g_AC97SysIntr = SYSINTR_UNDEFINED;
DWORD g_AC97Irq = IRQ_WDT_AC97;
DWORD AC97InterruptThread(void);
DWORD Codec_Ready_Irq = 0;

static DWORD AC97InterruptThread(void)
{
	
	while(1)
	{
		WaitForSingleObject(AC97_InterruptEvent, INFINITE);
		
		RETAILMSG(1,(_T("AC97InterruptThread() !!\r\n")));

		if ( (v_pAC97regs->AC_GLBSTAT& 0x400000))
		{
			Codec_Ready_Irq=1;
			RETAILMSG(1,(_T("Codec Ready!\r\n")));
			v_pAC97regs->AC_GLBCTRL &= ~(0x400000);	// codec ready interrupt disable
		}
		s2440INT->INTSUBMSK &= ~(1<< IRQ_SUB_AC97);
		s2440INT->INTMSK &= ~(1 << IRQ_WDT_AC97);
	}
}


static void AC97_InterruptThread_Initialize(void)
{
	DWORD         threadID; 

    	if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &g_AC97Irq, sizeof(UINT32), &g_AC97SysIntr, sizeof(UINT32), NULL))
    	{
       	 RETAILMSG(1, (TEXT("ERROR: AC97Irq: Failed to request sysintr value for AC97 interrupt.\r\n")));
        }
	
	if (AC97_InterruptEvent == NULL)
	{
	    AC97_InterruptEvent = CreateEvent(NULL, FALSE, FALSE,NULL);
	    
	    if (NULL == AC97_InterruptEvent) {
			RETAILMSG(1,(TEXT("AC97 interrupt event Error1\r\n")));
	    }
    	
	    // initialize the card insertion interrupt event
	    if (!InterruptInitialize (g_AC97SysIntr, AC97_InterruptEvent, 0, 0)) {
			RETAILMSG(1,(TEXT("AC97 interrupt event Error2\r\n")));
	    }
	}

	if (AC97_Thread == NULL)
	{
		AC97_Thread = CreateThread(NULL,
		                             0,
		                             (LPTHREAD_START_ROUTINE)AC97InterruptThread,
		                             0,
		                             0,
		                             &threadID);
		
		if (NULL == AC97_Thread ) {
			RETAILMSG(1,(TEXT("Create AC97 Interrupt Thread Fail\r\n")));
		}	
	}
	RETAILMSG(1,(TEXT("Use AC97 Int for initialization\r\n")));
}

#endif

// Kingfish2 AC97 Initialize function
BOOL HardwareContext::AC97_Init()
{
#if 0
	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()++\r\n")));


	
#if (AC97_READY_CHECK_METHOD == 1) 
	AC97_InterruptThread_Initialize();	
#endif

	//----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
	//					  we must first enable it.

	v_pCLKPWRreg->CLKCON |= AC97_INTERNAL_CLOCK_ENABLE;		// Enable the CPU clock to the AC97 controller
	Delay(10); 

	// Cold Reset
	v_pAC97regs->AC_GLBCTRL = 1;
	Delay(10); 
	v_pAC97regs->AC_GLBCTRL = 0;
	Delay(10);

	//AC-link On
	v_pAC97regs->AC_GLBCTRL = (1<<2);
	Delay(10);
	v_pAC97regs->AC_GLBCTRL = 0;
	Delay(10);
	
	//Warm Reset 
	v_pAC97regs->AC_GLBCTRL = (0x1<<1); 
	Delay(10); 
	v_pAC97regs->AC_GLBCTRL &= ~(0x1<<1);
	Delay(10);

	//AC-link On
	v_pAC97regs->AC_GLBCTRL = (1<<2);
	Delay(10);
//JEFF why set to zero???
//	v_pAC97regs->AC_GLBCTRL = 0;
//	Delay(10);
	
	//Transfer data enable using AC-link
	v_pAC97regs->AC_GLBCTRL |= (1<<3); // AC97 Data transfer active
	Delay(10);

	RETAILMSG(1,(_T("AC97-Link On...\r\n")));
	
	// Enable the Codec ready Interrupt
	v_pAC97regs->AC_GLBCTRL |= (1<<22);
	Delay(10);

#if (AC97_READY_CHECK_METHOD==1)
	while (Codec_Ready_Irq)
	{
		RETAILMSG(1,(_T("AC97 is not ready..1\r\n")));
		//Sleep(1);
	};
#else
	while ( !(v_pAC97regs->AC_GLBSTAT & 0x400000))
	{
		RETAILMSG(1,(_T("AC97 is not ready..2:0x%x\r\n"),v_pAC97regs->AC_GLBSTAT));
		Sleep(1);
	}
#endif

	RETAILMSG(1,(_T("WAVEDEV_AC97::AC97 Codec Ready!\r\n")));	
	
	v_pAC97regs->AC_GLBCTRL &= ~(0x400000);	// codec ready interrupt disable
	Delay(10);
	//Sleep(5);
#if AC97_RECORD_MICIN
	v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3f<<8)) |0x2200; // PCM_OUT=DMA,PCM_IN=OFF,MIC=DMA;
#else
	v_pAC97regs->AC_GLBCTRL = (v_pAC97regs->AC_GLBCTRL & ~(0x3f<<10)) | 0x2800; // PCM_OUT=DMA,PCM_IN=DMA,MIC=OFF;
#endif	

	RETAILMSG(1,(_T("WAVDEV_AC97::AC97_Init()--\r\n")));

	return TRUE;
#else
    //24A0 AC97_Init
	RETAILMSG(AC97_DEBUG,(_T("WAVDEV_AC97::AC97_Init()++\r\n")));
	
	//----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
	//					  we must first enable it.
	// v_pCLKPWRreg->CLKCON |= AC97_INTERNAL_CLOCK_ENABLE;		// Enable the CPU clock to the AC97 controller

	//AC97_GPIO_Init();

	// v_pAC97regs->AC_GLBCTRL = 0;
	// Delay(10); //Sleep(5);
		
	// Write into the AC97 Global Control Register
	
	//Cold Reset 
	v_pAC97regs->AC_GLBCTRL = 0x1; 
	Delay(10); //Sleep(5);
	v_pAC97regs->AC_GLBCTRL = 0x0;
	Delay(10); //Sleep(5);

	//Ajay
	v_pAC97regs->AC_GLBCTRL = 0x1; 
	Delay(10); //Sleep(5);
	v_pAC97regs->AC_GLBCTRL = 0x0;
	Delay(10); //Sleep(5);

	//AC-link On

⌨️ 快捷键说明

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