MCUXpresso_MIMXRT1052xxxxB/components/audio/fsl_adapter_sai.c

834 lines
29 KiB
C

/*
* 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;
}