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

📄 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 页
字号:
/*!
 * @brief This variable maintains the current state of the Voice CODEC.
 *
 * This variable tracks the current state of the Voice CODEC audio hardware
 * along with any information that is required by the device driver to
 * manage the hardware (e.g., callback functions and event notification
 * masks).
 *
 * The initial values represent the reset/power on state of the Voice CODEC.
 */
static PMIC_AUDIO_VCODEC_STATE vCodec = {
    (PMIC_AUDIO_HANDLE)NULL,                         /* handle             */
    HANDLE_FREE,                                     /* handleState        */
    AUDIO_DATA_BUS_2,                                /* busID              */
    NETWORK_MODE,                                    /* protocol           */
    BUS_SLAVE_MODE,                                  /* masterSlave        */
    USE_4_TIMESLOTS,                                 /* numSlots           */
    (PMIC_AUDIO_CALLBACK)NULL,                       /* callback           */
    (PMIC_AUDIO_EVENTS)NULL,                         /* eventMask          */
    CLOCK_IN_CLIB,                                   /* clockIn            */
    VCODEC_RATE_8_KHZ,                               /* samplingRate       */
    VCODEC_CLI_13MHZ,                                /* clockFreq          */
    NO_INVERT,                                       /* invert             */
    USE_TS0,                                         /* timeslot           */
    USE_TS2,                                         /* secondary timeslot */
    PMIC_AUDIO_VCODEC_CONFIG(INPUT_HIGHPASS_FILTER |
                             OUTPUT_HIGHPASS_FILTER),/* config             */
    (PMIC_AUDIO_INPUT_CONFIG)NULL,                   /* inputConfig        */
                                                     /* leftChannelMic     */
    { NO_MIC,                                        /*    mic             */
      MICROPHONE_OFF,                                /*    micOnOff        */
      CURRENT_TO_VOLTAGE,                            /*    ampMode         */
      MIC_GAIN_0DB                                   /*    gain            */
    },
                                                     /* rightChannelMic    */
    { NO_MIC,                                        /*    mic             */
      MICROPHONE_OFF,                                /*    micOnOff        */
      AMP_OFF,                                       /*    ampMode         */
      MIC_GAIN_0DB                                   /*    gain            */
    }
};

/*!
 * @brief This maintains the current state of the External Stereo Input.
 */
typedef struct
{
    PMIC_AUDIO_HANDLE         handle;      /*!< Handle used to access the
                                                External Stereo Inputs.     */
    HANDLE_STATE              handleState; /*!< Current handle state.       */
    PMIC_AUDIO_CALLBACK       callback;    /*!< Event notification callback
                                                function pointer.           */
    PMIC_AUDIO_EVENTS         eventMask;   /*!< Event notification mask.    */
    PMIC_AUDIO_STEREO_IN_GAIN inputGain;   /*!< External Stereo Input
                                                amplifier gain level.       */
} PMIC_AUDIO_EXT_STEREO_IN_STATE;

/*!
 * @brief This maintains the current state of the External Stereo Input.
 *
 * This variable tracks the current state of the External Stereo Input audio
 * hardware along with any information that is required by the device driver
 * to manage the hardware (e.g., callback functions and event notification
 * masks).
 *
 * The initial values represent the reset/power on state of the External
 * Stereo Input.
 */
static PMIC_AUDIO_EXT_STEREO_IN_STATE extStereoIn = {
    (PMIC_AUDIO_HANDLE)NULL,   /* handle      */
    HANDLE_FREE,               /* handleState */
    (PMIC_AUDIO_CALLBACK)NULL, /* callback    */
    (PMIC_AUDIO_EVENTS)NULL,   /* eventMask   */
    STEREO_IN_GAIN_0DB         /* inputGain   */
};

/*!
 * @brief This maintains the current state of the Audio Output Section.
 */
