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