📄 wmdeviceutil.c
字号:
/*-----------------------------------------------------------------------------
* 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: WMDeviceUtil.c 2828 2006-04-06 14:11:45Z ian $
*
* This file contains device utility functionality.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
* -----------------------------------------------------------------------------*/
/*
* 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 WMSystemCallsAllowed returns TRUE.
*
* 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.
*/
/*
* Include files
*/
#include "WMCommon.h"
#include "WMGlobals.h"
#include "WMACLink.h"
#include "WMAudio.h"
#include "WMTouch.h"
#include "WMPower.h"
#include "WMDevice.h"
/*
* Global definitions
*/
/*
* Private data
*/
/*
* Function prototypes
*/
/*-----------------------------------------------------------------------------
* Function: WMInitDeviceId
*
* Initialise our device type information.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMInitDeviceId( WM_DEVICE_HANDLE hDevice )
{
WMSTATUS status = WMS_UNSUPPORTED;
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_ASSERT( hDevice, NULL != pDeviceContext );
if ( pDeviceContext->fnInitDeviceId )
{
status = pDeviceContext->fnInitDeviceId( hDevice );
}
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMGetDeviceType
*
* Returns the chip type and revision. Note: this assumes the hardware will
* not be changing on the fly.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* pChipType variable to receive the type of chip (one of the
* WM_CHIP_XXX constants. Can be NULL.
* pRevision variable to receive the chip revision. Can be NULL.
*
* Returns: WMSTATUS
* See WMStatus.h
*---------------------------------------------------------------------------*/
WMSTATUS WMGetDeviceType( WM_DEVICE_HANDLE hDevice,
WM_CHIPTYPE *pChipType,
WM_CHIPREV *pRevision
)
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status;
/*
* Lock our global data.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto error0;
}
if ( WM_CHIP_UNKNOWN == pDeviceContext->deviceType ||
pDeviceContext->flags & DEVICE_TYPE_NEEDS_CHECKING
)
{
/*
* Our chipdef may not be valid.
*/
pDeviceContext->pChipDef = NULL;
status = WMInitDeviceId( hDevice );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, ( "WM: Couldn't get device type" ) );
goto error1;
}
}
/*
* Look up our chipdef.
*/
pDeviceContext->pChipDef = WMGetChipDef( hDevice );
if ( !pDeviceContext->pChipDef )
{
status = WMS_NO_SUPPORTED_DEVICE;
WM_TRACE( hDevice, ( "WM: No supported device" ) );
goto error1;
}
/*
* And we're done - return the details.
*/
if ( pChipType )
*pChipType = pDeviceContext->deviceType;
if ( pRevision )
*pRevision = pDeviceContext->revision;
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
return WMS_SUCCESS;
error1:
WMUnlockGlobalData( hDevice );
error0:
if ( pChipType )
*pChipType = WM_CHIP_UNSUPPORTED;
if ( pRevision )
*pRevision = WM_REV_UNKNOWN;
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMEnterSleep
*
* Enters sleep mode - powers down the device and does any state preservation
* needed for restoring later.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMEnterSleep( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_SUCCESS;
/*
* Lock our global data.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto lockError;
}
if ( !( pDeviceContext->v_pWMData->powerStateFlags & WM_ASLEEP ) )
{
#if !WM_CACHE_POWER_STATE
/*
* We won't be able to calculate it, so save the current power level.
*/
pDeviceContext->v_pWMData->preSleepPower = WMGetCurrentPowerState( hDevice );
#endif
/*
* Say we're entering sleep.
*/
pDeviceContext->v_pWMData->powerStateFlags |= WM_ENTERING_SLEEP;
/*
* Now power everything down.
*/
status = WMPowerDown( hDevice, WM_DRIVER_INTERNAL, WM_POWER_ALL );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, ( "Unable to power down device" ) );
}
/*
* And get the platform layer to power down.
*/
WMPlatformEnterSleep( hDevice );
/*
* Now we're asleep.
*/
pDeviceContext->v_pWMData->powerStateFlags |= WM_ASLEEP;
pDeviceContext->v_pWMData->powerStateFlags &= ~WM_ENTERING_SLEEP;
}
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
return WMS_SUCCESS;
lockError:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMLeaveSleep
*
* Leaves sleep mode - powers the device back on again and restores any
* settings which couldn't be preserved.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMLeaveSleep( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WMSTATUS status = WMS_SUCCESS;
WM_POWERFLAG powerUp = 0;
/*
* Lock our global data.
*/
if ( !WMLockGlobalData( hDevice ) )
{
status = WMS_LOCK_TIMED_OUT;
goto lockError;
}
if ( pDeviceContext->v_pWMData->powerStateFlags & WM_ASLEEP )
{
pDeviceContext->v_pWMData->powerStateFlags |= WM_LEAVING_SLEEP;
/*
* Wake up the platform layer.
*/
WMPlatformLeaveSleep( hDevice );
/*
* Work out what we need to power up again.
*
* If we've got the previous state cached, we don't need to power up
* anything for the internals; we can calculate it from the cached
* settings.
*
* If we don't have the previous state cached, use the state we saved
* when going to sleep.
*/
#if WM_CACHE_POWER_STATE
powerUp = 0;
#else
powerUp = pDeviceContext->v_pWMData->preSleepPower;
#endif
/*
* Now actually power up again.
*/
status = WMPowerUp( hDevice, WM_DRIVER_INTERNAL, powerUp );
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, ( "Unable to power up device" ) );
}
/*
* We're now awake.
*/
pDeviceContext->v_pWMData->powerStateFlags &= ~WM_LEAVING_SLEEP;
pDeviceContext->v_pWMData->powerStateFlags &= ~WM_ASLEEP;
}
/* Let other threads in again */
WMUnlockGlobalData( hDevice );
return WMS_SUCCESS;
lockError:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMPreventSystemCalls
*
* Tells this module whether we can allow system calls.
* Note this is re-entrant - you must allow as many times as you prevent.
* Note this assumes that it is called under the power manager and that the
* power manager is single-threaded. Therefore calls to WMPreventSystemCalls
* and WMSystemCallsAllowed will not interfere with themselves/each other.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* prevent Whether to prevent or allow.
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMPreventSystemCalls( WM_DEVICE_HANDLE hDevice, WM_BOOL prevent )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( prevent )
{
pDeviceContext->preventSyscallCount++;
WM_ASSERT( hDevice, 0 != pDeviceContext->preventSyscallCount );
}
else
{
WM_ASSERT( hDevice, 0 != pDeviceContext->preventSyscallCount );
pDeviceContext->preventSyscallCount--;
}
}
/*-----------------------------------------------------------------------------
* Function: WMSystemCallsAllowed
*
* Tells this module whether we can make system calls.
* Note this assumes that it is called under the power manager and that the
* power manager is single-threaded. Therefore calls to WMPreventSystemCalls
* and WMSystemCallsAllowed will not interfere with themselves/each other.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WM_BOOL
* Whether the driver has been told to allow system calls.
*---------------------------------------------------------------------------*/
WM_BOOL WMSystemCallsAllowed( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( 0 == pDeviceContext->preventSyscallCount )
return TRUE;
else
return FALSE;
}
/*-----------------------------------------------------------------------------
* Function: MilliSleep
*
* Sleeps for the given number of milliseconds.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* milliSeconds The number of milliseconds to sleep.
*
* Returns: void
*---------------------------------------------------------------------------*/
void MilliSleep( WM_DEVICE_HANDLE hDevice, unsigned milliSeconds )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( milliSeconds != 0 )
{
if ( pDeviceContext->fnSleep && WMSystemCallsAllowed( hDevice ) )
{
pDeviceContext->fnSleep( milliSeconds );
}
else
{
MicroSleep( hDevice, milliSeconds * 1000 );
}
}
}
/*-----------------------------------------------------------------------------
* Function: WMBeNice
*
* Allows other tasks to continue in a way which is safe for the power handler.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMBeNice( WM_DEVICE_HANDLE hDevice )
{
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
if ( pDeviceContext->fnSleep && WMSystemCallsAllowed( hDevice ) )
{
/*
* Let other things continue if appropriate.
*/
pDeviceContext->fnSleep( 0 );
}
}
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -