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

📄 aclinkcontrol.c

📁 Xcale270Bsp包,wince平台
💻 C
字号:
/* 
** INTEL CONFIDENTIAL
** Copyright 2000-2003 Intel Corporation All Rights Reserved.
**
** The source code contained or described herein and all documents
** related to the source code (Material) are owned by Intel Corporation
** or its suppliers or licensors.  Title to the Material remains with
** Intel Corporation or its suppliers and licensors. The Material contains
** trade secrets and proprietary and confidential information of Intel
** or its suppliers and licensors. The Material is protected by worldwide
** copyright and trade secret laws and treaty provisions. No part of the
** Material may be used, copied, reproduced, modified, published, uploaded,
** posted, transmitted, distributed, or disclosed in any way without Intel抯
** prior express written permission.
**
** No license under any patent, copyright, trade secret or other intellectual
** property right is granted to or conferred upon you by disclosure or
** delivery of the Materials, either expressly, by implication, inducement,
** estoppel or otherwise. Any license under such intellectual property rights
** must be express and approved by Intel in writing.
*/
/*++

Module Name:  aclinkcontrol.c

Abstract:  
 Intel XSC1 StrongARM  platform AC 97 control routines.

Notes:

$Date: 4/30/03 11:26a $

--*/

// now since we do not have ucbreg.c and it will be replaced by ACLinkControl.c we pass on some of the routines from
// that file which are listed below.

#include <windows.h>
#include <types.h>
#include "bvd1.h"
#include "gpio.h"
#include "aclinkcontrol.h"
#include "drv_glob.h"
#include "xllp_ac97.h"

//#define  DBG_SHOW_AC97
extern void usWait(unsigned usVal); 
extern void msWait(unsigned msVal); 
extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);

PDRIVER_GLOBALS					v_pDriverGlobals	= NULL;
XLLP_AC97_T						*v_pAc97regs		= NULL;
XLLP_OST_T						*v_pOSTRegs			= NULL;
XLLP_INTC_T 					*v_pICReg			= NULL;
XLLP_GPIO_T						*vp_GPIORegs 		= NULL;
XLLP_CLKMGR_T					*v_pClockRegs		= NULL;

volatile LPVOID					v_pCodecAddr		= NULL;

XLLP_AC97_CONTEXT_T				AC97CtxStruct;

short int RawAC97Read(BYTE Offset, unsigned short int * Data, BYTE DevId)
{
#ifdef  DBG_SHOW_AC97
    XLLP_AC97_ERROR_T status =
#endif  // def  DBG_SHOW_AC97
	XllpAc97Read((XLLP_UINT16_T) Offset, (XLLP_UINT16_T *)Data,
								 v_pAc97regs, 
								 v_pOSTRegs,
								 5000, 
								 XLLP_AC97_CODEC_PRIMARY) ;
#ifdef  DBG_SHOW_AC97
    // Skip UCB1400 non-audio registers.  Breaks system otherwise.
    if ((Offset<0x5a)||(Offset>0x68))
    {
        NKDbgPrintfW(TEXT("AcR: %X, %X, %d\r\n"),Offset,*Data,status);
    }
#endif  // def  DBG_SHOW_AC97
	return(SUCCESS);
}
	
//--------------------------------------------------------------------------------------------------------
// Function ReadAC97(Offset, *Data, DevId)
//
// Purpose: This function is responsible for reading the codec register specified by the Offset parameter
// and returning it back to the calling function. The contents will be passed by referencing the Data 
// pointer.
//
//--------------------------------------------------------------------------------------------------------

//  Note: In order to understand the following functions more carefully read the Ac 97 Contrller Unit of the Cotulla EAS,
//  in particularly read section 14.3.5, Operational flow for accessing codec registers on pg 14-6.
 

short int ReadAC97(BYTE Offset, unsigned short int * Data, BYTE DevId)
{
	short int retval;

//	DEBUGMSG(1,(TEXT("***********Entering ReadAC97\r\n")));

	Ac97Lock();

	retval=RawAC97Read(Offset,Data,DevId);

	Ac97Unlock();

//	DEBUGMSG(1,(TEXT("***********Leaving ReadAC97 with Data %d\r\n"),Data));

	return(retval);
}

