📄 hwctxt.cpp
字号:
// = 7 (for 16 bits/word)
// = 11 (for 24 bits/word)
//
OUTREG32(&pSSI->STCCR,
CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS) |
CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
CSP_BITFVAL(SSI_STCCR_WL, ssi_stccr_wl) |
CSP_BITFVAL(SSI_STCCR_DC, ssi_stccr_dc_mode) |
CSP_BITFVAL(SSI_STCCR_PM, 2));
}
else if (pSSI == STEREO_DAC_SSI)
{
// We want a 44.1 kHz sampling rate from the SSI for the Stereo DAC.
//
// The calculation of the appropriate SSI clock divider constants
// is done as follows:
//
// Ideal Sampling Rate = 44.1 kHz
// Oversampling Rate = 384
// Ideal MCLK Frequency = 44.1 kHz * 384 = 16.9344 MHz
// Serial PLL Frequency = 220.1472 MHz
//
// SSI Divider = 220.1472 / 16.9344 = 13
//
// So that means we can set the predivider to divide-by-one (by
// just writing 0) and the postdivider to divide-by-thirteen
// (which actually means writing a 12 to the postdivider control
// register).
//
// This will produce the exact 16.9344 MHz clock that we need
// as the input to the SSI.
DDKClockConfigBaud((pSSI == m_pSSI1) ? DDK_CLOCK_SIGNAL_SSI1 :
DDK_CLOCK_SIGNAL_SSI2,
(pSSI == m_pSSI1) ? SSI1_MASTER_CLOCK_SOURCE :
SSI2_MASTER_CLOCK_SOURCE,
0, 12);
// The associated SSI internal clock divider constants are
// calculated as follows:
//
// Ideal Sampling Rate = 44.1 kHz
//
// For NETWORK mode only:
// Bits/Word = 16
// Words/Frame = 4
// Ideal Bit Clock Frequency = 44.1 kHz * 16 * 4
// = 2.8224 MHz
// SSI Internal Clock Frequency = 16.9344 MHz (from above)
// SSI Internal Divider = 16.9344 / 2.8224 = 6
//
// For I2S mode only:
// Bits/Word = 32
// Words/Frame = 2
// Ideal Bit Clock Frequency = 44.1 kHz * 32 * 2
// = 2.8224 MHz
// SSI Internal Clock Frequency = 16.9344 MHz (from above)
// SSI Internal Divider = 16.9344 / 2.8224 = 6
//
// The corresponding SSI internal divider settings are as follows:
//
// For both NETWORK and I2S modes:
// DIV2 = 0
// PSR = 0
// PM = 2
//
// We also set the following to configure for bits/word and
// either 4 or 2 words/frame:
//
// DC = 3 (for network mode with 4 words/frame)
// = 1 (for I2S mode 2 words/frame)
// WL = 3 (for 8 bits/word)
// = 7 (for 16 bits/word)
// = 11 (for 24 bits/word)
//
// Note that for the I2S mode, the word length is fixed at 32
// bits/word and the WL value only serves to indicate how many
// out of the 32 bits/word are actually valid.
OUTREG32(&pSSI->STCCR,
CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS) |
CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
CSP_BITFVAL(SSI_STCCR_WL, ssi_stccr_wl) |
CSP_BITFVAL(SSI_STCCR_DC, ssi_stccr_dc_mode) |
CSP_BITFVAL(SSI_STCCR_PM, 2));
}
// Also set the SSI transmitter to use it's internal clock source to
// generate the bit clock and framesync signals for master mode.
SETREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TXDIR));
SETREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TFDIR));
}
else
{
// Configure the SSI transmit clock for slave mode operation where
// the internal divider and prescaler parameters are irrelevant. The
// key settings are DC to select words/frame and WL for bits/word to
// match the PMIC's configuration.
OUTREG32(&pSSI->STCCR,
CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS) |
CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
CSP_BITFVAL(SSI_STCCR_WL, ssi_stccr_wl) |
CSP_BITFVAL(SSI_STCCR_DC, ssi_stccr_dc_mode) |
CSP_BITFVAL(SSI_STCCR_PM, 0));
// We have already configured the SSI transmitter to use an external
// clock and framesync so nothing needs to be done here.
}
// Leave the SSI in a disabled state until we are actually ready to perform
// audio playback or recording.
//
// Also note that we leave all of the transmit and receive timeslots masked
// at this time and only unmask the required timeslots when we call either
// BSPAudioStartSsiOutput() or BSPAudioStartSsiInput().
// Disable SSI clocks to minimize power consumption.
DDKClockSetGatingMode((pSSI == m_pSSI1) ? DDK_CLOCK_GATE_INDEX_SSI1 :
DDK_CLOCK_GATE_INDEX_SSI2,
DDK_CLOCK_GATE_MODE_DISABLED);
}
//-----------------------------------------------------------------------------
//
// Function: BSPAudioStartSsiOutput
//
// This function configures SSI to start audio output.
//
// Parameters:
// pSSI
// [in] Points to SSI to be configured.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioStartSsiOutput(PCSP_SSI_REG pSSI,
const HWSAMPLE *const ssiFifoPrefill,
const unsigned nSsiFifoPrefill)
{
// Enable SSI clocks before we access the SSI registers.
DDKClockSetGatingMode((pSSI == m_pSSI1) ? DDK_CLOCK_GATE_INDEX_SSI1 :
DDK_CLOCK_GATE_INDEX_SSI2,
DDK_CLOCK_GATE_MODE_ENABLED_ALL);
// Enable the SSI and the transmit FIFO0 so that we can fill it up before
// we enable the transmitter later.
SETREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));
SETREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TFEN0));
// Prefill the transmit FIFO so that there is something ready to go when
// we enable the transmitter in the next step.
for (unsigned i = 0; i < nSsiFifoPrefill; i++)
{
OUTREG32(&pSSI->STX0, *(ssiFifoPrefill + i));
}
// Enable only the first two transmit timeslots (for the left+right audio
// channels).
OUTREG32(&pSSI->STMSK, ~0x3);
// The SSI has already been properly configured, we just need to enable
// the SSI transmitter DMA request and the transmitter to begin the
// audio output/playback process.
SETREG32(&pSSI->SIER, CSP_BITFMASK(SSI_SIER_TDMAE));
SETREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_TE));
}
//-----------------------------------------------------------------------------
//
// Function: BSPAudioStopSsiOutput
//
// This function configures SSI to stop audio output.
//
// Parameters:
// pSSI
// [in] Points to SSI to be configured.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioStopSsiOutput(PCSP_SSI_REG pSSI)
{
UINT32 scr;
// Start by disabling the SSI transmitter.
CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_TE));
// Disable the SSI transmit DMA request.
CLRREG32(&pSSI->SIER, CSP_BITFMASK(SSI_SIER_TDMAE));
// Disable the transmit FIFO0 and mask all transmit timeslots.
CLRREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TFEN0));
OUTREG32(&pSSI->STMSK, 0xffffffff);
// If the SSI receiver is also disabled, then turn off the entire SSI.
scr = INREG32(&pSSI->SCR);
if (!(scr & CSP_BITFMASK(SSI_SCR_RE)))
{
// Completely disable the SSI.
CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));
// Disable SSI clocks to minimize power consumption.
DDKClockSetGatingMode((pSSI == m_pSSI1) ? DDK_CLOCK_GATE_INDEX_SSI1 :
DDK_CLOCK_GATE_INDEX_SSI2,
DDK_CLOCK_GATE_MODE_DISABLED);
}
}
#ifdef AUDIO_RECORDING_ENABLED
//-----------------------------------------------------------------------------
//
// Function: BSPAudioStartSsiInput
//
// This function configures SSI to start audio input.
//
// Parameters:
// pSSI
// [in] Points to SSI to be configured.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioStartSsiInput(PCSP_SSI_REG pSSI)
{
// Enable SSI clocks before we access the SSI registers.
DDKClockSetGatingMode((pSSI == m_pSSI1) ? DDK_CLOCK_GATE_INDEX_SSI1 :
DDK_CLOCK_GATE_INDEX_SSI2,
DDK_CLOCK_GATE_MODE_ENABLED_ALL);
// Start off by enabling the SSI. This must be done first.
SETREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));
// Next, enable the SSI receiver DMA request and RX FIFO0.
OUTREG32(&pSSI->SIER, CSP_BITFVAL(SSI_SIER_RFF0_EN, TRUE));
SETREG32(&pSSI->SRCR, CSP_BITFMASK(SSI_SRCR_RFEN0));
// Unmask only the first two receive timeslots (for the primary and
// secondary audio recording channels).
OUTREG32(&pSSI->SRMSK, ~0x3);
// The SSI has already been properly configured, we just need to enable
// the SSI receiver DMA request and the receiver to begin the audio
// input/recording process.
SETREG32(&pSSI->SIER, CSP_BITFMASK(SSI_SIER_RDMAE));
SETREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_RE));
}
//-----------------------------------------------------------------------------
//
// Function: BSPAudioStopSsiInput
//
// This function configures SSI to stop audio input.
//
// Parameters:
// pSSI
// [in] Points to SSI to be configured.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioStopSsiInput(PCSP_SSI_REG pSSI)
{
UINT32 scr;
// Start by disabling the SSI receiver.
CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_RE));
// Disable the SSI receive DMA request
CLRREG32(&pSSI->SIER, CSP_BITFMASK(SSI_SIER_RDMAE));
// Disable the receive FIFO0 and mask all receive timeslots.
CLRREG32(&pSSI->SRCR, CSP_BITFMASK(SSI_SRCR_RFEN0));
OUTREG32(&pSSI->SRMSK, 0xffffffff);
// If the transmitter is also disabled, then turn off the entire SSI.
scr = INREG32(&pSSI->SCR);
if (!(scr & CSP_BITFMASK(SSI_SCR_TE)))
{
// Completely disable the SSI.
CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));
// Disable SSI clocks to minimize power consumption.
DDKClockSetGatingMode((pSSI == m_pSSI1) ? DDK_CLOCK_GATE_INDEX_SSI1 :
DDK_CLOCK_GATE_INDEX_SSI2,
DDK_CLOCK_GATE_MODE_DISABLED);
}
}
#endif // #ifdef AUDIO_RECORDING_ENABLED
//-----------------------------------------------------------------------------
//
// Function: BSPAudioSetCodecPower
//
// This function sets the power state of the external audio chip.
//
// Parameters:
// state
// [in] - Specifies the desired power state.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioSetCodecPower(AUDIO_PWR_STATE state)
{
UINT32 regMode0, audRx0, mask;
// Check if power state transition is required
if (state == m_CodecPwrState) return;
switch (state)
{
case AUDIO_PWR_STATE_OFF:
regMode0 = CSP_BITFVAL(MC13783_REG_MODE0_VAUDIOEN, FALSE) |
CSP_BITFVAL(MC13783_REG_MODE0_VAUDIOSTBY, TRUE) |
CSP_BITFVAL(MC13783_REG_MODE0_VAUDIOMODE, FALSE);
audRx0 = CSP_BITFVAL(MC13783_AUD_RX0_VAUDIOON,
MC13783_AUD_RX0_VAUDIOON_DISABLE) |
CSP_BITFVAL(MC13783_AUD_RX0_BIASEN,
MC13783_AUD_RX0_BIASEN_DISABLE) |
CSP_BITFVAL(MC13783_AUD_RX0_BIASSPEED,
MC13783_AUD_RX0_BIASSPEED_ENABLE);
break;
case AUDIO_PWR_STATE_STANDBY:
#ifdef AUDIO_RECORDING_ENABLED
// Only allow transition to standby state if both input
// and output are ina
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -