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

📄 wm97power.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------
 * 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: WM97Power.c 2828 2006-04-06 14:11:45Z ian $
 *
 * This file contains functionality for controlling power on AC97 codecs.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 * -----------------------------------------------------------------------------*/

 
/*
 * Include files
 */
#include "WMCommon.h"
#include "WMDevice.h"
#include "WMControlLink.h"
#include "WMPlatformACLink.h"
#include "WMACLink.h"
#include "WMPower.h"
#include "WM97Power.h"

/*
 * Global definitions
 */


/*
 * Touch panel masks.
 */

/*
 * Private data
 */

/*
 * Only provide these if we're supporting Wolfson AC97 devices.
 */
#if WM_AC97

/*
 * Function prototypes
 */
static WM_REGVAL private_CalcPdwValue( WM_DEVICE_HANDLE hDevice,
                                       WM_POWERFLAG     powerSections
                                     );

static WM_POWERFLAG private_CalcTouchPower( WM_DEVICE_HANDLE hDevice );

/*-----------------------------------------------------------------------------
 * Function:    WM97PowerUp
 *
 * Called to power up the specific sections of the chip on behalf of this
 * driver.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      driverId               The device ID (e.g. WM_DRIVER_TOUCH)
 *      powerSections       The sections to power up.
 *
 * Returns:     WMSTATUS
 *        See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WM97PowerUp( WM_DEVICE_HANDLE  hDevice,
                      WM_DRIVER_ID      driverId,
                      WM_POWERFLAG      powerSections
                    )
{
#if WM_CACHE_POWER_STATE
    WM_DEVICE_CONTEXT   *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
#endif /* WM_CACHE_POWER_STATE */
    WMSTATUS            status;
    WM_POWERFLAG        newPowered = 0; /* What should be powered when we finish */
    WM_POWERFLAG        powerUp;        /* What should be but isn't yet */
    WM_REGVAL           powerReg;
    WM_POWERFLAG        currentPower;
    
    /*
     * Work out what we need powered on.
     * newPowered is what will be powered on at the end.
     * powerUp is what will be powered up which isn't currently.
     * 
     * Note: there are things which need to be done even if the codec is
     * powered up, since some codecs start up with everything on.  In this
     * case we don't need to power anything up, but we still need to do
     * other things such as enabling on-board amplifiers (for example).
     */
    newPowered = calcPowered( hDevice, driverId, powerSections, 0, &currentPower );
    powerUp = newPowered & ~currentPower;

    /*
     * If the AC Link's not powered up, enable the controller to use the AC link
     *  and do a warm reset to start it up.
     */
    if ( !(currentPower & WM_POWER_LINK) )
    {
        WMPlatformACLinkEnableController( hDevice );
        status = WMWake( hDevice );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    }

    /*
     * Get the current reading if necessary.
     */
#if WM_CACHE_POWER_STATE
    if ( pDeviceContext->v_pWMData &&
         (pDeviceContext->v_pWMData->flags & WM_POWERREG_VALID)
       )
    {
        powerReg = pDeviceContext->v_pWMData->powerReg[PWR_REG_1];
    }
    else
#endif /* WM_CACHE_POWER_STATE */
    {
        status = WMRead( hDevice, WM97_POWER_CONTROL, &powerReg );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }

#if WM_CACHE_POWER_STATE
        if ( pDeviceContext->v_pWMData )
        {
            pDeviceContext->v_pWMData->flags |= WM_POWERREG_VALID;
        }
