📄 hwctxt.cpp
字号:
//------------------------------------------------------------------------------
//
// 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 + -