1 /*
2 * Copyright 2019-2021 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_asrc_sdma.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.easrc_sdma"
14 #endif
15
16 /*******************************************************************************
17 * Definitations
18 ******************************************************************************/
19 /*<! Structure definition for uart_sdma_private_handle_t. The structure is private. */
20 typedef struct _asrc_sdma_private_handle
21 {
22 ASRC_Type *base;
23 asrc_sdma_handle_t *handle;
24 } asrc_sdma_private_handle_t;
25 /*! @brief Private handle only used for internally. */
26 static asrc_sdma_private_handle_t s_sdmaPrivateHandle[FSL_FEATURE_SOC_ASRC_COUNT]
27 [ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER];
28 /*******************************************************************************
29 * Prototypes
30 ******************************************************************************/
31 /*!
32 * @brief ASRC SDMA callback for input data transfer finished.
33 *
34 * @param handle pointer to asrc_sdma_handle_t structure which stores the transfer state.
35 * @param userData Parameter for user callback.
36 * @param done If the DMA transfer finished.
37 * @param tcds The TCD index.
38 */
39 static void ASRC_InSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex);
40
41 /*!
42 * @brief ASRC SDMA callback for output data transfer finished.
43 *
44 * @param handle pointer to asrc_sdma_handle_t structure which stores the transfer state.
45 * @param userData Parameter for user callback.
46 * @param done If the DMA transfer finished.
47 * @param tcds The TCD index.
48 */
49 static void ASRC_OutSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex);
50
51 /*!
52 * @brief ASRC submit output request .
53 *
54 * @param base ASRC base address.
55 * @param handle ASRC sdma handler.
56 * @param outDataAddr output peripheral fifo address.
57 * @param outDataSize output sdma transfer data size.
58 *
59 */
60 static status_t ASRC_TransferSubmitOutM2MSDMA(ASRC_Type *base,
61 asrc_sdma_handle_t *handle,
62 uint32_t *outDataAddr,
63 uint32_t outDataSize);
64
65 /*!
66 * @brief ASRC sdma transfer output request .
67 *
68 * @param base ASRC base address.
69 * @param handle ASRC sdma handler.
70 * @param outDataAddr output peripheral fifo address.
71 * @param outDataSize output sdma transfer data size.
72 *
73 */
74 static status_t ASRC_TransferOutSDMA(ASRC_Type *base,
75 asrc_sdma_handle_t *handle,
76 uint32_t *outDataAddr,
77 uint32_t outDataSize);
78
79 /*!
80 * @brief ASRC sdma transfer input request .
81 *
82 * @param base ASRC base address.
83 * @param handle ASRC sdma handler.
84 * @param inDataAddr ASRC input sdma source address.
85 * @param inDataSize input sdma transfer data size.
86 */
87 static status_t ASRC_TransferInSDMA(ASRC_Type *base,
88 asrc_sdma_handle_t *handle,
89 uint32_t *inDataAddr,
90 uint32_t inDataSize);
91 /*******************************************************************************
92 * Code
93 ******************************************************************************/
ASRC_InSDMACallback(sdma_handle_t * handle,void * userData,bool transferDone,uint32_t bdIndex)94 static void ASRC_InSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex)
95 {
96 asrc_sdma_private_handle_t *privHandle = (asrc_sdma_private_handle_t *)userData;
97 asrc_sdma_handle_t *asrcHandle = privHandle->handle;
98 status_t callbackStatus = kStatus_ASRCIdle;
99
100 /* If finished a block, call the callback function */
101 asrcHandle->inDMAHandle.asrcQueue[asrcHandle->inDMAHandle.queueDriver] = NULL;
102
103 asrcHandle->inDMAHandle.queueDriver = (asrcHandle->inDMAHandle.queueDriver + 1U) % ASRC_XFER_IN_QUEUE_SIZE;
104
105 if (asrcHandle->inDMAHandle.asrcQueue[asrcHandle->inDMAHandle.queueDriver] == NULL)
106 {
107 ASRC_TransferAbortInSDMA(privHandle->base, asrcHandle);
108 callbackStatus = kStatus_ASRCQueueIdle;
109 }
110
111 if (asrcHandle->inDMAHandle.callback != NULL)
112 {
113 (asrcHandle->inDMAHandle.callback)(privHandle->base, asrcHandle, callbackStatus,
114 asrcHandle->inDMAHandle.userData);
115 }
116 }
117
ASRC_ReadFIFORemainedSampleSDMA(ASRC_Type * base,asrc_context_t context,uint32_t * outAddr,uint32_t outWidth,uint32_t size)118 static void ASRC_ReadFIFORemainedSampleSDMA(
119 ASRC_Type *base, asrc_context_t context, uint32_t *outAddr, uint32_t outWidth, uint32_t size)
120 {
121 uint32_t totalSize = size;
122 uint32_t *addr = outAddr;
123 uint32_t i = 0U;
124
125 for (i = 0U; i < totalSize / outWidth; i++)
126 {
127 (void)ASRC_ReadFIFORemainedSample(base, context, addr, outWidth, 1U);
128 addr = (uint32_t *)((uint32_t)addr + outWidth);
129 }
130 }
131
ASRC_OutSDMACallback(sdma_handle_t * handle,void * userData,bool transferDone,uint32_t bdIndex)132 static void ASRC_OutSDMACallback(sdma_handle_t *handle, void *userData, bool transferDone, uint32_t bdIndex)
133 {
134 asrc_sdma_private_handle_t *privHandle = (asrc_sdma_private_handle_t *)userData;
135 asrc_sdma_handle_t *asrcHandle = privHandle->handle;
136 uint32_t queueDriverIndex = asrcHandle->outDMAHandle.queueDriver;
137 status_t callbackStatus = kStatus_ASRCIdle;
138
139 /* If finished a block, call the callback function */
140 asrcHandle->outDMAHandle.asrcQueue[queueDriverIndex] = NULL;
141 asrcHandle->outDMAHandle.queueDriver = (uint8_t)(queueDriverIndex + 1U) % ASRC_XFER_OUT_QUEUE_SIZE;
142
143 /* If all data finished, just stop the transfer */
144 if (asrcHandle->outDMAHandle.asrcQueue[asrcHandle->outDMAHandle.queueDriver] == NULL)
145 {
146 if (asrcHandle->outDMAHandle.nonAlignSize != 0U)
147 {
148 /* please note that when read buffered samples, input sample will be ingored */
149 ASRC_ReadFIFORemainedSampleSDMA(
150 privHandle->base, asrcHandle->context, asrcHandle->outDMAHandle.nonAlignAddr,
151 asrcHandle->outDMAHandle.bytesPerSample, asrcHandle->outDMAHandle.nonAlignSize);
152 asrcHandle->outDMAHandle.nonAlignSize = 0U;
153 asrcHandle->outDMAHandle.nonAlignAddr = NULL;
154 }
155 ASRC_TransferAbortOutSDMA(privHandle->base, asrcHandle);
156 callbackStatus = kStatus_ASRCQueueIdle;
157 }
158
159 if (asrcHandle->outDMAHandle.callback != NULL)
160 {
161 (asrcHandle->outDMAHandle.callback)(privHandle->base, asrcHandle, callbackStatus,
162 asrcHandle->outDMAHandle.userData);
163 }
164 }
165
166 /*!
167 * brief Initializes the ASRC input SDMA handle.
168 *
169 * This function initializes the ASRC input DMA handle, which can be used for other ASRC transactional APIs.
170 * Usually, for a specified ASRC context, call this API once to get the initialized handle.
171 *
172 * param base ASRC base pointer.
173 * param handle ASRC SDMA handle pointer.
174 * param base ASRC peripheral base address.
175 * param callback Pointer to user callback function.
176 * param dmaHandle SDMA handle pointer, this handle shall be static allocated by users.
177 * param eventSource ASRC input sdma event source.
178 * param context ASRC context number.
179 * param periphConfig peripheral configurations, used for peripheral to peripheral case.
180 * param userData User parameter passed to the callback function.
181 */
ASRC_TransferInCreateHandleSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,asrc_sdma_callback_t callback,sdma_handle_t * dmaHandle,uint32_t eventSource,asrc_context_t context,const asrc_p2p_sdma_config_t * periphConfig,void * userData)182 void ASRC_TransferInCreateHandleSDMA(ASRC_Type *base,
183 asrc_sdma_handle_t *handle,
184 asrc_sdma_callback_t callback,
185 sdma_handle_t *dmaHandle,
186 uint32_t eventSource,
187 asrc_context_t context,
188 const asrc_p2p_sdma_config_t *periphConfig,
189 void *userData)
190 {
191 assert((handle != NULL) && (dmaHandle != NULL));
192
193 uint32_t instance = ASRC_GetInstance(base);
194
195 /* Zero the handle */
196 (void)memset(&handle->inDMAHandle, 0, sizeof(asrc_sdma_in_handle_t));
197
198 /* Set asrc base to handle */
199 handle->inDMAHandle.sdmaHandle = dmaHandle;
200 handle->inDMAHandle.callback = callback;
201 handle->inDMAHandle.userData = userData;
202 handle->inDMAHandle.eventSource = eventSource;
203
204 /* Set ASRC state to idle */
205 handle->inDMAHandle.state = kStatus_ASRCIdle;
206 handle->context = context;
207 handle->inDMAHandle.peripheralConfig = periphConfig;
208
209 s_sdmaPrivateHandle[instance][context].base = base;
210 s_sdmaPrivateHandle[instance][context].handle = handle;
211
212 SDMA_InstallBDMemory(dmaHandle, handle->inDMAHandle.bdPool, ASRC_XFER_IN_QUEUE_SIZE);
213 /* Install callback for in dma channel */
214 SDMA_SetCallback(dmaHandle, ASRC_InSDMACallback, &s_sdmaPrivateHandle[instance][context]);
215 }
216
217 /*!
218 * brief Initializes the ASRC output SDMA handle.
219 *
220 * This function initializes the ASRC out DMA handle, which can be used for other ASRC transactional APIs.
221 * Usually, for a specified ASRC context, call this API once to get the initialized handle.
222 *
223 * param base ASRC base pointer.
224 * param handle ASRC SDMA handle pointer.
225 * param callback, ASRC outcallback.
226 * param dmaHandle SDMA handle pointer, this handle shall be static allocated by users.
227 * param eventSource ASRC output event source.
228 * param context ASRC context number.
229 * param periphConfig peripheral configurations, used for case.
230 * param userData User parameter passed to the callback function.
231 */
ASRC_TransferOutCreateHandleSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,asrc_sdma_callback_t callback,sdma_handle_t * dmaHandle,uint32_t eventSource,asrc_context_t context,const asrc_p2p_sdma_config_t * periphConfig,void * userData)232 void ASRC_TransferOutCreateHandleSDMA(ASRC_Type *base,
233 asrc_sdma_handle_t *handle,
234 asrc_sdma_callback_t callback,
235 sdma_handle_t *dmaHandle,
236 uint32_t eventSource,
237 asrc_context_t context,
238 const asrc_p2p_sdma_config_t *periphConfig,
239 void *userData)
240 {
241 assert((handle != NULL) && (dmaHandle != NULL));
242
243 uint32_t instance = ASRC_GetInstance(base);
244
245 /* Zero the handle */
246 (void)memset(&handle->outDMAHandle, 0, sizeof(asrc_sdma_out_handle_t));
247
248 /* Set asrc base to handle */
249 handle->outDMAHandle.sdmaHandle = dmaHandle;
250 handle->outDMAHandle.callback = callback;
251 handle->outDMAHandle.userData = userData;
252 handle->outDMAHandle.eventSource = eventSource;
253 handle->outDMAHandle.peripheralConfig = periphConfig;
254
255 /* Set ASRC state to idle */
256 handle->outDMAHandle.state = kStatus_ASRCIdle;
257 handle->context = context;
258
259 s_sdmaPrivateHandle[instance][context].base = base;
260 s_sdmaPrivateHandle[instance][context].handle = handle;
261
262 /* Install callback for in dma channel */
263 SDMA_SetCallback(dmaHandle, ASRC_OutSDMACallback, &s_sdmaPrivateHandle[instance][context]);
264 SDMA_InstallBDMemory(dmaHandle, handle->outDMAHandle.bdPool, ASRC_XFER_OUT_QUEUE_SIZE);
265 }
266
267 /*!
268 * brief Configures the ASRC context.
269 *
270 * param base ASRC base pointer.
271 * param handle ASRC SDMA handle pointer.
272 * param asrcConfig asrc context configurations.
273 */
ASRC_TransferSetContextConfigSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,asrc_context_config_t * asrcConfig)274 status_t ASRC_TransferSetContextConfigSDMA(ASRC_Type *base,
275 asrc_sdma_handle_t *handle,
276 asrc_context_config_t *asrcConfig)
277 {
278 assert((handle != NULL) && (asrcConfig != NULL));
279
280 /* Configure the audio format to ASRC registers */
281 if (ASRC_SetContextConfig(base, handle->context, asrcConfig) != kStatus_Success)
282 {
283 return kStatus_ASRCConfigureFailed;
284 }
285
286 if (asrcConfig->contextInput.dataFormat.dataWidth == kASRC_DataWidth16Bit)
287 {
288 handle->inDMAHandle.bytesPerSample = 2U;
289 }
290 else
291 {
292 handle->inDMAHandle.bytesPerSample = 4U;
293 }
294
295 if (asrcConfig->contextOutput.dataFormat.dataWidth == kASRC_DataWidth16Bit)
296 {
297 handle->outDMAHandle.bytesPerSample = 2U;
298 }
299 else
300 {
301 handle->outDMAHandle.bytesPerSample = 4U;
302 }
303
304 handle->dataChannels = asrcConfig->contextChannelNums;
305 handle->outDMAHandle.asrcOutWatermark = (asrcConfig->contextOutput.watermark + 1U) * asrcConfig->contextChannelNums;
306 handle->inDMAHandle.asrcInWatermark = (asrcConfig->contextInput.watermark + 1U) * asrcConfig->contextChannelNums;
307
308 return kStatus_Success;
309 }
310
ASRC_TransferSubmitOutM2MSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,uint32_t * outDataAddr,uint32_t outDataSize)311 static status_t ASRC_TransferSubmitOutM2MSDMA(ASRC_Type *base,
312 asrc_sdma_handle_t *handle,
313 uint32_t *outDataAddr,
314 uint32_t outDataSize)
315 {
316 sdma_transfer_config_t outConfig = {0};
317 uint32_t asrcOutAddr = ASRC_GetReadContextFifoAddr(base, handle->context);
318 sdma_handle_t *outDMAHandle = handle->outDMAHandle.sdmaHandle;
319 uint32_t nonAlignSize = 0U;
320 uint32_t *nonAlignAddr = NULL;
321 uint32_t outWaterMarkSize = (uint32_t)handle->outDMAHandle.asrcOutWatermark * handle->outDMAHandle.bytesPerSample;
322
323 if (handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] != NULL)
324 {
325 return kStatus_ASRCQueueFull;
326 }
327
328 if (outDataSize < outWaterMarkSize)
329 {
330 handle->outDMAHandle.nonAlignSize = outDataSize;
331 handle->outDMAHandle.nonAlignAddr = outDataAddr;
332
333 return kStatus_Success;
334 }
335 else
336 {
337 nonAlignSize = outDataSize % outWaterMarkSize;
338 nonAlignAddr = (void *)(uint32_t *)((uint32_t)outDataAddr + outDataSize - nonAlignSize);
339 }
340
341 if (handle->outDMAHandle.peripheralConfig == NULL)
342 {
343 /* since the ASRC output fifo will generate SDMA request only when output fifo sample number > output fifo
344 * watermark, so part of data may need to polling out.
345 */
346 if (handle->outDMAHandle.nonAlignSize != 0U)
347 {
348 SDMA_PrepareTransfer(&outConfig, (uint32_t)asrcOutAddr,
349 (uint32_t)(uint32_t *)handle->outDMAHandle.nonAlignAddr,
350 handle->outDMAHandle.bytesPerSample, handle->outDMAHandle.bytesPerSample,
351 outWaterMarkSize, handle->outDMAHandle.nonAlignSize, handle->outDMAHandle.eventSource,
352 kSDMA_PeripheralASRCP2M, kSDMA_PeripheralToMemory);
353
354 if (handle->outDMAHandle.queueUser == ASRC_XFER_OUT_QUEUE_SIZE - 1U)
355 {
356 SDMA_ConfigBufferDescriptor(
357 &outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
358 (uint32_t)(uint32_t *)handle->outDMAHandle.nonAlignAddr, outConfig.destTransferSize,
359 handle->outDMAHandle.nonAlignSize, false, true, true, kSDMA_PeripheralToMemory);
360 }
361 else
362 {
363 SDMA_ConfigBufferDescriptor(
364 &outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
365 (uint32_t)(uint32_t *)handle->outDMAHandle.nonAlignAddr, outConfig.destTransferSize,
366 handle->outDMAHandle.nonAlignSize, false, true, false, kSDMA_PeripheralToMemory);
367 }
368
369 handle->outDMAHandle.sdmaTransferSize[handle->outDMAHandle.queueUser] = handle->outDMAHandle.nonAlignSize;
370 handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] = handle->outDMAHandle.nonAlignAddr;
371 handle->outDMAHandle.queueUser = (handle->outDMAHandle.queueUser + 1U) % ASRC_XFER_OUT_QUEUE_SIZE;
372 handle->outDMAHandle.nonAlignSize = 0U;
373 handle->outDMAHandle.nonAlignAddr = NULL;
374
375 if (handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] != NULL)
376 {
377 return kStatus_ASRCQueueFull;
378 }
379 }
380 else
381 {
382 SDMA_PrepareTransfer(&outConfig, (uint32_t)asrcOutAddr, (uint32_t)outDataAddr,
383 handle->outDMAHandle.bytesPerSample, handle->outDMAHandle.bytesPerSample,
384 outWaterMarkSize, outDataSize - nonAlignSize, handle->outDMAHandle.eventSource,
385 kSDMA_PeripheralASRCP2M, kSDMA_PeripheralToMemory);
386 }
387
388 if (handle->outDMAHandle.queueUser == ASRC_XFER_OUT_QUEUE_SIZE - 1U)
389 {
390 SDMA_ConfigBufferDescriptor(&outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
391 (uint32_t)outDataAddr, outConfig.destTransferSize, outDataSize - nonAlignSize,
392 false, true, true, kSDMA_PeripheralToMemory);
393 }
394 else
395 {
396 SDMA_ConfigBufferDescriptor(&outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
397 (uint32_t)outDataAddr, outConfig.destTransferSize, outDataSize - nonAlignSize,
398 false, true, false, kSDMA_PeripheralToMemory);
399 }
400
401 handle->outDMAHandle.sdmaTransferSize[handle->outDMAHandle.queueUser] = outDataSize - nonAlignSize;
402 handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] = outDataAddr;
403 handle->outDMAHandle.nonAlignSize = nonAlignSize;
404 handle->outDMAHandle.nonAlignAddr = nonAlignAddr;
405
406 handle->outDMAHandle.queueUser = (handle->outDMAHandle.queueUser + 1U) % ASRC_XFER_OUT_QUEUE_SIZE;
407
408 if (handle->outDMAHandle.state != (uint32_t)kStatus_ASRCBusy)
409 {
410 /* submit ASRC transfer firstly */
411 SDMA_SubmitTransfer(outDMAHandle, &outConfig);
412 /* Start DMA transfer */
413 SDMA_StartTransfer(outDMAHandle);
414
415 /* enable ASRC DMA request */
416 ASRC_EnableContextOutDMA(base, handle->context, true);
417 ASRC_ClearInterruptStatus(base, kASRC_ContextAllInterruptStatus);
418
419 if ((handle->outDMAHandle.peripheralConfig != NULL) &&
420 (handle->outDMAHandle.peripheralConfig->startPeripheral != NULL))
421 {
422 /* start peripheral */
423 handle->outDMAHandle.peripheralConfig->startPeripheral(true);
424 }
425
426 handle->outDMAHandle.state = kStatus_ASRCBusy;
427 }
428 }
429
430 return kStatus_Success;
431 }
432
ASRC_TransferOutSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,uint32_t * outDataAddr,uint32_t outDataSize)433 static status_t ASRC_TransferOutSDMA(ASRC_Type *base,
434 asrc_sdma_handle_t *handle,
435 uint32_t *outDataAddr,
436 uint32_t outDataSize)
437 {
438 sdma_transfer_config_t outConfig = {0};
439 uint32_t asrcOutAddr = ASRC_GetReadContextFifoAddr(base, handle->context);
440 sdma_handle_t *outDMAHandle = handle->outDMAHandle.sdmaHandle;
441 sdma_p2p_config_t p2pConfig = {0U};
442
443 if ((handle->outDMAHandle.peripheralConfig != NULL) && (handle->outDMAHandle.peripheralConfig->enableContinuous) &&
444 (handle->outDMAHandle.state == (uint32_t)kStatus_ASRCBusy))
445 {
446 return kStatus_Success;
447 }
448
449 if (handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] != NULL)
450 {
451 return kStatus_ASRCQueueFull;
452 }
453
454 if (handle->outDMAHandle.peripheralConfig != NULL)
455 {
456 p2pConfig.sourceWatermark = handle->outDMAHandle.asrcOutWatermark;
457 p2pConfig.destWatermark = handle->outDMAHandle.peripheralConfig->watermark;
458 p2pConfig.continuousTransfer = handle->outDMAHandle.peripheralConfig->enableContinuous;
459 /* Prepare sdma configure */
460 SDMA_PrepareP2PTransfer(&outConfig, (uint32_t)asrcOutAddr, (uint32_t)outDataAddr,
461 handle->outDMAHandle.bytesPerSample, handle->outDMAHandle.bytesPerSample,
462 (uint32_t)handle->outDMAHandle.asrcOutWatermark * handle->outDMAHandle.bytesPerSample,
463 outDataSize, handle->outDMAHandle.eventSource,
464 handle->outDMAHandle.peripheralConfig->eventSource, kSDMA_PeripheralASRCP2P,
465 &p2pConfig);
466
467 handle->outDMAHandle.sdmaTransferSize[handle->outDMAHandle.queueUser] = outDataSize;
468 handle->outDMAHandle.asrcQueue[handle->outDMAHandle.queueUser] = outDataAddr;
469
470 if (handle->outDMAHandle.queueUser == ASRC_XFER_OUT_QUEUE_SIZE - 1U)
471 {
472 SDMA_ConfigBufferDescriptor(&outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
473 (uint32_t)outDataAddr, outConfig.destTransferSize, outDataSize, false, true,
474 true, kSDMA_PeripheralToPeripheral);
475 }
476 else
477 {
478 SDMA_ConfigBufferDescriptor(&outDMAHandle->BDPool[handle->outDMAHandle.queueUser], (uint32_t)(asrcOutAddr),
479 (uint32_t)outDataAddr, outConfig.destTransferSize, outDataSize, false, true,
480 false, kSDMA_PeripheralToPeripheral);
481 }
482
483 handle->outDMAHandle.queueUser = (handle->outDMAHandle.queueUser + 1U) % ASRC_XFER_OUT_QUEUE_SIZE;
484
485 if (handle->outDMAHandle.state != (uint32_t)kStatus_ASRCBusy)
486 {
487 /* submit ASRC transfer firstly */
488 SDMA_SubmitTransfer(outDMAHandle, &outConfig);
489 /* Start DMA transfer */
490 SDMA_StartTransfer(outDMAHandle);
491
492 /* enable ASRC DMA request */
493 ASRC_EnableContextOutDMA(base, handle->context, true);
494 ASRC_ClearInterruptStatus(base, kASRC_ContextAllInterruptStatus);
495
496 if ((handle->outDMAHandle.peripheralConfig != NULL) &&
497 (handle->outDMAHandle.peripheralConfig->startPeripheral != NULL))
498 {
499 /* start peripheral */
500 handle->outDMAHandle.peripheralConfig->startPeripheral(true);
501 }
502
503 handle->outDMAHandle.state = kStatus_ASRCBusy;
504 }
505 }
506 else
507 {
508 return ASRC_TransferSubmitOutM2MSDMA(base, handle, outDataAddr, outDataSize);
509 }
510
511 return kStatus_Success;
512 }
513
ASRC_TransferInSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,uint32_t * inDataAddr,uint32_t inDataSize)514 static status_t ASRC_TransferInSDMA(ASRC_Type *base,
515 asrc_sdma_handle_t *handle,
516 uint32_t *inDataAddr,
517 uint32_t inDataSize)
518 {
519 sdma_transfer_config_t inConfig = {0};
520 uint32_t asrcInAddr = ASRC_GetWriteContextFifoAddr(base, handle->context);
521 sdma_handle_t *inDMAHandle = handle->inDMAHandle.sdmaHandle;
522 sdma_p2p_config_t p2pConfig = {0U};
523
524 if ((handle->inDMAHandle.peripheralConfig != NULL) && (handle->inDMAHandle.peripheralConfig->enableContinuous) &&
525 (handle->inDMAHandle.state == (uint32_t)kStatus_ASRCBusy))
526 {
527 return kStatus_Success;
528 }
529
530 if (handle->inDMAHandle.asrcQueue[handle->inDMAHandle.queueUser] != NULL)
531 {
532 return kStatus_ASRCQueueFull;
533 }
534
535 if (handle->inDMAHandle.peripheralConfig != NULL)
536 {
537 p2pConfig.sourceWatermark = handle->inDMAHandle.peripheralConfig->watermark;
538 p2pConfig.destWatermark = handle->inDMAHandle.asrcInWatermark;
539 p2pConfig.continuousTransfer = handle->inDMAHandle.peripheralConfig->enableContinuous;
540
541 /* Prepare sdma configure */
542 SDMA_PrepareP2PTransfer(&inConfig, (uint32_t)inDataAddr, asrcInAddr,
543 handle->inDMAHandle.peripheralConfig->fifoWidth, handle->inDMAHandle.bytesPerSample,
544 (uint32_t)handle->inDMAHandle.asrcInWatermark * handle->inDMAHandle.bytesPerSample,
545 inDataSize, handle->inDMAHandle.peripheralConfig->eventSource,
546 handle->inDMAHandle.eventSource, kSDMA_PeripheralASRCP2P, &p2pConfig);
547 }
548 else
549 {
550 SDMA_PrepareTransfer(&inConfig, (uint32_t)inDataAddr, asrcInAddr, handle->inDMAHandle.bytesPerSample,
551 handle->inDMAHandle.bytesPerSample,
552 (uint32_t)handle->inDMAHandle.asrcInWatermark * handle->inDMAHandle.bytesPerSample,
553 inDataSize, handle->inDMAHandle.eventSource, kSDMA_PeripheralASRCM2P,
554 kSDMA_MemoryToPeripheral);
555 }
556
557 handle->inDMAHandle.sdmaTransferSize[handle->inDMAHandle.queueUser] = inDataSize;
558 handle->inDMAHandle.asrcQueue[handle->inDMAHandle.queueUser] = inDataAddr;
559
560 if (handle->inDMAHandle.queueUser == ASRC_XFER_IN_QUEUE_SIZE - 1U)
561 {
562 SDMA_ConfigBufferDescriptor(&inDMAHandle->BDPool[handle->inDMAHandle.queueUser], (uint32_t)inDataAddr,
563 asrcInAddr, inConfig.destTransferSize, inDataSize, true, true, true,
564 kSDMA_MemoryToPeripheral);
565 }
566 else
567 {
568 SDMA_ConfigBufferDescriptor(&inDMAHandle->BDPool[handle->inDMAHandle.queueUser], (uint32_t)inDataAddr,
569 asrcInAddr, inConfig.destTransferSize, inDataSize, true, true, false,
570 kSDMA_MemoryToPeripheral);
571 }
572
573 handle->inDMAHandle.queueUser = (handle->inDMAHandle.queueUser + 1U) % ASRC_XFER_IN_QUEUE_SIZE;
574
575 if (handle->inDMAHandle.state != (uint32_t)kStatus_ASRCBusy)
576 {
577 /* submit ASRC write transfer */
578 SDMA_SubmitTransfer(inDMAHandle, &inConfig);
579 /* Start DMA transfer */
580 SDMA_StartTransfer(inDMAHandle);
581
582 /* enable ASRC DMA request */
583 ASRC_EnableContextInDMA(base, handle->context, true);
584 ASRC_ClearInterruptStatus(base, kASRC_ContextAllInterruptStatus);
585 /* enable context run */
586 ASRC_EnableContextRun(base, handle->context, true);
587
588 if ((handle->inDMAHandle.peripheralConfig != NULL) &&
589 (handle->inDMAHandle.peripheralConfig->startPeripheral != NULL))
590 {
591 /* start peripheral */
592 handle->inDMAHandle.peripheralConfig->startPeripheral(true);
593 }
594
595 handle->inDMAHandle.state = kStatus_ASRCBusy;
596 }
597
598 return kStatus_Success;
599 }
600
601 /*!
602 * brief Performs a non-blocking ASRC transfer using DMA.
603 *
604 *
605 * param base ASRC base pointer.
606 * param handle ASRC SDMA handle pointer.
607 * param xfer ASRC xfer configurations pointer.
608 * retval kStatus_Success Start a ASRC SDMA send successfully.
609 * retval kStatus_InvalidArgument The input argument is invalid.
610 * retval kStatus_TxBusy ASRC is busy sending data.
611 */
ASRC_TransferSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle,asrc_transfer_t * xfer)612 status_t ASRC_TransferSDMA(ASRC_Type *base, asrc_sdma_handle_t *handle, asrc_transfer_t *xfer)
613 {
614 assert((handle != NULL) && (xfer != NULL));
615
616 uint32_t *inPtr = xfer->inDataAddr, *outPtr = xfer->outDataAddr;
617 uint32_t inSize = xfer->inDataSize, inOneTimeSize = 0U;
618 uint32_t outSize = xfer->outDataSize, outOneTimeSize = 0U;
619 uint32_t outWaterMarkSize = ((uint32_t)handle->outDMAHandle.asrcOutWatermark * handle->outDMAHandle.bytesPerSample);
620
621 while ((inSize != 0U) || (outSize != 0U))
622 {
623 if (outSize != 0U)
624 {
625 outOneTimeSize = outSize > 64000U ? (64000U - 64000U % outWaterMarkSize) : outSize;
626 if (ASRC_TransferOutSDMA(base, handle, outPtr, outOneTimeSize) == kStatus_Success)
627 {
628 outSize -= outOneTimeSize;
629 outPtr = (uint32_t *)((uint32_t)outPtr + outOneTimeSize);
630 }
631 }
632
633 if (inSize != 0U)
634 {
635 inOneTimeSize = inSize > 64000U ? 64000U : inSize;
636 if (ASRC_TransferInSDMA(base, handle, inPtr, inOneTimeSize) == kStatus_Success)
637 {
638 inSize -= inOneTimeSize;
639 inPtr = (uint32_t *)((uint32_t)inPtr + inOneTimeSize);
640 }
641 }
642 }
643
644 return kStatus_Success;
645 }
646
647 /*!
648 * brief Aborts a ASRC in transfer using SDMA.
649 *
650 * param base ASRC base pointer.
651 * param handle ASRC SDMA handle pointer.
652 */
ASRC_TransferAbortInSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle)653 void ASRC_TransferAbortInSDMA(ASRC_Type *base, asrc_sdma_handle_t *handle)
654 {
655 assert(handle != NULL);
656
657 /* Disable dma */
658 SDMA_AbortTransfer(handle->inDMAHandle.sdmaHandle);
659
660 /* enable context run */
661 ASRC_EnableContextRunStop(base, handle->context, true);
662 /* stop peripheral */
663 if ((handle->inDMAHandle.peripheralConfig != NULL) &&
664 (handle->inDMAHandle.peripheralConfig->startPeripheral != NULL))
665 {
666 handle->inDMAHandle.peripheralConfig->startPeripheral(false);
667 }
668 /* Set the handle state */
669 handle->inDMAHandle.state = kStatus_ASRCIdle;
670 }
671
672 /*!
673 * brief Aborts a ASRC out transfer using SDMA.
674 *
675 * param base ASRC base pointer.
676 * param handle ASRC SDMA handle pointer.
677 */
ASRC_TransferAbortOutSDMA(ASRC_Type * base,asrc_sdma_handle_t * handle)678 void ASRC_TransferAbortOutSDMA(ASRC_Type *base, asrc_sdma_handle_t *handle)
679 {
680 assert(handle != NULL);
681
682 /* Disable dma */
683 SDMA_AbortTransfer(handle->outDMAHandle.sdmaHandle);
684 /* enable ASRC DMA request */
685 ASRC_EnableContextOutDMA(base, handle->context, false);
686 /* enable context run */
687 ASRC_EnableContextRun(base, handle->context, false);
688 ASRC_EnableContextRunStop(base, handle->context, false);
689 /* stop peripheral */
690 if ((handle->outDMAHandle.peripheralConfig != NULL) &&
691 (handle->outDMAHandle.peripheralConfig->startPeripheral != NULL))
692 {
693 handle->outDMAHandle.peripheralConfig->startPeripheral(false);
694 }
695 /* Set the handle state */
696 handle->outDMAHandle.state = kStatus_ASRCIdle;
697 }
698