#endif /* WM_CACHE_POWER_STATE */
    }

    /*
     * Enable audio.
     * Recommended power-up sequence is
     * PR5, PR3, PR2, PR1, PR0, PR6
     * (PR4 is automatic on wake-up)
     * 
     * Note: we use newPowered in this test (instead of powerUp)
     * because there are things we may still need to do if the
     * audio starts up powered up.
     * We do not want to do any of this if we are only powering up the
     * touch part of the device.
     */
    if ( ( newPowered & WM_POWER_AUDIO ) && ( powerUp & ~WM_POWER_TOUCH ) )
    {
        /*
         * The 9712 defaults to no ramp-down - turn it on (clear it) to
         * avoid clicks on muting, powerup/down, etc.
         */
        if ( IS_WM9712_FAMILY( hDevice ) )
        {
            status = WMClearField( hDevice, WM9712_ADD_FUN2, WM9712_ADDFUN_RAMPDOWN );
            if ( WM_ERROR( status ) )
            {
                WM_TRACE( hDevice,
                          ( "WMPowerUp - couldn't enable rampdown: %s",
                            WMStatusText( status ) ) );

                /*
                 * If this failed, something's gone seriously wrong - we can't read
                 * or we can't write - so there's no point trying to continue.
                 */
                goto error;
            }
        }

#if !WM_ZERO_DATA_DAC_SWITCH_ENABLE
        /* 
         * Very quiet samples which swing from total silence to 
         * a small noise floor can cause problems as the stereo DAC 
         * mutes output only for for the truly silent sections. 
         * If this causes a problem the following code should cure it.
         */ 
        if ( IS_WM9705_FAMILY( hDevice ) ||
             IS_WM9712_FAMILY( hDevice ) || 
             ( IS_WM9713_FAMILY( hDevice ) && WM_REVISION_EQUALS( hDevice, WM_REV_A ) )
           )
        {
            status = WMClearField( hDevice,
                                   WM97_ADD_FUN_CONTROL,
                                   WM97_ADDFUN_AMUTE
                                 );
            if ( WM_ERROR( status ) )
            {
                WM_TRACE( hDevice,
                          ( "WMPowerUp - couldn't disable automute: %s",
                            WMStatusText( status ) ) );

                /*
                 * If this failed, something's gone seriously wrong - we can't read
                 * or we can't write - so there's no point trying to continue.
                 */
                goto error;
            }
        }

        /*
         * When the DAC is operating at a sample rate other than 48KHz
         * it will switch to 48 khz when enough silence is played. 
         */
        if ( IS_WM9713_FAMILY( hDevice ) && WM_REVISION_EQUALS( hDevice, WM_REV_A ) )
        {
            status = WMSetField( hDevice, WM9713_RESERVED_1, 
                                 WM9713_ZERO_DATA_SWITCH_DISABLE,
                                 WM9713_ZERO_DATA_SWITCH_DISABLE );
            if ( WM_ERROR( status ) )
            {
                WM_TRACE( hDevice,
                          ( "WMPowerUp - couldn't disable zero data switch: %s",
                            WMStatusText( status ) ) );

                /*
                 * If this failed, something's gone seriously wrong - we can't read
                 * or we can't write - so there's no point trying to continue.
                 */
                goto error;
            }
        }
        else if ( IS_WM9712_FAMILY( hDevice ) )
        {
            status = WMSetField( hDevice, WM9712_ADD_FUN2, 
                                 WM9712_ZERO_DATA_SWITCH_DISABLE,
                                 WM9712_ZERO_DATA_SWITCH_DISABLE );
            if ( WM_ERROR( status ) )
            {
                WM_TRACE( hDevice,
                          ( "WMPowerUp - couldn't disable zero data switch: %s",
                            WMStatusText( status ) ) );

                /*
                 * If this failed, something's gone seriously wrong - we can't read
                 * or we can't write - so there's no point trying to continue.
                 */
                goto error;
            }
        }
#endif /* WM_ZERO_DATA_DAC_SWITCH_ENABLE */

        /* Turn on the clock (PR5). */
        if ( powerUp & WM_POWER_CLOCK )
        {
            powerReg &= ~WM97_PWR_CLOCK;
            status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
        }

        /* Turn on VREF (PR3). */
        if ( powerUp & WM_POWER_VREF )
        {

            powerReg &= ~WM97_PWR_VREF;
            status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }

            /* 
             * For WM9713 both the PR3 in register 26h and
             * MBIAS in register 3Ch must be cleared.
             */
            status = WMClearField( hDevice,
                                   WM9713_EXT_POWERDOWN_1,
                                   WM9713_EXTPWR_MBIAS
                                 );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
        }

        /* 
         * Turn on the mixers and input PGAs 
         * and for WM9712 only OUT2 (PR2).
         */
        if ( powerUp & WM_POWER_MIXERS )
        {
            powerReg &= ~WM97_PWR_MIXERS;
            status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }
            if ( IS_WM9713_FAMILY( hDevice ) )
            {
                /* 
                 * For WM9713 both the PR2 in register 26h and
                 * mixers in register 3Ch must be cleared.
                 */
                status = WMClearField( hDevice,
                                       WM9713_EXT_POWERDOWN_1,
                                       ( WM9713_EXTPWR_MONOMIX     |
                                         WM9713_EXTPWR_SPEAKERMIX  |
                                         WM9713_EXTPWR_HPMIX_RIGHT |
                                         WM9713_EXTPWR_HPMIX_LEFT )
                                     );
                if ( WM_ERROR( status ) )
                {
                    goto error;
                }

                /*
                 * For WM9713 both the PR2 in register 26h and
                 * input PGAs in register 3Eh must be cleared.
                 */
                status = WMClearField( hDevice,
                                       WM9713_EXT_POWERDOWN_2,
                                       ( WM9713_EXTPWR_MIC_PREAMP_B |
                                         WM9713_EXTPWR_MIC_PREAMP_A |
                                         WM9713_EXTPWR_MIC_B        |
                                         WM9713_EXTPWR_MIC_A        |
                                         WM9713_EXTPWR_MONOIN       |
                                         WM9713_EXTPWR_LINEIN_RIGHT |
                                         WM9713_EXTPWR_LINEIN_LEFT )
                                     );
                if ( WM_ERROR( status ) )
                {
                    goto error;
                }
            }
        }
        
        /* Turn on the DACs (PR1) */
        if ( powerUp & WM_POWER_AUDIO_DACS )
        {
            powerReg &= ~WM97_PWR_DAC;
            status = WMWrite( hDevice, WM97_POWER_CONTROL, powerReg );
            if ( WM_ERROR( status ) )
            {
                goto error;
            }

            if ( IS_WM9713_FAMILY( hDevice ) )
            {
                /*
                 * For WM9713 both the PR1 in register 26h and
                 * DACs in register 3Ch must be cleared.
                 */
                status = WMClearField( hDevice,
                                       WM9713_EXT_POWERDOWN_1,
                                       ( WM9713_EXTPWR_DAC_LEFT  |
                                         WM9713_EXTPWR_DAC_RIGHT |
                                         WM9713_EXTPWR_AUXDAC    |

⌨️ 快捷键说明

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