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

📄 hwctxt.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    AUDMUX_EXTERNAL_PORT extPort, BOOL bMaster)
{
    PUINT32 pPTCR, pPDCR;

    // Get pointers to the Audio MUX internal port registers.
    pPTCR = &m_pAUDMUX->PTCR1 + intPort*2;
    pPDCR = &m_pAUDMUX->PDCR1 + intPort*2;

    // Configure the Audio MUX internal port to connect with the SSI based
    // upon who is acting as the bus master.
    // 
    // But regardless of who is the master, we also configure the internal
    // port for synchronous 4-wire operation in normal mode (which is what
    // we actually need to support the SSI and PMIC for either network or I2S
    // modes).
    // 
    // Note that we only configure the transmit framesync and bitclock here
    // because we are using synchronous mode and the receiver clock
    // settings will be determined by the transmitter settings.
    if (bMaster)
    {
        // All clock signals for the internal port are input signals for
        // SSI master mode.
        OUTREG32(pPTCR,
            CSP_BITFVAL(AUDMUX_PTCR_TFSDIR,  AUDMUX_PTCR_TFSDIR_INPUT)  |
            CSP_BITFVAL(AUDMUX_PTCR_TCLKDIR, AUDMUX_PTCR_TCLKDIR_INPUT) |
            CSP_BITFVAL(AUDMUX_PTCR_SYN, AUDMUX_PTCR_SYN_SYNC));
    }
    else
    {
        // All clock signals for the internal port are all output signals for
        // PMIC master mode. The source of the clock signals is the external
        // port that is connected to the PMIC.
        OUTREG32(pPTCR,
            CSP_BITFVAL(AUDMUX_PTCR_TFSDIR,  AUDMUX_PTCR_TFSDIR_OUTPUT)  |
            CSP_BITFVAL(AUDMUX_PTCR_TFSEL,  extPort)                     |
            CSP_BITFVAL(AUDMUX_PTCR_TCLKDIR, AUDMUX_PTCR_TCLKDIR_OUTPUT) |
            CSP_BITFVAL(AUDMUX_PTCR_TCSEL,  extPort)                     |
            CSP_BITFVAL(AUDMUX_PTCR_SYN, AUDMUX_PTCR_SYN_SYNC));
    }

    OUTREG32(pPDCR,
        CSP_BITFVAL(AUDMUX_PDCR_RXDSEL, extPort)                    |
        CSP_BITFVAL(AUDMUX_PDCR_TXRXEN, AUDMUX_PDCR_TXRXEN_NO_SWAP) |
        CSP_BITFVAL(AUDMUX_PDCR_MODE,   AUDMUX_PDCR_MODE_NORMAL));

    // Get pointers to the Audio MUX external port registers.
    pPTCR = &m_pAUDMUX->PTCR1 + extPort * 2;
    pPDCR = &m_pAUDMUX->PDCR1 + extPort * 2;

    // Configure the Audio MUX external port to connect with the PMIC based
    // upon who is acting as the bus master.
    // 
    // But regardless of who is the master, we also configure the external
    // port for synchronous 4-wire operation in normal mode (which is what
    // we actually need to support the SSI and PMIC in either network or I2S
    // mode).
    if (bMaster)
    {
        // All clock signals for the external port are output signals for
        // SSI master mode. The source of the clock signals is the internal
        // port that is connected to the SSI.
        OUTREG32(pPTCR,
            CSP_BITFVAL(AUDMUX_PTCR_TFSDIR,  AUDMUX_PTCR_TFSDIR_OUTPUT)  |
            CSP_BITFVAL(AUDMUX_PTCR_TFSEL,  intPort)                     |
            CSP_BITFVAL(AUDMUX_PTCR_TCLKDIR, AUDMUX_PTCR_TCLKDIR_OUTPUT) |
            CSP_BITFVAL(AUDMUX_PTCR_TCSEL,  intPort)                     |
            CSP_BITFVAL(AUDMUX_PTCR_SYN, AUDMUX_PTCR_SYN_SYNC));
    }
    else
    {
        // All clock signals for the external port are input signals for
        // PMIC master mode.
        OUTREG32(pPTCR,
            CSP_BITFVAL(AUDMUX_PTCR_TFSDIR,  AUDMUX_PTCR_TFSDIR_INPUT)  |
            CSP_BITFVAL(AUDMUX_PTCR_TCLKDIR, AUDMUX_PTCR_TCLKDIR_INPUT) |
            CSP_BITFVAL(AUDMUX_PTCR_SYN, AUDMUX_PTCR_SYN_SYNC));
    }

    OUTREG32(pPDCR,
        CSP_BITFVAL(AUDMUX_PDCR_RXDSEL, intPort)                    |
        CSP_BITFVAL(AUDMUX_PDCR_TXRXEN, AUDMUX_PDCR_TXRXEN_NO_SWAP) |
        CSP_BITFVAL(AUDMUX_PDCR_MODE,   AUDMUX_PDCR_MODE_NORMAL));

    // Must also configure the IOMUX pins for connecting the Audio MUX
    // external port to off-chip peripherals such as the PMIC. Without
    // this step, we will not be able to connect the Audio MUX to the
    // PMIC audio buses.
    //
    // The key here is to configure the 4-wire interface (framesync, bitclock,
    // TX, and RX) through the IOMUX by enabling the functional/normal mode.
    // We leave the input/output direction control for all of the I/O pins up
    // to the Audio MUX.
    //
    // Note that we configure both the RX and TX pins here just for the sake
    // of completeness and simplicity even though the PMIC Stereo DAC does not
    // currently have any recording capabilities and we do not use the Voice
    // CODEC for playback.
    DDKIomuxSetPinMux((extPort == PORT4) ? DDK_IOMUX_PIN_SFS4 :
                                           DDK_IOMUX_PIN_SFS5,
                      DDK_IOMUX_OUT_FUNC,
                      DDK_IOMUX_IN_FUNC);
    DDKIomuxSetPinMux((extPort == PORT4) ? DDK_IOMUX_PIN_SCK4 :
                                           DDK_IOMUX_PIN_SCK5,
                      DDK_IOMUX_OUT_FUNC,
                      DDK_IOMUX_IN_FUNC);
    DDKIomuxSetPinMux((extPort == PORT4) ? DDK_IOMUX_PIN_STXD4 :
                                           DDK_IOMUX_PIN_STXD5,
                      DDK_IOMUX_OUT_FUNC,
                      DDK_IOMUX_IN_FUNC);
    DDKIomuxSetPinMux((extPort == PORT4) ? DDK_IOMUX_PIN_SRXD4 :
                                           DDK_IOMUX_PIN_SRXD5,
                      DDK_IOMUX_OUT_FUNC,
                      DDK_IOMUX_IN_FUNC);
}


