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

📄 wmwavepdd.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 5 页
字号:
/*-----------------------------------------------------------------------------
 * 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: WMWavepdd.c 3117 2006-04-28 13:46:49Z fb $
 *
 * The PDD (Platform Dependent Driver) is responsible for
 * communicating with the audio circuit to start and stop playback
 * and/or recording and initialize and deinitialize the circuits.
 *
 * Warning:
 *  This driver is specifically written for Wolfson Codecs. It is not a 
 *  general CODEC device driver.
 *
 * --------------------------------------------------------------------------*/

/*
 * Include files
 */
#include <wavemdd.h>
#if ( _WIN32_WCE >= 500 && !defined( WM_BSP_TAHITI ) )
#   include <bsp_cfg.h>
#else
#   include <oalintr.h>
#endif
#include "WDCL.h"

/*
 * NOTE: The audio path functions that are included by WMAudioPaths.h
 *       and used in this file is only an example of one way of setting
 *       up paths through the codec. In general we have gone for the
 *       approach of enabling as many paths through the codec as possible
 *       so that there is a good chance that which ever input and output
 *       is used some audio will get through.
 *
 *       It is therefore important that developers optimize this to suit
 *       the application. It may be that you need to make changes to these 
 *       functions or use different functions from this file.
 *
 *       If you have any queries, or suggestions for audio paths that
 *       are not covered in the Wolfson Device Control Library please feel
 *       free to contact the apps team (apps@wolfsonmicro.com). 
 */

#if !WM_AUDIO || !WM_AUDIO_STREAM
#error Mismatch: The Wolfson library is not configured for Audio or Audio Streaming, build system is configured for Audio
#endif /* !WM_AUDIO */

#if WM_USE_DYNAMIC_DMA_CHANNEL
#error WM_USE_DYNAMIC_DMA_CHANNEL _must_ be defined as FALSE in WMPlatformConfig.h.
#endif /* WM_USE_DYNAMIC_DMA_CHANNEL */

/*
 * Global definitions
 */
/* WinCE volume scheme: 16 bits of Left and 16 bits of Right (0xRRRRLLLL) */
#define RIGHT_VOLUME_MASK	0xFFFF0000
#define RIGHT_VOLUME_SHIFT	16
#define LEFT_VOLUME_MASK	0x0000FFFF
#define LEFT_VOLUME_SHIFT   0
#define RIGHT_VOL( _vol )   ((unsigned short)(((_vol) & RIGHT_VOLUME_MASK) >> RIGHT_VOLUME_SHIFT))
#define LEFT_VOL( _vol )    ((unsigned short)(((_vol) & LEFT_VOLUME_MASK) >> LEFT_VOLUME_SHIFT))

DWORD gIntrAudio = SYSINTR_AUDIO;

static WM_DEVICE_HANDLE g_hAudioDevice;
static WM_STREAM_HANDLE g_hOutputStream;
static WM_STREAM_HANDLE g_hInputStream;
static WM_CHIPTYPE s_deviceType;

/*
 * Shared audio data. This data is
 * shared between the device process
 * and the power managment process
 */
typedef struct tagWM_SHARED_AUDIO_DATA
{   
    BOOL inPowerHandler;
    BOOL moreData[2];
} WM_SHARED_AUDIO_DATA;

/*
 * Global audio data variable for the device process.
 */
static volatile WM_SHARED_AUDIO_DATA *g_pWMAudioDeviceData = NULL;

HANDLE g_hGlobalDataDeviceMutex;

#define WM_GLOBAL_DATA_MUTEX_NAME  _T("WMGlobalDataMutex")

#define WM_GLOBAL_TIME_OUT         1000 /* 1 second timeout */

/*
 * When the volume is zero we mute the
 * codec so that we get maximum attenuation.
 * This global define allows us to check if
 * we are at zero volume and should leave
 * the codec outputs muted.
 */
static BOOL g_OutputMaxAtten = FALSE;

static WM_AUDIO_SIGNAL g_SignalL;
static WM_AUDIO_SIGNAL g_SignalR;

struct _global_volume
{
    ULONG   dwMasterVolume;
    ULONG   dwLineInVolume;
    ULONG   dwMicVolume;
    BOOL    fMasterMute;
    BOOL    fLineInMute;
    BOOL    fMicMute;
    ULONG   dwInputSelect;
} g_VolumeSettings;

static CEDEVICE_POWER_STATE g_DxState;

/*
 * Work out what sort of chip it is.
 */
#define IS_WM9713_DEVICE( _device )  (WM_CHIP_WM9713 == (_device))

