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

📄 xllp_ac97.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/******************************************************************************
 **
 **  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_ac97.c
 **
 **  PURPOSE:        XLLP for Bulverde's AC'97 Controller Unit.
 **                  Includes initialization, API and support
 **                  functions.  Corresponds to XLLP_AC97_LLD.doc.
 **
 **  Valid for    :  Subset of AC '97 Rev 2.1
 **
 **
 ******************************************************************************/

#include "xllp_ac97.h"
#include "xllp_ac97acodec.h"
#include "xllp_ost.h"
#include "xllp_clkmgr.h"
#include "xllp_gpio.h"
#include "xllp_intc.h"

static XLLP_BOOL_T XllpAc97LinkLock(P_XLLP_AC97_T pAc97);


/*******************************************************************************
 *
 * FUNCTION:         XllpAc97Init
 *
 * 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_AC97_CONTEXT_T struct, which contains 
 *						necessary setup information.
 *
 * RETURNS:   
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_CODEC_NOT_READY
 *
 * 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:            XllpAc97ColdReset      
 *
 * CALLED BY:        
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97Init(XLLP_AC97_CONTEXT_T *pAc97ctxt);
 *
 *******************************************************************************/

XLLP_AC97_ERROR_T  XllpAc97Init(XLLP_AC97_CONTEXT_T *pAc97ctxt)
{
    XLLP_AC97_ERROR_T	status ;
    P_XLLP_GPIO_T		pGPIO = pAc97ctxt->pGpioReg;
	P_XLLP_INTC_T		pINTC = pAc97ctxt->pIntcReg;
	P_XLLP_CLKMGR_T		pCLKMGR = pAc97ctxt->pClockReg;
    XLLP_UINT32_T		pins[6], fn[6];
	
    // 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->useSecondaryCodec)
    {
		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(pGPIO, pins);
    XllpGpioSetAlternateFn(pGPIO, pins, fn);
    
    // Set sdata_out, sync, sysclock
    pins[0] = 2;
    pins[1] = XLLP_GPIO_AC97_SDATA_OUT;
    pins[2] = XLLP_GPIO_AC97_SYNC;
//    pins[3] = XLLP_GPIO_KP_MKIN4;     // use this pin as AC97_SYSCLK 
    fn[0] = 2;
    fn[1] = XLLP_GPIO_ALT_FN_2;
    fn[2] = XLLP_GPIO_ALT_FN_2;
//    fn[3] = XLLP_GPIO_ALT_FN_1;
    XllpGpioSetOutputState1(pGPIO, pins);
    XllpGpioSetDirectionOut(pGPIO, pins);
    XllpGpioSetAlternateFn(pGPIO, pins, fn);
    
    // 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(pGPIO, pins);
    XllpGpioSetDirectionOut(pGPIO, pins);
    XllpGpioSetAlternateFn(pGPIO, pins, fn);
    
    // Disable of ACUNIT interrupt.
    pINTC->icmr &= ~XLLP_INTC_AC97;
	
    // 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 = XllpAc97ColdReset(pAc97ctxt);
    
    return (status);

} // End XllpAc97Init ()

/*******************************************************************************
 *
 * FUNCTION:         XllpAc97DeInit
 *
 * DESCRIPTION:      Shutdown AC97 unit clearly and thoroughly.
 *                   Release GPIOs used by AC97.
 *                   Disable clock to AC97 unit and interrupts from it. 
 *
 * INPUT PARAMETERS: 
 *       pAc97ctxt   a pointer to a XLLP_AC97_CONTEXT_T struct, which contains 
 *						necessary information.
 *
 * RETURNS:
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_LINK_SHUTDOWN_FAIL
 *
 * CALLS:            XllpAc97ShutdownAclink
 *
 * CALLED BY:        
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97DeInit(P_XLLP_AC97_CONTEXT_T pAc97ctxt);
 *
 *******************************************************************************/

XLLP_AC97_ERROR_T  XllpAc97DeInit(P_XLLP_AC97_CONTEXT_T pAc97ctxt)
{
    XLLP_AC97_ERROR_T	status ;
    P_XLLP_GPIO_T		pGPIO = pAc97ctxt->pGpioReg;
	P_XLLP_INTC_T		pINTC = pAc97ctxt->pIntcReg;
	P_XLLP_CLKMGR_T		pCLKMGR = pAc97ctxt->pClockReg;
    XLLP_UINT32_T		pins[8];
	
    status = XllpAc97ShutdownAclink(pAc97ctxt->pAc97Reg, pAc97ctxt->pOstRegs);

	if (XLLP_AC97_NO_ERROR == status)
	{
        // Disable of ACUNIT interrupt.
	    pINTC->icmr &= ~XLLP_INTC_AC97;

	    // Disable clocking of AC '97 controller device in processor
	    pCLKMGR->cken &= ~XLLP_CLKEN_AC97;

		// Set all pins to default general input configuration.
    	pins[0] = 6;
        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_KP_MKIN4;     // use this pin as AC97_SYSCLK 
        pins[6] = XLLP_GPIO_AC97_RESET_n;

        if (XLLP_TRUE == pAc97ctxt->useSecondaryCodec)
        {
			pins[0] = 7;
			pins[7] = XLLP_GPIO_KP_MKIN5;      // use this pin as AC97_SDATA_IN_1 
		}
		XllpGpioSetDirectionIn(pGPIO, pins);
        XllpGpioClearAlternateFn(pGPIO, pins);
	}
    	
    return (status);
}

/*******************************************************************************
 *
 * FUNCTION:         XllpAc97GetStatus 
 *
 * DESCRIPTION:      Reports the value of the specified status indicator, as
 *                   obtained from the ACUNIT's GSR register.  Clears the
 *                   status indicator, if possible, after reading it.
 *
 *                   Should not be used for status types that are currently in 
 *                   use as interrupt triggers.
 *
 * INPUT PARAMETERS: 
 *             P_XLLP_AC97_T pAc97Reg : a pointer to AC97 unit registers structure.
 *             XLLP_AC97_CODEC_SEL_T codecSel : Select which codec to be concerned.
 *
 * OUTPUT PARAMETERS:
 *             XLLP_AC97_STAT_T *pStat : a pointer to a status structure where lies result. 
 *
 * RETURNS:    None
 *
 * CALLS:            
 *
 * CALLED BY:        
 *
 * PROTOTYPE:   void  XllpAc97GetStatus(XLLP_AC97_STAT_T *pStat, P_XLLP_AC97_T pAc97Reg,
 *                                       XLLP_AC97_CODEC_SEL_T codecSel);
 *
 *******************************************************************************/

void  XllpAc97GetStatus(XLLP_AC97_STAT_T *pStat, P_XLLP_AC97_T pAc97Reg, XLLP_AC97_CODEC_SEL_T codecSel)
{
	if (XLLP_AC97_CODEC_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;
	}
} // Ac97CtrlGetStatus()


/*******************************************************************************
 *
 * FUNCTION:         XllpAc97Write
 *
 * DESCRIPTION:      Write a value to a specific mixer register in a specific 
 *                   AC'97 codec or modem, using the AC Link.
 *
 * INPUT PARAMETERS: 
 *        XLLP_UINT16_T offset : the offset address of the codec register to write.  
 *        XLLP_UINT16_T data : the data to be written. 
 *        P_XLLP_AC97_T pAc97Reg : a pointer to AC97 unit registers structure.  
 *        XLLP_UINT32_T maxRWTimeOutUs : timeout value in the writing process. 
 *        XLLP_AC97_CODEC_SEL_T codecSel : specify which codec device to write.
 *
 * RETURNS:          
 *       Success:    0 (XLLP_AC97_NO_ERROR)
 *       Failure:    XLLP_AC97_LINK_LOCK_FAIL: AC Link was not available within the 
 *                           timeout interval.
 *                   XLLP_AC97_CODEC_ACCESS_TIMEOUT: Writing was not finished within the 
 *                           timeout interval.
 *
 *
 * CALLS:            XllpAc97LinkLock, XllpOstDelayMicroSeconds          
 *
 * CALLED BY:        
 *
 * PROTOTYPE:        XLLP_AC97_ERROR_T  XllpAc97Write(XLLP_UINT16_T offset, 
 *								 XLLP_UINT16_T data, 
 *								 P_XLLP_AC97_T pAc97Reg,
 *								 P_XLLP_OST_T pOstRegs,
 *								 XLLP_UINT32_T maxRWTimeOutUs, 
 *								 XLLP_AC97_CODEC_SEL_T codecSel);
 *
 *******************************************************************************/

XLLP_AC97_ERROR_T  XllpAc97Write(XLLP_UINT16_T offset, 
								 XLLP_UINT16_T data, 
								 P_XLLP_AC97_T pAc97Reg, 
								 P_XLLP_OST_T pOstRegs,
								 XLLP_UINT32_T maxRWTimeOutUs, 
								 XLLP_AC97_CODEC_SEL_T codecSel) 
{
    XLLP_AC97_ERROR_T	status = XLLP_AC97_NO_ERROR;
    XLLP_BOOL_T			gotLink;
    XLLP_UINT32_T		timeRemaining;
    P_XLLP_VUINT32_T	pCodecReg;
    
    // Point to specified register within area mapped to target codec regs

    // Check for special case register 54h the GPIO status register

    if(offset == XLLP_AC97_CR_E_MDM_GPIO_PIN_STAT)
    {
#ifdef WM9712
        
        // 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]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data will be sent out on slots 1&2 to register 54h.
        *pCodecReg = (XLLP_VUINT32_T)data;

        pCodecReg = &(pAc97Reg->CodecRegsPrimaryMdm[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data will be sent out on slot 12.
        *pCodecReg = (XLLP_VUINT32_T)offsetdata;
       
#else
        // Select the Primary or Secondary modem IO address space
	    if (XLLP_AC97_CODEC_PRIMARY == codecSel)
            pCodecReg = &(pAc97Reg->CodecRegsPrimaryMdm[0]);
        else
            pCodecReg = &(pAc97Reg->CodecRegsSecondaryMdm[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;

        // The data will be sent out on slot 12.
        *pCodecReg = data;
   
#endif
        goto done;
    }
    else
    {
        // Select the Primary or Secondary Audio IO address space
	    if (XLLP_AC97_CODEC_PRIMARY == codecSel)
            pCodecReg = &(pAc97Reg->CodecRegsPrimaryAud[0]);
        else
            pCodecReg = &(pAc97Reg->CodecRegsSecondaryAud[0]);

        pCodecReg += offset / XLLP_AC97_CODEC_REGS_PER_WORD;  
    }
    

	//Lock the ACLINK
    timeRemaining = XLLP_AC97_LOCK_TIMEOUT_DEF;

⌨️ 快捷键说明

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