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

📄 hwctxt.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//------------------------------------------------------------------------------
//
//  Copyright (C) 2004-2006, Freescale Semiconductor, Inc. All Rights Reserved.
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
//
//  File:  hwctxt.cpp
//
//  Provides BSP-specific configuration routines for the WAVEDEV driver.
//
//------------------------------------------------------------------------------

#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "bsp.h"
#include "wavemain.h"

#include "regs.h"
#include "regs_audio.h"
#include "regs_regulator.h"
#include "pmic_audio.h"     /* For the unified PMIC API interface. */
#include "pmic_lla.h"

//-----------------------------------------------------------------------------
// External Functions


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

#ifdef DEBUG

extern DBGPARAM dpCurSettings;

#endif // #ifdef DEBUG


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

// Define master/slave mode for each SSI. The only possible values are:
//
//     TRUE    then SSI is master and the PMIC is slave
//     FALSE   then the PMIC is master and the SSI is slave
//
// This setting will also be used to configure either the Stereo DAC or Voice
// CODEC to the complementary mode (i.e., slave mode if the SSI is configured
// as master and vice versa).
//
// It is possible to have each SSI operating in a different master/slave mode
// depending upon the system's clocking configuration and functional
// requirements.
//
// See also the definition of STEREO_DAC_BUS_MODE and VOICE_CODEC_BUS_MODE
// below which determines the protocol to be used for the digital audio bus.
//
// For SSI master mode, the proper clock source must also be defined in the
// SSI1_MASTER_CLOCK_SOURCE and/or SSI2_MASTER_CLOCK_SOURCE settings below.

#define BSP_SSI1_MASTER_BOOL        TRUE  // Default TRUE
#define BSP_SSI2_MASTER_BOOL        TRUE  // Default TRUE

// Define the SSI master mode clock source. This clock source is used by
// the SSI to internally generate the proper framesync and bitclock signals
// when operating in master mode. This clock source is not used when the SSI
// is operating in slave mode.
//
// The list of valid choices are:
//
//     DDK_CLOCK_BAUD_SOURCE_SERPLL to use the Serial PLL clock source
//     DDK_CLOCK_BAUD_SOURCE_USBPLL to use the USB PLL clock source
//     DDK_CLOCK_BAUD_SOURCE_MCUPLL to use the MCU PLL clock source
//
// It is possible to use the same clock source for both SSI1 and SSI2.
// However, a different master clock source may be used for each SSI if
// required in order to generate the desired sampling rate clock signals.

#define SSI1_MASTER_CLOCK_SOURCE    DDK_CLOCK_BAUD_SOURCE_SERPLL
                                        // Default DDK_CLOCK_BAUD_SOURCE_SERPLL
#define SSI2_MASTER_CLOCK_SOURCE    DDK_CLOCK_BAUD_SOURCE_SERPLL
                                        // Default DDK_CLOCK_BAUD_SOURCE_SERPLL

// Define the SSI to be used with the PMIC Stereo DAC and Voice CODEC. The
// only possible values are:
//
//     m_pSSI1 to use SSI1
//     m_pSSI2 to use SSI2
//
// Note that the STEREO_DAC_SSI value must be different from that defined for
// the VOICE_CODEC_SSI to avoid a hardware conflict.

#define STEREO_DAC_SSI              m_pSSI2 // Default m_pSSI2
#define VOICE_CODEC_SSI             m_pSSI1 // Default m_pSSI1

// Define the Digital Audio MUX port configuration. The internal ports that
// are connected to the SSIs are hardwired for each processor. The external
// ports that are connected to the PMIC audio buses are defined by the
// platform and/or ADS board design.
//
// The selection of the external ports to be used may not be unique for each
// platform or ADS board, but we've simply selected ports below that are
// consistent with the hardware design and the operation of this driver.

#define SSI1_AUDMUX_PORT            PORT1 // Default PORT1
#define SSI2_AUDMUX_PORT            PORT2 // Default PORT2
#define VOICE_CODEC_AUDMUX_PORT     PORT4 // Default PORT4
#define STEREO_DAC_AUDMUX_PORT      PORT5 // Default PORT5

// Define the digital audio bus selections for both the PMIC Voice CODEC and
// Stereo DAC components. The only possible choices are:
//
//     AUDIO_DATA_BUS_1
//     AUDIO_DATA_BUS_2
//
// Note that the Voice CODEC and Stereo DAC must be assigned to different
// audio data buses in order to avoid a hardware conflict.
//
// Furthermore, the audio data bus selections must be consistent with the
// the Digital Audio MUX external port selections that were made above.
// The typical hardware connections are as follows but this should be
// verified from the platform reference manual and/or the schematics:
//
//     Audio MUX External PORT4 <======> AUDIO_DATA_BUS_1
//     Audio MUX External PORT5 <======> AUDIO_DATA_BUS_2