#ifndef ZONE_ALWAYS
#   define ZONE_ALWAYS      TRUE
#endif

/*
 * Macros to check if the DMA is currently running
 */
#define OUTPUTDMARUNNING( _pWMAudioData )  ( TRUE == _pWMAudioData->moreData[WAPI_OUT] ) \
                            ? TRUE : FALSE

#define INPUTDMARUNNING( _pWMAudioData )  ( TRUE == _pWMAudioData->moreData[WAPI_IN] ) \
                            ? TRUE : FALSE



/*
 * Function prototypes
 */
static MMRESULT private_PddWaveGetDeviceCaps( WAPI_INOUT apidir, void * pCaps );
static MMRESULT private_PddWaveOpen( WAPI_INOUT apidir,
                                     LPWAVEFORMATEX lpFormat,
                                     BOOL fQueryFormatOnly
                                   );
static MMRESULT private_PddWaveOutStart( PWAVEHDR pwh, 
                                         volatile WM_SHARED_AUDIO_DATA *pWMAudioData 
                                       );
static MMRESULT private_PddWaveInStart( volatile WM_SHARED_AUDIO_DATA *pWMAudioData );
static void private_PddWaveOutContinue( PWAVEHDR pwh );
static void private_PddWaveInContinue( PWAVEHDR pwh );
static MMRESULT private_PddWaveOutStop( volatile WM_SHARED_AUDIO_DATA *pWMAudioData );
static MMRESULT private_PddWaveInStop( volatile WM_SHARED_AUDIO_DATA *pWMAudioData );
static void private_PddWaveFillBuffer( PWAVEHDR pwd );
static void private_PddWaveComplete( PWAVEHDR pwh, ULONG cbBytesCompleted );
static void private_PddWaveGetBuffer( PWAVEHDR pwh );
static ULONG private_PddWaveGetVolume( void ); 
static MMRESULT private_PddWaveSetVolume( ULONG volume );
static MMRESULT private_SetMixerValue( DWORD dwControl, DWORD dwSetting );
static MMRESULT private_GetMixerValue( DWORD dwControl, PDWORD pdwSetting );
static void private_PddPowerUp( void );
static void private_PddPowerDown( void );
static MMRESULT private_MuteAllOutputs( volatile WM_SHARED_AUDIO_DATA *pWMAudioData, 
                                        BOOL mute );
static MMRESULT private_PrepareOutputPaths( WM_STREAM_ID stream,
                                            volatile WM_SHARED_AUDIO_DATA *pWMAudioData,
                                            BOOL enable 
                                          );
static MMRESULT private_PrepareInputPaths( WM_STREAM_ID stream,
                                           volatile WM_SHARED_AUDIO_DATA *pWMAudioData,
                                           BOOL enable
                                         );

/*-----------------------------------------------------------------------------
 * Function:    PDD_AudioDeinitialize
 *
 * This function turns off and disconnects the audio device
 *
 * Parameters:
 *      none
 *
 * Returns:     void
 *---------------------------------------------------------------------------*/
void PDD_AudioDeinitialize( void )
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT( "PDD_AudioDeinitialize+\r\n" )) );   

    if ( g_hAudioDevice )
    {
        /*
         * Power down the device.
         */
        private_PddPowerDown();

        WMAudioShutdown( g_hAudioDevice );
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT( "PDD_AudioDeinitialize-\r\n" )) );   

}

/*-----------------------------------------------------------------------------
 * Function:    PDD_AudioGetInterruptType
 *
 * This function determines the cause of the audio interrupt and returns the
 * current device status.
 *
 * Parameters:
 *      none
 *
 * Returns:     AUDIO_STATE
 *      An interger indicating the type of interrupt.
 *      AUDIO_STATE_OUT_PLAYING     Sound is currently playing.
 *      AUDIO_STATE_OUT_UNDERFLOW   Sound was playing, but not enough data
 *                                  has been supplied to continue.
 *      AUDIO_STATE_IN_RECORDING    Sound is currently recording.
 *      AUDIO_STATE_IN_OVERFLOW     Sound was recording, but the reserve
 *                                  buffer was not processed in time.
 *      AUDIO_STATE_IN_STOPPED      Recording has stopped.
 *      AUDIO_STATE_IGNORE          Ignore this interrupt.
 *---------------------------------------------------------------------------*/
