1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_dma.h"
10 #include "fsl_i2s_dma.h"
11 #include "fsl_flexcomm.h"
12 #include <string.h>
13 
14 /*******************************************************************************
15  * Definitions
16  ******************************************************************************/
17 
18 /* Component ID definition, used by tools. */
19 #ifndef FSL_COMPONENT_ID
20 #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2s_dma"
21 #endif
22 
23 #define DMA_MAX_TRANSFER_BYTES (DMA_MAX_TRANSFER_COUNT * sizeof(uint32_t))
24 #define DMA_DESCRIPTORS        (2U)
25 
26 /*<! @brief Structure for statically allocated private data. */
27 typedef struct _i2s_dma_private_handle
28 {
29     I2S_Type *base;           /*!< I2S base address */
30     i2s_dma_handle_t *handle; /*!< I2S handle */
31 
32     volatile uint16_t enqueuedBytes[DMA_DESCRIPTORS]; /*!< Number of bytes being transferred by DMA descriptors */
33     volatile uint8_t enqueuedBytesStart;              /*!< First item in enqueuedBytes (for reading) */
34     volatile uint8_t enqueuedBytesEnd;                /*!< Last item in enqueuedBytes (for adding) */
35 
36     volatile uint8_t
37         dmaDescriptorsUsed; /*!< Number of DMA descriptors with valid data (in queue, excluding initial descriptor) */
38     volatile uint8_t descriptor; /*!< Index of next DMA descriptor in s_DmaDescriptors to be configured with data (does
39                                     not include I2S instance offset) */
40 
41     volatile uint8_t queueDescriptor;                         /*!< Queue index of buffer to be actually consumed by DMA
42                                                                * (queueUser - advanced when user adds a buffer,
43                                                                *  queueDescriptor - advanced when user buffer queued to DMA,
44                                                                *  queueDriver - advanced when DMA queued buffer sent out to I2S) */
45     volatile i2s_transfer_t descriptorQueue[I2S_NUM_BUFFERS]; /*!< Transfer data to be queued to DMA */
46 
47     volatile bool intA; /*!< If next scheduled DMA transfer will cause interrupt A or B */
48 } i2s_dma_private_handle_t;
49 
50 /*! @brief I2S DMA transfer private state. */
51 enum _i2s_dma_state
52 {
53     kI2S_DmaStateIdle = 0x0U,      /*!< I2S is in idle state */
54     kI2S_DmaStateTx,               /*!< I2S is busy transmitting data */
55     kI2S_DmaStateRx,               /*!< I2S is busy receiving data */
56     kI2S_DmaStateBusyLoopTransfer, /*!< I2S is busy loop transfer */
57 };
58 
59 /*******************************************************************************
60  * Prototypes
61  ******************************************************************************/
62 
63 static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
64 static uint32_t I2S_GetInstance(I2S_Type *base);
65 static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle);
66 static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle);
67 static void I2S_TxEnableDMA(I2S_Type *base, bool enable);
68 static void I2S_RxEnableDMA(I2S_Type *base, bool enable);
69 static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer);
70 static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
71 static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
72 
73 /*******************************************************************************
74  * Variables
75  ******************************************************************************/
76 /*<! @brief Allocate DMA transfer descriptors. */
77 #if (defined(CPU_MIMXRT685SEVKA_dsp) || defined(CPU_MIMXRT685SFVKB_dsp))
78 AT_NONCACHEABLE_SECTION_ALIGN(static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT],
79                               FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE);
80 #else
81 SDK_ALIGN(static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT],
82           FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE);
83 #endif
84 
85 /*<! @brief Buffer with dummy TX data. */
86 SDK_ALIGN(static uint32_t s_DummyBufferTx, 4U);
87 
88 /*<! @brief Buffer to fill with RX data to discard. */
89 SDK_ALIGN(static uint32_t s_DummyBufferRx, 4U);
90 
91 /*<! @brief Private array of data associated with available I2S peripherals. */
92 static i2s_dma_private_handle_t s_DmaPrivateHandle[FSL_FEATURE_SOC_I2S_COUNT];
93 
94 /*<! @brief Base addresses of available I2S peripherals. */
95 static const uint32_t s_I2sBaseAddrs[FSL_FEATURE_SOC_I2S_COUNT] = I2S_BASE_ADDRS;
96 
97 /*******************************************************************************
98  * Code
99  ******************************************************************************/
100 
I2S_EnqueueUserBuffer(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t transfer)101 static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
102 {
103     uint32_t instance                       = I2S_GetInstance(base);
104     i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
105 
106     /* Validate input data and transfer buffer */
107 
108     assert(handle != NULL);
109     if (handle == NULL)
110     {
111         return kStatus_InvalidArgument;
112     }
113 
114     assert((((uint32_t)transfer.data) % 4U) == 0U);
115     if ((((uint32_t)transfer.data) % 4U) != 0U)
116     {
117         /* Data not 4-bytes aligned */
118         return kStatus_InvalidArgument;
119     }
120 
121     assert(transfer.dataSize != 0U);
122     if (transfer.dataSize == 0U)
123     {
124         /* No data to send or receive */
125         return kStatus_InvalidArgument;
126     }
127 
128     assert((transfer.dataSize % 4U) == 0U);
129     if ((transfer.dataSize % 4U) != 0U)
130     {
131         /* Data length not multiply of 4 bytes */
132         return kStatus_InvalidArgument;
133     }
134 
135     if (handle->i2sQueue[handle->queueUser].dataSize != 0UL)
136     {
137         /* Previously prepared buffers not processed yet, reject request */
138         return kStatus_I2S_Busy;
139     }
140 
141     /* Enqueue data */
142     privateHandle->descriptorQueue[handle->queueUser].data     = transfer.data;
143     privateHandle->descriptorQueue[handle->queueUser].dataSize = transfer.dataSize;
144     handle->i2sQueue[handle->queueUser].data                   = transfer.data;
145     handle->i2sQueue[handle->queueUser].dataSize               = transfer.dataSize;
146     handle->queueUser                                          = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
147 
148     return kStatus_Success;
149 }
150 
I2S_GetInstance(I2S_Type * base)151 static uint32_t I2S_GetInstance(I2S_Type *base)
152 {
153     uint32_t i;
154 
155     for (i = 0U; i < ARRAY_SIZE(s_I2sBaseAddrs); i++)
156     {
157         if ((uint32_t)base == s_I2sBaseAddrs[i])
158         {
159             return i;
160         }
161     }
162 
163     assert(false);
164     return 0U;
165 }
166 
I2S_DisableDMAInterrupts(i2s_dma_handle_t * handle)167 static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle)
168 {
169     DMA_DisableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
170 }
171 
I2S_EnableDMAInterrupts(i2s_dma_handle_t * handle)172 static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle)
173 {
174     if (handle->state != (uint32_t)kI2S_DmaStateIdle)
175     {
176         DMA_EnableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
177     }
178 }
179 
180 /*!
181  * brief Initializes handle for transfer of audio data.
182  *
183  * param base I2S base pointer.
184  * param handle pointer to handle structure.
185  * param dmaHandle pointer to dma handle structure.
186  * param callback function to be called back when transfer is done or fails.
187  * param userData pointer to data passed to callback.
188  */
I2S_TxTransferCreateHandleDMA(I2S_Type * base,i2s_dma_handle_t * handle,dma_handle_t * dmaHandle,i2s_dma_transfer_callback_t callback,void * userData)189 void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
190                                    i2s_dma_handle_t *handle,
191                                    dma_handle_t *dmaHandle,
192                                    i2s_dma_transfer_callback_t callback,
193                                    void *userData)
194 {
195     assert(handle != NULL);
196     assert(dmaHandle != NULL);
197 
198     uint32_t instance                       = I2S_GetInstance(base);
199     i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
200 
201     (void)memset(handle, 0, sizeof(*handle));
202     handle->state              = (uint32_t)kI2S_DmaStateIdle;
203     handle->dmaHandle          = dmaHandle;
204     handle->completionCallback = callback;
205     handle->userData           = userData;
206 
207     handle->bytesPerFrame = (uint8_t)((((base->CFG1 & I2S_CFG1_DATALEN_MASK) >> I2S_CFG1_DATALEN_SHIFT) + 1U) / 8U);
208     /* if one channel is disabled, bytesPerFrame should be 4U, user should pay attention that when data length is
209      * shorter than 16, the data format: left data put in 0-15 bit and right data should put in 16-31
210      */
211     if (((base->CFG1 & I2S_CFG1_ONECHANNEL_MASK) == 0U))
212     {
213         handle->bytesPerFrame = 4U;
214     }
215     /* since DMA do not support 24bit transfer width, use 32bit instead */
216     if (handle->bytesPerFrame == 3U)
217     {
218         handle->bytesPerFrame = 4U;
219     }
220 
221     (void)memset(privateHandle, 0, sizeof(*privateHandle));
222     privateHandle->base   = base;
223     privateHandle->handle = handle;
224 
225     DMA_SetCallback(dmaHandle, I2S_DMACallback, privateHandle);
226 }
227 
228 /*!
229  * brief Begins or queue sending of the given data.
230  *
231  * param base I2S base pointer.
232  * param handle pointer to handle structure.
233  * param transfer data buffer.
234  *
235  * retval kStatus_Success
236  * retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
237  */
I2S_TxTransferSendDMA(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t transfer)238 status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
239 {
240     status_t status;
241 
242     I2S_DisableDMAInterrupts(handle);
243 
244     /* Enqueue transfer buffer */
245     status = I2S_EnqueueUserBuffer(base, handle, transfer);
246     if (status != kStatus_Success)
247     {
248         I2S_EnableDMAInterrupts(handle);
249         return status;
250     }
251 
252     /* Initialize DMA transfer */
253     if (handle->state == (uint32_t)kI2S_DmaStateIdle)
254     {
255         handle->state = (uint32_t)kI2S_DmaStateTx;
256         status        = I2S_StartTransferDMA(base, handle);
257         if (status != kStatus_Success)
258         {
259             I2S_EnableDMAInterrupts(handle);
260             return status;
261         }
262     }
263 
264     I2S_AddTransferDMA(base, handle);
265     I2S_EnableDMAInterrupts(handle);
266 
267     return kStatus_Success;
268 }
269 
270 /*!
271  * brief Aborts transfer of data.
272  *
273  * param base I2S base pointer.
274  * param handle pointer to handle structure.
275  */
I2S_TransferAbortDMA(I2S_Type * base,i2s_dma_handle_t * handle)276 void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle)
277 {
278     assert(handle != NULL);
279     assert(handle->dmaHandle != NULL);
280 
281     uint32_t instance                       = I2S_GetInstance(base);
282     i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
283 
284     I2S_DisableDMAInterrupts(handle);
285 
286     /* Abort operation */
287     DMA_AbortTransfer(handle->dmaHandle);
288 
289     if (handle->state == (uint32_t)kI2S_DmaStateTx)
290     {
291         /* Disable TX */
292         I2S_TxEnableDMA(base, false);
293     }
294     else
295     {
296         /* Disable RX */
297         I2S_RxEnableDMA(base, false);
298     }
299 
300     I2S_Disable(base);
301 
302     /* Reset state */
303     handle->state = (uint32_t)kI2S_DmaStateIdle;
304 
305     /* Clear transfer queue */
306     (void)memset((void *)&(handle->i2sQueue), 0, sizeof(handle->i2sQueue));
307     handle->queueDriver = 0U;
308     handle->queueUser   = 0U;
309 
310     /* Clear internal state */
311     (void)memset((void *)&(privateHandle->descriptorQueue), 0, sizeof(privateHandle->descriptorQueue));
312     (void)memset((void *)&(privateHandle->enqueuedBytes), 0, sizeof(privateHandle->enqueuedBytes));
313     privateHandle->enqueuedBytesStart = 0U;
314     privateHandle->enqueuedBytesEnd   = 0U;
315     privateHandle->dmaDescriptorsUsed = 0U;
316     privateHandle->descriptor         = 0U;
317     privateHandle->queueDescriptor    = 0U;
318     privateHandle->intA               = false;
319 }
320 
321 /*!
322  * brief Initializes handle for reception of audio data.
323  *
324  * param base I2S base pointer.
325  * param handle pointer to handle structure.
326  * param dmaHandle pointer to dma handle structure.
327  * param callback function to be called back when transfer is done or fails.
328  * param userData pointer to data passed to callback.
329  */
I2S_RxTransferCreateHandleDMA(I2S_Type * base,i2s_dma_handle_t * handle,dma_handle_t * dmaHandle,i2s_dma_transfer_callback_t callback,void * userData)330 void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
331                                    i2s_dma_handle_t *handle,
332                                    dma_handle_t *dmaHandle,
333                                    i2s_dma_transfer_callback_t callback,
334                                    void *userData)
335 {
336     I2S_TxTransferCreateHandleDMA(base, handle, dmaHandle, callback, userData);
337 }
338 
339 /*!
340  * brief Begins or queue reception of data into given buffer.
341  *
342  * param base I2S base pointer.
343  * param handle pointer to handle structure.
344  * param transfer data buffer.
345  *
346  * retval kStatus_Success
347  * retval kStatus_I2S_Busy if all queue slots are occupied with buffers
348  *         which are not full.
349  */
I2S_RxTransferReceiveDMA(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t transfer)350 status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
351 {
352     status_t status;
353 
354     I2S_DisableDMAInterrupts(handle);
355 
356     /* Enqueue transfer buffer */
357     status = I2S_EnqueueUserBuffer(base, handle, transfer);
358     if (status != kStatus_Success)
359     {
360         I2S_EnableDMAInterrupts(handle);
361         return status;
362     }
363 
364     /* Initialize DMA transfer */
365     if (handle->state == (uint32_t)kI2S_DmaStateIdle)
366     {
367         handle->state = (uint32_t)kI2S_DmaStateRx;
368         status        = I2S_StartTransferDMA(base, handle);
369         if (status != kStatus_Success)
370         {
371             I2S_EnableDMAInterrupts(handle);
372             return status;
373         }
374     }
375 
376     I2S_AddTransferDMA(base, handle);
377     I2S_EnableDMAInterrupts(handle);
378 
379     return kStatus_Success;
380 }
381 
I2S_TxEnableDMA(I2S_Type * base,bool enable)382 static void I2S_TxEnableDMA(I2S_Type *base, bool enable)
383 {
384     if (enable)
385     {
386         base->FIFOCFG |= I2S_FIFOCFG_DMATX_MASK;
387     }
388     else
389     {
390         base->FIFOCFG &= (~I2S_FIFOCFG_DMATX_MASK);
391         base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
392     }
393 }
394 
I2S_RxEnableDMA(I2S_Type * base,bool enable)395 static void I2S_RxEnableDMA(I2S_Type *base, bool enable)
396 {
397     if (enable)
398     {
399         base->FIFOCFG |= I2S_FIFOCFG_DMARX_MASK;
400     }
401     else
402     {
403         base->FIFOCFG &= (~I2S_FIFOCFG_DMARX_MASK);
404         base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
405     }
406 }
407 
I2S_GetTransferBytes(volatile i2s_transfer_t * transfer)408 static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer)
409 {
410     assert(transfer != NULL);
411 
412     uint16_t transferBytes;
413 
414     if (transfer->dataSize >= (2UL * DMA_MAX_TRANSFER_BYTES))
415     {
416         transferBytes = DMA_MAX_TRANSFER_BYTES;
417     }
418     else if (transfer->dataSize > DMA_MAX_TRANSFER_BYTES)
419     {
420         transferBytes = (uint16_t)(transfer->dataSize / 2U);
421         if ((transferBytes % 4U) != 0U)
422         {
423             transferBytes -= (transferBytes % 4U);
424         }
425     }
426     else
427     {
428         transferBytes = (uint16_t)transfer->dataSize;
429     }
430 
431     return transferBytes;
432 }
433 
434 /*!
435  * brief Install DMA descriptor memory for loop transfer only.
436  *
437  * This function used to register DMA descriptor memory for the i2s loop dma transfer.
438  *
439  * It must be callbed before I2S_TransferSendLoopDMA/I2S_TransferReceiveLoopDMA and after
440  * I2S_RxTransferCreateHandleDMA/I2S_TxTransferCreateHandleDMA.
441  *
442  * User should be take care about the address of DMA descriptor pool which required align with 16BYTE at least.
443  *
444  * param handle Pointer to i2s DMA transfer handle.
445  * param dmaDescriptorAddr DMA descriptor start address.
446  * param dmaDescriptorNum DMA descriptor number.
447  */
I2S_TransferInstallLoopDMADescriptorMemory(i2s_dma_handle_t * handle,void * dmaDescriptorAddr,size_t dmaDescriptorNum)448 void I2S_TransferInstallLoopDMADescriptorMemory(i2s_dma_handle_t *handle,
449                                                 void *dmaDescriptorAddr,
450                                                 size_t dmaDescriptorNum)
451 {
452     assert(handle != NULL);
453     assert((((uint32_t)(uint32_t *)dmaDescriptorAddr) & ((uint32_t)FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE - 1UL)) ==
454            0UL);
455 
456     handle->i2sLoopDMADescriptor    = (dma_descriptor_t *)dmaDescriptorAddr;
457     handle->i2sLoopDMADescriptorNum = dmaDescriptorNum;
458 }
459 
I2S_TransferLoopDMA(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t * xfer,uint32_t loopTransferCount)460 static status_t I2S_TransferLoopDMA(I2S_Type *base,
461                                     i2s_dma_handle_t *handle,
462                                     i2s_transfer_t *xfer,
463                                     uint32_t loopTransferCount)
464 {
465     assert(handle != NULL);
466     assert(handle->dmaHandle != NULL);
467     assert(xfer != NULL);
468 
469     uint32_t *srcAddr = NULL, *destAddr = NULL, srcInc = 4UL, destInc = 4UL;
470     i2s_transfer_t *currentTransfer = xfer;
471     bool intA                       = true;
472 
473     if (handle->i2sLoopDMADescriptor == NULL)
474     {
475         return kStatus_InvalidArgument;
476     }
477 
478     if (handle->state == (uint32_t)kI2S_DmaStateBusyLoopTransfer)
479     {
480         return kStatus_I2S_Busy;
481     }
482 
483     for (uint32_t i = 0U; i < loopTransferCount; i++)
484     {
485         currentTransfer = &xfer[i];
486 
487         if ((currentTransfer->data == NULL) || (currentTransfer->dataSize == 0U) ||
488             (i >= handle->i2sLoopDMADescriptorNum) ||
489             (currentTransfer->dataSize / handle->bytesPerFrame > DMA_MAX_TRANSFER_COUNT))
490         {
491             return kStatus_InvalidArgument;
492         }
493 
494         if (handle->state == (uint32_t)kI2S_DmaStateTx)
495         {
496             srcAddr  = (uint32_t *)(uint32_t)currentTransfer->data;
497             destAddr = (uint32_t *)(uint32_t)(&(base->FIFOWR));
498             srcInc   = 1U;
499             destInc  = 0UL;
500         }
501         else
502         {
503             srcAddr  = (uint32_t *)(uint32_t)(&(base->FIFORD));
504             destAddr = (uint32_t *)(uint32_t)currentTransfer->data;
505             srcInc   = 0U;
506             destInc  = 1UL;
507         }
508 
509         intA = intA == true ? false : true;
510 
511         if (i == (loopTransferCount - 1U))
512         {
513             /* set up linked descriptor */
514             DMA_SetupDescriptor(&handle->i2sLoopDMADescriptor[i],
515                                 DMA_CHANNEL_XFER(true, false, intA, !intA, handle->bytesPerFrame, (uint8_t)srcInc,
516                                                  (uint8_t)destInc, currentTransfer->dataSize),
517                                 srcAddr, destAddr, &handle->i2sLoopDMADescriptor[0U]);
518         }
519         else
520         {
521             /* set up linked descriptor */
522             DMA_SetupDescriptor(&handle->i2sLoopDMADescriptor[i],
523                                 DMA_CHANNEL_XFER(true, false, intA, !intA, handle->bytesPerFrame, (uint8_t)srcInc,
524                                                  (uint8_t)destInc, currentTransfer->dataSize),
525                                 srcAddr, destAddr, &handle->i2sLoopDMADescriptor[i + 1U]);
526         }
527     }
528 
529     /* transferSize make sense to non link transfer only */
530     if (handle->state == (uint32_t)kI2S_DmaStateTx)
531     {
532         srcAddr  = (uint32_t *)(uint32_t)xfer->data;
533         destAddr = (uint32_t *)(uint32_t)(&(base->FIFOWR));
534         srcInc   = 1U;
535         destInc  = 0UL;
536     }
537     else
538     {
539         srcAddr  = (uint32_t *)(uint32_t)(&(base->FIFORD));
540         destAddr = (uint32_t *)(uint32_t)xfer->data;
541         srcInc   = 0U;
542         destInc  = 1UL;
543     }
544 
545     DMA_SubmitChannelTransferParameter(handle->dmaHandle,
546                                        DMA_CHANNEL_XFER(true, false, false, true, handle->bytesPerFrame,
547                                                         (uint8_t)srcInc, (uint8_t)destInc, (uint32_t)xfer->dataSize),
548                                        srcAddr, destAddr, (void *)&handle->i2sLoopDMADescriptor[1U]);
549 
550     /* Submit and start initial DMA transfer */
551     if (handle->state == (uint32_t)kI2S_DmaStateTx)
552     {
553         I2S_TxEnableDMA(base, true);
554     }
555     else
556     {
557         I2S_RxEnableDMA(base, true);
558     }
559     DMA_EnableChannelPeriphRq(handle->dmaHandle->base, handle->dmaHandle->channel);
560     /* start transfer */
561     DMA_StartTransfer(handle->dmaHandle);
562     I2S_Enable(base);
563 
564     handle->state = (uint32_t)kI2S_DmaStateBusyLoopTransfer;
565 
566     return kStatus_Success;
567 }
568 
569 /*!
570  * brief Send loop transfer data using DMA.
571  *
572  * This function receives data using DMA. This is a non-blocking function, which returns
573  * right away. When all data is received, the receive callback function is called.
574  *
575  * This function support loop transfer, such as A->B->...->A, the loop transfer chain
576  * will be converted into a chain of descriptor and submit to dma.
577  * Application must be aware of that the more counts of the loop transfer, then more DMA descriptor memory required,
578  * user can use function I2S_InstallDMADescriptorMemory to register the dma descriptor memory.
579  *
580  * As the DMA support maximum 1024 transfer count, so application must be aware of that this transfer function support
581  * maximum 1024 samples in each transfer, otherwise assert error or error status will be returned. Once the loop
582  * transfer start, application can use function I2S_TransferAbortDMA to stop the loop transfer.
583  *
584  * param base I2S peripheral base address.
585  * param handle Pointer to usart_dma_handle_t structure.
586  * param xfer I2S DMA transfer structure. See #i2s_transfer_t.
587  * param i2s_channel I2S start channel number
588  * retval kStatus_Success
589  */
I2S_TransferSendLoopDMA(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t * xfer,uint32_t loopTransferCount)590 status_t I2S_TransferSendLoopDMA(I2S_Type *base,
591                                  i2s_dma_handle_t *handle,
592                                  i2s_transfer_t *xfer,
593                                  uint32_t loopTransferCount)
594 {
595     assert(handle != NULL);
596     assert(handle->i2sLoopDMADescriptor != NULL);
597 
598     handle->state = (uint32_t)kI2S_DmaStateTx;
599 
600     return I2S_TransferLoopDMA(base, handle, xfer, loopTransferCount);
601 }
602 
603 /*!
604  * brief Receive loop transfer data using DMA.
605  *
606  * This function receives data using DMA. This is a non-blocking function, which returns
607  * right away. When all data is received, the receive callback function is called.
608  *
609  * This function support loop transfer, such as A->B->...->A, the loop transfer chain
610  * will be converted into a chain of descriptor and submit to dma.
611  * Application must be aware of that the more counts of the loop transfer, then more DMA descriptor memory required,
612  * user can use function I2S_InstallDMADescriptorMemory to register the dma descriptor memory.
613  *
614  * As the DMA support maximum 1024 transfer count, so application must be aware of that this transfer function support
615  * maximum 1024 samples in each transfer, otherwise assert error or error status will be returned. Once the loop
616  * transfer start, application can use function I2S_TransferAbortDMA to stop the loop transfer.
617  *
618  * param base I2S peripheral base address.
619  * param handle Pointer to usart_dma_handle_t structure.
620  * param xfer I2S DMA transfer structure. See #i2s_transfer_t.
621  * param i2s_channel I2S start channel number
622  * retval kStatus_Success
623  */
I2S_TransferReceiveLoopDMA(I2S_Type * base,i2s_dma_handle_t * handle,i2s_transfer_t * xfer,uint32_t loopTransferCount)624 status_t I2S_TransferReceiveLoopDMA(I2S_Type *base,
625                                     i2s_dma_handle_t *handle,
626                                     i2s_transfer_t *xfer,
627                                     uint32_t loopTransferCount)
628 {
629     assert(handle != NULL);
630     assert(handle->i2sLoopDMADescriptor != NULL);
631 
632     handle->state = (uint32_t)kI2S_DmaStateRx;
633 
634     return I2S_TransferLoopDMA(base, handle, xfer, loopTransferCount);
635 }
636 
I2S_StartTransferDMA(I2S_Type * base,i2s_dma_handle_t * handle)637 static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
638 {
639     uint32_t instance                       = I2S_GetInstance(base);
640     i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
641     volatile i2s_transfer_t *transfer       = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
642     uint16_t transferBytes                  = I2S_GetTransferBytes(transfer);
643     uint32_t i                              = 0U;
644     uint32_t xferConfig                     = 0U;
645     uint32_t *srcAddr = NULL, *destAddr = NULL, srcInc = 4UL, destInc = 4UL;
646 
647     if (handle->state == (uint32_t)kI2S_DmaStateTx)
648     {
649         srcAddr  = (uint32_t *)(uint32_t)transfer->data;
650         destAddr = (uint32_t *)(uint32_t)(&(base->FIFOWR));
651         srcInc   = 1U;
652         destInc  = 0UL;
653     }
654     else
655     {
656         srcAddr  = (uint32_t *)(uint32_t)(&(base->FIFORD));
657         destAddr = (uint32_t *)(uint32_t)transfer->data;
658         srcInc   = 0U;
659         destInc  = 1UL;
660     }
661     /* Initial descriptor is stored in another place in memory, but treat it as another descriptor for simplicity */
662     privateHandle->dmaDescriptorsUsed = 1U;
663     privateHandle->intA               = false;
664 
665     /* submit transfer parameter directly */
666     xferConfig = DMA_CHANNEL_XFER(true, false, false, true, handle->bytesPerFrame, (uint8_t)srcInc, (uint8_t)destInc,
667                                   (uint32_t)transferBytes);
668 
669     DMA_SubmitChannelTransferParameter(handle->dmaHandle, xferConfig, srcAddr, destAddr,
670                                        (void *)&(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + 0U]));
671 
672     privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
673     privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
674 
675     transfer->dataSize -= transferBytes;
676     transfer->data = (uint8_t *)((uint32_t)transfer->data + transferBytes);
677 
678     if (transfer->dataSize == 0U)
679     {
680         transfer->data                 = NULL;
681         privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
682     }
683 
684     /* Link the DMA descriptors for the case when no additional transfer is queued before the initial one finishes
685      * The configuration for the DMA dummy descriptor make no sense to tx or rx transfer, since it will be overwritten
686      * when another transfer request comes before the previous finished.
687      * To make sure the audio data transfer continuously, application must request another transfer by call
688      * I2S_RxTransferReceiveDMA or I2S_TxTransferSendDMA before previous transfer finished.
689      */
690     for (i = 0; i < DMA_DESCRIPTORS; i++)
691     {
692         /* DMA_CHANNEL_XFER(1UL, 0UL, 0UL, 0UL, sizeof(uint32_t), 0U, 0U, 8U) = 0x10203UL  */
693         DMA_SetupDescriptor(
694             &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + i]), 0x10203UL,
695             ((handle->state == (uint32_t)kI2S_DmaStateTx) ? &s_DummyBufferTx : (uint32_t *)(uint32_t)(&(base->FIFORD))),
696             ((handle->state == (uint32_t)kI2S_DmaStateTx) ? (uint32_t *)(uint32_t)(&(base->FIFOWR)) : &s_DummyBufferRx),
697             &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + ((i + 1U) % DMA_DESCRIPTORS)]));
698     }
699 
700     /* Submit and start initial DMA transfer */
701     if (handle->state == (uint32_t)kI2S_DmaStateTx)
702     {
703         I2S_TxEnableDMA(base, true);
704     }
705     else
706     {
707         I2S_RxEnableDMA(base, true);
708     }
709     /* enable I2S peripheral request and put the channel into triggered status */
710     DMA_EnableChannelPeriphRq(handle->dmaHandle->base, handle->dmaHandle->channel);
711     DMA_StartTransfer(handle->dmaHandle);
712 
713     I2S_Enable(base);
714 
715     return kStatus_Success;
716 }
717 
I2S_AddTransferDMA(I2S_Type * base,i2s_dma_handle_t * handle)718 static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
719 {
720     volatile i2s_transfer_t *transfer;
721     uint16_t transferBytes;
722     uint32_t instance;
723     i2s_dma_private_handle_t *privateHandle;
724     dma_descriptor_t *descriptor;
725     dma_descriptor_t *nextDescriptor;
726     uint32_t xferConfig = 0U;
727     bool intA           = false;
728     uint32_t *srcAddr = NULL, *destAddr = NULL, srcInc = 4UL, destInc = 4UL;
729 
730     instance      = I2S_GetInstance(base);
731     privateHandle = &(s_DmaPrivateHandle[instance]);
732 
733     while (privateHandle->dmaDescriptorsUsed < DMA_DESCRIPTORS)
734     {
735         transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
736         intA     = privateHandle->intA;
737         if (transfer->dataSize == 0U)
738         {
739             /* Nothing to be added */
740             return;
741         }
742 
743         if (handle->state == (uint32_t)kI2S_DmaStateTx)
744         {
745             srcAddr  = (uint32_t *)(uint32_t)transfer->data;
746             destAddr = (uint32_t *)(uint32_t)(&(base->FIFOWR));
747             srcInc   = 1U;
748             destInc  = 0UL;
749         }
750         else
751         {
752             srcAddr  = (uint32_t *)(uint32_t)(&(base->FIFORD));
753             destAddr = (uint32_t *)(uint32_t)transfer->data;
754             srcInc   = 0U;
755             destInc  = 1UL;
756         }
757 
758         /* Determine currently configured descriptor and the other which it will link to */
759         descriptor                = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
760         privateHandle->descriptor = (privateHandle->descriptor + 1U) % DMA_DESCRIPTORS;
761         nextDescriptor            = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
762 
763         transferBytes                                                 = I2S_GetTransferBytes(transfer);
764         privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
765         privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
766 
767         xferConfig = DMA_CHANNEL_XFER(true, false, !intA, intA, handle->bytesPerFrame, (uint8_t)srcInc,
768                                       (uint8_t)destInc, (uint32_t)transferBytes);
769 
770         DMA_SetupDescriptor(descriptor, xferConfig, srcAddr, destAddr, nextDescriptor);
771 
772         /* Advance internal state */
773         privateHandle->dmaDescriptorsUsed++;
774         privateHandle->intA = !privateHandle->intA;
775 
776         transfer->dataSize -= transferBytes;
777         transfer->data += transferBytes;
778         if (transfer->dataSize == 0U)
779         {
780             transfer->data                 = NULL;
781             privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
782         }
783     }
784 }
785 
786 /*!
787  * brief Invoked from DMA interrupt handler.
788  *
789  * param handle pointer to DMA handle structure.
790  * param userData argument for user callback.
791  * param transferDone if transfer was done.
792  * param tcds
793  */
I2S_DMACallback(dma_handle_t * handle,void * userData,bool transferDone,uint32_t tcds)794 void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
795 {
796     i2s_dma_private_handle_t *privateHandle = (i2s_dma_private_handle_t *)userData;
797     i2s_dma_handle_t *i2sHandle             = privateHandle->handle;
798     I2S_Type *base                          = privateHandle->base;
799     uint8_t queueDriverIndex                = i2sHandle->queueDriver;
800     uint32_t enqueueBytes                   = privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
801     uint32_t queueDataAddr                  = (uint32_t)i2sHandle->i2sQueue[queueDriverIndex].data;
802 
803     if ((!transferDone) || (i2sHandle->state == (uint32_t)kI2S_DmaStateIdle))
804     {
805         return;
806     }
807 
808     if (privateHandle->dmaDescriptorsUsed > 0U)
809     {
810         /* Finished descriptor, decrease amount of data to be processed */
811 
812         i2sHandle->i2sQueue[queueDriverIndex].dataSize -= enqueueBytes;
813         i2sHandle->i2sQueue[queueDriverIndex].data                      = (uint8_t *)(queueDataAddr + enqueueBytes);
814         privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] = 0U;
815         privateHandle->enqueuedBytesStart = (privateHandle->enqueuedBytesStart + 1U) % DMA_DESCRIPTORS;
816         privateHandle->dmaDescriptorsUsed--;
817     }
818 
819     if (i2sHandle->i2sQueue[queueDriverIndex].dataSize == 0U)
820     {
821         /* Entire user buffer sent or received - advance to next one */
822         i2sHandle->i2sQueue[queueDriverIndex].data = NULL;
823         i2sHandle->queueDriver                     = (queueDriverIndex + 1U) % I2S_NUM_BUFFERS;
824         /* Notify user about buffer completion */
825         if (i2sHandle->completionCallback != NULL)
826         {
827             (i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_BufferComplete, i2sHandle->userData);
828         }
829     }
830 
831     if (i2sHandle->state != (uint32_t)kI2S_DmaStateBusyLoopTransfer)
832     {
833         /* check next buffer queue is avaliable or not */
834         if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
835         {
836             if (i2sHandle->state == (uint32_t)kI2S_DmaStateTx)
837             {
838                 (void)I2S_EmptyTxFifo(base);
839             }
840             /* All user buffers processed */
841             I2S_TransferAbortDMA(base, i2sHandle);
842         }
843         else
844         {
845             /* Enqueue another user buffer to DMA if it could not be done when in I2S_Rx/TxTransferSendDMA */
846             I2S_AddTransferDMA(base, i2sHandle);
847         }
848     }
849 }
850