#define VOICE_CODEC_AUDIO_BUS   AUDIO_DATA_BUS_1 // Default AUDIO_DATA_BUS_1
#define STEREO_DAC_AUDIO_BUS    AUDIO_DATA_BUS_2 // Default AUDIO_DATA_BUS_2

// Define the digital audio bus mode for both the Stereo DAC and Voice CODEC.
// The only valid values for the MC13783 PMIC are:
//
//     NETWORK_MODE  to use a time-slotted network mode
//     I2S_MODE      to use the I2S mode
//
// See also the definition of BSP_SSI1_MASTER_BOOL and BSP_SSI2_MASTER_BOOL
// above which determines whether the SSI will act as the bus master or slave.

#define STEREO_DAC_BUS_MODE         NETWORK_MODE // Default NETWORK_MODE
#define VOICE_CODEC_BUS_MODE        NETWORK_MODE // Default NETWORK_MODE

// Define the SSI transmitter low water and receiver high watermarks. These
// watermark levels are used to trigger DMA requests to the core so that
// additional data can be added to the FIFO (for transmit) or data can be
// read from the FIFO (for receive).
//
// The valid values are from 1 to 8 (the SSI FIFO depth). Note that 0 is not
// a valid value for either the transmitter or receiver watermark levels and
// setting the watermark level to zero will prevent the SSI from functioning
// correctly.
//
// The proper watermark level to be used for a particular platform may need to
// be determined through performance testing and tuning. The key requirement is
// that both transmitter underrun and receiver overrun conditions must be
// avoided. Otherwise audio data will be lost. There is even the possibility
// of the left/right audio channels being randomly switched due to the nature
// of how the SSI hardware handles underrun and overrun conditions.
//
// See also the definition of AUDIO_DMA_PAGE_SIZE (in hwctxt.h) which defines
// the size in bytes of each DMA buffer. The size of the DMA buffer along with
// the SSI FIFO watermark levels are the two performance tuning parameters
// that are available for avoiding SSI FIFO underrun and overrun errors.

#define SSI_SFCSR_TX_WATERMARK      4 // Default 4
#define SSI_SFCSR_RX_WATERMARK      4 // Default 4

// Define the required timing delays for enabling/disabling the MC13783 PMIC
// audio components. These values are part of the MC13783 hardware specification
// and should not be modified.

#define MC13783_AUD_ENB_DELAY_BIAS_OFF    50      // 50 ms
#define MC13783_AUD_ENB_DELAY_BIAS_ON     5       // 5 ms

// Define the default output PGA gain. The valid values range from
// OUTPGA_GAIN_MINUS_33DB to OUTPGA_GAIN_6DB in 3 dB steps.
//
// WinCE seems to be better at reducing the volume than increasing it so it is
// recommended that the default gain be set above the halfway mark of -12 dB.
//

#define DEFAULT_OUTPGA_GAIN             OUTPGA_GAIN_MINUS_3DB
                                            // Default OUTPGA_GAIN_MINUS_3DB


//-----------------------------------------------------------------------------
// Types


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

PMIC_AUDIO_HANDLE hStDAC      = NULL; // Device handle for the PMIC Stereo DAC.
// #ifdef AUDIO_RECORDING_ENABLED
PMIC_AUDIO_HANDLE hVoiceCODEC = NULL; // Device handle for the PMIC Voice CODEC.
// #endif


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