AUDIO_STATE PDD_AudioGetInterruptType(void)
{
    AUDIO_STATE retval = AUDIO_STATE_IGNORE;
    WMAUDIO_INTSTATE    intState;

    /*
     * An audio interrupt has occured. We need to tell the MDD who owns it
     * and what state that puts us in.
     *
     * NOTE: You can return both an input and an output state simultaneously
     * by simply OR'ing the two values together (output and input are held
     * in upper and lower nibbles respectively).
     */

    /*
     * I N P U T
     */

    /*
     * Call the Wolfson library to find out which interrupts occured on the input stream.
     * This function will clear the interrupt, if necessary, for us as well.
     */
    intState = WMAudioCheckStreamInterrupts( g_hAudioDevice, g_hInputStream );

    /*
     * Check for DMA bus error on input stream.
     */
    if ( intState & WMAUDIO_INT_ERROR )
    {
        /*
         * If a bus error is received this is treated as fatal as we should
         * not be getting errors of this sort.
         */
        DEBUGMSG( ZONE_ERROR, ( TEXT ( "DCSR_BUSERRINTR on input\r\n" ) ) );

        retval |= AUDIO_STATE_IGNORE;

        ASSERT(0);
    }

    /*
     * Check for DMA end interrupt on input stream.
     */
    if ( intState & WMAUDIO_INT_END )
    {
        /*
         * Let the Wolfson library know that another DMA buffer has
         * been filled.
         */
        WMAudioHandleInterrupt( g_hAudioDevice, g_hInputStream );

        /*
         * If the driver is still expecting more data
         * then signal that to the MDD that it is still recording,
         * else signal that it has stopped recording.
         */
        if ( INPUTDMARUNNING( g_pWMAudioDeviceData ) )
            retval |= AUDIO_STATE_IN_RECORDING;
        else
            retval |= AUDIO_STATE_IN_STOPPED;
    }

    /*
     * Check for DMA start interrupt on input stream.
     */
    if ( intState & WMAUDIO_INT_START )  
    {
        /*
         * We do not use start interrupts for this driver so we should never
         * receive a start interrupt for this stream.
         */
        DEBUGMSG( ZONE_ERROR, ( TEXT ( "DCSR_STARTINTER on input\r\n" ) ) );

        retval |= AUDIO_STATE_IGNORE;

        ASSERT(0);
    }

    /*
     * O U T P U T
     */

    /*
     * Call the Wolfson library to find out which interrupts occured on the output stream.
     * This function will clear the interrupt, if necessary, for us as well.
     */
    intState = WMAudioCheckStreamInterrupts( g_hAudioDevice, g_hOutputStream );

    /*
     * Check for DMA bus error on output stream.
     */
    if ( intState & WMAUDIO_INT_ERROR )
    {
        /*
         * If a bus error is received this is treated as fatal as we should
         * not be getting errors of this sort.
         */
        DEBUGMSG( ZONE_ERROR, ( TEXT ( "DCSR_BUSERRINTR on output\r\n" ) ) );

        retval |= AUDIO_STATE_IGNORE;

        ASSERT(0);
    }

    /*
     * Check for DMA end interrupt on output stream.
     */
    if ( intState & WMAUDIO_INT_END )
    {
        /*
         * Let the Wolfson library know that another DMA buffer has
         * been transmitted.
         */
        WMAudioHandleInterrupt( g_hAudioDevice, g_hOutputStream );

        /*
         * If the driver is still expecting more data
         * then signal that to the MDD that it is still playing,
         * else signal that it has stopped playing.
         */
        if ( OUTPUTDMARUNNING( g_pWMAudioDeviceData ) )
            retval |= AUDIO_STATE_OUT_PLAYING;
        else
            retval |= AUDIO_STATE_OUT_STOPPED;
    }

    /*
     * Check for DMA start interrupt on output stream.
     */
    if ( intState & WMAUDIO_INT_START )   
    {
        /*
         * We do not use start interrupts for this driver so we should never
         * receive a start interrupt for this stream.
         */
        DEBUGMSG( ZONE_ERROR, ( TEXT ( "DCSR_STARTINTER on output\r\n" ) ) );

        retval |= AUDIO_STATE_IGNORE;

        ASSERT(0);
    }

    return retval;
}

/*-----------------------------------------------------------------------------
 * Function:    PDD_AudioInitialize
 *
 * This function initializes the audio device for operation
 *
 * Parameters:
 *      dwIndex     Passed to the WAV_Init function. This allows the PDD layer
 *                  to get device configuration information from the driver's
 *                  registry entry.
 *
 * Returns:     BOOL
 *      TRUE indicates success. FALSE indicates failure.
 *---------------------------------------------------------------------------*/
BOOL PDD_AudioInitialize( DWORD dwIndex )

⌨️ 快捷键说明

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