1 /*
2 * Copyright 2021 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_common.h"
10 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
11 #include "fsl_dma.h"
12 #include "fsl_i2s.h"
13 #include "fsl_i2s_dma.h"
14 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
15 #include "fsl_adapter_audio.h"
16
17 /*******************************************************************************
18 * Definitions
19 ******************************************************************************/
20
21 /*! @brief hal i2s state structure. */
22 typedef struct _hal_audio_state
23 {
24 hal_audio_transfer_callback_t callback;
25 void *callbackParam;
26 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
27 i2s_dma_handle_t xferDmaHandle;
28 dma_handle_t dmaHandle;
29 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
30 uint8_t dmaInstance;
31 uint8_t instance;
32 uint8_t occupied;
33 } hal_audio_state_t;
34
35 /*******************************************************************************
36 * Prototypes
37 ******************************************************************************/
38
39 /*******************************************************************************
40 * Variables
41 ******************************************************************************/
42 /*! @brief Pointers to i2s bases for each instance. */
43 static I2S_Type *const s_i2sBases[] = I2S_BASE_PTRS;
44 #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U))
45 /*! @brief Resource for each i2s instance. */
46 static uint8_t s_dmaOccupied[ARRAY_SIZE((DMA_Type *[])DMA_BASE_PTRS)];
47 #endif /* HAL_AUDIO_DMA_INIT_ENABLE */
48
49 /*******************************************************************************
50 * Code
51 ******************************************************************************/
52
HAL_AudioGetStatus(status_t status)53 static hal_audio_status_t HAL_AudioGetStatus(status_t status)
54 {
55 hal_audio_status_t returnStatus;
56 switch (status)
57 {
58 case kStatus_Success:
59 returnStatus = kStatus_HAL_AudioSuccess;
60 break;
61
62 case kStatus_I2S_Busy:
63 returnStatus = kStatus_HAL_AudioBusy;
64 break;
65
66 case kStatus_I2S_BufferComplete:
67 case kStatus_I2S_Done:
68 case kStatus_NoTransferInProgress:
69 returnStatus = kStatus_HAL_AudioIdle;
70 break;
71
72 default:
73 returnStatus = kStatus_HAL_AudioError;
74 break;
75 }
76 return returnStatus;
77 }
78
79 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
HAL_AudioCallbackDMA(I2S_Type * base,i2s_dma_handle_t * handle,status_t status,void * userData)80 static void HAL_AudioCallbackDMA(I2S_Type *base, i2s_dma_handle_t *handle, status_t status, void *userData)
81 {
82 hal_audio_state_t *audioHandle;
83
84 assert(userData);
85
86 audioHandle = (hal_audio_state_t *)userData;
87
88 if (NULL != audioHandle->callback)
89 {
90 audioHandle->callback(audioHandle, HAL_AudioGetStatus(status), audioHandle->callbackParam);
91 }
92 }
93 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
94
HAL_AudioCommonInit(hal_audio_handle_t handle,const hal_audio_config_t * config,bool direction)95 static hal_audio_status_t HAL_AudioCommonInit(hal_audio_handle_t handle,
96 const hal_audio_config_t *config,
97 bool direction)
98 {
99 hal_audio_state_t *audioHandle;
100 i2s_config_t i2sConfig;
101 hal_audio_dma_config_t *dmaConfig;
102 DMA_Type *dmaBases[] = DMA_BASE_PTRS;
103 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
104 IRQn_Type dmaIrqNumber[] = DMA_IRQS;
105 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
106 uint8_t channelNum;
107
108 assert(handle);
109 assert(config);
110 assert(config->dmaConfig);
111 /* If asserted, please check if the value of I2S_NUM_BUFFERS defined in the fsl_i2s.h is modified.
112 If modified, please modify the value of HAL_AUDIO_QUEUE_SIZE defined in the fsl_adapter_audio.h to be the same as
113 I2S_NUM_BUFFERS. */
114 assert(HAL_AUDIO_HANDLE_SIZE >= sizeof(hal_audio_state_t));
115 assert(config->instance < ARRAY_SIZE(s_i2sBases));
116 assert(config->dmaConfig->instance < ARRAY_SIZE(dmaBases));
117
118 dmaConfig = (hal_audio_dma_config_t *)config->dmaConfig;
119 audioHandle = (hal_audio_state_t *)handle;
120
121 if (audioHandle->occupied != 0U)
122 {
123 return kStatus_HAL_AudioSuccess;
124 }
125
126 audioHandle->instance = config->instance;
127 audioHandle->dmaInstance = dmaConfig->instance;
128 audioHandle->occupied = 1;
129 channelNum = (uint8_t)config->lineChannels;
130
131 if (direction)
132 {
133 I2S_TxGetDefaultConfig(&i2sConfig);
134 }
135 else
136 {
137 I2S_RxGetDefaultConfig(&i2sConfig);
138 }
139
140 if (channelNum == (uint8_t)kHAL_AudioMono)
141 {
142 i2sConfig.oneChannel = true;
143 channelNum = 1;
144 }
145 else if (channelNum == (uint8_t)kHAL_AudioMonoRight)
146 {
147 i2sConfig.oneChannel = true;
148 i2sConfig.position = config->bitWidth;
149 channelNum = 2;
150 }
151 else if (channelNum == (uint8_t)kHAL_AudioMonoLeft)
152 {
153 i2sConfig.oneChannel = true;
154 channelNum = 2;
155 }
156 else
157 {
158 /* no action */
159 }
160
161 i2sConfig.divider =
162 (uint16_t)(config->srcClock_Hz / (uint32_t)config->sampleRate_Hz / (uint32_t)config->bitWidth / channelNum);
163 i2sConfig.dataLength = config->bitWidth;
164 if (0U == config->frameLength)
165 {
166 i2sConfig.frameLength = (uint16_t)config->bitWidth * channelNum;
167 }
168 else
169 {
170 i2sConfig.frameLength = config->frameLength;
171 }
172
173 if ((uint8_t)kHAL_AudioSampleOnFallingEdge == (uint8_t)config->bclkPolarity)
174 {
175 i2sConfig.sckPol = true;
176 }
177 else
178 {
179 i2sConfig.sckPol = false;
180 }
181
182 switch (config->masterSlave)
183 {
184 case kHAL_AudioMaster:
185 i2sConfig.masterSlave = kI2S_MasterSlaveNormalMaster;
186 break;
187
188 case kHAL_AudioSlave:
189 i2sConfig.masterSlave = kI2S_MasterSlaveNormalSlave;
190 i2sConfig.divider = 1; /* As slave, divider need to set to 1 according to the spec. */
191 break;
192
193 case kHAL_AudioBclkMasterFrameSyncSlave:
194 i2sConfig.masterSlave = kI2S_MasterSlaveWsSyncMaster;
195 break;
196
197 case kHAL_AudioBclkSlaveFrameSyncMaster:
198 i2sConfig.masterSlave = kI2S_MasterSlaveExtSckMaster;
199 i2sConfig.divider = 1; /* As slave, divider need to set to 1 according to the spec. */
200 break;
201
202 default:
203 assert(false);
204 break;
205 }
206
207 switch (config->dataFormat)
208 {
209 case kHAL_AudioDataFormatI2sClassic:
210 i2sConfig.mode = kI2S_ModeI2sClassic;
211 i2sConfig.wsPol = false;
212
213 if ((uint8_t)config->lineChannels == (uint8_t)kHAL_AudioMonoRight)
214 {
215 i2sConfig.position += 0x100U; /* Special case for i2s classic mode */
216 }
217 break;
218
219 case kHAL_AudioDataFormatLeftJustified:
220 case kHAL_AudioDataFormatRightJustified:
221 i2sConfig.mode = kI2S_ModeDspWs50;
222 i2sConfig.wsPol = true;
223 break;
224
225 case kHAL_AudioDataFormatDspModeA:
226 case kHAL_AudioDataFormatDspModeB:
227 i2sConfig.wsPol = true;
228
229 if ((uint8_t)config->dataFormat == (uint8_t)kHAL_AudioDataFormatDspModeA)
230 {
231 i2sConfig.position += 1U;
232 }
233
234 if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthOneBitClk)
235 {
236 i2sConfig.mode = kI2S_ModeDspWsShort;
237 }
238 else if ((uint8_t)config->frameSyncWidth == (uint8_t)kHAL_AudioFrameSyncWidthPerWordWidth)
239 {
240 i2sConfig.mode = kI2S_ModeDspWsLong;
241 }
242 else
243 {
244 i2sConfig.mode = kI2S_ModeDspWs50;
245 }
246 break;
247
248 default:
249 assert(false);
250 break;
251 }
252
253 if (direction)
254 {
255 I2S_TxInit(s_i2sBases[audioHandle->instance], &i2sConfig);
256 }
257 else
258 {
259 I2S_RxInit(s_i2sBases[audioHandle->instance], &i2sConfig);
260 }
261
262 if (channelNum > (uint8_t)kHAL_AudioStereo)
263 {
264 #if (defined(FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL) && FSL_FEATURE_I2S_SUPPORT_SECONDARY_CHANNEL)
265 bool oneChannel = (channelNum % 2U != 0U) ? true : false;
266
267 if (channelNum <= (uint8_t)kHAL_AudioStereo4Channel)
268 {
269 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel1, oneChannel,
270 (uint32_t)config->bitWidth * 2U + i2sConfig.position);
271 }
272 else if (channelNum <= (uint8_t)kHAL_AudioStereo6Channel)
273 {
274 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel1, false,
275 (uint32_t)config->bitWidth * 2U + i2sConfig.position);
276 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel2, oneChannel,
277 (uint32_t)config->bitWidth * 4U + i2sConfig.position);
278 }
279 else if (channelNum <= (uint8_t)kHAL_AudioStereo8Channel)
280 {
281 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel1, false,
282 (uint32_t)config->bitWidth * 2U + i2sConfig.position);
283 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel2, false,
284 (uint32_t)config->bitWidth * 4U + i2sConfig.position);
285 I2S_EnableSecondaryChannel(s_i2sBases[audioHandle->instance], kI2S_SecondaryChannel3, oneChannel,
286 (uint32_t)config->bitWidth * 6U + i2sConfig.position);
287 }
288 else
289
290 {
291 assert(false);
292 }
293 #else
294 assert(false);
295 #endif
296 }
297
298 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
299 #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U))
300 if (s_dmaOccupied[dmaConfig->instance] == 0U)
301 {
302 DMA_Init(dmaBases[dmaConfig->instance]);
303 }
304 s_dmaOccupied[dmaConfig->instance]++;
305 #endif /* HAL_AUDIO_DMA_INIT_ENABLE */
306
307 DMA_EnableChannel(dmaBases[dmaConfig->instance], dmaConfig->channel);
308
309 if ((uint8_t)kHAL_AudioDmaChannelPriorityDefault != (uint8_t)dmaConfig->priority)
310 {
311 assert((dma_priority_t)dmaConfig->priority <= kDMA_ChannelPriority7);
312
313 DMA_SetChannelPriority(dmaBases[dmaConfig->instance], dmaConfig->channel, (dma_priority_t)dmaConfig->priority);
314 }
315
316 NVIC_SetPriority((IRQn_Type)dmaIrqNumber[dmaConfig->instance], HAL_AUDIO_ISR_PRIORITY);
317 DMA_CreateHandle(&audioHandle->dmaHandle, dmaBases[dmaConfig->instance], dmaConfig->channel);
318
319 if (direction)
320 {
321 I2S_TxTransferCreateHandleDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle,
322 &audioHandle->dmaHandle, HAL_AudioCallbackDMA, audioHandle);
323 }
324 else
325 {
326 I2S_RxTransferCreateHandleDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle,
327 &audioHandle->dmaHandle, HAL_AudioCallbackDMA, audioHandle);
328 }
329 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
330
331 return kStatus_HAL_AudioSuccess;
332 }
333
HAL_AudioCommonDeinit(hal_audio_handle_t handle,bool direction)334 static hal_audio_status_t HAL_AudioCommonDeinit(hal_audio_handle_t handle, bool direction)
335 {
336 hal_audio_state_t *audioHandle;
337 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
338 reset_ip_name_t flexcommResets[] = FLEXCOMM_RSTS;
339 #endif
340 #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U))
341 DMA_Type *dmaBases[] = DMA_BASE_PTRS;
342 #endif /* HAL_AUDIO_DMA_INIT_ENABLE */
343
344 assert(handle);
345
346 audioHandle = (hal_audio_state_t *)handle;
347
348 if (audioHandle->occupied == 0U)
349 {
350 return kStatus_HAL_AudioSuccess;
351 }
352 audioHandle->occupied = 0;
353
354 #if !(defined(FSL_FEATURE_FLEXCOMM_HAS_NO_RESET) && FSL_FEATURE_FLEXCOMM_HAS_NO_RESET)
355 /* Reset the FLEXCOMM module */
356 RESET_PeripheralReset(flexcommResets[audioHandle->instance]);
357 #endif
358
359 /* if (direction)
360 {
361 HAL_AudioTransferAbortSend(handle);
362 }
363 else
364 {
365 HAL_AudioTransferAbortReceive(handle);
366 } */
367
368 I2S_Deinit(s_i2sBases[audioHandle->instance]);
369
370 #if (defined(HAL_AUDIO_DMA_INIT_ENABLE) && (HAL_AUDIO_DMA_INIT_ENABLE > 0U))
371 if (s_dmaOccupied[audioHandle->dmaInstance] != 0U)
372 {
373 s_dmaOccupied[audioHandle->dmaInstance]--;
374
375 if (s_dmaOccupied[audioHandle->dmaInstance] == 0U)
376 {
377 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
378 DMA_Deinit(dmaBases[audioHandle->dmaInstance]);
379 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
380 }
381 }
382 #endif /* HAL_AUDIO_DMA_INIT_ENABLE */
383
384 return kStatus_HAL_AudioSuccess;
385 }
386
HAL_AudioTxInit(hal_audio_handle_t handle,const hal_audio_config_t * config)387 hal_audio_status_t HAL_AudioTxInit(hal_audio_handle_t handle, const hal_audio_config_t *config)
388 {
389 return HAL_AudioCommonInit(handle, config, true);
390 }
391
HAL_AudioRxInit(hal_audio_handle_t handle,const hal_audio_config_t * config)392 hal_audio_status_t HAL_AudioRxInit(hal_audio_handle_t handle, const hal_audio_config_t *config)
393 {
394 return HAL_AudioCommonInit(handle, config, false);
395 }
396
HAL_AudioTxDeinit(hal_audio_handle_t handle)397 hal_audio_status_t HAL_AudioTxDeinit(hal_audio_handle_t handle)
398 {
399 return HAL_AudioCommonDeinit(handle, true);
400 }
401
HAL_AudioRxDeinit(hal_audio_handle_t handle)402 hal_audio_status_t HAL_AudioRxDeinit(hal_audio_handle_t handle)
403 {
404 return HAL_AudioCommonDeinit(handle, false);
405 }
406
HAL_AudioTxInstallCallback(hal_audio_handle_t handle,hal_audio_transfer_callback_t callback,void * callbackParam)407 hal_audio_status_t HAL_AudioTxInstallCallback(hal_audio_handle_t handle,
408 hal_audio_transfer_callback_t callback,
409 void *callbackParam)
410 {
411 hal_audio_state_t *audioHandle;
412
413 assert(handle);
414
415 audioHandle = (hal_audio_state_t *)handle;
416
417 audioHandle->callback = callback;
418 audioHandle->callbackParam = callbackParam;
419
420 return kStatus_HAL_AudioSuccess;
421 }
422
HAL_AudioRxInstallCallback(hal_audio_handle_t handle,hal_audio_transfer_callback_t callback,void * callbackParam)423 hal_audio_status_t HAL_AudioRxInstallCallback(hal_audio_handle_t handle,
424 hal_audio_transfer_callback_t callback,
425 void *callbackParam)
426 {
427 hal_audio_state_t *audioHandle;
428
429 assert(handle);
430
431 audioHandle = (hal_audio_state_t *)handle;
432
433 audioHandle->callback = callback;
434 audioHandle->callbackParam = callbackParam;
435
436 return kStatus_HAL_AudioSuccess;
437 }
438
HAL_AudioTransferSendNonBlocking(hal_audio_handle_t handle,hal_audio_transfer_t * xfer)439 hal_audio_status_t HAL_AudioTransferSendNonBlocking(hal_audio_handle_t handle, hal_audio_transfer_t *xfer)
440 {
441 i2s_transfer_t transfer;
442 hal_audio_state_t *audioHandle;
443
444 assert(handle);
445
446 audioHandle = (hal_audio_state_t *)handle;
447
448 transfer.data = (uint8_t *)xfer->data;
449 transfer.dataSize = xfer->dataSize;
450
451 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
452 return HAL_AudioGetStatus(
453 I2S_TxTransferSendDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, transfer));
454 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
455 }
456
HAL_AudioTransferReceiveNonBlocking(hal_audio_handle_t handle,hal_audio_transfer_t * xfer)457 hal_audio_status_t HAL_AudioTransferReceiveNonBlocking(hal_audio_handle_t handle, hal_audio_transfer_t *xfer)
458 {
459 i2s_transfer_t transfer;
460 hal_audio_state_t *audioHandle;
461
462 assert(handle);
463
464 audioHandle = (hal_audio_state_t *)handle;
465
466 transfer.data = (uint8_t *)xfer->data;
467 transfer.dataSize = xfer->dataSize;
468
469 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
470 return HAL_AudioGetStatus(
471 I2S_RxTransferReceiveDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle, transfer));
472 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
473 }
474
HAL_AudioTransferGetSendCount(hal_audio_handle_t handle,size_t * count)475 hal_audio_status_t HAL_AudioTransferGetSendCount(hal_audio_handle_t handle, size_t *count)
476 {
477 assert(handle);
478
479 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
480 *count = 0;
481 return kStatus_HAL_AudioSuccess;
482 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
483 }
484
HAL_AudioTransferGetReceiveCount(hal_audio_handle_t handle,size_t * count)485 hal_audio_status_t HAL_AudioTransferGetReceiveCount(hal_audio_handle_t handle, size_t *count)
486 {
487 assert(handle);
488
489 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
490 *count = 0;
491 return kStatus_HAL_AudioSuccess;
492 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
493 }
494
HAL_AudioTransferAbortSend(hal_audio_handle_t handle)495 hal_audio_status_t HAL_AudioTransferAbortSend(hal_audio_handle_t handle)
496 {
497 hal_audio_state_t *audioHandle;
498
499 assert(handle);
500
501 audioHandle = (hal_audio_state_t *)handle;
502
503 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
504 I2S_TransferAbortDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle);
505 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
506
507 return kStatus_HAL_AudioSuccess;
508 }
509
HAL_AudioTransferAbortReceive(hal_audio_handle_t handle)510 hal_audio_status_t HAL_AudioTransferAbortReceive(hal_audio_handle_t handle)
511 {
512 hal_audio_state_t *audioHandle;
513
514 assert(handle);
515
516 audioHandle = (hal_audio_state_t *)handle;
517
518 #if (defined(FSL_FEATURE_SOC_DMA_COUNT) && (FSL_FEATURE_SOC_DMA_COUNT > 0U))
519 I2S_TransferAbortDMA(s_i2sBases[audioHandle->instance], &audioHandle->xferDmaHandle);
520 #endif /* FSL_FEATURE_SOC_DMA_COUNT */
521
522 return kStatus_HAL_AudioSuccess;
523 }
524