short int RawAC97Write(BYTE Offset, unsigned short int Data, BYTE DevId)
{
#ifdef  DBG_SHOW_AC97
    XLLP_AC97_ERROR_T status =
#endif  // def  DBG_SHOW_AC97
	XllpAc97Write((XLLP_UINT16_T) Offset , (XLLP_UINT16_T) Data, 
								 v_pAc97regs, 
								 v_pOSTRegs,
								 5000, 
								 XLLP_AC97_CODEC_PRIMARY) ;
#ifdef  DBG_SHOW_AC97
    // Skip UCB1400 non-audio registers.  Breaks system otherwise.
    if ((Offset<0x5a)||(Offset>0x68))
    {
        NKDbgPrintfW(TEXT("AcW: %X, %X, %d\r\n"),Offset,Data,status);
    } 
#endif  // def  DBG_SHOW_AC97
	return(SUCCESS);
}

//-------------------------------------------------------------------------------------------------------------
// Function WriteAC97(Offset, Data, DevId)
//
// Purpose: This function is responsible for writing the data specified by the Data parameter to the codec
// register specified by the Offset parameter.  
//
//--------------------------------------------------------------------------------------------------------------

short int WriteAC97(BYTE Offset, unsigned short int Data, BYTE DevId)
{
	short int retval;
//	DEBUGMSG(1,(TEXT("***********Entering WriteAC97\r\n")));

	Ac97Lock();

	retval=RawAC97Write(Offset,Data,DevId);

	Ac97Unlock();
	return(retval);
}

//------------------------------------------------------------------------------------------------------------
// Function: AllocAcLink(BYTE DevId)
//
// Purpose: Allocate the virtual addresses and space for all the registers the other functions will be using
// the AC Link.  Also create an AcController Mutex.
//-------------------------------------------------------------------------------------------------------------
short int AllocAcLink(BYTE DevId)
{
	if(v_pICReg == NULL)
	{
		v_pICReg =  (XLLP_INTC_T *) VirtualAllocCopy(sizeof(XLLP_INTC_T),(char *)TEXT("AC97: INTC_BASE_U_VIRTUAL"),
													(PVOID)INTC_BASE_U_VIRTUAL);
	}

	if(v_pAc97regs == NULL) 
	{
		v_pAc97regs = (XLLP_AC97_T *) VirtualAllocCopy(sizeof(XLLP_AC97_T), (char *)TEXT("AC97 contol registers"),
													   (PVOID) AC97_BASE_U_VIRTUAL);
	}

	if(v_pDriverGlobals == NULL)
	{
		v_pDriverGlobals = (PDRIVER_GLOBALS) VirtualAllocCopy(DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,(char *)TEXT("AC97: DRIVER_GLOBALS"),
															 (PVOID)DRIVER_GLOBALS_PHYSICAL_MEMORY_START);
	}
	
	if(v_pClockRegs == NULL)
	{
		v_pClockRegs = (XLLP_CLKMGR_T *) VirtualAllocCopy(sizeof(XLLP_CLKMGR_T),(char *)TEXT("aclink Alloc 4 clock"),
					       								  (PVOID)CLK_BASE_U_VIRTUAL);
	}

	if(vp_GPIORegs == NULL)
	{
		vp_GPIORegs = (XLLP_GPIO_T *) VirtualAllocCopy(sizeof(XLLP_GPIO_T),(char *)TEXT("AllocAclink: XLLP_GPIO_T *"),
													  (PVOID)GPIO_BASE_U_VIRTUAL);
	}

	if(v_pOSTRegs == NULL)
    {
		v_pOSTRegs = (XLLP_OST_T *)VirtualAllocCopy(sizeof(XLLP_OST_T),"usWait OSTRegs",(PVOID)(OST_BASE_U_VIRTUAL));
	}

    if (NULL == hAcLinkControlMutex)
    {
    	hAcLinkControlMutex = CreateMutex(NULL,FALSE, ACLINK_MUTEX_NAME);
    }

    usWait(1);  // Minimal wait but guarantees self-init in safe zone.

	if(v_pAc97regs!=NULL)
	{	DEBUGMSG(1,(TEXT("***********ACLink Alloc successfull \r\n")));
		return(SUCCESS);
	}
	else
	{	DEBUGMSG(1,(TEXT("***********ACLink Alloc Failed \r\n")));
		DeAllocAcLink(DevId);
		return(FALSE);
	}
}

