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

📄 wmxscaleaclink.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 4 页
字号:
/*-----------------------------------------------------------------------------
 * Copyright (c) Wolfson Microelectronics plc.  All rights reserved.
 *
 * This software as well as any related documentation 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 Wolfson Microelectronics plc. Wolfson Microelectronics plc
 * 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 Wolfson Microelectronics plc. 
 *
 * $Id: WMXScaleACLink.c 2924 2006-04-12 12:50:25Z fb $
 *
 * This file contains XScale AC Link functionality for the drivers for
 * the Wolfson chips.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 *  This platform file is specifically designed to work with the Cotulla AC'97
 *  controller and the Lubbock and Mainstone XScale platforms from Intel.  There
 *  is no guarantee of correct operation with other platforms/controllers.
 *
 * -----------------------------------------------------------------------------*/

/*
 * IMPORTANT
 *
 * The functions in this file must obey two rules:
 *
 * 1. They do not use any memory other than stack space and parameters passed in.
 * 2. They do not make system calls, unless the context parameter 
 *    preventSyscallCount is zero.
 *
 * All functions take a context parameter, which passes in pointers to the virtual
 * addresses of memory-mapped registers, and stores what type of device is being
 * accessed.
 * 
 * Some client functions provide shared memory via the v_pWMData member of the
 * context structure.  This cannot be relied on.
 */
 
/*
 * Note:  In some circumstances, checking the CAIP bit in the CAR can cause
 * Bulverde (PXA270) to hang.  This means that these raw functions are not
 * synchronised across threads/processes, and hence the higher level functions
 * are responsible for ensuring this synchronisation.
 */
 
/*
 * Include files
 */
#include "WMCommon.h"
#include "WMPlatformACLink.h"
#include "WMInterrupts.h"
#include "WMDevice.h"
#include "WMPlatformDeviceContext.h"
#include "Test/WMTestCommon.h"
#include "Test/WMInternalTests.h"

#if WM_USE_XLLP_AC97
#   include "xllp_acodec.h"
#   include "xllp_ac97acodec.h"
#endif /* WM_USE_XLLP_AC97 */

#if WM_BOARD_MAINSTONEII
#   include "xllp_bcr.h"
#endif /* WM_BOARD_MAINSTONEII */

#if WM_AC97

/*
 * Global definitions
 */

/*
 * Access to the register spaces.
 */
#define PRIMARY_CODEC_REGS(_ctx)    ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsPrimaryAud)
#if XLLP_AVAILABLE
#define SECONDARY_CODEC_REGS(_ctx)  ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsSecondaryAud)
#define PRIMARY_MODEM_REGS(_ctx)    ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsPrimaryMdm)
#define SECONDARY_MODEM_REGS(_ctx)  ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsSecondaryMdm)
#else /* XLLP_AVAILABLE */
#define SECONDARY_CODEC_REGS(_ctx)  ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsPrimaryAud + 0x100)
#define PRIMARY_MODEM_REGS(_ctx)    ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsPrimaryAud + 0x200)
#define SECONDARY_MODEM_REGS(_ctx)  ((unsigned int)&_ctx->v_pAC97Regs->CodecRegsPrimaryAud + 0x300)
#endif /* XLLP_AVAILABLE */

/*
 * Build up an ACodec context structure from our pDeviceContext.
 */
