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

📄 wmdevice.c

📁 pxa270平台 windows mobile 5.2 wm9713 触摸屏+音频驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*-----------------------------------------------------------------------------
 * 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: WMDevice.c 2717 2006-02-02 12:26:48Z ib $
 *
 * This file contains functionality for opening and closing a device.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 * -----------------------------------------------------------------------------*/

/*
 * IMPORTANT
 *
 * This is one of the few files which can allocate memory.  All functions in
 * this file must still follow the following rules and guidelines:
 *
 * 1. 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 "WMControlLink.h"
#include "WM2WireLink.h"
#include "WMPlatformACLink.h"
#include "WMPlatform2Wire.h"
#include "WMAudio.h"
#include "WMTouch.h"
#include "WMAuxADC.h"
#include "WMPlatform_OS.h"
#include "WMACLink.h"
#include "WMPower.h"
#include "WM8753Power.h"
#include "WMDevice.h"

/*
 * Global definitions
 */
#if WM_MUTEX_LOCK_DEBUG
#   define WM_LOCK_TRACE    WM_TRACE
#else
#   define WM_LOCK_TRACE( _hDevice, _args )     
#endif /* WM_MUTEX_LOCK_DEBUG */

/*
 * Private data
 */
/* The maximum length of time (in ms) to wait for the lock */
#define LINK_LOCK_TIMEOUT   50

/* The maximum length of time (in ms) to wait for the lock */
#define GLOBALS_LOCK_TIMEOUT    50

/* Mutex for the AC Link */
#ifdef WIN32
#   define WM_LINK_MUTEX_NAME  _T("WMLinkMutex")
#else
#   define WM_LINK_MUTEX_NAME  'WMLink'
#endif

/* Mutex for protecting the global shared memory */
#define WM_GLOBALS_MEMORY_NAME _T("WMGlobalsMemory")
#ifdef WIN32
#   define WM_GLOBALS_MUTEX_NAME  _T("WMGlobalsMutex")
#else
#   define WM_GLOBALS_MUTEX_NAME  'WMDT'
#endif

/*
 * Function prototypes
 */
static WMSTATUS private_InitDeviceContext( WM_DRIVER_ID      driverID,
                                           WM_DEVICE_ID      devID,
                                           WM_DEVICE_CONTEXT **ppContext
                                         );
static void private_FreeDeviceContext( WM_DEVICE_HANDLE hDevice );

#if WM_AC97
static WM_BOOL private_WMLockLink( WM_DEVICE_HANDLE  hDevice,
                                   const char        *file,
                                   int               line
                                 );
static void private_WMUnlockLink( WM_DEVICE_HANDLE  hDevice,
                                  const char        *file,
                                  int               line
                                );
#endif /* WM_AC97 */

static WM_BOOL private_WMLockGlobalData( WM_DEVICE_HANDLE  hDevice,
                                         const char        *file,
                                         int               line
                                       );
static void private_WMUnlockGlobalData( WM_DEVICE_HANDLE  hDevice,
                                        const char        *file,
                                        int               line
                                      );
                                 
/*-----------------------------------------------------------------------------
 * Function:    WMOpenDevice
 *
 * Initialises the use of the Wolfson device by a given driver.
 *
 * Parameters:
 *      devID               The device ID (e.g. WM_DEV_AC97_PRIMARY)
 *      driverID            The driver ID (e.g. WM_DRIVER_TOUCH)
 *      phDevice            A variable to receive the handle to the device
 *
 * Returns:     WMSTATUS
 *      See WMStatus.h.
 *---------------------------------------------------------------------------*/
