📄 xllp_ac97acodec.c
字号:
/******************************************************************************
**
** COPYRIGHT (C) 2000, 2001 Intel Corporation.
**
** This software as well as the software described in it is furnished under
** license and may only be used or copied in accordance with the terms of the
** license. The information in this file is furnished for informational use
** only, is subject to change without notice, and should not be construed as
** a commitment by Intel Corporation. Intel Corporation assumes no
** responsibility or liability for any errors or inaccuracies that may appear
** in this document or any software that may be provided in association with
** this document.
** Except as permitted by such license, no part of this document may be
** reproduced, stored in a retrieval system, or transmitted in any form or by
** any means without the express written consent of Intel Corporation.
**
** FILENAME: xllp_ac97acodec.c
**
** PURPOSE: XLLP for Bulverde's AC'97 Controller Unit.
** Includes initialization, API and support
** functions.
**
** Valid for : Subset of AC '97 Rev 2.1
**
**
******************************************************************************/
#include "xllp_ac97acodec.h"
#include "xllp_ost.h"
#include "xllp_clkmgr.h"
#include ".\xllp_gpio.h"
#include "xllp_intc.h"
//#define FORCE_ZOAR_SSPTXD_HIGH 1
//#define USE_AC97SYSCLK 1
//#define MSII 1
static XLLP_BOOL_T XllpAc97ACODECLinkLock(XLLP_AC97ACODEC_T * pAc97);
static XLLP_ACODEC_ERROR_T XllpAc97ACODECShutdownAclink(XLLP_AC97ACODEC_T * pAc97Reg, P_XLLP_OST_T pOstRegs);
static XLLP_ACODEC_ERROR_T XllpAc97ACODECColdReset(XLLP_ACODEC_CONTEXT_T * pAc97ctxt);
/*******************************************************************************
*
* FUNCTION: XllpAc97ACodecInit
*
* DESCRIPTION: Set up AC'97 relative GPIOs.
* Enable AC'97 Controller device clock.
* Perform a cold reset of the AC'97 controller and codec(s).
*
* Note: Does not enable any interrupt types within the
* ACUNIT, so no interrupts should occur at this point.
*
* INPUT PARAMETERS:
* pAc97ctxt a pointer to a XLLP_ACODEC_CONTEXT_T struct, which contains
* necessary setup information.
*
* RETURNS:
* Success: 0
* Failure: Refer to XllpAc97ACodecColdReset
*
* GLOBAL EFFECTS:
*
* ASSUMPTIONS: - No other systems, such as debuggers, are using the
* AC '97 Controller or codecs, or the AC Link.
* - The software system will be unharmed by a cold reset of
* the entire AC '97 subsystem and any associated devices.
*
* CALLS: XllpAc97ACodecColdReset
*
* CALLED BY:
*
* PROTOTYPE: XLLP_ACODEC_ERROR_T XllpAc97ACodecInit(XLLP_ACODEC_CONTEXT_T *pAc97ctxt)
*
*******************************************************************************/
XLLP_ACODEC_ERROR_T XllpAc97ACodecInit(XLLP_ACODEC_CONTEXT_T *pAc97ctxt)
{
XLLP_ACODEC_ERROR_T status ;
volatile XLLP_GPIO_T *pGPIO = (volatile XLLP_GPIO_T *) pAc97ctxt->pGpioReg;
volatile XLLP_CLKMGR_T *pCLKMGR = (volatile XLLP_CLKMGR_T *) pAc97ctxt->pClockReg;
XLLP_UINT32_T pins[9], fn[6];
/*
#ifdef FORCE_ZOAR_SSPTXD_HIGH
//force gpio 87 low
pins[0] = 1; //SPECIFY 3 PIN ITEMS
pins[1] = 87; //ssptxd2
fn[0] = 1;
fn[1] = XLLP_GPIO_ALT_FN_0; ////no alt function, use as gpio
XllpGpioSetOutput0((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioSetDirectionOut((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioSetAlternateFn((XLLP_GPIO_T *)pGPIO, pins, fn);
#endif
*/
// Set bitclk, sdata_in_0
pins[0] = 2;
pins[1] = XLLP_GPIO_AC97BITCLK;
pins[2] = XLLP_GPIO_AC97_SDATA_IN_0;
fn[0] = 2;
fn[1] = XLLP_GPIO_ALT_FN_1;
fn[2] = XLLP_GPIO_ALT_FN_1;
if (XLLP_TRUE == pAc97ctxt->bUseSecondaryCodec)
{
pins[0] = 3;
pins[3] = XLLP_GPIO_KP_MKIN5; // use this pin as AC97_SDATA_IN_1
fn[0] = 3;
fn[3] = XLLP_GPIO_ALT_FN_2;
}
XllpGpioSetDirectionIn((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioSetAlternateFn((XLLP_GPIO_T *)pGPIO, pins, fn);
// Set sdata_out, sync, sysclock
#ifdef USE_AC97SYSCLK //this is broken, we need to address this in another layer
pins[0] = 3; //SPECIFY 3 PIN ITEMS
#else
pins[0] = 2; //SPECIFY 2 PIN ITEMS
#endif
pins[1] = XLLP_GPIO_AC97_SDATA_OUT;
pins[2] = XLLP_GPIO_AC97_SYNC;
#ifdef USE_AC97SYSCLK
#ifdef MSII //this is broken, we need to address this in another layer
pins[3] = XLLP_GPIO_BTRTS; // use GPIO 45 as AC97_SYSCLK
#else //ZOAR
pins[3] = XLLP_GPIO_KP_MKIN4; // use GPIO 98 as AC97_SYSCLK
#endif
#endif
fn[0] = 3; //SPECIFY 3 FUNCTION ITEMS
fn[1] = XLLP_GPIO_ALT_FN_2; //SDATA_OUT IS ALT FN 2
fn[2] = XLLP_GPIO_ALT_FN_2; //AC97_SYC IS ALT FN 2
fn[3] = XLLP_GPIO_ALT_FN_1; ////AC97_SYSCLK IS ALT FN on pin 45 or 98
XllpGpioSetOutputState1((XLLP_GPIO_T *)pGPIO, pins); //INITIAL STATE OF THE GPIO
XllpGpioSetDirectionOut((XLLP_GPIO_T *)pGPIO, pins); //SET THEM FOR OUTPUT
XllpGpioSetAlternateFn((XLLP_GPIO_T *)pGPIO, pins, fn); //ASSIGN ALT FUNC FOR GPIOS
// Set sdata_reset_n
pins[0] = 1;
pins[1] = XLLP_GPIO_AC97_RESET_n;
fn[0] = 1;
fn[1] = XLLP_GPIO_ALT_FN_0;
XllpGpioSetOutput0((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioSetDirectionOut((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioSetAlternateFn((XLLP_GPIO_T *)pGPIO, pins, fn);
// Enable clocking of AC '97 controller device in processor
pCLKMGR->cken |= XLLP_CLKEN_AC97;
// Perform the cold reset.
// Also enables the codec(s), control unit and the control unit's FIFOs
status = XllpAc97ACODECColdReset(pAc97ctxt);
return (status);
} // End XllpAc97Init ()
/*******************************************************************************
*
* FUNCTION: XllpAc97ACODECDeInit
*
* DESCRIPTION: Shutdown AC97 unit clearly and thoroughly.
* Release GPIOs used by AC97.
* Disable clock to AC97 unit.
*
* INPUT PARAMETERS:
* pAc97ctxt a pointer to a XLLP_ACODEC_CONTEXT_T struct, which contains
* necessary information.
*
* RETURNS:
* Success: 0 (XLLP_AC97_NO_ERROR)
* Failure: Refer to XllpAc97ACODECShutdownAclink
*
* CALLS: XllpAc97ACODECShutdownAclink
*
* CALLED BY:
*
* PROTOTYPE: XLLP_ACODEC_ERROR_T XllpAc97ACODECDeInit(P_XLLP_ACODEC_CONTEXT_T pAc97ctxt);
*
*******************************************************************************/
XLLP_ACODEC_ERROR_T XllpAc97ACodecDeInit(XLLP_ACODEC_CONTEXT_T * pAc97ctxt)
{
XLLP_ACODEC_ERROR_T status ;
volatile XLLP_GPIO_T *pGPIO = (volatile XLLP_GPIO_T *) pAc97ctxt->pGpioReg;
volatile XLLP_CLKMGR_T *pCLKMGR = (volatile XLLP_CLKMGR_T *) pAc97ctxt->pClockReg;
XLLP_UINT32_T pins[8];
status = XllpAc97ACODECShutdownAclink((P_XLLP_AC97ACODEC_T)(pAc97ctxt->pPCMReg), pAc97ctxt->pOSTRegs);
if (XLLP_ACODEC_SUCCESS == status)
{
// Disable clocking of AC '97 controller device in processor
pCLKMGR->cken &= ~XLLP_CLKEN_AC97;
// Set all pins to default general input configuration.
pins[0] = 5;
#ifdef USE_AC97SYSCLK
#ifndef MSII //for zoar
pins[0] = 6;
pins[6] = XLLP_GPIO_KP_MKIN4; // use this pin as AC97_SYSCLK
#endif
#endif
pins[1] = XLLP_GPIO_AC97BITCLK;
pins[2] = XLLP_GPIO_AC97_SDATA_IN_0;
pins[3] = XLLP_GPIO_AC97_SDATA_OUT;
pins[4] = XLLP_GPIO_AC97_SYNC;
pins[5] = XLLP_GPIO_AC97_RESET_n;
if (XLLP_TRUE == pAc97ctxt->bUseSecondaryCodec)
{
pins[0] ++;
pins[pins[0]] = XLLP_GPIO_KP_MKIN5; // use this pin as AC97_SDATA_IN_1
}
XllpGpioSetDirectionIn((XLLP_GPIO_T *)pGPIO, pins);
XllpGpioClearAlternateFn((XLLP_GPIO_T *)pGPIO, pins);
}
return (status);
}
static void XllpAc97ACODECGetStatus(XLLP_AC97_ACODEC_STAT_T *pStat, P_XLLP_AC97ACODEC_T pAc97Reg, XLLP_AC97_ACODEC_SEL_T codecSel)
{
if (XLLP_AC97_ACODEC_PRIMARY == codecSel)
{
pStat->codecReady = (pAc97Reg->GSR & XLLP_AC97_GSR_PCRDY_MSK) ? XLLP_TRUE : XLLP_FALSE;
}
else
{
pStat->codecReady = (pAc97Reg->GSR & XLLP_AC97_GSR_SCRDY_MSK) ? XLLP_TRUE : XLLP_FALSE;
}
}
XLLP_ACODEC_ERROR_T XllpAc97ACodecWrite (XLLP_ACODEC_CONTEXT_T *pDevContext, XLLP_UINT16_T offset, XLLP_UINT16_T data)
{
XLLP_ACODEC_ERROR_T status = XLLP_ACODEC_SUCCESS;
XLLP_BOOL_T gotLink;
XLLP_UINT32_T timeRemaining;
P_XLLP_VUINT32_T pCodecReg;
P_XLLP_AC97ACODEC_T pAc97Reg = (P_XLLP_AC97ACODEC_T)(pDevContext->pPCMReg);
P_XLLP_OST_T pOstRegs = pDevContext->pOSTRegs;
XLLP_UINT32_T maxRWTimeOutUs = (pDevContext->uMaxReadWriteTimeOutMs) * 1000;
XLLP_AC97_ACODEC_SEL_T codecSel = XLLP_AC97_ACODEC_PRIMARY;
if((offset == XLLP_AC97_CR_E_MDM_GPIO_PIN_STAT) && (WM_9712_ID == pDevContext->ACodecId))
{
// This is a work around for the WM9712 GPIO status issue.
// Note that the WM9712 can only be used as a primary
// AC97 device.
XLLP_UINT16_T offsetdata = data << 1;
pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -