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

📄 hwctxt.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//-----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//-----------------------------------------------------------------------------
//
//  Copyright (C) 2005, 2006, Freescale Semiconductor, Inc. All Rights Reserved.
//  THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
//  BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
//  FREESCALE SEMICONDUCTOR, INC.
//
//-----------------------------------------------------------------------------
//
//  File:  hwctxt.cpp
//
//  Platform dependent code for the WinCE WAV audio driver. This code's primary
//  responsibilities are:
//
//    1. Initialize the platform's audio hardware (e.g., audio CODEC,
//       amplifiers, etc.).
//    2. Initialize and configure all associated hardware components (e.g.,
//       DMA controllers, Synchronous Serial Interfaces (SSIs), audio MUXes,
//       interrupt controllers, etc.).
//    3. Configure DMA operations to move audio data between the memory buffers
//       and the SSIs.
//    4. Handle audio hardware-related interrupt events.
//    5. Configure the audio hardware to perform audio playback and recording
//       functions.
//    6. Provide smart power management to minimize power consumption (e.g.,
//       powering up components only as required and powering them down when
//       they are no longer needed). Note, however, that we don't do any
//       power management for components that are not directly audio-related.
//       For example, we will disable the clock signal for the SSIs when
//       we stop playing audio but we won't powerdown the clock/reset module
//       since that may still be needed by other parts of the system.
//
//  All other tasks (e.g., audio stream mixing, resampling etc.) are currently
//  handled by the "upper" layers of the WinCE audio driver.
//
//  This device driver implementation is based upon the audio features and
//  components provided by the Freescale Power Management ICs (PMICs) in
//  conjunction with either an i.MX or MXC-based platform.
//
//  More specifically, the following key platform-dependent hardware components
//  are used to provide the audio playback and recording functions:
//
//    PMIC Components:
//
//      * Stereo DAC for playback along with associated mixers, output
//        amplifiers, and audio output jacks.
//      * Voice CODEC for recording along with associated mixers, input
//        amplifiers, and audio microphone input jacks.
//
//    i.MX or MXC Components:
//
//      * SSI1 for Voice CODEC I/O
//      * SSI2 for Stereo DAC I/O
//      * SDMA to handle audio I/O between memory and SSI1/SSI2.
//      * Audio MUX to route the audio stream between the SSI and the
//        PMIC Voice CODEC or Stereo DAC.
//      * Clock and Reset Module to generate the required clock signals for
//        SSI1/SSI2 (and the PMIC clock input in the case of the MC13783 PMIC).
//
//  See also the corresponding PMIC-specific source files for complete details
//  about the implementation of the BSP interface for audio. For example, in
//  the case of the MX31 platform, the rest of the audio driver code can be
//  found in the following files:
//
//      WINCE500\PLATFORM\MX31\SRC\DRIVERS\WAVEDEV\ATLAS\HWCTXT.CPP
//      WINCE500\PUBLIC\COMMON\OAK\CSP\ARM\FREESCALE\PMIC\ATLAS\...
//          ...\SDK\PMIC_AUDIO.CPP
//
//-----------------------------------------------------------------------------

#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <Mmsystem.h>   // For timer driver interface.
#include "wavemain.h"

// Define the size (in data words) of the SSI TX FIFO. This is normally 8.

#define SSI_TX_FIFO_DEPTH               8 // Default 8


//-----------------------------------------------------------------------------
// External Variables

#ifdef DEBUG

extern DBGPARAM dpCurSettings;

#endif // #ifdef DEBUG


//-----------------------------------------------------------------------------
// Defines

const unsigned short HardwareContext::INTR_PRIORITY_REGKEY[12] =
    TEXT("IntPriority");


//-----------------------------------------------------------------------------
// Exported Global Variables

HardwareContext *g_pHWContext = NULL;


//-----------------------------------------------------------------------------
// Local Global Variables

static PHYSICAL_ADDRESS g_PhysDMABufferAddr;
static BOOL g_saveOutputDMARunning = FALSE;

#ifdef AUDIO_RECORDING_ENABLED
static BOOL g_saveInputDMARunning  = FALSE;
#endif


//-----------------------------------------------------------------------------
//
//  Function: CreateHWContext
//
//  This function is invoked by the WAV_Init to create a device instance
//  that will be passed to the WAV_Open and WAV_DeInit functions.  If
//  multiple devices are supported, a unique device instance should be
//  returned for each device.
//
//  Parameters:
//      Index
//          [in] Context parameter passed to the WAV_Init function
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::CreateHWContext(DWORD Index)
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::CreateHWContext\n")));

    if (g_pHWContext)
    {
        return(TRUE);
    }

    g_pHWContext = new HardwareContext;
    if (!g_pHWContext)
    {
        return(FALSE);
    }

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::CreateHWContext\n")));

    return(g_pHWContext->Init(Index));
}


//-----------------------------------------------------------------------------
//
//  Function: HardwareContext
//
//  This function is the constructor for the hardware context class.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
HardwareContext::HardwareContext()
#ifdef AUDIO_RECORDING_ENABLED
    : m_InputDeviceContext(), m_OutputDeviceContext()
#else
    : m_OutputDeviceContext()
#endif
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::HardwareContext\n")));

    InitializeCriticalSection(&m_Lock);
    m_Initialized = FALSE;

    // This flag is only set to TRUE when PowerDown() is called.
    m_audioPowerdown = FALSE;

    // The actual interrupt handler thread will be created later by calling
    // CreateThread() in InitInterruptThread().
    m_hAudioInterruptThread = NULL;

    // Initialize the timer ID and timeout event for both playback and
    // recording operations.
    //
    // We must create the events before we create the event handling thread
    // because the event handling thread will immediately begin to run once
    // it has been created.
    m_AudioDelayDisableTimerID[0] = NULL;
    m_hAudioDelayDisableEvent[0]  = CreateEvent(NULL, FALSE, FALSE, NULL);
#ifdef AUDIO_RECORDING_ENABLED
    m_AudioDelayDisableTimerID[1] = NULL;
    m_hAudioDelayDisableEvent[1]  = CreateEvent(NULL, FALSE, FALSE, NULL);
#endif

    // Also initialize the delayed disable timer event handling thread.
    // The actual thread will be created later by calling CreateThread()
    // in Init().
    m_hAudioDelayedDisableThread = NULL;

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::HardwareContext\n")));
}


//-----------------------------------------------------------------------------
//
//  Function: ~HardwareContext
//
//  This function is the destructor for the hardware context class.
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
HardwareContext::~HardwareContext()
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::~HardwareContext\n")));

    Lock();

    if (m_AudioDelayDisableTimerID[0] != NULL)
    {
        timeKillEvent(m_AudioDelayDisableTimerID[0]);
        m_AudioDelayDisableTimerID[0] = NULL;
    }
#ifdef AUDIO_RECORDING_ENABLED
    if (m_AudioDelayDisableTimerID[1] != NULL)
    {
        timeKillEvent(m_AudioDelayDisableTimerID[1]);
        m_AudioDelayDisableTimerID[1] = NULL;
    }
#endif

    Unlock();

    DeleteCriticalSection(&m_Lock);

    if (m_hAudioDelayDisableEvent[0] != NULL)
    {
        CloseHandle(m_hAudioDelayDisableEvent[0]);
        m_hAudioDelayDisableEvent[0] = NULL;
    }
#ifdef AUDIO_RECORDING_ENABLED
    if (m_hAudioDelayDisableEvent[1] != NULL)
    {
        CloseHandle(m_hAudioDelayDisableEvent[1]);
        m_hAudioDelayDisableEvent[1] = NULL;
    }
#endif

    DEBUGMSG(ZONE_FUNCTION,(_T("-HardwareContext::~HardwareContext\n")));
}


//-----------------------------------------------------------------------------
//
//  Function: Init
//
//  This function initializes the hardware context for the audio device.
//
//  Parameters:
//      Index
//          [in] Context parameter passed to the WAV_Init function
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::Init(DWORD Index)
{
    DEBUGMSG(ZONE_FUNCTION,(_T("+HardwareContext::Init\n")));

    // If we have already initialized this device, return error
    if (m_Initialized)
    {
        return(FALSE);
    }

    // Initialize hardware context to be muted and zero gain since hardware
    // should currently be in a powered down state. The audio hardware will
    // be automatically powered up when audio playback/recording is actually
    // initiated.
    m_dwOutputGain  = 0;
    m_fOutputMute   = TRUE;
#ifdef AUDIO_RECORDING_ENABLED
    m_dwInputGain   = 0x0000;
    m_fInputMute    = TRUE;
#endif
    m_CodecPwrState = AUDIO_PWR_STATE_OFF;

    // Initialize the driver state/status variables
    m_DriverIndex      = Index;
    m_OutputDMARunning = FALSE;
    m_OutputDMAStatus  = DMA_CLEAR;
#ifdef AUDIO_RECORDING_ENABLED
    m_InputDMARunning  = FALSE;
    m_InputDMAStatus   = DMA_CLEAR;
#endif

    // Initialize BSP-specific configuration.
    if (!BSPAudioInit())
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - ")
                              TEXT("BSPInit failed\r\n")));
        goto cleanUp;
    }

    // Map the DMA buffers.
    if (!MapDMABuffers())
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - ")
                              TEXT("MapDMABuffers failed\r\n")));
        goto cleanUp;
    }

    // Initialize the output DMA.
    if (!InitOutputDMA())
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - ")
                              TEXT("Failed to initialize output DMA.\r\n")));
        goto cleanUp;
    }

#ifdef AUDIO_RECORDING_ENABLED
    // Initialize the input DMA.
    if (!InitInputDMA())
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - ")
                              TEXT("Failed to initialize input DMA.\r\n")));
        goto cleanUp;
    }
#endif

    // Initialize and create audio processing IST.
    if ((m_hAudioInterruptThread == NULL) && (!InitInterruptThread()))
    {
        DEBUGMSG(ZONE_ERROR, (TEXT("WAVEDEV.DLL:HardwareContext::Init() - ")
                  TEXT("Failed to initialize interrupt thread.\r\n")));
        goto cleanUp;
    }

    // Initialize and create delayed disable timer event handling thread.
    if ((m_hAudioDelayedDisableThread == NULL) &&
        ((PLAYBACK_DISABLE_DELAY_MSEC > 0) || (RECORD_DISABLE_DELAY_MSEC > 0)))
    {
        // Create a thread to handle the CODEC disable delay timer events.
        m_hAudioDelayedDisableThread =
            CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                         0,
                         (LPTHREAD_START_ROUTINE)BSPAudioDisableDelayHandler,
                         this,
                         0,
                         NULL);

        if (!m_hAudioDelayedDisableThread)
        {
            ERRMSG("Unable to create audio CODEC delayed disable timer event "
                   "handling thread");
            goto cleanUp;
        }
    }

    m_Initialized = TRUE;

cleanUp:

⌨️ 快捷键说明

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