WMSTATUS WMOpenDevice( WM_DEVICE_ID       devID,
                       WM_DRIVER_ID       driverID,
                       WM_DEVICE_HANDLE   *phDevice
                       )
{
    WM_DEVICE_CONTEXT   *pDeviceContext;
    WM_DEVICE_HANDLE    hDevice;
    WMSTATUS            status;
    
    /*
     * Check we're using a supported combination of driver and device.
     */

    switch ( driverID )
    {
    case WM_DRIVER_RAW:
#if WM_AUDIO
    case WM_DRIVER_AUDIO:
#endif
        /* All codecs support these */
        break;

#if WM_TOUCH || WM_AUXADC
    case WM_DRIVER_TOUCH:
    case WM_DRIVER_AUXADC:
    case WM_DRIVER_BATTERY:
        /* Only AC'97 devices support these at present */
        if ( !WM_IS_AC97_DEVICE_ID( devID ) )
        {
            status = WMS_NO_SUPPORTED_DEVICE;
            goto error0;
        }
        break;
#endif /* WM_TOUCH || WM_AUXADC */
    
    default:
        status = WMS_INVALID_PARAMETER;
        goto error0;
    }
    
    status = private_InitDeviceContext( driverID, devID, &pDeviceContext );
    if ( WM_ERROR( status ) )
    {
        goto error0;
    }
    hDevice = WMDEVICE_TO_HANDLE( pDeviceContext );
                
    status = WMLinkInit( hDevice, driverID );
    if ( WM_ERROR( status ) && WMS_UNSUPPORTED != status)
    {
        goto error0;
    }

	if ( WMS_UNSUPPORTED == status )
	{
		/* 
		 * The generic I2S drivers do not support full Link initialisation,
		 * for _any_ other drivers this is a fatal error
		 */
		if ( ! WM_IS_I2S_GENERIC_ID( devID ) )
		{
			goto error0;
		}
	}

    /*
     * Now initialise the subsystem.
     */
    switch ( driverID )
    {
    case WM_DRIVER_RAW:
        /* Nothing to do here */
        break;

#if WM_AUDIO
    case WM_DRIVER_AUDIO:
        /* Initialise the audio subsystem */
        status = WMAudioInit( hDevice );
        if ( WM_ERROR( status ) )
        {
            goto error1;
        }
        break;
#endif

#if WM_TOUCH
    case WM_DRIVER_TOUCH:
        /* Initialise the touch subsystem */
		status = WMTouchInit( hDevice );
        if ( WM_ERROR( status ) )
        {
            goto error1;
        }
        break;
#endif

#if WM_AUXADC
    case WM_DRIVER_AUXADC:
    case WM_DRIVER_BATTERY:
        /* Initialise the AuxADC subsystem */
		status = WMAuxADCInit( hDevice );
        if ( WM_ERROR( status ) )
        {
            goto error1;
        }
        break;
#endif
    
    default:
        status = WMS_INVALID_PARAMETER;
        goto error0;
    }
   
    /*
     * And we're done.
     */
    *phDevice = hDevice;
    return WMS_SUCCESS;
    
    /*
     * Error cleanup.
     */

error1:
	WMLinkShutdown( hDevice, driverID );
    
error0:
    *phDevice = NULL;
    return status;
}

/*-----------------------------------------------------------------------------
 * Function:    WMCloseDevice
 *
 * Marks the end of use of the codec by this driver.
 *
 * Parameters:
 *      hDevice             handle to the device (from WMOpenDevice)
 *      driverID            The driver ID (e.g. WM_DRIVER_TOUCH)
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void WMCloseDevice( WM_DEVICE_HANDLE hDevice, WM_DRIVER_ID driverID )
{
    WMLinkShutdown( hDevice, driverID );
    private_FreeDeviceContext( hDevice );
}

/*-----------------------------------------------------------------------------
 * Function:    private_InitDeviceContext
 *
 * Initialises and returns a pointer to the global device context for passing
 * to the Raw functions.
 *
 * This must in some way allocate space for the global data area g_pWMData
 * (definition in WMGlobals.h) so that the memory is common to all instances
 * of drivers using the library.
 * 
 * Parameters:
 *      driverID    The driver ID (e.g. WM_DRIVER_AUDIO)
 *      devID       The device ID (e.g. WM_DEV_AC97_PRIMARY)
 *      ppContext   a variable to receive the pointer to the context structure.
 *
 * Returns:     WMSTATUS
 *        See WMStatus.h
 *---------------------------------------------------------------------------*/