#define ACODEC_FROM_DEVICE_CONTEXT( pACodecIn, pDeviceContext ) do {            \
    XLLP_ACODEC_CONTEXT_T *pACodec = pACodecIn;                                 \
    switch ( pDeviceContext->deviceType )                                       \
    {                                                                           \
        case WM_CHIP_WM9703:                                                    \
            pACodec->ACodecId = WM_9703_ID;                                     \
            break;                                                              \
        case WM_CHIP_WM9704:                                                    \
            pACodec->ACodecId = WM_9704_ID;                                     \
            break;                                                              \
        case WM_CHIP_WM9705:                                                    \
            pACodec->ACodecId = WM_9705_ID;                                     \
            break;                                                              \
        case WM_CHIP_WM9712:                                                    \
            pACodec->ACodecId = WM_9712_ID;                                     \
            break;                                                              \
        case WM_CHIP_WM9713:                                                    \
            pACodec->ACodecId = WM_9713_ID;                                     \
            break;                                                              \
        default:                                                                \
            pACodec->ACodecId = 0;                                              \
    }                                                                           \
    pACodec->pGpioReg = pDeviceContext->v_pGPIORegs;                            \
    pACodec->pPCMReg = (XLLP_I2S_T *) pDeviceContext->v_pAC97Regs;              \
    pACodec->pCtrlReg = NULL;                                                   \
    pACodec->pClockReg = pDeviceContext->v_pClkRegs;                            \
    pACodec->pSSPReg = NULL;                                                    \
    pACodec->pOSTRegs = (XLLP_OST_T *) pDeviceContext->v_pOSTimerRegs;          \
    pACodec->uMaxReadWriteTimeOutMs = CODEC_TIMEOUT;                            \
    pACodec->uMaxSetupTimeOutMs = CODEC_TIMEOUT;                                \
                                                                                \
    if ( WM_DEV_AC97_PRIMARY == pDeviceContext->deviceID )                      \
        pACodec->bUseSecondaryCodec = 0;                                        \
    else                                                                        \
        pACodec->bUseSecondaryCodec = 1;                                        \
    } while (0)


/*
 * Function prototypes
 */

/*-----------------------------------------------------------------------------
 * Macro:    private_IsCodecReady
 *
 * Detects whether the codec is ready to rumble - whether the appropriate
 * codec ready bit is set.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WM_BOOL
 *      TRUE if the codec is ready.
 *---------------------------------------------------------------------------*/
#define private_IsCodecReady( pDeviceContext )                      \
    ((((WM_XSCALE_DEVICE_CONTEXT *)pDeviceContext)->v_pAC97Regs->GSR & AC97GSR_CODEC_READY)\
     ? TRUE : FALSE )

/*
 * Private data
 */

/*
 * Function prototypes
 */
static WMSTATUS private_WaitForCommandDone( WM_DEVICE_HANDLE hDevice );
static WMSTATUS private_WaitForStatusDone( WM_DEVICE_HANDLE hDevice );
static WMSTATUS private_ConfigureACLinkGPIO( WM_DEVICE_HANDLE hDevice );
static void private_UnconfigureACLinkGPIO( WM_DEVICE_HANDLE hDevice );

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkInit
 *
 * Initialises the WM97xx platform-specific layer for the specific hardware
 * and leaves it with the AC-Link up and running.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h
 *---------------------------------------------------------------------------*/
