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

📄 pmic_audio.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 *
 * @retval      PMIC_SUCCESS         If the close request was successful.
 * @retval      PMIC_PARAMETER_ERROR If the handle is invalid.
 */
PMIC_STATUS PmicAudioClose(const PMIC_AUDIO_HANDLE handle)
{
    PMIC_STATUS rc = PMIC_PARAMETER_ERROR;

    /* We need a critical section here to maintain a consistent state. */
    down_interruptible(mutex);

    /* We can now call pmic_audio_close_handle() to actually do the work. */
    rc = pmic_audio_close_handle(handle);

    /* Exit the critical section. */
    up(mutex);

    return rc;
}

/*!
 * @brief Configure the data bus protocol to be used.
 *
 * Provide the parameters needed to properly configure the audio data bus
 * protocol so that data can be read/written to either the Stereo DAC or
 * the Voice CODEC.
 *
 * @param[in]   handle          Device handle from pmic_audio_open() call.
 * @param[in]   busID           Select data bus to be used.
 * @param[in]   protocol        Select the data bus protocol.
 * @param[in]   masterSlave     Select the data bus timing mode.
 * @param[in]   numSlots        Define the number of timeslots (only if in
 *                              master mode).
 *
 * @retval      PMIC_SUCCESS         If the protocol was successful configured.
 * @retval      PMIC_PARAMETER_ERROR If the handle or the protocol parameters
 *                                   are invalid.
 */