static WMSTATUS private_InitDeviceContext( WM_DRIVER_ID      driverID,
                                           WM_DEVICE_ID      devID,
                                           WM_DEVICE_CONTEXT **ppContext
                                         )
{
    WMSTATUS                    status;
    WM_DEVICE_CONTEXT           *pDeviceContext;
    WM_DEVICE_HANDLE            hDevice;    /* for WM_TRACE, MAP_MEMORY and WM_ASSERT */
    volatile WM_SHARED_DATA     *pWMData = NULL;
    WM_DEVICE_ID                deviceID;
    WM_DEVICE_ID                devOrdinal;
    WM_CHIPTYPE                 chipType;

    /*
     * Decode the device ID.
     */
    chipType = WM_DEV_GET_CHIP( devID );
    devOrdinal = WM_DEV_GET_ORDINAL( devID );
    
    /*
     * Convert to a generic ID.
     */
    if ( WM_IS_AC97_DEVICE_ID( devID ) )
    {
        deviceID = devID;
    }
    else if ( WM_IS_I2S_DEVICE_ID( devID ) )
    {
        deviceID = WM_DEV_MAKE_DEVICE( WM_DEV_I2S, devOrdinal );
    }
    else
    {
        status = WMS_NO_SUPPORTED_DEVICE;
        goto error0;
    }

    /*
     * Get ourselves a device context.
     */
    status = WMPlatformAllocateDeviceContext( deviceID, &pDeviceContext );
    if ( WM_ERROR( status ) )
    {
        goto error0;
    }

	if ( WM_IS_I2S_DEVICE_ID( deviceID ) )
	{
		/*
		 * Select our codec addresses as appropriate for I2S.
		 */
		switch ( devOrdinal )
		{
		case WM_DEV_PRIMARY:
			pDeviceContext->codecAddress = WM_2WIRE_ADDR_1;
			break;

		case WM_DEV_SECONDARY:
			pDeviceContext->codecAddress = WM_2WIRE_ADDR_2;
			break;

		default:
			status = WMS_NO_SUPPORTED_DEVICE;
			goto error0;
		}
	}

    /*
     * And remember our device ID.
     */
    pDeviceContext->deviceID = deviceID;

    /*
     * Create our device handle.
     */    
    hDevice = WMDEVICE_TO_HANDLE( pDeviceContext );
    
    /*
     * Allocate our global data.
     */
    if ( !pDeviceContext->v_pWMData )
    {
        pWMData = ALLOC_SHARED_MEMORY( hDevice,
                                       volatile WM_SHARED_DATA,
                                       sizeof( WM_SHARED_DATA ),
                                       WM_GLOBALS_MEMORY_NAME
                                     );
        if ( !pWMData )
        {
            status = WMS_RESOURCE_FAIL;
            goto error1;
        }

        pDeviceContext->v_pWMData = pWMData;
    }
        
#if WM_AUXADC
    /*
     * Our digitiser memory is part of the global memory.
     */
    pDeviceContext->v_pADCData = &pDeviceContext->v_pWMData->adcData;
#endif

    /*
     * Allocate platform memory.  Note we always need to do this in
     * case this is a second driver on the same device context which
     * needs different areas of memory mapped.  It shouldn't allocate
     * the same area twice.
     */
    status = WMPlatformAllocatePlatformMemory( hDevice, driverID );
    if ( WM_ERROR( status ) )
    {
        goto error1;
    }
        
    /* Check whether we're initialised */
    if ( pDeviceContext->flags & DEVICE_CONTEXT_INITIALISED )
    {
        goto InitDone;
    }
 
    /*
     * Create the global data mutex.
     * Note this will return the existing handle if another thread
     * got in first.
     */
    status = CREATE_MUTEX( &pDeviceContext->globalsMutex, WM_GLOBALS_MUTEX_NAME );
    if ( WM_ERROR( status ) )
    {
        goto error1;
    }
    
    if ( WM_IS_AC97_DEVICE_ID( deviceID ) )
    {
        /*
         * And now the AC link mutex.
         */
        status = CREATE_MUTEX( &pDeviceContext->linkMutex, WM_LINK_MUTEX_NAME );
        if ( WM_ERROR( status ) )
        {
            goto error1;
        }
    }
    
    /*
     * And we can do locking and system calls.
     */
    pDeviceContext->preventSyscallCount = 0;

	/*
	 * Now set up our device context with as much info as we can at this point.

⌨️ 快捷键说明

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