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 #ifndef FSL_I2S_DMA_H_
9 #define FSL_I2S_DMA_H_
10 
11 #include "fsl_device_registers.h"
12 #include "fsl_common.h"
13 #include "fsl_flexcomm.h"
14 
15 #include "fsl_dma.h"
16 #include "fsl_i2s.h"
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 /*!
23  * @addtogroup i2s_dma_driver
24  * @{
25  */
26 
27 /*! @name Driver version */
28 /*! @{ */
29 /*! @brief I2S DMA driver version 2.3.2. */
30 #define FSL_I2S_DMA_DRIVER_VERSION (MAKE_VERSION(2, 3, 2))
31 /*! @} */
32 
33 /*! @brief Members not to be accessed / modified outside of the driver. */
34 typedef struct _i2s_dma_handle i2s_dma_handle_t;
35 
36 /*!
37  * @brief Callback function invoked from DMA API on completion.
38  *
39  * @param base I2S base pointer.
40  * @param handle pointer to I2S transaction.
41  * @param completionStatus status of the transaction.
42  * @param userData optional pointer to user arguments data.
43  */
44 typedef void (*i2s_dma_transfer_callback_t)(I2S_Type *base,
45                                             i2s_dma_handle_t *handle,
46                                             status_t completionStatus,
47                                             void *userData);
48 /*! @brief i2s dma handle */
49 struct _i2s_dma_handle
50 {
51     uint32_t state;                                    /*!< Internal state of I2S DMA transfer */
52     uint8_t bytesPerFrame;                             /*!< bytes per frame */
53     i2s_dma_transfer_callback_t completionCallback;    /*!< Callback function pointer */
54     void *userData;                                    /*!< Application data passed to callback */
55     dma_handle_t *dmaHandle;                           /*!< DMA handle */
56     volatile i2s_transfer_t i2sQueue[I2S_NUM_BUFFERS]; /*!< Transfer queue storing transfer buffers */
57     volatile uint8_t queueUser;                        /*!< Queue index where user's next transfer will be stored */
58     volatile uint8_t queueDriver;                      /*!< Queue index of buffer actually used by the driver */
59 
60     dma_descriptor_t *i2sLoopDMADescriptor; /*!< descriptor pool pointer */
61     size_t i2sLoopDMADescriptorNum;         /*!< number of descriptor in descriptors pool */
62 };
63 
64 /*******************************************************************************
65  * API
66  ******************************************************************************/
67 
68 #if defined(__cplusplus)
69 extern "C" {
70 #endif
71 
72 /*!
73  * @name Initialization and deinitialization
74  * @{
75  */
76 
77 /*! @} */
78 
79 /*!
80  * @name DMA API
81  * @{
82  */
83 
84 /*!
85  * @brief Initializes handle for transfer of audio data.
86  *
87  * @param base I2S base pointer.
88  * @param handle pointer to handle structure.
89  * @param dmaHandle pointer to dma handle structure.
90  * @param callback function to be called back when transfer is done or fails.
91  * @param userData pointer to data passed to callback.
92  */
93 void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
94                                    i2s_dma_handle_t *handle,
95                                    dma_handle_t *dmaHandle,
96                                    i2s_dma_transfer_callback_t callback,
97                                    void *userData);
98 
99 /*!
100  * @brief Begins or queue sending of the given data.
101  *
102  * @param base I2S base pointer.
103  * @param handle pointer to handle structure.
104  * @param transfer data buffer.
105  *
106  * @retval kStatus_Success
107  * @retval kStatus_I2S_Busy if all queue slots are occupied with unsent buffers.
108  */
109 status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
110 
111 /*!
112  * @brief Aborts transfer of data.
113  *
114  * @param base I2S base pointer.
115  * @param handle pointer to handle structure.
116  */
117 void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle);
118 
119 /*!
120  * @brief Initializes handle for reception of audio data.
121  *
122  * @param base I2S base pointer.
123  * @param handle pointer to handle structure.
124  * @param dmaHandle pointer to dma handle structure.
125  * @param callback function to be called back when transfer is done or fails.
126  * @param userData pointer to data passed to callback.
127  */
128 void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
129                                    i2s_dma_handle_t *handle,
130                                    dma_handle_t *dmaHandle,
131                                    i2s_dma_transfer_callback_t callback,
132                                    void *userData);
133 
134 /*!
135  * @brief Begins or queue reception of data into given buffer.
136  *
137  * @param base I2S base pointer.
138  * @param handle pointer to handle structure.
139  * @param transfer data buffer.
140  *
141  * @retval kStatus_Success
142  * @retval kStatus_I2S_Busy if all queue slots are occupied with buffers
143  *         which are not full.
144  */
145 status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
146 
147 /*!
148  * @brief Invoked from DMA interrupt handler.
149  *
150  * @param handle pointer to DMA handle structure.
151  * @param userData argument for user callback.
152  * @param transferDone if transfer was done.
153  * @param tcds
154  */
155 void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds);
156 
157 /*!
158  * @brief Install DMA descriptor memory for loop transfer only.
159  *
160  * This function used to register DMA descriptor memory for the i2s loop dma transfer.
161  *
162  * It must be callbed before I2S_TransferSendLoopDMA/I2S_TransferReceiveLoopDMA and after
163  * I2S_RxTransferCreateHandleDMA/I2S_TxTransferCreateHandleDMA.
164  *
165  * User should be take care about the address of DMA descriptor pool which required align with 16BYTE at least.
166  *
167  * @param handle Pointer to i2s DMA transfer handle.
168  * @param dmaDescriptorAddr DMA descriptor start address.
169  * @param dmaDescriptorNum DMA descriptor number.
170  */
171 void I2S_TransferInstallLoopDMADescriptorMemory(i2s_dma_handle_t *handle,
172                                                 void *dmaDescriptorAddr,
173                                                 size_t dmaDescriptorNum);
174 
175 /*!
176  * @brief Send link transfer data using DMA.
177  *
178  * This function receives data using DMA. This is a non-blocking function, which returns
179  * right away. When all data is received, the receive callback function is called.
180  *
181  * This function support loop transfer, such as A->B->...->A, the loop transfer chain
182  * will be converted into a chain of descriptor and submit to dma.
183  * Application must be aware of that the more counts of the loop transfer, then more DMA descriptor memory required,
184  * user can use function I2S_InstallDMADescriptorMemory to register the dma descriptor memory.
185  *
186  * As the DMA support maximum 1024 transfer count, so application must be aware of that this transfer function support
187  * maximum 1024 samples in each transfer, otherwise assert error or error status will be returned. Once the loop
188  * transfer start, application can use function I2S_TransferAbortDMA to stop the loop transfer.
189  *
190  * @param base I2S peripheral base address.
191  * @param handle Pointer to usart_dma_handle_t structure.
192  * @param xfer I2S DMA transfer structure. See #i2s_transfer_t.
193  * @param loopTransferCount loop count
194  * @retval kStatus_Success
195  */
196 status_t I2S_TransferSendLoopDMA(I2S_Type *base,
197                                  i2s_dma_handle_t *handle,
198                                  i2s_transfer_t *xfer,
199                                  uint32_t loopTransferCount);
200 
201 /*!
202  * @brief Receive link transfer data using DMA.
203  *
204  * This function receives data using DMA. This is a non-blocking function, which returns
205  * right away. When all data is received, the receive callback function is called.
206  *
207  * This function support loop transfer, such as A->B->...->A, the loop transfer chain
208  * will be converted into a chain of descriptor and submit to dma.
209  * Application must be aware of that the more counts of the loop transfer, then more DMA descriptor memory required,
210  * user can use function I2S_InstallDMADescriptorMemory to register the dma descriptor memory.
211  *
212  * As the DMA support maximum 1024 transfer count, so application must be aware of that this transfer function support
213  * maximum 1024 samples in each transfer, otherwise assert error or error status will be returned. Once the loop
214  * transfer start, application can use function I2S_TransferAbortDMA to stop the loop transfer.
215  *
216  * @param base I2S peripheral base address.
217  * @param handle Pointer to usart_dma_handle_t structure.
218  * @param xfer I2S DMA transfer structure. See #i2s_transfer_t.
219  * @param loopTransferCount loop count
220  * @retval kStatus_Success
221  */
222 status_t I2S_TransferReceiveLoopDMA(I2S_Type *base,
223                                     i2s_dma_handle_t *handle,
224                                     i2s_transfer_t *xfer,
225                                     uint32_t loopTransferCount);
226 
227 /*! @} */
228 
229 /*! @} */
230 
231 #if defined(__cplusplus)
232 }
233 #endif
234 
235 #endif /* FSL_I2S_DMA_H_ */
236