/* * Copyright 2021 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_common.h" #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) #include "fsl_dmamux.h" #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #include "fsl_edma.h" #include "fsl_sai.h" #include "fsl_sai_edma.h" #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) #include "fsl_dma.h" #include "fsl_sai.h" #include "fsl_sai_dma.h" #else #endif /* FSL_FEATURE_SOC_EDMA_COUNT or FSL_FEATURE_SOC_DMA_COUNT */ #include "fsl_adapter_audio.h" /******************************************************************************* * Definitions ******************************************************************************/ /*! @brief hal audio state structure. */ typedef struct _hal_audio_state { hal_audio_transfer_callback_t callback; void *callbackParam; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) sai_edma_handle_t xferDmaHandle; edma_handle_t dmaHandle; #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) sai_dma_handle_t xferDmaHandle; dma_handle_t dmaHandle; #else #endif #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) uint8_t dmaMuxInstance; #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ uint8_t dmaInstance; uint8_t dmaChannel; uint8_t instance; uint8_t occupied; } hal_audio_state_t; /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ /*! @brief Pointers to audio bases for each instance. */ static I2S_Type *const s_i2sBases[] = I2S_BASE_PTRS; /*! @brief Resource for each i2s instance. */ static uint8_t s_i2sOccupied[ARRAY_SIZE(s_i2sBases)]; #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) /*! @brief Resource for each dma instance. */ static uint8_t s_dmaOccupied[ARRAY_SIZE((DMA_Type *[])DMA_BASE_PTRS)]; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) /*! @brief Resource for each dma mux instance. */ static uint8_t s_dmaMuxOccupied[ARRAY_SIZE((DMAMUX_Type *[])DMAMUX_BASE_PTRS)]; #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ /******************************************************************************* * Code ******************************************************************************/ #if (defined(FSL_FEATURE_SOC_I2S_COUNT) && (FSL_FEATURE_SOC_I2S_COUNT > 0U)) static void HAL_AudioFifoErrorIsr(I2S_Type *base) { if (0U != (base->TCSR & (uint32_t)kSAI_FIFOErrorFlag)) { /* Clear the FIFO error flag */ SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag); /* Reset FIFO */ SAI_TxSoftwareReset(base, kSAI_ResetTypeFIFO); } if (0U != (base->RCSR & (uint32_t)kSAI_FIFOErrorFlag)) { /* Clear the FIFO error flag */ SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag); /* Reset FIFO */ SAI_RxSoftwareReset(base, kSAI_ResetTypeFIFO); } SDK_ISR_EXIT_BARRIER; } #endif /* IRQHandler for I2S0 */ #if defined(I2S0) && (FSL_FEATURE_SOC_I2S_COUNT > 0U) void I2S0_Tx_IRQHandler(void); void I2S0_Rx_IRQHandler(void); void I2S0_Tx_IRQHandler(void) { HAL_AudioFifoErrorIsr(I2S0); } void I2S0_Rx_IRQHandler(void) { HAL_AudioFifoErrorIsr(I2S0); } #endif /* IRQHandler for SAI1 */ #if defined(SAI1) && (FSL_FEATURE_SOC_I2S_COUNT > 0U) void SAI1_IRQHandler(void); void SAI1_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI1); } #endif /* IRQHandler for SAI2 */ #if defined(SAI2) && (FSL_FEATURE_SOC_I2S_COUNT > 0U) void SAI2_IRQHandler(void); void SAI2_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI2); } #endif /* IRQHandler for SAI3 */ #if defined(SAI3) && (FSL_FEATURE_SOC_I2S_COUNT > 0U) void SAI3_TX_IRQHandler(void); void SAI3_RX_IRQHandler(void); void SAI3_TX_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI3); } void SAI3_RX_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI3); } #endif /* IRQHandler for SAI4 */ #if defined(SAI4) && (FSL_FEATURE_SOC_I2S_COUNT > 0U) void SAI4_TX_IRQHandler(void); void SAI4_RX_IRQHandler(void); void SAI4_TX_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI4); } void SAI4_RX_IRQHandler(void) { HAL_AudioFifoErrorIsr(SAI4); } #endif static hal_audio_status_t HAL_AudioGetStatus(status_t status) { hal_audio_status_t returnStatus; switch (status) { case kStatus_Success: returnStatus = kStatus_HAL_AudioSuccess; break; case kStatus_SAI_TxBusy: case kStatus_SAI_RxBusy: returnStatus = kStatus_HAL_AudioBusy; break; case kStatus_SAI_TxIdle: case kStatus_SAI_RxIdle: case kStatus_NoTransferInProgress: returnStatus = kStatus_HAL_AudioIdle; break; case kStatus_SAI_QueueFull: returnStatus = kStatus_HAL_AudioQueueFull; break; default: returnStatus = kStatus_HAL_AudioError; break; } return returnStatus; } #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) static void HAL_AudioCallbackEDMA(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData) { hal_audio_state_t *audioHandle; assert(userData); audioHandle = (hal_audio_state_t *)userData; if (NULL != audioHandle->callback) { audioHandle->callback(audioHandle, HAL_AudioGetStatus(status), audioHandle->callbackParam); } } #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) static void HAL_AudioCallbackDMA(I2S_Type *base, sai_dma_handle_t *handle, status_t status, void *userData) { hal_audio_state_t *audioHandle; assert(userData); audioHandle = (hal_audio_state_t *)userData; if (NULL != audioHandle->callback) { audioHandle->callback(audioHandle, HAL_AudioGetStatus(status), audioHandle->callbackParam); } } #else #endif static hal_audio_status_t HAL_AudioCommonInit(hal_audio_handle_t handle, const hal_audio_config_t *config, bool direction) { hal_audio_state_t *audioHandle; sai_transceiver_t saiConfig; hal_audio_dma_config_t *dmaConfig; hal_audio_ip_config_t *featureConfig; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U) && \ (defined(FSL_EDMA_SOC_IP_DMA3) && (FSL_EDMA_SOC_IP_DMA3 > 0) || \ defined(FSL_EDMA_SOC_IP_DMA4) && (FSL_EDMA_SOC_IP_DMA4 > 0))) EDMA_Type *dmaBases[] = EDMA_BASE_PTRS; #else DMA_Type *dmaBases[] = DMA_BASE_PTRS; #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ IRQn_Type txIrqNumber[] = I2S_TX_IRQS; IRQn_Type rxIrqNumber[] = I2S_RX_IRQS; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_EDMA_SOC_IP_DMA3) && (FSL_EDMA_SOC_IP_DMA3 > 0) || \ defined(FSL_EDMA_SOC_IP_DMA4) && (FSL_EDMA_SOC_IP_DMA4 > 0)) IRQn_Type dmaIrqNumber[][FSL_FEATURE_EDMA_MODULE_CHANNEL] = EDMA_CHN_IRQS; #else IRQn_Type dmaIrqNumber[][FSL_FEATURE_EDMA_MODULE_CHANNEL] = DMA_CHN_IRQS; #endif #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) edma_config_t audioDmaConfig; #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ edma_channel_Preemption_config_t preemptionConfig; #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) DMAMUX_Type *dmaMuxBases[] = DMAMUX_BASE_PTRS; hal_audio_dma_mux_config_t *dmaMuxConfig; #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) IRQn_Type dmaIrqNumber[][FSL_FEATURE_DMA_MODULE_CHANNEL] = DMA_CHN_IRQS; #else #endif /* FSL_FEATURE_SOC_EDMA_COUNT or FSL_FEATURE_SOC_DMA_COUNT */ #if (defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE > 0U)) uint32_t u32Temp; uint8_t lineNum; #endif /* FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE */ uint8_t channelNum; assert(handle); assert(config); assert(config->dmaConfig); assert(config->ipConfig); /* If asserted, please check if the value of SAI_XFER_QUEUE_SIZE defined in the fsl_sai.h is modified. If modified, please modify the value of HAL_AUDIO_QUEUE_SIZE defined in the fsl_adapter_audio.h to be the same as SAI_XFER_QUEUE_SIZE. */ assert(HAL_AUDIO_HANDLE_SIZE >= sizeof(hal_audio_state_t)); assert(config->instance < ARRAY_SIZE(s_i2sBases)); assert(config->dmaConfig->instance < ARRAY_SIZE(dmaBases)); dmaConfig = (hal_audio_dma_config_t *)config->dmaConfig; featureConfig = (hal_audio_ip_config_t *)config->ipConfig; audioHandle = (hal_audio_state_t *)handle; assert(featureConfig->sai.lineMask != 0U); if (audioHandle->occupied != 0U) { return kStatus_HAL_AudioSuccess; } audioHandle->instance = config->instance; audioHandle->dmaInstance = dmaConfig->instance; audioHandle->dmaChannel = dmaConfig->channel; audioHandle->occupied = 1; SAI_GetClassicI2SConfig(&saiConfig, (sai_word_width_t)config->bitWidth, kSAI_Stereo, featureConfig->sai.lineMask); #if (defined(FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE) && (FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE > 0U)) lineNum = 0; u32Temp = featureConfig->sai.lineMask; while (u32Temp > 0U) { u32Temp &= u32Temp - 1U; lineNum++; } if (lineNum > 1U) { saiConfig.fifo.fifoCombine = kSAI_FifoCombineModeEnabledOnWrite; } #endif /* FSL_FEATURE_SAI_HAS_FIFO_COMBINE_MODE */ #if (defined(FSL_FEATURE_SAI_HAS_FIFO) && (FSL_FEATURE_SAI_HAS_FIFO > 0U)) if (config->fifoWatermark < (uint16_t)FSL_FEATURE_SAI_FIFO_COUNTn(s_i2sBases[audioHandle->instance])) { saiConfig.fifo.fifoWatermark = (uint8_t)config->fifoWatermark; } else { saiConfig.fifo.fifoWatermark = (uint8_t)FSL_FEATURE_SAI_FIFO_COUNTn(s_i2sBases[audioHandle->instance]) - 1U; } #endif /* FSL_FEATURE_SAI_HAS_FIFO */ if ((uint8_t)config->bclkPolarity == (uint8_t)kHAL_AudioSampleOnFallingEdge) { saiConfig.bitClock.bclkPolarity = kSAI_SampleOnFallingEdge; } else { saiConfig.bitClock.bclkPolarity = kSAI_SampleOnRisingEdge; } channelNum = (uint8_t)config->lineChannels; if (channelNum == (uint8_t)kHAL_AudioMono) { saiConfig.frameSync.frameSyncWidth = config->bitWidth >> 1U; saiConfig.serialData.dataWordNum = 1U; channelNum = 1; } else if (channelNum < (uint8_t)kHAL_AudioStereo) { saiConfig.frameSync.frameSyncWidth = config->bitWidth; saiConfig.serialData.dataWordNum = 2U; saiConfig.serialData.dataMaskedWord = 0x1UL << channelNum; channelNum = 2; } else { saiConfig.frameSync.frameSyncWidth = config->bitWidth * channelNum >> 1U; saiConfig.serialData.dataWordNum = channelNum; } if ((uint8_t)featureConfig->sai.syncMode == (uint8_t)kHAL_AudioSaiModeAsync) { saiConfig.syncMode = kSAI_ModeAsync; } else { saiConfig.syncMode = kSAI_ModeSync; } switch (config->msaterSlave) { case kHAL_AudioMaster: saiConfig.masterSlave = kSAI_Master; break; case kHAL_AudioSlave: saiConfig.masterSlave = kSAI_Slave; break; case kHAL_AudioBclkMasterFrameSyncSlave: saiConfig.masterSlave = kSAI_Bclk_Master_FrameSync_Slave; break; case kHAL_AudioBclkSlaveFrameSyncMaster: saiConfig.masterSlave = kSAI_Bclk_Slave_FrameSync_Master; break; default: assert(false); break; } switch (config->dataFormat) { case kHAL_AudioDataFormatI2sClassic: saiConfig.frameSync.frameSyncEarly = true; saiConfig.frameSync.frameSyncPolarity = kSAI_PolarityActiveLow; break; case kHAL_AudioDataFormatLeftJustified: saiConfig.frameSync.frameSyncEarly = false; saiConfig.frameSync.frameSyncPolarity = kSAI_PolarityActiveHigh; break; case kHAL_AudioDataFormatRightJustified: saiConfig.frameSync.frameSyncEarly = false; saiConfig.frameSync.frameSyncPolarity = kSAI_PolarityActiveHigh; break; case kHAL_AudioDataFormatDspModeA: saiConfig.frameSync.frameSyncEarly = true; saiConfig.frameSync.frameSyncPolarity = kSAI_PolarityActiveHigh; if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthOneBitClk) { saiConfig.frameSync.frameSyncWidth = 1; } else if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthPerWordWidth) { saiConfig.frameSync.frameSyncWidth = config->bitWidth; } else { /* no action */ } break; case kHAL_AudioDataFormatDspModeB: saiConfig.frameSync.frameSyncEarly = false; saiConfig.frameSync.frameSyncPolarity = kSAI_PolarityActiveHigh; if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthOneBitClk) { saiConfig.frameSync.frameSyncWidth = 1; } else if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthPerWordWidth) { saiConfig.frameSync.frameSyncWidth = config->bitWidth; } else { /* no action */ } break; default: assert(false); break; } if (s_i2sOccupied[audioHandle->instance] == 0U) { SAI_Init(s_i2sBases[audioHandle->instance]); } s_i2sOccupied[audioHandle->instance]++; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) assert(dmaConfig->dmaMuxConfig); dmaMuxConfig = (hal_audio_dma_mux_config_t *)dmaConfig->dmaMuxConfig; audioHandle->dmaMuxInstance = dmaMuxConfig->dmaMuxConfig.dmaMuxInstance; #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) if (s_dmaMuxOccupied[audioHandle->dmaMuxInstance] == 0U) { DMAMUX_Init(dmaMuxBases[audioHandle->dmaMuxInstance]); } s_dmaMuxOccupied[audioHandle->dmaMuxInstance]++; #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ DMAMUX_SetSource(dmaMuxBases[audioHandle->dmaMuxInstance], dmaConfig->channel, (int32_t)dmaMuxConfig->dmaMuxConfig.dmaRequestSource); DMAMUX_EnableChannel(dmaMuxBases[audioHandle->dmaMuxInstance], dmaConfig->channel); #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) EDMA_GetDefaultConfig(&audioDmaConfig); #if (defined(FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION) && \ (FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION > 0U)) if (dmaConfig->dmaExtraConfig != NULL) { audioDmaConfig.enableMasterIdReplication = ((hal_audio_dma_extra_config_t *)dmaConfig->dmaExtraConfig)->edmaExtraConfig.enableMasterIdReplication; } #endif /* FSL_FEATURE_EDMA_HAS_GLOBAL_MASTER_ID_REPLICATION */ if (s_dmaOccupied[dmaConfig->instance] == 0U) { EDMA_Init(dmaBases[dmaConfig->instance], &audioDmaConfig); } s_dmaOccupied[dmaConfig->instance]++; #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ #if (defined(FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG) && (FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG > 0U)) if (dmaConfig->dmaChannelConfig != NULL) { EDMA_InitChannel(dmaBases[dmaConfig->instance], dmaConfig->channel, dmaConfig->dmaChannelConfig); } #endif /* FSL_FEATURE_EDMA_HAS_CHANNEL_CONFIG */ NVIC_SetPriority((IRQn_Type)dmaIrqNumber[dmaConfig->instance][dmaConfig->channel], HAL_AUDIO_ISR_PRIORITY); EDMA_CreateHandle(&audioHandle->dmaHandle, dmaBases[dmaConfig->instance], dmaConfig->channel); #if (defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && (FSL_FEATURE_EDMA_HAS_CHANNEL_MUX > 0U)) assert(dmaConfig->dmaChannelMuxConfig); EDMA_SetChannelMux(dmaBases[dmaConfig->instance], dmaConfig->channel, (int32_t)((hal_audio_dma_channel_mux_config_t *)dmaConfig->dmaChannelMuxConfig) ->dmaChannelMuxConfig.dmaRequestSource); #endif /* FSL_FEATURE_EDMA_HAS_CHANNEL_MUX */ if ((uint8_t)kHAL_AudioDmaChannelPriorityDefault != (uint8_t)dmaConfig->priority) { preemptionConfig.enableChannelPreemption = dmaConfig->enablePreemption; preemptionConfig.enablePreemptAbility = dmaConfig->enablePreemptAbility; preemptionConfig.channelPriority = (uint8_t)dmaConfig->priority; EDMA_SetChannelPreemptionConfig(dmaBases[dmaConfig->instance], dmaConfig->channel, &preemptionConfig); } if (direction) { SAI_TransferTxCreateHandleEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, HAL_AudioCallbackEDMA, audioHandle, &audioHandle->dmaHandle); SAI_TransferTxSetConfigEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &saiConfig); } else { SAI_TransferRxCreateHandleEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, HAL_AudioCallbackEDMA, audioHandle, &audioHandle->dmaHandle); SAI_TransferRxSetConfigEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &saiConfig); } #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) if (s_dmaOccupied[dmaConfig->instance] == 0U) { DMA_Init(dmaBases[dmaConfig->instance]); } s_dmaOccupied[dmaConfig->instance]++; #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ NVIC_SetPriority((IRQn_Type)dmaIrqNumber[dmaConfig->instance][dmaConfig->channel], HAL_AUDIO_ISR_PRIORITY); DMA_CreateHandle(&audioHandle->dmaHandle, dmaBases[dmaConfig->instance], dmaConfig->channel); if (direction) { SAI_TransferTxCreateHandleDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, HAL_AudioCallbackDMA, audioHandle, &audioHandle->dmaHandle); SAI_TransferTxSetConfigDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &saiConfig); } else { SAI_TransferRxCreateHandleDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, HAL_AudioCallbackDMA, audioHandle, &audioHandle->dmaHandle); SAI_TransferRxSetConfigDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &saiConfig); } #else #endif /* FSL_FEATURE_SOC_EDMA_COUNT or FSL_FEATURE_SOC_DMA_COUNT */ if (direction) { SAI_TxSetBitClockRate(s_i2sBases[audioHandle->instance], config->srcClock_Hz, config->sampleRate_Hz, config->bitWidth, channelNum); (void)EnableIRQ(txIrqNumber[audioHandle->instance]); SAI_TxEnableInterrupts(s_i2sBases[audioHandle->instance], kSAI_FIFOErrorInterruptEnable); } else { SAI_RxSetBitClockRate(s_i2sBases[audioHandle->instance], config->srcClock_Hz, config->sampleRate_Hz, config->bitWidth, channelNum); (void)EnableIRQ(rxIrqNumber[audioHandle->instance]); SAI_RxEnableInterrupts(s_i2sBases[audioHandle->instance], kSAI_FIFOErrorInterruptEnable); } return kStatus_HAL_AudioSuccess; } static hal_audio_status_t HAL_AudioCommonDeinit(hal_audio_handle_t handle, bool direction) { hal_audio_state_t *audioHandle; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U) && \ (defined(FSL_EDMA_SOC_IP_DMA3) && (FSL_EDMA_SOC_IP_DMA3 > 0) || \ defined(FSL_EDMA_SOC_IP_DMA4) && (FSL_EDMA_SOC_IP_DMA4 > 0))) #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) || \ (defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && (FSL_FEATURE_EDMA_HAS_CHANNEL_MUX > 0U)) EDMA_Type *dmaBases[] = EDMA_BASE_PTRS; #endif /* HAL_AUDIO_DMA_INIT_ENABLE or FSL_FEATURE_EDMA_HAS_CHANNEL_MUX */ #else #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) || \ (defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && (FSL_FEATURE_EDMA_HAS_CHANNEL_MUX > 0U)) DMA_Type *dmaBases[] = DMA_BASE_PTRS; #endif /* HAL_AUDIO_DMA_INIT_ENABLE or FSL_FEATURE_EDMA_HAS_CHANNEL_MUX */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) DMAMUX_Type *dmaMuxBases[] = DMAMUX_BASE_PTRS; #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ assert(handle); audioHandle = (hal_audio_state_t *)handle; if (audioHandle->occupied == 0U) { return kStatus_HAL_AudioSuccess; } audioHandle->occupied = 0; if (direction) { (void)HAL_AudioTransferAbortSend(handle); } else { (void)HAL_AudioTransferAbortReceive(handle); } if (s_i2sOccupied[audioHandle->instance] != 0U) { s_i2sOccupied[audioHandle->instance]--; if (s_i2sOccupied[audioHandle->instance] == 0U) { SAI_Deinit(s_i2sBases[audioHandle->instance]); } } #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && (FSL_FEATURE_EDMA_HAS_CHANNEL_MUX > 0U)) EDMA_SetChannelMux(dmaBases[audioHandle->dmaInstance], audioHandle->dmaChannel, 0); #endif /* FSL_FEATURE_EDMA_HAS_CHANNEL_MUX */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U)) if (s_dmaOccupied[audioHandle->dmaInstance] != 0U) { s_dmaOccupied[audioHandle->dmaInstance]--; if (s_dmaOccupied[audioHandle->dmaInstance] == 0U) { #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) EDMA_Deinit(dmaBases[audioHandle->dmaInstance]); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) DMA_Deinit(dmaBases[audioHandle->dmaInstance]); #else #endif } } #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) #if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && (FSL_FEATURE_SOC_DMAMUX_COUNT > 0U)) if (s_dmaMuxOccupied[audioHandle->dmaMuxInstance] != 0U) { s_dmaMuxOccupied[audioHandle->dmaMuxInstance]--; if (s_dmaMuxOccupied[audioHandle->dmaMuxInstance] == 0U) { DMAMUX_Deinit(dmaMuxBases[audioHandle->dmaMuxInstance]); } } #endif /* FSL_FEATURE_SOC_DMAMUX_COUNT */ #endif /* FSL_FEATURE_SOC_EDMA_COUNT */ #endif /* HAL_AUDIO_DMA_INIT_ENABLE */ return kStatus_HAL_AudioSuccess; } hal_audio_status_t HAL_AudioTxInit(hal_audio_handle_t handle, const hal_audio_config_t *config) { return HAL_AudioCommonInit(handle, config, true); } hal_audio_status_t HAL_AudioRxInit(hal_audio_handle_t handle, const hal_audio_config_t *config) { return HAL_AudioCommonInit(handle, config, false); } hal_audio_status_t HAL_AudioTxDeinit(hal_audio_handle_t handle) { return HAL_AudioCommonDeinit(handle, true); } hal_audio_status_t HAL_AudioRxDeinit(hal_audio_handle_t handle) { return HAL_AudioCommonDeinit(handle, false); } hal_audio_status_t HAL_AudioTxInstallCallback(hal_audio_handle_t handle, hal_audio_transfer_callback_t callback, void *callbackParam) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; audioHandle->callback = callback; audioHandle->callbackParam = callbackParam; return kStatus_HAL_AudioSuccess; } hal_audio_status_t HAL_AudioRxInstallCallback(hal_audio_handle_t handle, hal_audio_transfer_callback_t callback, void *callbackParam) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; audioHandle->callback = callback; audioHandle->callbackParam = callbackParam; return kStatus_HAL_AudioSuccess; } hal_audio_status_t HAL_AudioTransferSendNonBlocking(hal_audio_handle_t handle, hal_audio_transfer_t *xfer) { sai_transfer_t transfer; hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; transfer.data = (uint8_t *)xfer->data; transfer.dataSize = xfer->dataSize; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferSendEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &transfer)); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferSendDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &transfer)); #else #endif } hal_audio_status_t HAL_AudioTransferReceiveNonBlocking(hal_audio_handle_t handle, hal_audio_transfer_t *xfer) { sai_transfer_t transfer; hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; transfer.data = (uint8_t *)xfer->data; transfer.dataSize = xfer->dataSize; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferReceiveEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &transfer)); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferReceiveDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, &transfer)); #else #endif } hal_audio_status_t HAL_AudioTransferGetSendCount(hal_audio_handle_t handle, size_t *count) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferGetSendCountEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, count)); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferGetSendCountDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, count)); #else #endif } hal_audio_status_t HAL_AudioTransferGetReceiveCount(hal_audio_handle_t handle, size_t *count) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferGetReceiveCountEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, count)); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) return HAL_AudioGetStatus( SAI_TransferGetReceiveCountDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, count)); #else #endif } hal_audio_status_t HAL_AudioTransferAbortSend(hal_audio_handle_t handle) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) SAI_TransferTerminateSendEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) SAI_TransferAbortSendDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle); #else #endif return kStatus_HAL_AudioSuccess; } hal_audio_status_t HAL_AudioTransferAbortReceive(hal_audio_handle_t handle) { hal_audio_state_t *audioHandle; assert(handle); audioHandle = (hal_audio_state_t *)handle; #if (defined(FSL_FEATURE_SOC_EDMA_COUNT) && (FSL_FEATURE_SOC_EDMA_COUNT > 0U)) SAI_TransferTerminateReceiveEDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle); #elif (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U)) SAI_TransferAbortReceiveDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle); #else #endif return kStatus_HAL_AudioSuccess; }