typedef struct
{
    PMIC_AUDIO_OUTPUT_PORT            outputPort;       /*!< Current audio
                                                             output port.     */
    PMIC_AUDIO_OUTPUT_PGA_GAIN        outputStDACPGAGain; /*!< Output PGA gain
                                                               level.         */
    PMIC_AUDIO_OUTPUT_PGA_GAIN        outputVCodecPGAGain; /*!< Output PGA gain
                                                                level.        */
    PMIC_AUDIO_OUTPUT_PGA_GAIN        outputExtStereoInPGAGain; /*!< Output PGA
                                                                     gain level.
                                                                              */
    PMIC_AUDIO_OUTPUT_BALANCE_GAIN    balanceLeftGain;  /*!< Left channel
                                                             balance gain
                                                             level.           */
    PMIC_AUDIO_OUTPUT_BALANCE_GAIN    balanceRightGain; /*!< Right channel
                                                             balance gain
                                                             level.           */
    PMIC_AUDIO_MONO_ADDER_OUTPUT_GAIN monoAdderGain;    /*!< Mono adder gain
                                                             level.           */
    PMIC_AUDIO_OUTPUT_CONFIG          config;           /*!< Audio output
                                                             section config
                                                             options.         */
} PMIC_AUDIO_AUDIO_OUTPUT_STATE;

/*!
 * @brief This variable maintains the current state of the Audio Output Section.
 *
 * This variable tracks the current state of the Audio Output Section.
 *
 * The initial values represent the reset/power on state of the Audio
 * Output Section.
 */
static PMIC_AUDIO_AUDIO_OUTPUT_STATE audioOutput = {
    (PMIC_AUDIO_OUTPUT_PORT)NULL, /* outputPort               */
    OUTPGA_GAIN_0DB,              /* outputStDACPGAGain       */
    OUTPGA_GAIN_0DB,              /* outputVCodecPGAGain      */
    OUTPGA_GAIN_0DB,              /* outputExtStereoInPGAGain */
    BAL_GAIN_0DB,                 /* balanceLeftGain          */
    BAL_GAIN_0DB,                 /* balanceRightGain         */
    MONOADD_GAIN_0DB,             /* monoAdderGain            */
    (PMIC_AUDIO_OUTPUT_CONFIG)0   /* config                   */
};

/*! The current headset status. */
static HEADSET_STATUS headsetState = NO_HEADSET;

/*! Define a 1 ms wait interval that is needed to ensure that certain
 *  hardware operations are successfully completed.
 */
static const unsigned long delay_1ms = 1;

/*! Define a handle to a mutex object for implementing mutual exclusion.
 *
 *  Note that because this source file will be part of a DLL, we cannot
 *  just call CreateMutex() here to initialize the mutex handle. Attempting
 *  to do so will result in a LNK4210 warning when the linker tries to
 *  create the DLL. This warning indicates that no CRT (C runtime) code
 *  is available to handle non-trivial static initializers (such as those
 *  that involve a function call). Therefore, we must defer the CreateMutex()
 *  call until the DLL is actually loaded by the Device Manager and
 *  activated. This will result in a call to pmic_audio_driver_init() where
 *  we can finally make our CreateMutex() call.
 *
 *  The mutex handle is released and the mutex destroyed when the Device
 *  Manager deactivates the device and pmic_audio_driver_deinit() is called.
 */
static HANDLE mutex = NULL;

/*! Declare a global flag that is only set to TRUE when the powerdown handler
 *  is running. This allows us to bypass any timed delay calls that would
 *  have normally been made. Because the powerdown handler runs at priority 0
 *  with interrupts disabled, it cannot do anything that would cause it to
 *  block or otherwise wait.
 */
static BOOL g_audioPowerdown = FALSE;

/*! We need to have a globally accessible handle to the timed delay event
 *  object so that the powerdown handler can forcibly cancel an in-progress
 *  timer. All in-progress timed delays must be immediately cancelled so
 *  that the thread can wake up and quickly release the critical section
 *  (which is guarded by the mutex handle that was declared above).
 *  Otherwise, the powerdown handler will block when it too tries to
 *  acquire the critical section.
 */
static HANDLE hTimedDelay = NULL;

/* Prototypes for all static audio driver functions. */

static PMIC_STATUS pmic_read_reg(const pmic_control_register regID,
                                 const unsigned *regValue);
static PMIC_STATUS pmic_write_reg(const pmic_control_register regID,
                                  const unsigned regValue,
                                  const unsigned regMask);
static inline void down_interruptible(HANDLE hMutex);
static inline void up(HANDLE hMutex);
static PMIC_STATUS pmic_adc_convert(const unsigned short  channel,
                                    const unsigned short *adcResult);
