Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:01

0001 /*
0002  * Copyright (c) 2016, Freescale Semiconductor, Inc.
0003  * Copyright 2017-2020 NXP
0004  * All rights reserved.
0005  *
0006  *
0007  * SPDX-License-Identifier: BSD-3-Clause
0008  */
0009 
0010 #include "fsl_spdif_edma.h"
0011 
0012 /* Component ID definition, used by tools. */
0013 #ifndef FSL_COMPONENT_ID
0014 #define FSL_COMPONENT_ID "platform.drivers.spdif_edma"
0015 #endif
0016 
0017 /*******************************************************************************
0018  * Definitations
0019  ******************************************************************************/
0020 /* Used for 32byte aligned */
0021 #define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)(address) + 32U) & ~0x1FU)
0022 
0023 /*<! Structure definition for uart_edma_private_handle_t. The structure is private. */
0024 typedef struct _spdif_edma_private_handle
0025 {
0026     SPDIF_Type *base;
0027     spdif_edma_handle_t *handle;
0028 } spdif_edma_private_handle_t;
0029 
0030 /*!
0031  * @brief Used for conversion between `void*` and `uint32_t`.
0032  */
0033 typedef union pvoid_to_u32
0034 {
0035     void *pvoid;
0036     uint32_t u32;
0037 } pvoid_to_u32_t;
0038 
0039 /*! @brief spdif edma transfer state. */
0040 enum
0041 {
0042     kSPDIF_Busy = 0x0U, /*!< SPDIF is busy */
0043     kSPDIF_Idle,        /*!< Transfer is done. */
0044 };
0045 
0046 /*<! Private handle only used for internally. */
0047 static spdif_edma_private_handle_t s_edmaPrivateHandle[FSL_FEATURE_SOC_SPDIF_COUNT][2];
0048 static uint8_t s_spdif_tx_watermark[4] = {16, 12, 8, 4};
0049 static uint8_t s_spdif_rx_watermark[4] = {1, 4, 8, 16};
0050 
0051 /*******************************************************************************
0052  * Prototypes
0053  ******************************************************************************/
0054 /*!
0055  * @brief Submit SPDIF tcds to EDMA.
0056  *
0057  * @param base SPDIF base pointer.
0058  */
0059 static status_t SPDIF_SubmitTransfer(edma_handle_t *handle,
0060                                      const edma_transfer_config_t *config,
0061                                      uint32_t rightChannel);
0062 
0063 /*!
0064  * @brief SPDIF EDMA callback for send.
0065  *
0066  * @param handle pointer to spdif_edma_handle_t structure which stores the transfer state.
0067  * @param userData Parameter for user callback.
0068  * @param done If the DMA transfer finished.
0069  * @param tcds The TCD index.
0070  */
0071 static void SPDIF_TxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
0072 
0073 /*!
0074  * @brief SPDIF EDMA callback for receive.
0075  *
0076  * @param handle pointer to spdif_edma_handle_t structure which stores the transfer state.
0077  * @param userData Parameter for user callback.
0078  * @param done If the DMA transfer finished.
0079  * @param tcds The TCD index.
0080  */
0081 static void SPDIF_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds);
0082 
0083 /*******************************************************************************
0084  * Code
0085  ******************************************************************************/
0086 static void SPDIF_TxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
0087 {
0088     spdif_edma_private_handle_t *privHandle = (spdif_edma_private_handle_t *)userData;
0089     spdif_edma_handle_t *spdifHandle        = privHandle->handle;
0090 
0091     /* If finished a block, call the callback function */
0092     (void)memset(&spdifHandle->spdifQueue[spdifHandle->queueDriver], 0, sizeof(spdif_edma_transfer_t));
0093     spdifHandle->queueDriver = (spdifHandle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0094     if (spdifHandle->callback != NULL)
0095     {
0096         (spdifHandle->callback)(privHandle->base, spdifHandle, kStatus_SPDIF_TxIdle, spdifHandle->userData);
0097     }
0098 
0099     /* If all data finished, just stop the transfer */
0100     if (spdifHandle->spdifQueue[spdifHandle->queueDriver].rightData == NULL)
0101     {
0102         SPDIF_TransferAbortSendEDMA(privHandle->base, spdifHandle);
0103     }
0104 }
0105 
0106 static void SPDIF_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, uint32_t tcds)
0107 {
0108     spdif_edma_private_handle_t *privHandle = (spdif_edma_private_handle_t *)userData;
0109     spdif_edma_handle_t *spdifHandle        = privHandle->handle;
0110 
0111     /* If finished a block, call the callback function */
0112     (void)memset(&spdifHandle->spdifQueue[spdifHandle->queueDriver], 0, sizeof(spdif_edma_transfer_t));
0113     spdifHandle->queueDriver = (spdifHandle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0114     if (spdifHandle->callback != NULL)
0115     {
0116         (spdifHandle->callback)(privHandle->base, spdifHandle, kStatus_SPDIF_RxIdle, spdifHandle->userData);
0117     }
0118 
0119     /* If all data finished, just stop the transfer */
0120     if (spdifHandle->spdifQueue[spdifHandle->queueDriver].rightData == NULL)
0121     {
0122         SPDIF_TransferAbortReceiveEDMA(privHandle->base, spdifHandle);
0123     }
0124 }
0125 
0126 static status_t SPDIF_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config, uint32_t rightChannel)
0127 {
0128     edma_tcd_t *tcdRegs = (edma_tcd_t *)(uint32_t)&handle->base->TCD[handle->channel];
0129     uint32_t primask;
0130     uint16_t csr;
0131     int8_t currentTcd;
0132     int8_t previousTcd;
0133     int8_t nextTcd;
0134     int8_t tcdUsed = handle->tcdUsed;
0135     int8_t tcdSize = handle->tcdSize;
0136 
0137     /* Check if tcd pool is full. */
0138     primask = DisableGlobalIRQ();
0139     if (tcdUsed >= tcdSize)
0140     {
0141         EnableGlobalIRQ(primask);
0142 
0143         return kStatus_EDMA_QueueFull;
0144     }
0145     currentTcd = handle->tail;
0146     handle->tcdUsed++;
0147     /* Calculate index of next TCD */
0148     nextTcd = currentTcd + 0x01;
0149     if (nextTcd == handle->tcdSize)
0150     {
0151         nextTcd = 0x00;
0152     }
0153     /* Advance queue tail index */
0154     handle->tail = nextTcd;
0155     EnableGlobalIRQ(primask);
0156     /* Calculate index of previous TCD */
0157     previousTcd = (currentTcd != 0x00) ? (currentTcd - 0x01) : (handle->tcdSize - 0x01);
0158     /* Configure current TCD block. */
0159     EDMA_TcdReset(&handle->tcdPool[currentTcd]);
0160     EDMA_TcdSetTransferConfig(&handle->tcdPool[currentTcd], config, NULL);
0161     /* Set channel link */
0162     EDMA_TcdSetChannelLink(&handle->tcdPool[currentTcd], kEDMA_MinorLink, rightChannel);
0163     EDMA_TcdSetChannelLink(&handle->tcdPool[currentTcd], kEDMA_MajorLink, rightChannel);
0164     /* Enable major interrupt */
0165     handle->tcdPool[currentTcd].CSR |= DMA_CSR_INTMAJOR_MASK;
0166     /* Link current TCD with next TCD for identification of current TCD */
0167     handle->tcdPool[currentTcd].DLAST_SGA = (uint32_t)&handle->tcdPool[nextTcd];
0168     /* Chain from previous descriptor unless tcd pool size is 1(this descriptor is its own predecessor). */
0169     if (currentTcd != previousTcd)
0170     {
0171         /* Enable scatter/gather feature in the previous TCD block. */
0172         csr = (handle->tcdPool[previousTcd].CSR | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
0173         handle->tcdPool[previousTcd].CSR = csr;
0174         /*
0175             Check if the TCD block in the registers is the previous one (points to current TCD block). It
0176             is used to check if the previous TCD linked has been loaded in TCD register. If so, it need to
0177             link the TCD register in case link the current TCD with the dead chain when TCD loading occurs
0178             before link the previous TCD block.
0179         */
0180         if (tcdRegs->DLAST_SGA == (uint32_t)&handle->tcdPool[currentTcd])
0181         {
0182             /* Enable scatter/gather also in the TCD registers. */
0183             csr = (tcdRegs->CSR | (uint16_t)DMA_CSR_ESG_MASK) & ~(uint16_t)DMA_CSR_DREQ_MASK;
0184             /* Must write the CSR register one-time, because the transfer maybe finished anytime. */
0185             tcdRegs->CSR = csr;
0186             /*
0187                 It is very important to check the ESG bit!
0188                 Because this hardware design: if DONE bit is set, the ESG bit can not be set. So it can
0189                 be used to check if the dynamic TCD link operation is successful. If ESG bit is not set
0190                 and the DLAST_SGA is not the next TCD address(it means the dynamic TCD link succeed and
0191                 the current TCD block has been loaded into TCD registers), it means transfer finished
0192                 and TCD link operation fail, so must install TCD content into TCD registers and enable
0193                 transfer again. And if ESG is set, it means transfer has notfinished, so TCD dynamic
0194                 link succeed.
0195             */
0196             if ((tcdRegs->CSR & DMA_CSR_ESG_MASK) != 0x00U)
0197             {
0198                 return kStatus_Success;
0199             }
0200             /*
0201                 Check whether the current TCD block is already loaded in the TCD registers. It is another
0202                 condition when ESG bit is not set: it means the dynamic TCD link succeed and the current
0203                 TCD block has been loaded into TCD registers.
0204             */
0205             if (tcdRegs->DLAST_SGA == (uint32_t)&handle->tcdPool[nextTcd])
0206             {
0207                 return kStatus_Success;
0208             }
0209             /*
0210                 If go to this, means the previous transfer finished, and the DONE bit is set.
0211                 So shall configure TCD registers.
0212             */
0213         }
0214         else if (tcdRegs->DLAST_SGA != 0x00U)
0215         {
0216             /* The current TCD block has been linked successfully. */
0217             return kStatus_Success;
0218         }
0219         else
0220         {
0221             /*
0222                 DLAST_SGA is 0 and it means the first submit transfer, so shall configure
0223                 TCD registers.
0224             */
0225         }
0226     }
0227     /* There is no live chain, TCD block need to be installed in TCD registers. */
0228     EDMA_InstallTCD(handle->base, handle->channel, &handle->tcdPool[currentTcd]);
0229     /* Enable channel request again. */
0230     if ((handle->flags & 0x80U) != 0x00U)
0231     {
0232         handle->base->SERQ = DMA_SERQ_SERQ(handle->channel);
0233     }
0234     else
0235     {
0236         ; /* Intentional empty */
0237     }
0238 
0239     return kStatus_Success;
0240 }
0241 
0242 /*!
0243  * brief Initializes the SPDIF eDMA handle.
0244  *
0245  * This function initializes the SPDIF master DMA handle, which can be used for other SPDIF master transactional APIs.
0246  * Usually, for a specified SPDIF instance, call this API once to get the initialized handle.
0247  *
0248  * param base SPDIF base pointer.
0249  * param handle SPDIF eDMA handle pointer.
0250  * param base SPDIF peripheral base address.
0251  * param callback Pointer to user callback function.
0252  * param userData User parameter passed to the callback function.
0253  * param dmaLeftHandle eDMA handle pointer for left channel, this handle shall be static allocated by users.
0254  * param dmaRightHandle eDMA handle pointer for right channel, this handle shall be static allocated by users.
0255  */
0256 void SPDIF_TransferTxCreateHandleEDMA(SPDIF_Type *base,
0257                                       spdif_edma_handle_t *handle,
0258                                       spdif_edma_callback_t callback,
0259                                       void *userData,
0260                                       edma_handle_t *dmaLeftHandle,
0261                                       edma_handle_t *dmaRightHandle)
0262 {
0263     assert(handle != NULL);
0264     assert(dmaLeftHandle != NULL);
0265     assert(dmaRightHandle != NULL);
0266 
0267     uint32_t instance = SPDIF_GetInstance(base);
0268 
0269     /* Zero the handle */
0270     (void)memset(handle, 0, sizeof(*handle));
0271 
0272     /* Set spdif base to handle */
0273     handle->dmaLeftHandle  = dmaLeftHandle;
0274     handle->dmaRightHandle = dmaRightHandle;
0275     handle->callback       = callback;
0276     handle->userData       = userData;
0277     handle->count =
0278         s_spdif_tx_watermark[(base->SCR & SPDIF_SCR_TXFIFOEMPTY_SEL_MASK) >> SPDIF_SCR_TXFIFOEMPTY_SEL_SHIFT];
0279 
0280     /* Set SPDIF state to idle */
0281     handle->state = kSPDIF_Idle;
0282 
0283     s_edmaPrivateHandle[instance][0].base   = base;
0284     s_edmaPrivateHandle[instance][0].handle = handle;
0285 
0286     /* Need to use scatter gather */
0287     EDMA_InstallTCDMemory(dmaLeftHandle, STCD_ADDR(handle->leftTcd), SPDIF_XFER_QUEUE_SIZE);
0288     EDMA_InstallTCDMemory(dmaRightHandle, STCD_ADDR(handle->rightTcd), SPDIF_XFER_QUEUE_SIZE);
0289 
0290     /* Install callback for Tx dma channel, only right channel finished, a transfer finished */
0291     EDMA_SetCallback(dmaRightHandle, SPDIF_TxEDMACallback, &s_edmaPrivateHandle[instance][0]);
0292 }
0293 
0294 /*!
0295  * brief Initializes the SPDIF Rx eDMA handle.
0296  *
0297  * This function initializes the SPDIF slave DMA handle, which can be used for other SPDIF master transactional APIs.
0298  * Usually, for a specified SPDIF instance, call this API once to get the initialized handle.
0299  *
0300  * param base SPDIF base pointer.
0301  * param handle SPDIF eDMA handle pointer.
0302  * param base SPDIF peripheral base address.
0303  * param callback Pointer to user callback function.
0304  * param userData User parameter passed to the callback function.
0305  * param dmaLeftHandle eDMA handle pointer for left channel, this handle shall be static allocated by users.
0306  * param dmaRightHandle eDMA handle pointer for right channel, this handle shall be static allocated by users.
0307  */
0308 void SPDIF_TransferRxCreateHandleEDMA(SPDIF_Type *base,
0309                                       spdif_edma_handle_t *handle,
0310                                       spdif_edma_callback_t callback,
0311                                       void *userData,
0312                                       edma_handle_t *dmaLeftHandle,
0313                                       edma_handle_t *dmaRightHandle)
0314 {
0315     assert(handle != NULL);
0316     assert(dmaLeftHandle != NULL);
0317     assert(dmaRightHandle != NULL);
0318 
0319     uint32_t instance = SPDIF_GetInstance(base);
0320 
0321     /* Zero the handle */
0322     (void)memset(handle, 0, sizeof(*handle));
0323 
0324     /* Set spdif base to handle */
0325     handle->dmaLeftHandle  = dmaLeftHandle;
0326     handle->dmaRightHandle = dmaRightHandle;
0327     handle->callback       = callback;
0328     handle->userData       = userData;
0329     handle->count = s_spdif_rx_watermark[(base->SCR & SPDIF_SCR_RXFIFOFULL_SEL_MASK) >> SPDIF_SCR_RXFIFOFULL_SEL_SHIFT];
0330 
0331     /* Set SPDIF state to idle */
0332     handle->state = kSPDIF_Idle;
0333 
0334     s_edmaPrivateHandle[instance][1].base   = base;
0335     s_edmaPrivateHandle[instance][1].handle = handle;
0336 
0337     /* Need to use scatter gather */
0338     EDMA_InstallTCDMemory(dmaLeftHandle, STCD_ADDR(handle->leftTcd), SPDIF_XFER_QUEUE_SIZE);
0339     EDMA_InstallTCDMemory(dmaRightHandle, STCD_ADDR(handle->rightTcd), SPDIF_XFER_QUEUE_SIZE);
0340 
0341     /* Install callback for Tx dma channel */
0342     EDMA_SetCallback(dmaRightHandle, SPDIF_RxEDMACallback, &s_edmaPrivateHandle[instance][1]);
0343 }
0344 
0345 /*!
0346  * brief Performs a non-blocking SPDIF transfer using DMA.
0347  *
0348  * note This interface returns immediately after the transfer initiates. Call
0349  * SPDIF_GetTransferStatus to poll the transfer status and check whether the SPDIF transfer is finished.
0350  *
0351  * param base SPDIF base pointer.
0352  * param handle SPDIF eDMA handle pointer.
0353  * param xfer Pointer to the DMA transfer structure.
0354  * retval kStatus_Success Start a SPDIF eDMA send successfully.
0355  * retval kStatus_InvalidArgument The input argument is invalid.
0356  * retval kStatus_TxBusy SPDIF is busy sending data.
0357  */
0358 status_t SPDIF_TransferSendEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle, spdif_edma_transfer_t *xfer)
0359 {
0360     assert(handle != NULL);
0361     assert(xfer != NULL);
0362 
0363     pvoid_to_u32_t destAddr;
0364     edma_transfer_config_t config = {0};
0365     destAddr.u32                  = SPDIF_TxGetLeftDataRegisterAddress(base);
0366 
0367     /* Check if input parameter invalid */
0368     if ((xfer->leftData == NULL) || (xfer->dataSize == 0U) || (xfer->rightData == NULL))
0369     {
0370         return kStatus_InvalidArgument;
0371     }
0372 
0373     if ((handle->spdifQueue[handle->queueUser].leftData != NULL) ||
0374         (handle->spdifQueue[handle->queueUser].rightData != NULL))
0375     {
0376         return kStatus_SPDIF_QueueFull;
0377     }
0378 
0379     /* Change the state of handle */
0380     handle->state = kSPDIF_Busy;
0381 
0382     /* Update the queue state */
0383     handle->transferSize[handle->queueUser]         = xfer->dataSize;
0384     handle->spdifQueue[handle->queueUser].leftData  = xfer->leftData;
0385     handle->spdifQueue[handle->queueUser].dataSize  = xfer->dataSize;
0386     handle->spdifQueue[handle->queueUser].rightData = xfer->rightData;
0387     handle->queueUser                               = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0388 
0389     /* Store the initially configured eDMA minor byte transfer count into the SPDIF handle */
0390     handle->nbytes = handle->count * 8U;
0391 
0392     /* Prepare edma configure */
0393     EDMA_PrepareTransfer(&config, xfer->leftData, 4U, destAddr.pvoid, 4U, (uint32_t)handle->count * 4U, xfer->dataSize,
0394                          kEDMA_MemoryToPeripheral);
0395     (void)SPDIF_SubmitTransfer(handle->dmaLeftHandle, &config, handle->dmaRightHandle->channel);
0396 
0397     /* Prepare right channel */
0398     destAddr.u32 = SPDIF_TxGetRightDataRegisterAddress(base);
0399     EDMA_PrepareTransfer(&config, xfer->rightData, 4U, destAddr.pvoid, 4U, (uint32_t)handle->count * 4U, xfer->dataSize,
0400                          kEDMA_MemoryToPeripheral);
0401     (void)EDMA_SubmitTransfer(handle->dmaRightHandle, &config);
0402 
0403     /* Start DMA transfer */
0404     EDMA_StartTransfer(handle->dmaLeftHandle);
0405     EDMA_StartTransfer(handle->dmaRightHandle);
0406 
0407     /* Enable DMA enable bit */
0408     SPDIF_EnableDMA(base, kSPDIF_TxDMAEnable, true);
0409 
0410     /* Enable SPDIF Tx clock */
0411     SPDIF_TxEnable(base, true);
0412 
0413     return kStatus_Success;
0414 }
0415 
0416 /*!
0417  * brief Performs a non-blocking SPDIF receive using eDMA.
0418  *
0419  * note This interface returns immediately after the transfer initiates. Call
0420  * the SPDIF_GetReceiveRemainingBytes to poll the transfer status and check whether the SPDIF transfer is finished.
0421  *
0422  * param base SPDIF base pointer
0423  * param handle SPDIF eDMA handle pointer.
0424  * param xfer Pointer to DMA transfer structure.
0425  * retval kStatus_Success Start a SPDIF eDMA receive successfully.
0426  * retval kStatus_InvalidArgument The input argument is invalid.
0427  * retval kStatus_RxBusy SPDIF is busy receiving data.
0428  */
0429 status_t SPDIF_TransferReceiveEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle, spdif_edma_transfer_t *xfer)
0430 {
0431     assert(handle != NULL);
0432     assert(xfer != NULL);
0433 
0434     pvoid_to_u32_t srcAddr;
0435     edma_transfer_config_t config = {0};
0436     srcAddr.u32                   = SPDIF_RxGetLeftDataRegisterAddress(base);
0437 
0438     /* Check if input parameter invalid */
0439     if ((xfer->leftData == NULL) || (xfer->dataSize == 0U) || (xfer->rightData == NULL))
0440     {
0441         return kStatus_InvalidArgument;
0442     }
0443 
0444     if ((handle->spdifQueue[handle->queueUser].leftData != NULL) ||
0445         (handle->spdifQueue[handle->queueUser].rightData != NULL))
0446     {
0447         return kStatus_SPDIF_QueueFull;
0448     }
0449 
0450     /* Change the state of handle */
0451     handle->state = kSPDIF_Busy;
0452 
0453     /* Update the queue state */
0454     handle->transferSize[handle->queueUser]         = xfer->dataSize;
0455     handle->spdifQueue[handle->queueUser].leftData  = xfer->leftData;
0456     handle->spdifQueue[handle->queueUser].dataSize  = xfer->dataSize;
0457     handle->spdifQueue[handle->queueUser].rightData = xfer->rightData;
0458     handle->queueUser                               = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
0459 
0460     /* Store the initially configured eDMA minor byte transfer count into the SPDIF handle */
0461     handle->nbytes = handle->count * 8U;
0462 
0463     /* Prepare edma configure */
0464     EDMA_PrepareTransfer(&config, srcAddr.pvoid, 4U, xfer->leftData, 4U, (uint32_t)handle->count * 4U, xfer->dataSize,
0465                          kEDMA_PeripheralToMemory);
0466     /* Use specific submit function to enable channel link */
0467     (void)SPDIF_SubmitTransfer(handle->dmaLeftHandle, &config, handle->dmaRightHandle->channel);
0468 
0469     /* Prepare right channel */
0470     srcAddr.u32 = SPDIF_RxGetRightDataRegisterAddress(base);
0471     EDMA_PrepareTransfer(&config, srcAddr.pvoid, 4U, xfer->rightData, 4U, (uint32_t)handle->count * 4U, xfer->dataSize,
0472                          kEDMA_PeripheralToMemory);
0473     (void)EDMA_SubmitTransfer(handle->dmaRightHandle, &config);
0474 
0475     /* Start DMA transfer */
0476     EDMA_StartTransfer(handle->dmaLeftHandle);
0477     EDMA_StartTransfer(handle->dmaRightHandle);
0478 
0479     /* Enable DMA enable bit */
0480     SPDIF_EnableDMA(base, kSPDIF_RxDMAEnable, true);
0481 
0482     /* Enable SPDIF Rx clock */
0483     SPDIF_RxEnable(base, true);
0484 
0485     return kStatus_Success;
0486 }
0487 
0488 /*!
0489  * brief Aborts a SPDIF transfer using eDMA.
0490  *
0491  * param base SPDIF base pointer.
0492  * param handle SPDIF eDMA handle pointer.
0493  */
0494 void SPDIF_TransferAbortSendEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle)
0495 {
0496     assert(handle != NULL);
0497 
0498     /* Disable dma */
0499     EDMA_AbortTransfer(handle->dmaLeftHandle);
0500     EDMA_AbortTransfer(handle->dmaRightHandle);
0501 
0502     /* Disable DMA enable bit */
0503     SPDIF_EnableDMA(base, kSPDIF_TxDMAEnable, false);
0504 
0505     /* Set internal state */
0506     (void)memset(handle->spdifQueue, 0, sizeof(handle->spdifQueue));
0507     (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
0508     handle->queueUser   = 0U;
0509     handle->queueDriver = 0U;
0510 
0511     /* Set the handle state */
0512     handle->state = kSPDIF_Idle;
0513 }
0514 
0515 /*!
0516  * brief Aborts a SPDIF receive using eDMA.
0517  *
0518  * param base SPDIF base pointer
0519  * param handle SPDIF eDMA handle pointer.
0520  */
0521 void SPDIF_TransferAbortReceiveEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle)
0522 {
0523     assert(handle != NULL);
0524 
0525     /* Disable dma */
0526     EDMA_AbortTransfer(handle->dmaLeftHandle);
0527     EDMA_AbortTransfer(handle->dmaRightHandle);
0528 
0529     /* Disable DMA enable bit */
0530     SPDIF_EnableDMA(base, kSPDIF_RxDMAEnable, false);
0531 
0532     /* Set internal state */
0533     (void)memset(handle->spdifQueue, 0, sizeof(handle->spdifQueue));
0534     (void)memset(handle->transferSize, 0, sizeof(handle->transferSize));
0535     handle->queueUser   = 0U;
0536     handle->queueDriver = 0U;
0537 
0538     /* Set the handle state */
0539     handle->state = kSPDIF_Idle;
0540 }
0541 
0542 /*!
0543  * brief Gets byte count sent by SPDIF.
0544  *
0545  * param base SPDIF base pointer.
0546  * param handle SPDIF eDMA handle pointer.
0547  * param count Bytes count sent by SPDIF.
0548  * retval kStatus_Success Succeed get the transfer count.
0549  * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress.
0550  */
0551 status_t SPDIF_TransferGetSendCountEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle, size_t *count)
0552 {
0553     assert(handle != NULL);
0554 
0555     status_t status = kStatus_Success;
0556 
0557     if (handle->state != (uint32_t)kSPDIF_Busy)
0558     {
0559         status = kStatus_NoTransferInProgress;
0560     }
0561     else
0562     {
0563         *count = (handle->transferSize[handle->queueDriver] -
0564                   (uint32_t)handle->nbytes *
0565                       EDMA_GetRemainingMajorLoopCount(handle->dmaRightHandle->base, handle->dmaRightHandle->channel));
0566     }
0567 
0568     return status;
0569 }
0570 
0571 /*!
0572  * brief Gets byte count received by SPDIF.
0573  *
0574  * param base SPDIF base pointer
0575  * param handle SPDIF eDMA handle pointer.
0576  * param count Bytes count received by SPDIF.
0577  * retval kStatus_Success Succeed get the transfer count.
0578  * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress.
0579  */
0580 status_t SPDIF_TransferGetReceiveCountEDMA(SPDIF_Type *base, spdif_edma_handle_t *handle, size_t *count)
0581 {
0582     assert(handle != NULL);
0583 
0584     status_t status = kStatus_Success;
0585 
0586     if (handle->state != (uint32_t)kSPDIF_Busy)
0587     {
0588         status = kStatus_NoTransferInProgress;
0589     }
0590     else
0591     {
0592         *count = (handle->transferSize[handle->queueDriver] -
0593                   (uint32_t)handle->nbytes *
0594                       EDMA_GetRemainingMajorLoopCount(handle->dmaRightHandle->base, handle->dmaRightHandle->channel));
0595     }
0596 
0597     return status;
0598 }