//-----------------------------------------------------------------------------
//
//  Function: BSPAudioInitSsi
//
//  This function initializes the specified audio port for input/output.
//
//  Parameters:
//      The SSI configuration to be used.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioInitSsi(AUDIO_BUS bus, PCSP_SSI_REG pSSI)
{
    // These are the only SSI configuration parameters that are different
    // between the network and I2S modes. We just default to setting up for
    // network mode and then adjust the settings if I2S mode was actually
    // selected.
    unsigned ssi_i2s_mode        = SSI_SCR_I2S_MODE_NORMAL;
    unsigned ssi_stcr_tsckp_mode = SSI_STCR_TSCKP_RISING_EDGE;
    unsigned ssi_stcr_tfsi_mode  = SSI_STCR_TFSI_ACTIVE_HIGH;
    unsigned ssi_stccr_dc_mode   = 3;
    unsigned ssi_scr_net_mode    = SSI_SCR_NET_ENABLE;
    unsigned ssi_stcr_tfsl_mode  = SSI_STCR_TFSL_1BIT;
    unsigned ssi_stccr_wl        = SSI_STCCR_WL_8BIT;

    if (sizeof(HWSAMPLE) == sizeof(INT16))
    {
        ssi_stccr_wl = SSI_STCCR_WL_16BIT;
    }
    else if (sizeof(HWSAMPLE) == sizeof(INT32))
    {
        // The SSI only supports a maximum transfer size of 24 bits/word.
        ssi_stccr_wl = SSI_STCCR_WL_24BIT;
    }

    // Reconfigure the SSI to use the I2S mode instead if that was what was
    // selected.
    //
    // The required SSI configuration changes consist of the following:
    //
    //     * Either I2S master/slave mode.
    //     * The transmit data clocked at the falling edge.
    //     * Transmit frame sync is active low.
    //     * Select 2 words/frame.
    //
    if (((STEREO_DAC_BUS_MODE == I2S_MODE)  && (pSSI == STEREO_DAC_SSI)) ||
        ((VOICE_CODEC_BUS_MODE == I2S_MODE) && (pSSI == VOICE_CODEC_SSI)))
    {
        ssi_i2s_mode = (((pSSI == m_pSSI1) && (BSP_SSI1_MASTER_BOOL)) ||
                        ((pSSI == m_pSSI2) && (BSP_SSI2_MASTER_BOOL))) ?
                           SSI_SCR_I2S_MODE_MASTER : SSI_SCR_I2S_MODE_SLAVE;
        ssi_stcr_tsckp_mode = SSI_STCR_TSCKP_FALLING_EDGE;
        ssi_stcr_tfsi_mode  = SSI_STCR_TFSI_ACTIVE_LOW;
        ssi_stccr_dc_mode   = 1;                        // 2 words/frame
        ssi_scr_net_mode    = SSI_SCR_NET_DISABLE;      // disable NETWORK mode
        ssi_stcr_tfsl_mode  = SSI_STCR_TFSL_1WORD;      // 1-word long framesync
    }

    // 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);

    // Disable the SSI transmitter and receiver.
    CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_RE) | CSP_BITFMASK(SSI_SCR_TE));

    // Also mask all transmitter and receiver timeslots until we are ready
    // to begin a new audio I/O operation.
    OUTREG32(&pSSI->STMSK, 0xffffffff);
    OUTREG32(&pSSI->SRMSK, 0xffffffff);

    // Next disable the SSI so that we can reconfigure the items that
    // can only be changed when the SSI is disabled.
    //
    // We should do this as a separate write from disabling the SSI
    // transmitter and receiver in order to give the SSI sufficient
    // time to properly complete the previous operation.
    CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));

    // Disable all SSI interrupts and DMA requests.
    OUTREG32(&pSSI->SIER, 0);

    // Also disable the transmit and receive FIFOs so that we can configure
    // the DMA watermark levels later.
    OUTREG32(&pSSI->STCR, 0);
    OUTREG32(&pSSI->SRCR, 0);

    // We can now begin reconfiguring the SSI for synchronous 4-wire mode.
    // Since we are using synchronous mode, we only need to configure the
    // SSI transmitter clock in the following stages and there is no need to
    // separately set the SSI receiver clock configuration.
    //
    // The SSI is configured for I2S master/slave mode here or just "normal"
    // mode if NETWORK_MODE was selected for the audio bus above. All clock
    // configuration settings for the selected master/slave mode will be done
    // later.
    //
    // The SSI SYS_CLK clock output is also disabled here since we do not need
    // it (even if the SSI is operated in master mode since the slave device
    // just needs to receive the framesync and bitclock signals).
    //
    // We never use 2-channel mode (where both FIFO0 and FIFO1 are active) so
    // that is disabled here as well.
    OUTREG32(&pSSI->SCR, 
        CSP_BITFVAL(SSI_SCR_CLK_IST, SSI_SCR_CLK_IST_HIGH)      |
        CSP_BITFVAL(SSI_SCR_TCH_EN, SSI_SCR_TCH_EN_2CHAN_OFF)   |
        CSP_BITFVAL(SSI_SCR_SYS_CLK_EN, SSI_SCR_SYS_CLK_EN_OFF) |
        CSP_BITFVAL(SSI_SCR_I2S_MODE, ssi_i2s_mode)             |
        CSP_BITFVAL(SSI_SCR_SYN, SSI_SCR_SYN_SYNC)              |
        CSP_BITFVAL(SSI_SCR_NET, ssi_scr_net_mode));
 
    // Next, continue with the configuration of the SSI transmitter for
    // audio output/playback.
    //
    // To match the PMIC's capabilities, the SSI transmitter must transmit
    // 16-bit words MSB-first. Only FIFO0 is needed for single channel
    // operation but we leave it disabled until we are actually ready to
    // start an audio I/O operation.
    //
    // Also, the SSI transmitter's clock and framesync signals are configured
    // here for the slave mode of operation. We will change this later if it
    // turns out that the SSI is to be operated in bus master mode.
    //
    // Note that we must configure the transmitter's clock settings even if we
    // never use this SSI for audio playback because we are using synchronous
    // mode where the receiver shares the same clock configuration as the
    // transmitter.
    OUTREG32(&pSSI->STCR,
        CSP_BITFVAL(SSI_STCR_TXBIT0, SSI_STCR_TXBIT0_LSB_ALIGNED) |
        CSP_BITFVAL(SSI_STCR_TFEN1,  SSI_STCR_TFEN1_DISABLE)      |
        CSP_BITFVAL(SSI_STCR_TFEN0,  SSI_STCR_TFEN0_DISABLE)      |
        CSP_BITFVAL(SSI_STCR_TFDIR,  SSI_STCR_TFDIR_EXTERNAL)     |
        CSP_BITFVAL(SSI_STCR_TXDIR,  SSI_STCR_TXDIR_EXTERNAL)     |
        CSP_BITFVAL(SSI_STCR_TSHFD,  SSI_STCR_TSHFD_MSB_FIRST)    |
        CSP_BITFVAL(SSI_STCR_TSCKP,  ssi_stcr_tsckp_mode)         |
        CSP_BITFVAL(SSI_STCR_TFSI,   ssi_stcr_tfsi_mode)          |
        CSP_BITFVAL(SSI_STCR_TFSL,   ssi_stcr_tfsl_mode)          |
        CSP_BITFVAL(SSI_STCR_TEFS,   SSI_STCR_TEFS_EARLY)
    );
 
    // Now configure the SSI receiver for audio input/recording.
    //
    // To match the PMIC's capabilities, the SSI receiver must receive 
    // 16-bit words MSB-first. Only FIFO0 is needed for single channel
    // operation but we leave it disabled until we are actually ready to
    // start an audio I/O operation.
    //
    // Also, we skip configuring the SSI receiver's clock settings here because
    // we're using synchronous mode and we've already configured the SSI's
    // transmitter clock configuration above. The receiver will simply share
    // the same clock configuration as the transmitter.
    //
    // Note that it is harmless to also configure the SSI receiver even if we
    // never use this SSI for audio recording.
    OUTREG32(&pSSI->SRCR,
        CSP_BITFVAL(SSI_SRCR_RXBIT0, SSI_SRCR_RXBIT0_LSB_ALIGNED) |
        CSP_BITFVAL(SSI_SRCR_RFEN1,  SSI_SRCR_RFEN1_DISABLE)      |
        CSP_BITFVAL(SSI_SRCR_RFEN0,  SSI_SRCR_RFEN0_DISABLE)      |
        CSP_BITFVAL(SSI_SRCR_RSHFD,  SSI_SRCR_RSHFD_MSB_FIRST)
    );

    // Set the Receive FIFO empty and Transmit FIFO full watermark levels.
    //
    // We set the watermark levels for both FIFO0 and FIFO1 here even though
    // we will only use FIFO0 because all of the watermark levels must be set
    // to a valid value (regardless of whether the FIFO is used or not) in
    // order for the SSI to operate properly.
    OUTREG32(&pSSI->SFCSR,
        CSP_BITFVAL(SSI_SFCSR_RFWM0, SSI_SFCSR_RX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_TFWM0, SSI_SFCSR_TX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_RFWM1, SSI_SFCSR_RX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_TFWM1, SSI_SFCSR_TX_WATERMARK));

    if (((pSSI == m_pSSI1) && (BSP_SSI1_MASTER_BOOL)) ||
        ((pSSI == m_pSSI2) && (BSP_SSI2_MASTER_BOOL)))
    {
        // First configure the Clock Control Module to route the correct
        // system clock signal to the SSI.
        if (pSSI == VOICE_CODEC_SSI)
        {
            // We want a 16 kHz sampling rate from the SSI for the Voice CODEC.
            //
            // The calculation of the appropriate SSI clock divider constants
            // is as follows:
            //
            //    Ideal Sampling Rate  = 16 kHz
            //    Oversampling Rate    = 384
            //    Ideal MCLK Frequency = 16 kHz * 384 = 6.144 MHz
            //    Serial PLL Frequency = 220.1472 MHz
            //
            //    SSI Divider = 220.1472 / 6.144 = 35.83125
            //                = 36 (rounded up)
            //
            // So that means we can set the predivider to divide-by-one (by
            // just writing 0) and the postdivider to divide-by-thirty-six
            // (which actually means writing a 35 to the postdivider control
            // register).
            DDKClockConfigBaud((pSSI == m_pSSI1) ? DDK_CLOCK_SIGNAL_SSI1 :
                                                   DDK_CLOCK_SIGNAL_SSI2,
                               (pSSI == m_pSSI1) ? SSI1_MASTER_CLOCK_SOURCE :
                                                   SSI2_MASTER_CLOCK_SOURCE,
                               0, 35);

            // The associated SSI internal clock divider constants are:
            //
            //    Ideal Sampling Rate          = 16 kHz
            //    Bits/Word                    = 16
            //    Words/Frame                  = 4
            //    Ideal Bit Clock Frequency    = 16 kHz * 16 * 4 = 1.024 MHz
            //    SSI Internal Clock Frequency = 6.144 MHz (from above)
            //    SSI Internal Divider         = 6.144 / 1.024 = 6
            //
            // An internal divider value of 6 can be achieved by setting the
            // following:
            //
            //    DIV2 = 0
            //    PSR  = 0
            //    PM   = 2
            //
            // We also set the following to configure for bits/word and
            // words/frame:
            //
            //    DC = 3  (for network mode with 4 words/frame)
            //       = 1  (for I2S mode with 2 words/frame)
            //    WL = 3  (for 8 bits/word)

⌨️ 快捷键说明

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