//---------------------------------------------------------------------------------------------------------------
// Function DeAllocAcLink(DevId)
//
// Purpose: This function will reverse the effect of AllocAcLink by deallocating all the memory.
//
//----------------------------------------------------------------------------------------------------------------
short int DeAllocAcLink(BYTE DevId)
{
	if (v_pAc97regs) 
	{	
		VirtualFree((void *)v_pAc97regs,sizeof(unsigned int),MEM_RELEASE);
        v_pAc97regs = NULL;
    }
	
	if (v_pDriverGlobals) 
	{	
		VirtualFree((void *)v_pDriverGlobals,sizeof(unsigned int),MEM_RELEASE);
        v_pAc97regs = NULL;
    }

	if(v_pICReg)
	{
		VirtualFree((void *)v_pICReg,sizeof(unsigned int),MEM_RELEASE);
		v_pICReg = NULL;
	}

	if(v_pClockRegs)
	{
		VirtualFree((void *)v_pClockRegs,sizeof(unsigned int),MEM_RELEASE);
		v_pClockRegs = NULL;
	}

	if(vp_GPIORegs)
	{
		VirtualFree((void *)vp_GPIORegs,sizeof(unsigned int),MEM_RELEASE);
		vp_GPIORegs = NULL;
	}

	if(v_pOSTRegs)
	{
		VirtualFree((void *)v_pOSTRegs,sizeof(unsigned int),MEM_RELEASE);
		v_pOSTRegs = NULL;
	}

	return(SUCCESS);
}

//----------------------------------------------------------------------------------------------------------------
//
// Function Ac97Lock()
//
// Purpose: This function will ensure that the AC 97 Link Controller is being used mutually exclusively.
// Either a read of a write operation is in progress at anytime.
//
//----------------------------------------------------------------------------------------------------------------

short int Ac97Lock()
{	
	DWORD  retval;
	retval=WaitForSingleObject(hAcLinkControlMutex, 3000);

	if(retval==WAIT_OBJECT_0)		
		return(SUCCESS);
	else
	{	DEBUGCHK(1);
		return(FALSE);
	}
}

//----------------------------------------------------------------------------------------------------------------
//
// Function Ac97Unlock()
//
// Purpose: To Unlock the channel.
//
//----------------------------------------------------------------------------------------------------------------

short int Ac97Unlock()
{
	v_pAc97regs->CAR &= ~AC97CAR_CAIP;			// clear the Caip bit 
	ReleaseMutex(hAcLinkControlMutex);
	
	return(SUCCESS);
}
//----------------------------------------------------------------------------------------------------------------
//
// Function AC97GpioConfigure
//
// Purpose: This function must be called from the power handler of the respective drivers using this
// library. This function will configure the GPIO pins according to the functionality shown in the table below
//
//		Signals			Pin#		Direction		Alternate Function
//		SYNC			GP31		output				2
//		SDATA_OUT		GP30		output				2
//		BIT_CLK			GP28		input				1
//		SDATA_IN_0		GP29		input				1
//		SDATA_IN_1		GP32		input				1

//		for nACRESET we have to program BIT_CLK direction and set bit 0 of ACUNIT's GCR
//
//      Assumes that DevId <= 7
//
//----------------------------------------------------------------------------------------------------------------

short int AC97CtrlConfigure(BOOL inPowerHandler, BYTE DevId)
{	
	short int retval=FALSE;

	if(v_pDriverGlobals != NULL)
	{
        // If already activated, just log this client and no-op gracefully
		if(0 != v_pDriverGlobals->ac97.GpioIsConfigured)
		{	
            // Log activation by this client
            v_pDriverGlobals->ac97.GpioIsConfigured |= 1u << DevId;				
			return(SUCCESS);
		}
	
	}
	else
	{
		return(FALSE);
	}
		
    // Transition to active. Log this client and perform the activation
    v_pDriverGlobals->ac97.GpioIsConfigured |= 1u << DevId;
	XllpAc97Init(&AC97CtxStruct);

	return(TRUE);
}

