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

📄 wm97power.c

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 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 4176 2006-10-17 07:50:59Z 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:    WM97PowerInit
 *
 * Initalise the driver in a low power state.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      driverId            The device ID (e.g. WM_DRIVER_TOUCH)
 *
 * Returns:     WMSTATUS
 *        See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WM97PowerInit( WM_DEVICE_HANDLE  hDevice,
                        WM_DRIVER_ID      driverId
                      )
{
    WMSTATUS status;

#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 */

    /*
     * For all other AC97 device, except the WM9713 family, that start powered
     * up, power down the audio section of the device.
     */

    if ( !IS_WM9713_FAMILY( hDevice ) )
    {
        status = WM97PowerDown( hDevice, driverId, WM_POWER_AUDIO );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    }
    else
    {
        /*
         * To reduce pops and clicks on the outputs always
         * leave them powered up but leave the mixer to outputs at Vmid
         * until we need it. This also requires the 1 Meg Vmid resistor
         * string to be powered up.
         * 
         * Enable the thermal sensor to protect
         * the outputs from becoming too hot.
         *
         */

        /*
         * Power up PR3 (VREF)in reg 0x26
         */
        status = WMClearField( hDevice, WM97_POWER_CONTROL, WM97_PWR_VREF );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }

        /*
         * Power up VREF, the 1 Meg Vmid resistor string and thermal shutdown bits
         * in register 0x3C
         */
        status = WMClearField( hDevice,
                               WM9713_EXT_POWERDOWN_1,
                               ( WM9713_EXTPWR_VREF              |
                                 WM9713_EXTPWR_VMID1M            |
                                 WM9713_EXTPWR_THERMALSHUT
                               )
                             );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }

        /*
         * Enable fast power up of outputs.
         */
        status = WMSetField( hDevice, 
                             WM9713_FAST_POWER_CONTROL, 
                             (  WM9713_FAST_POWER_OUT4_ENABLE |
                                WM9713_FAST_POWER_OUT3_ENABLE |
                                WM9713_FAST_POWER_HPR_ENABLE  |
                                WM9713_FAST_POWER_HPL_ENABLE  |
                                WM9713_FAST_POWER_SPKR_ENABLE |
                                WM9713_FAST_POWER_SPKL_ENABLE |
                                WM9713_FAST_POWER_MONO_ENABLE ),
                             (  WM9713_FAST_POWER_OUT4_ENABLE |
                                WM9713_FAST_POWER_OUT3_ENABLE |
                                WM9713_FAST_POWER_HPR_ENABLE  |
                                WM9713_FAST_POWER_HPL_ENABLE  |
                                WM9713_FAST_POWER_SPKR_ENABLE |
                                WM9713_FAST_POWER_SPKL_ENABLE |
                                WM9713_FAST_POWER_MONO_ENABLE )
                           );
        /*
         * Power up PR6 (Ouputs) in reg 0x26
         */
        status = WMClearField( hDevice, WM97_POWER_CONTROL, WM97_PWR_OUTPUTS );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
        /*
         * Power up the output PGAs in register 0x3E.
         */
        status = WMClearField( hDevice,
                               WM9713_EXT_POWERDOWN_2,
                               ( WM9713_EXTPWR_SPEAKER_RIGHT    |
                                 WM9713_EXTPWR_SPEAKER_LEFT     |
                                 WM9713_EXTPWR_HEADPHONE_RIGHT  |
                                 WM9713_EXTPWR_HEADPHONE_LEFT   |
                                 WM9713_EXTPWR_OUT3             |
                                 WM9713_EXTPWR_OUT4             |
                                 WM9713_EXTPWR_MONOOUT )
                             );
        if ( WM_ERROR( status ) )
        {
            goto error;
        }
    }
    return WMS_SUCCESS;

error:
    return status;
}

/*-----------------------------------------------------------------------------
 * 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;
            }
        }

        /* 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;
                }

⌨️ 快捷键说明

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