PMIC_STATUS PmicAudioSetProtocol(
    const PMIC_AUDIO_HANDLE       handle,
    const PMIC_AUDIO_DATA_BUS     busID,
    const PMIC_AUDIO_BUS_PROTOCOL protocol,
    const PMIC_AUDIO_BUS_MODE     masterSlave,
    const PMIC_AUDIO_NUMSLOTS     numSlots)
{
    PMIC_STATUS rc = PMIC_PARAMETER_ERROR;

    const unsigned int ST_DAC_MASK1 = regSTEREO_DAC.STDCSSISEL.mask |
                                      regSTEREO_DAC.STDCSM.mask     |
                                      regSTEREO_DAC.STDCCLKEN.mask;
    const unsigned int ST_DAC_MASK2 = regSSI_NETWORK.STDCSLOTS.mask;
    const unsigned int VCODEC_MASK  = regAUDIO_CODEC.CDCSSISEL.mask |
                                      regAUDIO_CODEC.CDCSM.mask     |
                                      regAUDIO_CODEC.CDCCLKEN.mask;
    unsigned int reg_value  = 0;
    unsigned int reg_value2 = 0;

    /* Enter a critical section so that we can ensure only one
     * state change request is completed at a time.
     */
    down_interruptible(mutex);

    if ((handle == stDAC.handle) &&
        (stDAC.handleState == HANDLE_IN_USE))
    {
        /* Make sure that the MC13783 PMIC supports the requested
         * Stereo DAC data bus protocol.
         */
        if ((protocol == NETWORK_MODE) &&
            !((numSlots == USE_2_TIMESLOTS) ||
              (numSlots == USE_4_TIMESLOTS) ||
              (numSlots == USE_8_TIMESLOTS)))
        {
            /* The Stereo DAC only supports 2, 4, or 8 time slots when in
             * Network Mode.
             */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Invalid numSlots parameter (Stereo DAC only ")
                     _T("supports 2,4, or 8 timeslots in Network Mode)\n"),
                     __FILE__));
            rc = PMIC_NOT_SUPPORTED;
        }
        else if (((protocol == NORMAL_MSB_JUSTIFIED_MODE) ||
                  (protocol == I2S_MODE)) &&
                 (numSlots != USE_2_TIMESLOTS))
        {
            /* The Stereo DAC only supports the use of 2 time slots when in
             * Normal Mode or I2S Mode.
             */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Invalid numSlots parameter (Stereo DAC only ")
                     _T("supports 2 timeslots in Normal or I2S Mode)\n"),
                     __FILE__));
            rc = PMIC_NOT_SUPPORTED;
        }
        else if ((masterSlave == BUS_MASTER_MODE) &&
                 ((stDAC.clockIn == CLOCK_IN_FSYNC) ||
                  (stDAC.clockIn == CLOCK_IN_BITCLK)))
        {
            /* Invalid clock inputs for master mode. */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Invalid Stereo DAC clock selection for ")
                     _T("Master Mode\n"),
                     __FILE__));
            rc = PMIC_PARAMETER_ERROR;
        }
        else if ((masterSlave == BUS_SLAVE_MODE) &&
                 (stDAC.clockIn == CLOCK_IN_DEFAULT))
        {
            /* Invalid clock inputs for slave mode. */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Invalid Stereo DAC clock selection for ")
                     _T("Slave Mode\n"),
                     __FILE__));
            rc = PMIC_PARAMETER_ERROR;
        }
        else if ((vCodec.handleState == HANDLE_IN_USE) &&
                 (vCodec.busID == busID))
        {
            /* The requested data bus is already in use by the Voice CODEC. */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Requested data bus already in use by the Voice ")
                     _T("CODEC\n"), __FILE__));
            rc = PMIC_ERROR;
        }
        else if (protocol == SPD_IF_MODE)
        {
            /* SPD/IF mode is no longer supported. */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: The SPD/IF Stereo DAC mode is no longer ")
                     _T("supported\n"), __FILE__));
            rc = PMIC_NOT_SUPPORTED;
        }
        else
        {
            /* The Voice CODEC is not currently being used but we still need
             * to switch it to the other data bus so that there is no conflict
             * with the Stereo DAC.
             */
            if (vCodec.busID == busID)
            {
                reg_value = SET_BITS(regAUDIO_CODEC, CDCSM, 1);
                if (busID == AUDIO_DATA_BUS_1)
                {
                    reg_value |= SET_BITS(regAUDIO_CODEC, CDCSSISEL,
                                          AUDIO_DATA_BUS_2);
                }
                else
                {
                    reg_value |= SET_BITS(regAUDIO_CODEC, CDCSSISEL, 
                                          AUDIO_DATA_BUS_1);
                }

                /* Note that this update to the AUD_CODEC register also has the
                 * side effect of disabling the Voice CODEC master mode clock
                 * outputs (if they are currently enabled) and changing the
                 * Voice CODEC back to slave mode. We have to do this now
                 * because we want the Voice CODEC to be in a safe idle state
                 * when we switch it over to the other data bus.
                 */
                if (pmic_write_reg(REG_AUDIO_CODEC, reg_value,
                                   VCODEC_MASK) != PMIC_SUCCESS)
                {
                    rc = PMIC_ERROR;
                }
                else
                {
                    vCodec.busID = (busID == AUDIO_DATA_BUS_1) ?
                                       AUDIO_DATA_BUS_2 : AUDIO_DATA_BUS_1;
                }
            }

            if (rc != PMIC_ERROR)
            {
                /* We can now proceed with the Stereo DAC configuration. */
                reg_value = SET_BITS(regSTEREO_DAC, STDCSSISEL, busID)    |
                            SET_BITS(regSTEREO_DAC, STDCFS, protocol)     |
                            SET_BITS(regSTEREO_DAC, STDCSM, masterSlave);

                if (masterSlave == BUS_MASTER_MODE)
                {
                    /* Enable clock outputs when in master mode. */
                    reg_value |= SET_BITS(regSTEREO_DAC, STDCCLKEN, 1);
                }

                if (numSlots == USE_2_TIMESLOTS)
                {
                    /* Use 2 time slots (left, right). */
                    reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 3);
                }
                else if (numSlots == USE_4_TIMESLOTS)
                {
                    /* Use 4 time slots (left, right, 2 other). */
                    reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 2);
                }
                else if ((stDAC.samplingRate == STDAC_RATE_64_KHZ) ||
                         (stDAC.samplingRate == STDAC_RATE_96_KHZ))
                {
                    /* Use 8 time slots (must use this mode for 64 kHz or
                     * 96 kHz sampling rates).
                     */
                    reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 0);
                }
                else
                {
                    /* Use 8 time slots (left, right, 6 other) for all
                     * sampling rates other than 64 kHz or 96 kHz.
                     */
                    reg_value2 |= SET_BITS(regSSI_NETWORK, STDCSLOTS, 1);
                }

                if ((pmic_write_reg(REG_STEREO_DAC, reg_value,
                                    ST_DAC_MASK1 | regSTEREO_DAC.STDCFS.mask) ==
                     PMIC_SUCCESS) &&
                    (pmic_write_reg(REG_SSI_NETWORK, reg_value2, ST_DAC_MASK2) ==
                     PMIC_SUCCESS))
                {
                    stDAC.busID       = busID;
                    stDAC.protocol    = protocol;
                    stDAC.masterSlave = masterSlave;
                    stDAC.numSlots    = numSlots;

                    rc = PMIC_SUCCESS;
                }
                else
                {
                    rc = PMIC_ERROR;
                }
            }
        }
    }
    else if ((handle == vCodec.handle) &&
             (vCodec.handleState == HANDLE_IN_USE))
    {
        /* The MC13783 Voice CODEC only supports a network or I2S mode with 4
         * timeslots.
         */
        if (!((protocol == NETWORK_MODE) || (protocol == I2S_MODE)))
        {
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Voice CODEC only supports Network or I2S ")
                     _T("modes\n"), __FILE__));
            rc = PMIC_NOT_SUPPORTED;
        }
        else if (numSlots != USE_4_TIMESLOTS)
        {
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Voice CODEC only supports using 4 timeslots\n"),
                     __FILE__));
            rc = PMIC_NOT_SUPPORTED;
        }
        else if ((stDAC.handleState == HANDLE_IN_USE) && (stDAC.busID == busID))
        {
            /* The requested data bus is already in use by the Stereo DAC. */
            DEBUGMSG(ZONE_ERROR,
                     (_T("%s: Requested data bus already in use by the Stereo ")
                     _T("DAC\n"), __FILE__));
            rc = PMIC_ERROR;
        }
        else
        {
            /* The Stereo DAC is not currently being used but we still need
             * to switch it to the other data bus so that there is no conflict
             * with the Voice CODEC.
             */
            if (stDAC.busID == busID)
            {
                reg_value = SET_BITS(regSTEREO_DAC, STDCSM, 1);
                if (busID == AUDIO_DATA_BUS_1)
                {
                    reg_value |= SET_BITS(regSTEREO_DAC, STDCSSISEL,
                                          AUDIO_DATA_BUS_2);
                }
                else
                {
                    reg_value |= SET_BITS(regSTEREO_DAC, STDCSSISEL,
                                          AUDIO_DATA_BUS_1);
                }

                /* Note that this update to STEREO_DAC register also has the
                 * side effect of disabling the Stereo DAC master mode clock
                 * outputs (if they are currently enabled) and changing the
                 * Stereo DAC back to slave mode. We have to do this now
                 * because we want the Stereo DAC to be in a safe idle state
                 * when we switch it over to the other data bus.
                 */
                if (pmic_write_reg(REG_STEREO_DAC, reg_value, ST_DAC_MASK1) !=
                    PMIC_SUCCESS)
                {
                    rc = PMIC_ERROR;
                }
                else
                {
                    stDAC.busID = (busID == AUDIO_DATA_BUS_1) ?
                                      AUDIO_DATA_BUS_2 : AUDIO_DATA_BUS_1;

⌨️ 快捷键说明

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