1 /* 2 * Copyright 2021-2022 NXP 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #ifndef _SRTM_PDM_EDMA_ADAPTER_H_ 9 #define _SRTM_PDM_EDMA_ADAPTER_H_ 10 11 #include "srtm_audio_service.h" 12 #include "fsl_pdm_edma.h" 13 14 /*! 15 * @addtogroup srtm_service 16 * @{ 17 */ 18 19 /******************************************************************************* 20 * Definitions 21 ******************************************************************************/ 22 #ifndef SRTM_PDM_EDMA_ADAPTER_USE_HWVAD 23 #define SRTM_PDM_EDMA_ADAPTER_USE_HWVAD (1U) 24 #endif 25 26 #ifndef SRTM_PDM_EDMA_ADAPTER_USE_EXTRA_BUFFER 27 #define SRTM_PDM_EDMA_ADAPTER_USE_EXTRA_BUFFER (1U) 28 #endif 29 30 #ifndef SRTM_PDM_EDMA_DATA_INJECTION 31 #define SRTM_PDM_EDMA_DATA_INJECTION (0) 32 #endif 33 34 #ifndef SRTM_DDR_RETENTION_USED 35 #define SRTM_DDR_RETENTION_USED (0) 36 #endif 37 38 /* Compile option to force usage of local and extra buffers. 39 * Help saving code space by removing code needed when one of 40 * these buffers is not used. 41 * Will generate errors if application does not configure them. 42 */ 43 #ifndef SRTM_PDM_EDMA_ADAPTER_FORCE_LOCAL_AND_EXTRA_BUFFERS 44 #define SRTM_PDM_EDMA_ADAPTER_FORCE_LOCAL_AND_EXTRA_BUFFERS 0 45 #endif 46 47 #define SRTM_PDM_EDMA_MAX_LOCAL_PERIOD_ALIGNMENT (4U) 48 49 /*! @brief Extra device intitialize function for PDM EDMA adapter. */ 50 typedef void (*pdm_dev_init)(bool enable); 51 /*! @brief Extra device configuration function based on format and sample rate, return PMD clock source in HZ. */ 52 typedef uint32_t (*pdm_dev_conf)(srtm_audio_format_type_t format, uint32_t srate); 53 54 #ifndef EDMA_Type 55 typedef void EDMA_Type; 56 #endif 57 58 /*! @brief Misc configuration structure. */ 59 typedef struct _pdm_misc_set 60 { 61 pdm_dev_init audioDevInit; /*!< Audio device init function. */ 62 pdm_dev_conf audioDevConf; /*!< config audio device based on format and sample rate, return source clock in HZ */ 63 } pdm_misc_set_t; 64 65 /*! @brief PDM EDMA configuration. */ 66 typedef struct _srtm_pdm_edma_config 67 { 68 pdm_config_t config; /*!< PDM user configuration. */ 69 pdm_channel_config_t channelConfig; /*!< PDM channel configurations. */ 70 uint32_t pdmSrcClk; /*!< PDM source clock in Hz. */ 71 uint32_t dmaChannel; /*!< DMA channel. */ 72 uint8_t channelPriority; /*!< The priority of DMA channel. */ 73 bool stopOnSuspend; /*!< Stop capture when received suspend command. */ 74 uint32_t eventSource; /*!< DMA request source. */ 75 76 // edma_context_data_t rxContext; 77 pdm_misc_set_t extendConfig; 78 } srtm_pdm_edma_config_t; 79 80 /*! @brief PDM EDMA local buffer. */ 81 typedef struct _srtm_pdm_edma_local_buf 82 { 83 uint8_t *buf; /*!< Pointer of the buffer */ 84 uint32_t bufSize; /*!< bytes of the whole local buffer */ 85 uint32_t periods; /*!< periods in local buffer */ 86 uint32_t samplesPerPeriod; /*!< number of samples per period (ignored if set to 0 - otherwise "periods" field is 87 re-computed based on the value and bufSize) */ 88 uint32_t threshold; /*!< Threshold period number: under which will trigger copy from local buffer to extra buffer if 89 extra buffer is used. Otherwise the local buffer is overwritten.*/ 90 } srtm_pdm_edma_local_buf_t; 91 92 #if SRTM_PDM_EDMA_ADAPTER_USE_EXTRA_BUFFER 93 /*! @brief Buffer access enable/disable function for power saving. */ 94 typedef void (*buff_access_enable)(bool enable); 95 96 /*! @brief PDM EDMA extra buffer. When the local buffer is full, the data can be copied to extra buffer. */ 97 typedef struct _srtm_pdm_edma_ext_buf 98 { 99 uint8_t *buf; /*!< Pointer of the buffer */ 100 uint32_t bufSize; /*!< bytes of the whole extra buffer */ 101 uint32_t periods; /*!< periods in the buffer, it will be recalculated by the driver using given bufSize and local 102 buffer configuration. */ 103 EDMA_Type *mem2memDmaBase; /*!< The DMA to use for memory copies to/from this external buffer. */ 104 uint32_t bufWriteDmaChannel; /*!< The extra buffer write DMA channel. */ 105 uint32_t bufReadDmaChannel; /*!< The extra buffer read DMA channel. */ 106 uint8_t channelPriority; /*!< The priority of DMA channel. */ 107 buff_access_enable buff_access_cb; /*!< callback to enable or disable access to this buffer for power management*/ 108 } srtm_pdm_edma_ext_buf_t; 109 #endif 110 111 #if SRTM_PDM_EDMA_ADAPTER_USE_HWVAD 112 typedef enum _srtm_pdm_hwvad_mode 113 { 114 kSRTM_PDM_Hwvad_Disabled = 0U, 115 kSRTM_PDM_Hwvad_EnergyBasedMode = 1U, 116 kSRTM_PDM_Hwvad_EnvelopeBasedMode = 2U, 117 } srtm_pdm_hwvad_mode_t; 118 119 typedef struct _srtm_pdm_hwvad_config 120 { 121 srtm_pdm_hwvad_mode_t mode; 122 pdm_hwvad_config_t hwvadConfig; 123 pdm_hwvad_noise_filter_t noiseFilterConfig; 124 pdm_hwvad_zero_cross_detector_t zcdConfig; 125 uint32_t signalGain; 126 } srtm_pdm_hwvad_config_t; 127 128 /*! @brief HWVAD callback function pointer. The callback is called when voice activity is detected by HWVAD. 129 */ 130 typedef void (*srtm_pdm_edma_hwvad_callback_t)(srtm_sai_adapter_t adapter, void *params); 131 #endif /* SRTM_PDM_EDMA_ADAPTER_USE_HWVAD */ 132 133 /*! @brief The callback function pointer. Voice data can be passed to application via callback when the host side is 134 * suspend. The callback is also a notification to the application for the host side resumes from suspend when the data 135 * and bytes are 0(NULL). */ 136 typedef void (*srtm_pdm_edma_data_callback_t)(srtm_sai_adapter_t adapter, void *data, uint32_t bytes, void *params); 137 138 /******************************************************************************* 139 * API 140 ******************************************************************************/ 141 #ifdef __cplusplus 142 extern "C" { 143 #endif 144 145 /*! 146 * @brief Create PDM EDMA adapter. 147 * 148 * @param pdm PDM base address. 149 * @param dma DMA base address. 150 * @param rxConfig PDM Rx channel configuration. 151 * @return SRTM PDM EDMA adapter on success or NULL on failure. 152 */ 153 srtm_sai_adapter_t SRTM_PdmEdmaAdapter_Create(PDM_Type *pdm, EDMA_Type *dma, srtm_pdm_edma_config_t *rxConfig); 154 155 /*! 156 * @brief Destroy PDM EDMA adapter. 157 * 158 * @param adapter PDM EDMA adapter to destroy. 159 */ 160 void SRTM_PdmEdmaAdapter_Destroy(srtm_sai_adapter_t adapter); 161 162 /*! 163 * @brief Get the audio service status. 164 * @param adapter PDM EDMA adapter. 165 * @param pRxState status pointer. 166 */ 167 void SRTM_PdmEdmaAdapter_GetAudioServiceState(srtm_sai_adapter_t adapter, srtm_audio_state_t *pRxState); 168 169 /*! 170 * @brief Set local buffer to use in DMA transfer. If local buffer is set, the audio data will be captured 171 * and transfered to local buffer, then copied to share buffer. Otherwise the data will be 172 * transfered from PDM interface to shared buffer directly. 173 * NOTE: it must be called before service start. 174 * 175 * @param adapter PDM EDMA adapter to set. 176 * @param localBuf Local buffer information to be set to the adapter RX path. 177 */ 178 void SRTM_PdmEdmaAdapter_SetRxLocalBuf(srtm_sai_adapter_t adapter, srtm_pdm_edma_local_buf_t *localBuf); 179 180 #if SRTM_PDM_EDMA_ADAPTER_USE_EXTRA_BUFFER 181 /*! 182 * @brief Set extra buffer to be used when local buffer is full. The extra buffer could be in external memory. 183 * If extra buffer is set, once the local buffer is full it will not be overwritten, instead the audio data in the local 184 * buffer will be copied to the extra buffer, then copied to the shared buffer. 185 * NOTE: It used only if local buffer is set by SRTM_PdmEdmaAdapter_SetRxLocalBuf and it must be called before service 186 * start. 187 * 188 * @param adapter PDM EDMA adapter to set. 189 * @param extBuf extra buffer information to be set to the adapter RX path. 190 */ 191 void SRTM_PdmEdmaAdapter_SetRxExtBuf(srtm_sai_adapter_t adapter, srtm_pdm_edma_ext_buf_t *extBuf); 192 193 /*! 194 * @brief configure a callback function that SRTM will call before and after accessing 195 * the Rx ext buffer, so power can be reduced when access to this buffer is not needed. 196 * 197 * @param adapter PDM EDMA adapter for which to configure the callback 198 * @param cb_func callback function 199 */ 200 void SRTM_PdmEdmaAdapter_SetRxExtBufAccessCb(srtm_sai_adapter_t adapter, buff_access_enable cb_func); 201 #endif /* SRTM_PDM_EDMA_ADAPTER_USE_EXTRA_BUFFER */ 202 203 /*! 204 * @brief When the host driver suspends, voice data can be passed to application via callback. 205 * When the host driver is waking up, the notfication is sent via callback. 206 * The callback is called in SRTM dispatcher task context and should not cost much time. 207 * 208 * @param adapter PDM EDMA adapter instance. 209 * @param cb Callback function pointer. 210 * @param param Callback function argument to be passed back to applicaiton. 211 */ 212 void SRTM_PdmEdmaAdapter_SetDataHandlerOnHostSuspend(srtm_sai_adapter_t adapter, 213 srtm_pdm_edma_data_callback_t cb, 214 void *param); 215 216 /*! 217 * @brief When key word detected, voice data will be sent to host again. 218 * 219 * @param adapter PDM EDMA adapter instance. 220 */ 221 void SRTM_PdmEdmaAdapter_ResumeHost(srtm_sai_adapter_t adapter); 222 223 /*! 224 * @brief get audio format currently configured on an adapter. 225 * 226 * @return audio format setting 227 */ 228 srtm_audio_format_type_t SRTM_PdmEdmaAdapter_GetDataFormat(srtm_sai_adapter_t adapter); 229 230 #if SRTM_PDM_EDMA_ADAPTER_USE_HWVAD 231 232 /* clang-format off */ 233 /*! 234 * @brief Setup HWVAD. This function is used to configure the HWVAD function of PDM module, the API should be called 235 * before the start of PDM capture. Once successfully configured and HWVAD mode is not kSRTM_PDM_Hwvad_Disabled mode, 236 * the HWVAD will be enabled when the PDM capture starts. SRTM_PdmEdmaAdapter_EnableHwvad can be used to disable or 237 * re-enable the HWVAD function during capture. 238 * Sample configurations for EnvelopeBasedMode, 239 * code 240 * static srtm_pdm_hwvad_config_t pdm_hwvad_config = { 241 * .mode = kSRTM_PDM_Hwvad_EnvelopeBasedMode, 242 * .hwvadConfig.channel = 0U, 243 * .hwvadConfig.initializeTime = 10U, 244 * .hwvadConfig.cicOverSampleRate = 0U, 245 * .hwvadConfig.inputGain = 0U, 246 * .hwvadConfig.frameTime = 10U, 247 * .hwvadConfig.cutOffFreq = kPDM_HwvadHpfBypassed, 248 * .hwvadConfig.enableFrameEnergy = false, 249 * .hwvadConfig.enablePreFilter = true, 250 * .noiseFilterConfig.enableAutoNoiseFilter = false, 251 * .noiseFilterConfig.enableNoiseMin = true, 252 * .noiseFilterConfig.enableNoiseDecimation = true, 253 * .noiseFilterConfig.noiseFilterAdjustment = 0U, 254 * .noiseFilterConfig.noiseGain = 7U, 255 * .noiseFilterConfig.enableNoiseDetectOR = true, 256 * .signalGain = 0U, 257 * }; 258 * code 259 * @param adapter PDM EDMA adapter instance. 260 * @param hwvadConfig The HWVAD configuration structure. 261 * @param cb The callback function pointer. 262 * @param param Callback function argument to be passed back to applicaiton. 263 * @return Configured the HWVAD successfully or with failure. 264 */ 265 /* clang-format on */ 266 srtm_status_t SRTM_PdmEdmaAdapter_ConfigHwvad(srtm_sai_adapter_t adapter, 267 const srtm_pdm_hwvad_config_t *hwvadConfig, 268 srtm_pdm_edma_hwvad_callback_t cb, 269 void *param); 270 271 /*! 272 * @brief Enable/Disable the HWVAD, this API is used to enable/disable the HWVAD during PDM capture. 273 * 274 * @param adapter PDM EDMA adapter instance. 275 * @param enable Enable or disable the HWVAD. 276 */ 277 void SRTM_PdmEdmaAdapter_EnableHwvad(srtm_sai_adapter_t adapter, bool enable); 278 #endif /* SRTM_PDM_EDMA_ADAPTER_USE_HWVAD */ 279 /******************************************************************************* 280 * Definitions from other files 281 ******************************************************************************/ 282 283 #ifdef __cplusplus 284 } 285 #endif 286 287 /*! @} */ 288 289 #endif /* __SRTM_SAI_EDMA_ADAPTER_H__ */ 290