WMSTATUS WMPlatformACLinkInit( WM_DEVICE_HANDLE hDevice )
{
    WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = 
								(WM_XSCALE_DEVICE_CONTEXT*) hDevice;
    WMSTATUS                     status;

	/*
	 * Multiple drivers may try to initialise the codec. We need to 
	 * check with the codec to see if it is already initialised.
	 * If we can succesfully check to see if the codec ready bit is set
	 * then the device has already been initialised.
	 * This also stops the code from trying to perform a cold or warm
	 * reset when the link is running which is a good side effect.
	 */
	if ( private_IsCodecReady( hDevice ) )
	{
		goto done;
	}

	if ( ! pDeviceContext->v_pWMData->powerStateFlags & WM_ASLEEP )
    {
        /*
         * Check our internals code, if
         * this is _not_ WakeUp form SLEEP/IDLE
         */
        WMTEST_RUN( WMTestPlatformInternals( hDevice ) );
	}
    
    /*
     * If we're using XLLP, let it take care of the details.
     */
#if WM_USE_XLLP_AC97
    {
        XLLP_ACODEC_CONTEXT_T   ACodecCtxStruct;
        XLLP_ACODEC_ERROR_T     xllpStatus;
        
        ACODEC_FROM_DEVICE_CONTEXT( &ACodecCtxStruct, pDeviceContext );
        
#if !WM_MULTIPLE_CHIP_SUPPORT && WM9713_FAMILY
        /* 
         * The WM9713 has specific requirements so we should tell XLLP
         * as soon as possible.
         */
        ACodecCtxStruct.ACodecId = WM_9713_ID;
#else /* !WM_MULTIPLE_CHIP_SUPPORT && WM9713_FAMILY */
        /* 
         * Take a guess for now which will tell XLLP it's one of our
         * AC97 codecs - we'll check later exactly which one.
         */
        ACodecCtxStruct.ACodecId = WM_9712_ID;
#endif /* ! WM_MULTIPLE_CHIP_SUPPORT && WM9713_FAMILY*/

        /*
         * And call through to XLLP to do the work for us.
         */        
        xllpStatus = XllpACodecInit( &ACodecCtxStruct );
        if ( XLLP_ACODEC_SUCCESS != xllpStatus )
        {
            WM_TRACE( hDevice, (
                      "XllpACodecInit failed: 0x%X", xllpStatus ));
            status = XllpStatusToWMStatus( xllpStatus );
            goto error;
        }

#if WM_MULTIPLE_CHIP_SUPPORT && WM9713_FAMILY

		status = WMGetDeviceType(hDevice, NULL, NULL);
		if ( WM_ERROR(status) )
		{
			WM_TRACE( hDevice, ( "WMGetDeviceType failed: %s",
                WMStatusText( status ) ) );
			goto error;
		}

		if ( IS_WM9713_FAMILY( hDevice ) )
		{
			/* 
			 * The WM9713 has specific requirements so we should tell XLLP
			 * as soon as possible.
			 */
			ACodecCtxStruct.ACodecId = WM_9713_ID;

			/*
			 * And call through to XLLP to do the work for us (again).
			 */        
			xllpStatus = XllpACodecInit( &ACodecCtxStruct );
			if ( XLLP_ACODEC_SUCCESS != xllpStatus )
			{
				WM_TRACE( hDevice, ( "XllpACodecInit failed: 0x%X", xllpStatus ));
				status = XllpStatusToWMStatus( xllpStatus );
				goto error;
			}
		}
#endif /* WM_MULTIPLE_CHIP_SUPPORT && WM9713_FAMILY  */

    }
#else   /* WM_USE_XLLP_AC97 */
    /*
     * No XLLP - we need to do it all ourselves.
     */

    /*
     * Set up the GPIOs.
     */
    status = private_ConfigureACLinkGPIO( hDevice );
    if ( WM_ERROR( status ) )
    {
        goto error;
	}

    /*
     * Make sure the clock's running.
     */
    pDeviceContext->v_pClkRegs->cken |= XLLP_CLKEN_AC97;

    /* Wake up the AC Link */
    status = WMPlatformACLinkColdReset( hDevice );
    if ( WM_ERROR( status ) )
    {
        goto error;
    }

    /* Check for the codec ready bit */
    if ( !private_IsCodecReady( hDevice ) )
    {
        WM_TRACE( hDevice, ( "WMPlatformACLinkInit: Codec ready bit not set" ));
        status = WMS_CODEC_NOT_READY;
        goto error;
    }

#endif /* WM_USE_XLLP_AC97 */

#ifdef DEBUG
    if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_CODEC0_READY )
    {
        WM_TRACE( hDevice, ( "WM97: Codec on SDATA_IN_0" ));
    }
    if ( pDeviceContext->v_pAC97Regs->GSR & AC97GSR_CODEC1_READY )
    {
        WM_TRACE( hDevice, ( "WM97: Codec on SDATA_IN_1" ));
    }
#endif /* DEBUG */

    /*
     * It worked.
     */
done:
    pDeviceContext->flags |= DEVICE_INITIALISED;
    return WMS_SUCCESS;

error:
    WMPlatformACLinkShutdown( hDevice );
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WMPlatformACLinkShutdown
 *
 * Shuts down the WM97xx platform-specific layer.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/

⌨️ 快捷键说明

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