//-----------------------------------------------------------------------------
//
//  Function: BSPAudioInit
//
//  This function maps the peripheral registers of the audio devices for
//  direct access by the driver.
//
//  Parameters:
//      None.
//
//  Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
//
//-----------------------------------------------------------------------------
BOOL HardwareContext::BSPAudioInit()
{
    UINT32 irq;
    BOOL rc = FALSE;
    PHYSICAL_ADDRESS phyAddr;

    DEBUGMSG(ZONE_FUNCTION, (_T("+HardwareContext::BSPAudioInit\n")));

    // Get a device handle to the PMIC's Stereo DAC for performing audio
    // playback. If this call succeeds, then we have a device handle that
    // we must use when calling all of the other PMIC Audio APIs.
    if (PmicAudioOpen(&hStDAC, STEREO_DAC) != PMIC_SUCCESS)
    {
        ERRORMSG(1, (_T("PmicAudioOpen: failed to get Stereo DAC device ")
                     _T("handle!\r\n")));

        // We can just return here without jumping to "cleanUp" because we
        // haven't done any memory allocations or acquired any other system
        // resources.
        DEBUGMSG(ZONE_FUNCTION, (_T("-HardwareContext::BSPAudioInit\n")));
        return rc;
    }

    // We must immediately select the Stereo DAC's data bus here before we
    // also request a device handle for the Voice CODEC. Otherwise, the
    // underlying PMIC Audio API implementation may think that both audio
    // data buses are already in use and prevent any attempts at switching
    // the audio data buses.
    //
    // This call will also have the side-effect of automatically switching
    // the Voice CODEC over to the other audio data bus (which is fine since
    // that's what we wanted anyways).
    if (PmicAudioSetProtocol(hStDAC,
                             STEREO_DAC_AUDIO_BUS, 
                             STEREO_DAC_BUS_MODE,
                             (((STEREO_DAC_SSI == m_pSSI1) &&
                               (BSP_SSI1_MASTER_BOOL))        ||
                              ((STEREO_DAC_SSI == m_pSSI2) &&
                               (BSP_SSI2_MASTER_BOOL))) ? BUS_SLAVE_MODE :
                                                          BUS_MASTER_MODE,
                             (STEREO_DAC_BUS_MODE == NETWORK_MODE) ?
                                 USE_4_TIMESLOTS : USE_2_TIMESLOTS) !=
        PMIC_SUCCESS)
    {
        ERRORMSG(1, (_T("PmicAudioOpen: failed to switch Stereo DAC over ")
                     _T("to audio bus %d!\r\n"), STEREO_DAC_AUDIO_BUS));

        // Need to free up previously acquired Stereo DAC device handle.
        goto cleanUp;
    }

#ifdef AUDIO_RECORDING_ENABLED

    // Also get a device handle to the PMIC's Voice CODEC for performing audio
    // recording. If this call succeeds, then we have a device handle that we
    // must use to call all of the other PMIC Audio APIs.
    if (PmicAudioOpen(&hVoiceCODEC, VOICE_CODEC) != PMIC_SUCCESS)
    {
        ERRORMSG(1, (_T("PmicAudioOpen: failed to get Voice CODEC device ")
                     _T("handle!\r\n")));

        // Need to free up previously acquired Stereo DAC device handle.
        goto cleanUp;
    }

#endif // #ifdef AUDIO_RECORDING_ENABLED

    // Now that we have valid device handles to both the PMIC Stereo DAC and
    // Voice CODEC, we can proceed to setup access to the other hardware
    // components that are also needed for audio playback and recording. This
    // includes SSI1, SSI2, and the Digital Audio MUX.

    // Start by getting access to the SSI1 hardware control registers.
    phyAddr.QuadPart = CSP_BASE_REG_PA_SSI1;

    // Map peripheral physical address to virtual address.
    m_pSSI1 = (PCSP_SSI_REG) MmMapIoSpace(phyAddr, sizeof(CSP_SSI_REG), FALSE); 
        
    // Check if the virtual mapping failed.
    if (m_pSSI1 == NULL)
    {
        ERRORMSG(1, (_T("MapRegisters:  MmMapIoSpace failed for SSI1!\r\n")));
        goto cleanUp;
    }

    // Call the OAL to translate the SSI1 IRQ into a SYSINTR value.
    irq = IRQ_SSI1;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(UINT32),
                         &m_dwSysintrSSI1, sizeof(UINT32), NULL))
    {
        RETAILMSG(TRUE, (TEXT("ERROR: HardwareContext::Init: Failed to obtain ")
                         TEXT("sysintr value for SSI1 interrupt.\r\n")));
        goto cleanUp;
    }
 
    // Also get access to the SSI2 hardware control registers.
    phyAddr.QuadPart = CSP_BASE_REG_PA_SSI2;

    // Map peripheral physical address to virtual address.
    m_pSSI2 = (PCSP_SSI_REG) MmMapIoSpace(phyAddr, sizeof(CSP_SSI_REG), FALSE); 
        
    // Check if the virtual mapping failed.
    if (m_pSSI2 == NULL)
    {
        ERRORMSG(1, (_T("MapRegisters:  MmMapIoSpace failed for SSI2!\r\n")));
        goto cleanUp;
    }

    // Call the OAL to translate the SSI2 IRQ into a SYSINTR value.
    irq = IRQ_SSI2;
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &irq, sizeof(UINT32),
                         &m_dwSysintrSSI2, sizeof(UINT32), NULL))
    {
        RETAILMSG(TRUE, (TEXT("ERROR: HardwareContext::Init: Failed to obtain ")
                         TEXT("sysintr value for SSI2 interrupt.\r\n")));
        goto cleanUp;
    }

    // Finally, get access to the Digital Audio MUX hardware control registers.
    phyAddr.QuadPart = CSP_BASE_REG_PA_AUDMUX;

    // Map peripheral physical address to virtual address.
    m_pAUDMUX= (PCSP_AUDMUX_REG) MmMapIoSpace(phyAddr, sizeof(CSP_AUDMUX_REG), 
                                              FALSE); 
        
    // Check if the virtual mapping failed.
    if (m_pAUDMUX == NULL)

⌨️ 快捷键说明

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