📄 aclinkcontrol.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 + -