static PMIC_STATUS pmic_audio_mic_boost_enable(void);
static PMIC_STATUS pmic_audio_mic_boost_disable(void);
static PMIC_STATUS pmic_audio_close_handle(const PMIC_AUDIO_HANDLE handle);
static PMIC_STATUS pmic_audio_reset_device(const PMIC_AUDIO_HANDLE handle);

/*************************************************************************
 * Audio device access APIs.
 *************************************************************************
 */

/*!
 * @name General Setup and Configuration APIs
 * Functions for general setup and configuration of the PMIC Audio
 * hardware.
 */
/*@{*/

/*!
 * @brief Request exclusive access to the PMIC Audio hardware.
 *
 * Attempt to open and gain exclusive access to a key PMIC audio hardware
 * component (e.g., the Stereo DAC or the Voice CODEC). Depending upon the
 * type of audio operation that is desired and the nature of the audio data
 * stream, the Stereo DAC and/or the Voice CODEC will be a required hardware
 * component and needs to be acquired by calling this function.
 *
 * If the open request is successful, then a numeric handle is returned
 * and this handle must be used in all subsequent function calls to complete
 * the configuration of either the Stereo DAC or the Voice CODEC and along
 * with any other associated audio hardware components that will be needed.
 *
 * The same handle must also be used in the close call when use of the PMIC
 * audio hardware is no longer required.
 *
 * The open request will fail if the requested audio hardware component has
 * already been acquired by a previous open call but not yet closed.
 *
 * @param[out]  handle          Device handle to be used for subsequent PMIC
 *                              audio API calls.
 * @param[in]   device          The required PMIC audio hardware component.
 *
 * @retval      PMIC_SUCCESS         If the open request was successful
 * @retval      PMIC_PARAMETER_ERROR If the handle argument is NULL.
 * @retval      PMIC_ERROR           If the audio hardware component is
 *                                   unavailable.
 */
PMIC_STATUS PmicAudioOpen(
    PMIC_AUDIO_HANDLE *const handle,
    const PMIC_AUDIO_SOURCE  device)
{
    PMIC_STATUS rc = PMIC_ERROR;

    if (handle == (PMIC_AUDIO_HANDLE *)NULL)
    {
        /* Do not dereference a NULL pointer. */
        return PMIC_PARAMETER_ERROR;
    }

    /* We only need to acquire a mutex here because the interrupt handler
     * never modifies the device handle or device handle state. Therefore,
     * we don't need to worry about conflicts with the interrupt handler
     * or the need to execute in an interrupt context.
     *
     * But we do need a critical section here to avoid problems in case
     * multiple calls to pmic_audio_open() are made since we can only allow
     * one of them to succeed.
     */
    down_interruptible(mutex);

    /* Check the current device handle state and acquire the handle if
     * it is available.
     */
    if ((device == STEREO_DAC) && (stDAC.handleState == HANDLE_FREE))
    {
        stDAC.handle      = (PMIC_AUDIO_HANDLE)(&stDAC);
        stDAC.handleState = HANDLE_IN_USE;
        *handle = stDAC.handle;

        rc = PMIC_SUCCESS;
    }
    else if ((device == VOICE_CODEC) && (vCodec.handleState == HANDLE_FREE))
    {
        vCodec.handle      = (PMIC_AUDIO_HANDLE)(&vCodec);
        vCodec.handleState = HANDLE_IN_USE;
        *handle = vCodec.handle;

        rc = PMIC_SUCCESS;
    }
    else if ((device == EXTERNAL_STEREO_IN) &&
             (extStereoIn.handleState == HANDLE_FREE))
    {
        extStereoIn.handle      = (PMIC_AUDIO_HANDLE)(&extStereoIn);
        extStereoIn.handleState = HANDLE_IN_USE;
        *handle = extStereoIn.handle;

        rc = PMIC_SUCCESS;

    } else {

        *handle = AUDIO_HANDLE_NULL;
    }

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

    return rc;
}

/*!
 * @brief Terminate further access to the PMIC audio hardware.
 *
 * Terminate further access to the PMIC audio hardware that was previously
 * acquired by calling pmic_audio_open(). This now allows another thread to
 * successfully call pmic_audio_open() to gain access.
 *
 * Note that we will shutdown/reset the Voice CODEC or Stereo DAC as well as
 * any associated audio input/output components that are no longer required.
 *
 * @param[in]   handle          Device handle from pmic_audio_open() call.

⌨️ 快捷键说明

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