//------------------------------------------------------------------------------------------------------------
// Function: Ac97ColdReset()
//
// Purpose: Write to bit 1 of the Ac97 controller to do a Controller and Codec reset
//-------------------------------------------------------------------------------------------------------------
short int Ac97ColdReset()
{
    XllpAc97ColdReset(&AC97CtxStruct);
	return(TRUE);
} // Ac97ColdReset()

//------------------------------------------------------------------------------------------------------------
// Function: InitAcLink(volatile GPIO_REGS *v_pGPIOReg, BOOL inPowerHandler, BYTE DevId)
//
// Purpose: This function will do everything it needs to do to initialise the AC Link Controller.
//-------------------------------------------------------------------------------------------------------------
short int InitAcLink(BOOL inPowerHandler, BYTE DevId)
{
//	DEBUGMSG(1,(TEXT("***********Entering InitAcLink\r\n")));

	if (AllocAcLink(DevId)!=SUCCESS)		// Allocate virtual addresses for AC97 controller and associated registers.
    {
		return (FALSE);
    }    

//	DEBUGMSG(1,(TEXT("***********Before GPIO Configure\r\n")));

	AC97CtxStruct.pGpioReg = vp_GPIORegs;
	AC97CtxStruct.pClockReg = v_pClockRegs;
	AC97CtxStruct.pAc97Reg = v_pAc97regs;
	AC97CtxStruct.pOstRegs = v_pOSTRegs;
	AC97CtxStruct.pIntcReg = v_pICReg;
	AC97CtxStruct.maxSetupTimeOutUs = 1000;
	AC97CtxStruct.useSecondaryCodec = 0;

	//assuming Init can never be called from a power handler, hence param 2 =0
	if (AC97CtrlConfigure(inPowerHandler,DevId)!=SUCCESS)  
	{
		return (FALSE);
	}

//	DEBUGMSG(1,(TEXT("***********After GPIO Configure\r\n")));

	return (SUCCESS);

} // InitAcLink()

//---------------------------------------------------------------------------------------------------------------
// Function DeInitAcLink()
//
// Purpose: This function will reverse the effect of InitAcLink by deallocating GPIOs, doing a cold reset,
//          and dealocating other internally used registers.
//
//----------------------------------------------------------------------------------------------------------------
short int DeInitAcLink(BOOL inPowerHandler, BYTE DevId)
{
	if (AC97CtrlUnConfigure(inPowerHandler, DevId)!=SUCCESS)	//this may have nasty side effects like turning off mute
    {
		return (FALSE);
    }    

	if (DeAllocAcLink(DevId)!=SUCCESS)
    {
		return (FALSE);
    }    

	return (SUCCESS);

} // DeInitAcLink()
//----------------------------------------------------------------------------------------------------------------
//
// Function AC97GpioUnConfigure
//
// Purpose: This function must be called from the power handler of the respective drivers using this
// library. This function will return the GPIO pins back to the GPIO controller
//
//		Signals			Pin#		Direction		Alternate Function
//		SYNC			GP31		output				2
//		SDATA_OUT		GP30		output				2
//		BIT_CLK			GP28		input				1
//		SDATA_IN_0		GP29		input				1
//		SDATA_IN_1		GP32		input				1
//
//		for nACRESET we have to program BIT_CLK direction and set bit 0 of ACUNIT's GCR
//----------------------------------------------------------------------------------------------------------------
short int AC97CtrlUnConfigure(BOOL inPowerHandler, BYTE DevId)
{
    short status = FALSE;   // Assume failure

	if(NULL != v_pDriverGlobals)	
	{
        //If already deactivated, skip this.  Current convention returns FALSE
		if(0 != v_pDriverGlobals->ac97.GpioIsConfigured)
		{	
            // Clear this client's usage state
            v_pDriverGlobals->ac97.GpioIsConfigured &= ~(1u << DevId);

            // For transition to no active clients, run effective code.
            if(!v_pDriverGlobals->ac97.GpioIsConfigured)
            {
	            if(v_pAc97regs) 
	            {	// Force cold reset of AC97 devices
		            status = SUCCESS;
	            }
            } // Transition to no active clients
         } // 0 != v_pDriverGlobals->ac97.GpioIsConfigured
    } // NULL != v_pDriverGlobals
    return(status);
    
} // AC97GpioUnConfigure()

⌨️ 快捷键说明

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