1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of the copyright holder nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "fsl_sai.h"
32 
33 /*******************************************************************************
34  * Definitations
35  ******************************************************************************/
36 enum _sai_transfer_state
37 {
38     kSAI_Busy = 0x0U, /*!< SAI is busy */
39     kSAI_Idle,        /*!< Transfer is done. */
40     kSAI_Error        /*!< Transfer error occured. */
41 };
42 
43 /*! @brief Typedef for sai tx interrupt handler. */
44 typedef void (*sai_tx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle);
45 
46 /*! @brief Typedef for sai rx interrupt handler. */
47 typedef void (*sai_rx_isr_t)(I2S_Type *base, sai_handle_t *saiHandle);
48 
49 /*******************************************************************************
50  * Prototypes
51  ******************************************************************************/
52 #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
53 
54 /*!
55  * @brief Set the master clock divider.
56  *
57  * This API will compute the master clock divider according to master clock frequency and master
58  * clock source clock source frequency.
59  *
60  * @param base SAI base pointer.
61  * @param mclk_Hz Mater clock frequency in Hz.
62  * @param mclkSrcClock_Hz Master clock source frequency in Hz.
63  */
64 static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz);
65 #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
66 
67 /*!
68  * @brief Get the instance number for SAI.
69  *
70  * @param base SAI base pointer.
71  */
72 uint32_t SAI_GetInstance(I2S_Type *base);
73 
74 /*!
75  * @brief sends a piece of data in non-blocking way.
76  *
77  * @param base SAI base pointer
78  * @param channel Data channel used.
79  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
80  * @param buffer Pointer to the data to be written.
81  * @param size Bytes to be written.
82  */
83 static void SAI_WriteNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
84 
85 /*!
86  * @brief Receive a piece of data in non-blocking way.
87  *
88  * @param base SAI base pointer
89  * @param channel Data channel used.
90  * @param bitWidth How many bits in a audio word, usually 8/16/24/32 bits.
91  * @param buffer Pointer to the data to be read.
92  * @param size Bytes to be read.
93  */
94 static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size);
95 /*******************************************************************************
96  * Variables
97  ******************************************************************************/
98 /* Base pointer array */
99 static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS;
100 /*!@brief SAI handle pointer */
101 sai_handle_t *s_saiHandle[ARRAY_SIZE(s_saiBases)][2];
102 /* IRQ number array */
103 static const IRQn_Type s_saiTxIRQ[] = I2S_TX_IRQS;
104 static const IRQn_Type s_saiRxIRQ[] = I2S_RX_IRQS;
105 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
106 /* Clock name array */
107 static const clock_ip_name_t s_saiClock[] = SAI_CLOCKS;
108 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
109 /*! @brief Pointer to tx IRQ handler for each instance. */
110 static sai_tx_isr_t s_saiTxIsr;
111 /*! @brief Pointer to tx IRQ handler for each instance. */
112 static sai_rx_isr_t s_saiRxIsr;
113 
114 /*******************************************************************************
115  * Code
116  ******************************************************************************/
117 #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
SAI_SetMasterClockDivider(I2S_Type * base,uint32_t mclk_Hz,uint32_t mclkSrcClock_Hz)118 static void SAI_SetMasterClockDivider(I2S_Type *base, uint32_t mclk_Hz, uint32_t mclkSrcClock_Hz)
119 {
120     uint32_t freq = mclkSrcClock_Hz;
121     uint16_t fract, divide;
122     uint32_t remaind = 0;
123     uint32_t current_remainder = 0xFFFFFFFFU;
124     uint16_t current_fract = 0;
125     uint16_t current_divide = 0;
126     uint32_t mul_freq = 0;
127     uint32_t max_fract = 256;
128 
129     /*In order to prevent overflow */
130     freq /= 100;
131     mclk_Hz /= 100;
132 
133     /* Compute the max fract number */
134     max_fract = mclk_Hz * 4096 / freq + 1;
135     if (max_fract > 256)
136     {
137         max_fract = 256;
138     }
139 
140     /* Looking for the closet frequency */
141     for (fract = 1; fract < max_fract; fract++)
142     {
143         mul_freq = freq * fract;
144         remaind = mul_freq % mclk_Hz;
145         divide = mul_freq / mclk_Hz;
146 
147         /* Find the exactly frequency */
148         if (remaind == 0)
149         {
150             current_fract = fract;
151             current_divide = mul_freq / mclk_Hz;
152             break;
153         }
154 
155         /* Closer to next one, set the closest to next data */
156         if (remaind > mclk_Hz / 2)
157         {
158             remaind = mclk_Hz - remaind;
159             divide += 1;
160         }
161 
162         /* Update the closest div and fract */
163         if (remaind < current_remainder)
164         {
165             current_fract = fract;
166             current_divide = divide;
167             current_remainder = remaind;
168         }
169     }
170 
171     /* Fill the computed fract and divider to registers */
172     base->MDR = I2S_MDR_DIVIDE(current_divide - 1) | I2S_MDR_FRACT(current_fract - 1);
173 
174     /* Waiting for the divider updated */
175     while (base->MCR & I2S_MCR_DUF_MASK)
176     {
177     }
178 }
179 #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
180 
SAI_GetInstance(I2S_Type * base)181 uint32_t SAI_GetInstance(I2S_Type *base)
182 {
183     uint32_t instance;
184 
185     /* Find the instance index from base address mappings. */
186     for (instance = 0; instance < ARRAY_SIZE(s_saiBases); instance++)
187     {
188         if (s_saiBases[instance] == base)
189         {
190             break;
191         }
192     }
193 
194     assert(instance < ARRAY_SIZE(s_saiBases));
195 
196     return instance;
197 }
198 
SAI_WriteNonBlocking(I2S_Type * base,uint32_t channel,uint32_t bitWidth,uint8_t * buffer,uint32_t size)199 static void SAI_WriteNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
200 {
201     uint32_t i = 0;
202     uint8_t j = 0;
203     uint8_t bytesPerWord = bitWidth / 8U;
204     uint32_t data = 0;
205     uint32_t temp = 0;
206 
207     for (i = 0; i < size / bytesPerWord; i++)
208     {
209         for (j = 0; j < bytesPerWord; j++)
210         {
211             temp = (uint32_t)(*buffer);
212             data |= (temp << (8U * j));
213             buffer++;
214         }
215         base->TDR[channel] = data;
216         data = 0;
217     }
218 }
219 
SAI_ReadNonBlocking(I2S_Type * base,uint32_t channel,uint32_t bitWidth,uint8_t * buffer,uint32_t size)220 static void SAI_ReadNonBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
221 {
222     uint32_t i = 0;
223     uint8_t j = 0;
224     uint8_t bytesPerWord = bitWidth / 8U;
225     uint32_t data = 0;
226 
227     for (i = 0; i < size / bytesPerWord; i++)
228     {
229         data = base->RDR[channel];
230         for (j = 0; j < bytesPerWord; j++)
231         {
232             *buffer = (data >> (8U * j)) & 0xFF;
233             buffer++;
234         }
235     }
236 }
237 
SAI_TxInit(I2S_Type * base,const sai_config_t * config)238 void SAI_TxInit(I2S_Type *base, const sai_config_t *config)
239 {
240     uint32_t val = 0;
241 
242 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
243     /* Enable the SAI clock */
244     CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]);
245 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
246 
247 #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
248     /* Master clock source setting */
249     val = (base->MCR & ~I2S_MCR_MICS_MASK);
250     base->MCR = (val | I2S_MCR_MICS(config->mclkSource));
251 
252     /* Configure Master clock output enable */
253     val = (base->MCR & ~I2S_MCR_MOE_MASK);
254     base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable));
255 #endif /* FSL_FEATURE_SAI_HAS_MCR */
256 
257     /* Configure audio protocol */
258     switch (config->protocol)
259     {
260         case kSAI_BusLeftJustified:
261             base->TCR2 |= I2S_TCR2_BCP_MASK;
262             base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
263             base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
264             break;
265 
266         case kSAI_BusRightJustified:
267             base->TCR2 |= I2S_TCR2_BCP_MASK;
268             base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
269             base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
270             break;
271 
272         case kSAI_BusI2S:
273             base->TCR2 |= I2S_TCR2_BCP_MASK;
274             base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
275             base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(31U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(1U) | I2S_TCR4_FRSZ(1U);
276             break;
277 
278         case kSAI_BusPCMA:
279             base->TCR2 &= ~I2S_TCR2_BCP_MASK;
280             base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
281             base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(1U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
282             break;
283 
284         case kSAI_BusPCMB:
285             base->TCR2 &= ~I2S_TCR2_BCP_MASK;
286             base->TCR3 &= ~I2S_TCR3_WDFL_MASK;
287             base->TCR4 = I2S_TCR4_MF(1U) | I2S_TCR4_SYWD(0U) | I2S_TCR4_FSE(0U) | I2S_TCR4_FSP(0U) | I2S_TCR4_FRSZ(1U);
288             break;
289 
290         default:
291             break;
292     }
293 
294     /* Set master or slave */
295     if (config->masterSlave == kSAI_Master)
296     {
297         base->TCR2 |= I2S_TCR2_BCD_MASK;
298         base->TCR4 |= I2S_TCR4_FSD_MASK;
299 
300         /* Bit clock source setting */
301         val = base->TCR2 & (~I2S_TCR2_MSEL_MASK);
302         base->TCR2 = (val | I2S_TCR2_MSEL(config->bclkSource));
303     }
304     else
305     {
306         base->TCR2 &= ~I2S_TCR2_BCD_MASK;
307         base->TCR4 &= ~I2S_TCR4_FSD_MASK;
308     }
309 
310     /* Set Sync mode */
311     switch (config->syncMode)
312     {
313         case kSAI_ModeAsync:
314             val = base->TCR2;
315             val &= ~I2S_TCR2_SYNC_MASK;
316             base->TCR2 = (val | I2S_TCR2_SYNC(0U));
317             break;
318         case kSAI_ModeSync:
319             val = base->TCR2;
320             val &= ~I2S_TCR2_SYNC_MASK;
321             base->TCR2 = (val | I2S_TCR2_SYNC(1U));
322             /* If sync with Rx, should set Rx to async mode */
323             val = base->RCR2;
324             val &= ~I2S_RCR2_SYNC_MASK;
325             base->RCR2 = (val | I2S_RCR2_SYNC(0U));
326             break;
327         case kSAI_ModeSyncWithOtherTx:
328             val = base->TCR2;
329             val &= ~I2S_TCR2_SYNC_MASK;
330             base->TCR2 = (val | I2S_TCR2_SYNC(2U));
331             break;
332         case kSAI_ModeSyncWithOtherRx:
333             val = base->TCR2;
334             val &= ~I2S_TCR2_SYNC_MASK;
335             base->TCR2 = (val | I2S_TCR2_SYNC(3U));
336             break;
337         default:
338             break;
339     }
340 }
341 
SAI_RxInit(I2S_Type * base,const sai_config_t * config)342 void SAI_RxInit(I2S_Type *base, const sai_config_t *config)
343 {
344     uint32_t val = 0;
345 
346 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
347     /* Enable SAI clock first. */
348     CLOCK_EnableClock(s_saiClock[SAI_GetInstance(base)]);
349 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
350 
351 #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
352     /* Master clock source setting */
353     val = (base->MCR & ~I2S_MCR_MICS_MASK);
354     base->MCR = (val | I2S_MCR_MICS(config->mclkSource));
355 
356     /* Configure Master clock output enable */
357     val = (base->MCR & ~I2S_MCR_MOE_MASK);
358     base->MCR = (val | I2S_MCR_MOE(config->mclkOutputEnable));
359 #endif /* FSL_FEATURE_SAI_HAS_MCR */
360 
361     /* Configure audio protocol */
362     switch (config->protocol)
363     {
364         case kSAI_BusLeftJustified:
365             base->RCR2 |= I2S_RCR2_BCP_MASK;
366             base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
367             base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
368             break;
369 
370         case kSAI_BusRightJustified:
371             base->RCR2 |= I2S_RCR2_BCP_MASK;
372             base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
373             base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
374             break;
375 
376         case kSAI_BusI2S:
377             base->RCR2 |= I2S_RCR2_BCP_MASK;
378             base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
379             base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(31U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(1U) | I2S_RCR4_FRSZ(1U);
380             break;
381 
382         case kSAI_BusPCMA:
383             base->RCR2 &= ~I2S_RCR2_BCP_MASK;
384             base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
385             base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(1U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
386             break;
387 
388         case kSAI_BusPCMB:
389             base->RCR2 &= ~I2S_RCR2_BCP_MASK;
390             base->RCR3 &= ~I2S_RCR3_WDFL_MASK;
391             base->RCR4 = I2S_RCR4_MF(1U) | I2S_RCR4_SYWD(0U) | I2S_RCR4_FSE(0U) | I2S_RCR4_FSP(0U) | I2S_RCR4_FRSZ(1U);
392             break;
393 
394         default:
395             break;
396     }
397 
398     /* Set master or slave */
399     if (config->masterSlave == kSAI_Master)
400     {
401         base->RCR2 |= I2S_RCR2_BCD_MASK;
402         base->RCR4 |= I2S_RCR4_FSD_MASK;
403 
404         /* Bit clock source setting */
405         val = base->RCR2 & (~I2S_RCR2_MSEL_MASK);
406         base->RCR2 = (val | I2S_RCR2_MSEL(config->bclkSource));
407     }
408     else
409     {
410         base->RCR2 &= ~I2S_RCR2_BCD_MASK;
411         base->RCR4 &= ~I2S_RCR4_FSD_MASK;
412     }
413 
414     /* Set Sync mode */
415     switch (config->syncMode)
416     {
417         case kSAI_ModeAsync:
418             val = base->RCR2;
419             val &= ~I2S_RCR2_SYNC_MASK;
420             base->RCR2 = (val | I2S_RCR2_SYNC(0U));
421             break;
422         case kSAI_ModeSync:
423             val = base->RCR2;
424             val &= ~I2S_RCR2_SYNC_MASK;
425             base->RCR2 = (val | I2S_RCR2_SYNC(1U));
426             /* If sync with Tx, should set Tx to async mode */
427             val = base->TCR2;
428             val &= ~I2S_TCR2_SYNC_MASK;
429             base->TCR2 = (val | I2S_TCR2_SYNC(0U));
430             break;
431         case kSAI_ModeSyncWithOtherTx:
432             val = base->RCR2;
433             val &= ~I2S_RCR2_SYNC_MASK;
434             base->RCR2 = (val | I2S_RCR2_SYNC(2U));
435             break;
436         case kSAI_ModeSyncWithOtherRx:
437             val = base->RCR2;
438             val &= ~I2S_RCR2_SYNC_MASK;
439             base->RCR2 = (val | I2S_RCR2_SYNC(3U));
440             break;
441         default:
442             break;
443     }
444 }
445 
SAI_Deinit(I2S_Type * base)446 void SAI_Deinit(I2S_Type *base)
447 {
448     SAI_TxEnable(base, false);
449     SAI_RxEnable(base, false);
450 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
451     CLOCK_DisableClock(s_saiClock[SAI_GetInstance(base)]);
452 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
453 }
454 
SAI_TxGetDefaultConfig(sai_config_t * config)455 void SAI_TxGetDefaultConfig(sai_config_t *config)
456 {
457     config->bclkSource = kSAI_BclkSourceMclkDiv;
458     config->masterSlave = kSAI_Master;
459     config->mclkSource = kSAI_MclkSourceSysclk;
460     config->protocol = kSAI_BusLeftJustified;
461     config->syncMode = kSAI_ModeAsync;
462 #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
463     config->mclkOutputEnable = true;
464 #endif /* FSL_FEATURE_SAI_HAS_MCR */
465 }
466 
SAI_RxGetDefaultConfig(sai_config_t * config)467 void SAI_RxGetDefaultConfig(sai_config_t *config)
468 {
469     config->bclkSource = kSAI_BclkSourceMclkDiv;
470     config->masterSlave = kSAI_Master;
471     config->mclkSource = kSAI_MclkSourceSysclk;
472     config->protocol = kSAI_BusLeftJustified;
473     config->syncMode = kSAI_ModeSync;
474 #if defined(FSL_FEATURE_SAI_HAS_MCR) && (FSL_FEATURE_SAI_HAS_MCR)
475     config->mclkOutputEnable = true;
476 #endif /* FSL_FEATURE_SAI_HAS_MCR */
477 }
478 
SAI_TxReset(I2S_Type * base)479 void SAI_TxReset(I2S_Type *base)
480 {
481     /* Set the software reset and FIFO reset to clear internal state */
482     base->TCSR = I2S_TCSR_SR_MASK | I2S_TCSR_FR_MASK;
483 
484     /* Clear software reset bit, this should be done by software */
485     base->TCSR &= ~I2S_TCSR_SR_MASK;
486 
487     /* Reset all Tx register values */
488     base->TCR2 = 0;
489     base->TCR3 = 0;
490     base->TCR4 = 0;
491     base->TCR5 = 0;
492     base->TMR = 0;
493 }
494 
SAI_RxReset(I2S_Type * base)495 void SAI_RxReset(I2S_Type *base)
496 {
497     /* Set the software reset and FIFO reset to clear internal state */
498     base->RCSR = I2S_RCSR_SR_MASK | I2S_RCSR_FR_MASK;
499 
500     /* Clear software reset bit, this should be done by software */
501     base->RCSR &= ~I2S_RCSR_SR_MASK;
502 
503     /* Reset all Rx register values */
504     base->RCR2 = 0;
505     base->RCR3 = 0;
506     base->RCR4 = 0;
507     base->RCR5 = 0;
508     base->RMR = 0;
509 }
510 
SAI_TxEnable(I2S_Type * base,bool enable)511 void SAI_TxEnable(I2S_Type *base, bool enable)
512 {
513     if (enable)
514     {
515         /* If clock is sync with Rx, should enable RE bit. */
516         if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) == 0x1U)
517         {
518             base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
519         }
520         base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
521     }
522     else
523     {
524         /* Should not close RE even sync with Rx */
525         base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~I2S_TCSR_TE_MASK));
526     }
527 }
528 
SAI_RxEnable(I2S_Type * base,bool enable)529 void SAI_RxEnable(I2S_Type *base, bool enable)
530 {
531     if (enable)
532     {
533         /* If clock is sync with Tx, should enable TE bit. */
534         if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) == 0x1U)
535         {
536             base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
537         }
538         base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
539     }
540     else
541     {
542         base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~I2S_RCSR_RE_MASK));
543     }
544 }
545 
SAI_TxSetFormat(I2S_Type * base,sai_transfer_format_t * format,uint32_t mclkSourceClockHz,uint32_t bclkSourceClockHz)546 void SAI_TxSetFormat(I2S_Type *base,
547                      sai_transfer_format_t *format,
548                      uint32_t mclkSourceClockHz,
549                      uint32_t bclkSourceClockHz)
550 {
551     uint32_t bclk = format->sampleRate_Hz * 32U * 2U;
552 
553 /* Compute the mclk */
554 #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
555     /* Check if master clock divider enabled, then set master clock divider */
556     if (base->MCR & I2S_MCR_MOE_MASK)
557     {
558         SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz);
559     }
560 #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
561 
562     /* Set bclk if needed */
563     if (base->TCR2 & I2S_TCR2_BCD_MASK)
564     {
565         base->TCR2 &= ~I2S_TCR2_DIV_MASK;
566         base->TCR2 |= I2S_TCR2_DIV((bclkSourceClockHz / bclk) / 2U - 1U);
567     }
568 
569     /* Set bitWidth */
570     if (format->protocol == kSAI_BusRightJustified)
571     {
572         base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(31U);
573     }
574     else
575     {
576         base->TCR5 = I2S_TCR5_WNW(31U) | I2S_TCR5_W0W(31U) | I2S_TCR5_FBT(format->bitWidth - 1);
577     }
578 
579     /* Set mono or stereo */
580     base->TMR = (uint32_t)format->stereo;
581 
582     /* Set data channel */
583     base->TCR3 &= ~I2S_TCR3_TCE_MASK;
584     base->TCR3 |= I2S_TCR3_TCE(1U << format->channel);
585 
586 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
587     /* Set watermark */
588     base->TCR1 = format->watermark;
589 #endif /* FSL_FEATURE_SAI_FIFO_COUNT  */
590 }
591 
SAI_RxSetFormat(I2S_Type * base,sai_transfer_format_t * format,uint32_t mclkSourceClockHz,uint32_t bclkSourceClockHz)592 void SAI_RxSetFormat(I2S_Type *base,
593                      sai_transfer_format_t *format,
594                      uint32_t mclkSourceClockHz,
595                      uint32_t bclkSourceClockHz)
596 {
597     uint32_t bclk = format->sampleRate_Hz * 32U * 2U;
598 
599 /* Compute the mclk */
600 #if defined(FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER) && (FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER)
601     /* Check if master clock divider enabled */
602     if (base->MCR & I2S_MCR_MOE_MASK)
603     {
604         SAI_SetMasterClockDivider(base, format->masterClockHz, mclkSourceClockHz);
605     }
606 #endif /* FSL_FEATURE_SAI_HAS_MCLKDIV_REGISTER */
607 
608     /* Set bclk if needed */
609     if (base->RCR2 & I2S_RCR2_BCD_MASK)
610     {
611         base->RCR2 &= ~I2S_RCR2_DIV_MASK;
612         base->RCR2 |= I2S_RCR2_DIV((bclkSourceClockHz / bclk) / 2U - 1U);
613     }
614 
615     /* Set bitWidth */
616     if (format->protocol == kSAI_BusRightJustified)
617     {
618         base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(31U);
619     }
620     else
621     {
622         base->RCR5 = I2S_RCR5_WNW(31U) | I2S_RCR5_W0W(31U) | I2S_RCR5_FBT(format->bitWidth - 1);
623     }
624 
625     /* Set mono or stereo */
626     base->RMR = (uint32_t)format->stereo;
627 
628     /* Set data channel */
629     base->RCR3 &= ~I2S_RCR3_RCE_MASK;
630     base->RCR3 |= I2S_RCR3_RCE(1U << format->channel);
631 
632 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
633     /* Set watermark */
634     base->RCR1 = format->watermark;
635 #endif /* FSL_FEATURE_SAI_FIFO_COUNT  */
636 }
637 
SAI_WriteBlocking(I2S_Type * base,uint32_t channel,uint32_t bitWidth,uint8_t * buffer,uint32_t size)638 void SAI_WriteBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
639 {
640     uint32_t i = 0;
641     uint8_t bytesPerWord = bitWidth / 8U;
642 
643     while (i < size)
644     {
645         /* Wait until it can write data */
646         while (!(base->TCSR & I2S_TCSR_FWF_MASK))
647         {
648         }
649 
650         SAI_WriteNonBlocking(base, channel, bitWidth, buffer, bytesPerWord);
651         buffer += bytesPerWord;
652         i += bytesPerWord;
653     }
654 
655     /* Wait until the last data is sent */
656     while (!(base->TCSR & I2S_TCSR_FWF_MASK))
657     {
658     }
659 }
660 
SAI_ReadBlocking(I2S_Type * base,uint32_t channel,uint32_t bitWidth,uint8_t * buffer,uint32_t size)661 void SAI_ReadBlocking(I2S_Type *base, uint32_t channel, uint32_t bitWidth, uint8_t *buffer, uint32_t size)
662 {
663     uint32_t i = 0;
664     uint8_t bytesPerWord = bitWidth / 8U;
665 
666     while (i < size)
667     {
668         /* Wait until data is received */
669         while (!(base->RCSR & I2S_RCSR_FWF_MASK))
670         {
671         }
672 
673         SAI_ReadNonBlocking(base, channel, bitWidth, buffer, bytesPerWord);
674         buffer += bytesPerWord;
675         i += bytesPerWord;
676     }
677 }
678 
SAI_TransferTxCreateHandle(I2S_Type * base,sai_handle_t * handle,sai_transfer_callback_t callback,void * userData)679 void SAI_TransferTxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData)
680 {
681     assert(handle);
682 
683     /* Zero the handle */
684     memset(handle, 0, sizeof(*handle));
685 
686     s_saiHandle[SAI_GetInstance(base)][0] = handle;
687 
688     handle->callback = callback;
689     handle->userData = userData;
690 
691     /* Set the isr pointer */
692     s_saiTxIsr = SAI_TransferTxHandleIRQ;
693 
694     /* Enable Tx irq */
695     EnableIRQ(s_saiTxIRQ[SAI_GetInstance(base)]);
696 }
697 
SAI_TransferRxCreateHandle(I2S_Type * base,sai_handle_t * handle,sai_transfer_callback_t callback,void * userData)698 void SAI_TransferRxCreateHandle(I2S_Type *base, sai_handle_t *handle, sai_transfer_callback_t callback, void *userData)
699 {
700     assert(handle);
701 
702     /* Zero the handle */
703     memset(handle, 0, sizeof(*handle));
704 
705     s_saiHandle[SAI_GetInstance(base)][1] = handle;
706 
707     handle->callback = callback;
708     handle->userData = userData;
709 
710     /* Set the isr pointer */
711     s_saiRxIsr = SAI_TransferRxHandleIRQ;
712 
713     /* Enable Rx irq */
714     EnableIRQ(s_saiRxIRQ[SAI_GetInstance(base)]);
715 }
716 
SAI_TransferTxSetFormat(I2S_Type * base,sai_handle_t * handle,sai_transfer_format_t * format,uint32_t mclkSourceClockHz,uint32_t bclkSourceClockHz)717 status_t SAI_TransferTxSetFormat(I2S_Type *base,
718                                  sai_handle_t *handle,
719                                  sai_transfer_format_t *format,
720                                  uint32_t mclkSourceClockHz,
721                                  uint32_t bclkSourceClockHz)
722 {
723     assert(handle);
724 
725     if ((mclkSourceClockHz < format->sampleRate_Hz) || (bclkSourceClockHz < format->sampleRate_Hz))
726     {
727         return kStatus_InvalidArgument;
728     }
729 
730     /* Copy format to handle */
731     handle->bitWidth = format->bitWidth;
732 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
733     handle->watermark = format->watermark;
734 #endif
735     handle->channel = format->channel;
736 
737     SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
738 
739     return kStatus_Success;
740 }
741 
SAI_TransferRxSetFormat(I2S_Type * base,sai_handle_t * handle,sai_transfer_format_t * format,uint32_t mclkSourceClockHz,uint32_t bclkSourceClockHz)742 status_t SAI_TransferRxSetFormat(I2S_Type *base,
743                                  sai_handle_t *handle,
744                                  sai_transfer_format_t *format,
745                                  uint32_t mclkSourceClockHz,
746                                  uint32_t bclkSourceClockHz)
747 {
748     assert(handle);
749 
750     if ((mclkSourceClockHz < format->sampleRate_Hz) || (bclkSourceClockHz < format->sampleRate_Hz))
751     {
752         return kStatus_InvalidArgument;
753     }
754 
755     /* Copy format to handle */
756     handle->bitWidth = format->bitWidth;
757 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
758     handle->watermark = format->watermark;
759 #endif
760     handle->channel = format->channel;
761 
762     SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz);
763 
764     return kStatus_Success;
765 }
766 
SAI_TransferSendNonBlocking(I2S_Type * base,sai_handle_t * handle,sai_transfer_t * xfer)767 status_t SAI_TransferSendNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer)
768 {
769     assert(handle);
770 
771     /* Check if the queue is full */
772     if (handle->saiQueue[handle->queueUser].data)
773     {
774         return kStatus_SAI_QueueFull;
775     }
776 
777     /* Add into queue */
778     handle->transferSize[handle->queueUser] = xfer->dataSize;
779     handle->saiQueue[handle->queueUser].data = xfer->data;
780     handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
781     handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
782 
783     /* Set the state to busy */
784     handle->state = kSAI_Busy;
785 
786 /* Enable interrupt */
787 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
788     /* Use FIFO request interrupt and fifo error*/
789     SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
790 #else
791     SAI_TxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
792 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
793 
794     /* Enable Tx transfer */
795     SAI_TxEnable(base, true);
796 
797     return kStatus_Success;
798 }
799 
SAI_TransferReceiveNonBlocking(I2S_Type * base,sai_handle_t * handle,sai_transfer_t * xfer)800 status_t SAI_TransferReceiveNonBlocking(I2S_Type *base, sai_handle_t *handle, sai_transfer_t *xfer)
801 {
802     assert(handle);
803 
804     /* Check if the queue is full */
805     if (handle->saiQueue[handle->queueUser].data)
806     {
807         return kStatus_SAI_QueueFull;
808     }
809 
810     /* Add into queue */
811     handle->transferSize[handle->queueUser] = xfer->dataSize;
812     handle->saiQueue[handle->queueUser].data = xfer->data;
813     handle->saiQueue[handle->queueUser].dataSize = xfer->dataSize;
814     handle->queueUser = (handle->queueUser + 1) % SAI_XFER_QUEUE_SIZE;
815 
816     /* Set state to busy */
817     handle->state = kSAI_Busy;
818 
819 /* Enable interrupt */
820 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
821     /* Use FIFO request interrupt and fifo error*/
822     SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
823 #else
824     SAI_RxEnableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
825 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
826 
827     /* Enable Rx transfer */
828     SAI_RxEnable(base, true);
829 
830     return kStatus_Success;
831 }
832 
SAI_TransferGetSendCount(I2S_Type * base,sai_handle_t * handle,size_t * count)833 status_t SAI_TransferGetSendCount(I2S_Type *base, sai_handle_t *handle, size_t *count)
834 {
835     assert(handle);
836 
837     status_t status = kStatus_Success;
838 
839     if (handle->state != kSAI_Busy)
840     {
841         status = kStatus_NoTransferInProgress;
842     }
843     else
844     {
845         *count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize);
846     }
847 
848     return status;
849 }
850 
SAI_TransferGetReceiveCount(I2S_Type * base,sai_handle_t * handle,size_t * count)851 status_t SAI_TransferGetReceiveCount(I2S_Type *base, sai_handle_t *handle, size_t *count)
852 {
853     assert(handle);
854 
855     status_t status = kStatus_Success;
856 
857     if (handle->state != kSAI_Busy)
858     {
859         status = kStatus_NoTransferInProgress;
860     }
861     else
862     {
863         *count = (handle->transferSize[handle->queueDriver] - handle->saiQueue[handle->queueDriver].dataSize);
864     }
865 
866     return status;
867 }
868 
SAI_TransferAbortSend(I2S_Type * base,sai_handle_t * handle)869 void SAI_TransferAbortSend(I2S_Type *base, sai_handle_t *handle)
870 {
871     assert(handle);
872 
873     /* Stop Tx transfer and disable interrupt */
874     SAI_TxEnable(base, false);
875 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
876     /* Use FIFO request interrupt and fifo error */
877     SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
878 #else
879     SAI_TxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
880 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
881 
882     handle->state = kSAI_Idle;
883 
884     /* Clear the queue */
885     memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
886     handle->queueDriver = 0;
887     handle->queueUser = 0;
888 }
889 
SAI_TransferAbortReceive(I2S_Type * base,sai_handle_t * handle)890 void SAI_TransferAbortReceive(I2S_Type *base, sai_handle_t *handle)
891 {
892     assert(handle);
893 
894     /* Stop Tx transfer and disable interrupt */
895     SAI_RxEnable(base, false);
896 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
897     /* Use FIFO request interrupt and fifo error */
898     SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFORequestInterruptEnable);
899 #else
900     SAI_RxDisableInterrupts(base, kSAI_FIFOErrorInterruptEnable | kSAI_FIFOWarningInterruptEnable);
901 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
902 
903     handle->state = kSAI_Idle;
904 
905     /* Clear the queue */
906     memset(handle->saiQueue, 0, sizeof(sai_transfer_t) * SAI_XFER_QUEUE_SIZE);
907     handle->queueDriver = 0;
908     handle->queueUser = 0;
909 }
910 
SAI_TransferTxHandleIRQ(I2S_Type * base,sai_handle_t * handle)911 void SAI_TransferTxHandleIRQ(I2S_Type *base, sai_handle_t *handle)
912 {
913     assert(handle);
914 
915     uint8_t *buffer = handle->saiQueue[handle->queueDriver].data;
916     uint8_t dataSize = handle->bitWidth / 8U;
917 
918     /* Handle Error */
919     if (base->TCSR & I2S_TCSR_FEF_MASK)
920     {
921         /* Clear FIFO error flag to continue transfer */
922         SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag);
923 
924         /* Call the callback */
925         if (handle->callback)
926         {
927             (handle->callback)(base, handle, kStatus_SAI_TxError, handle->userData);
928         }
929     }
930 
931 /* Handle transfer */
932 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
933     if (base->TCSR & I2S_TCSR_FRF_MASK)
934     {
935         /* Judge if the data need to transmit is less than space */
936         uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize),
937                            (size_t)((FSL_FEATURE_SAI_FIFO_COUNT - handle->watermark) * dataSize));
938 
939         /* Copy the data from sai buffer to FIFO */
940         SAI_WriteNonBlocking(base, handle->channel, handle->bitWidth, buffer, size);
941 
942         /* Update the internal counter */
943         handle->saiQueue[handle->queueDriver].dataSize -= size;
944         handle->saiQueue[handle->queueDriver].data += size;
945     }
946 #else
947     if (base->TCSR & I2S_TCSR_FWF_MASK)
948     {
949         uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize);
950 
951         SAI_WriteNonBlocking(base, handle->channel, handle->bitWidth, buffer, size);
952 
953         /* Update internal counter */
954         handle->saiQueue[handle->queueDriver].dataSize -= size;
955         handle->saiQueue[handle->queueDriver].data += size;
956     }
957 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
958 
959     /* If finished a blcok, call the callback function */
960     if (handle->saiQueue[handle->queueDriver].dataSize == 0U)
961     {
962         memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
963         handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
964         if (handle->callback)
965         {
966             (handle->callback)(base, handle, kStatus_SAI_TxIdle, handle->userData);
967         }
968     }
969 
970     /* If all data finished, just stop the transfer */
971     if (handle->saiQueue[handle->queueDriver].data == NULL)
972     {
973         SAI_TransferAbortSend(base, handle);
974     }
975 }
976 
SAI_TransferRxHandleIRQ(I2S_Type * base,sai_handle_t * handle)977 void SAI_TransferRxHandleIRQ(I2S_Type *base, sai_handle_t *handle)
978 {
979     assert(handle);
980 
981     uint8_t *buffer = handle->saiQueue[handle->queueDriver].data;
982     uint8_t dataSize = handle->bitWidth / 8U;
983 
984     /* Handle Error */
985     if (base->RCSR & I2S_RCSR_FEF_MASK)
986     {
987         /* Clear FIFO error flag to continue transfer */
988         SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag);
989 
990         /* Call the callback */
991         if (handle->callback)
992         {
993             (handle->callback)(base, handle, kStatus_SAI_RxError, handle->userData);
994         }
995     }
996 
997 /* Handle transfer */
998 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
999     if (base->RCSR & I2S_RCSR_FRF_MASK)
1000     {
1001         /* Judge if the data need to transmit is less than space */
1002         uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), (handle->watermark * dataSize));
1003 
1004         /* Copy the data from sai buffer to FIFO */
1005         SAI_ReadNonBlocking(base, handle->channel, handle->bitWidth, buffer, size);
1006 
1007         /* Update the internal counter */
1008         handle->saiQueue[handle->queueDriver].dataSize -= size;
1009         handle->saiQueue[handle->queueDriver].data += size;
1010     }
1011 #else
1012     if (base->RCSR & I2S_RCSR_FWF_MASK)
1013     {
1014         uint8_t size = MIN((handle->saiQueue[handle->queueDriver].dataSize), dataSize);
1015 
1016         SAI_ReadNonBlocking(base, handle->channel, handle->bitWidth, buffer, size);
1017 
1018         /* Update internal state */
1019         handle->saiQueue[handle->queueDriver].dataSize -= size;
1020         handle->saiQueue[handle->queueDriver].data += size;
1021     }
1022 #endif /* FSL_FEATURE_SAI_FIFO_COUNT */
1023 
1024     /* If finished a blcok, call the callback function */
1025     if (handle->saiQueue[handle->queueDriver].dataSize == 0U)
1026     {
1027         memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t));
1028         handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE;
1029         if (handle->callback)
1030         {
1031             (handle->callback)(base, handle, kStatus_SAI_RxIdle, handle->userData);
1032         }
1033     }
1034 
1035     /* If all data finished, just stop the transfer */
1036     if (handle->saiQueue[handle->queueDriver].data == NULL)
1037     {
1038         SAI_TransferAbortReceive(base, handle);
1039     }
1040 }
1041 
1042 #if defined(I2S0)
I2S0_DriverIRQHandler(void)1043 void I2S0_DriverIRQHandler(void)
1044 {
1045 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1046     if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFORequestFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) &&
1047                                ((I2S0->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable)))
1048 #else
1049     if ((s_saiHandle[0][1]) && ((I2S0->RCSR & kSAI_FIFOWarningFlag) || (I2S0->RCSR & kSAI_FIFOErrorFlag)) &&
1050                                ((I2S0->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->RCSR & kSAI_FIFOErrorInterruptEnable)))
1051 #endif
1052     {
1053         s_saiRxIsr(I2S0, s_saiHandle[0][1]);
1054     }
1055 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1056     if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFORequestFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) &&
1057                                ((I2S0->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable)))
1058 #else
1059     if ((s_saiHandle[0][0]) && ((I2S0->TCSR & kSAI_FIFOWarningFlag) || (I2S0->TCSR & kSAI_FIFOErrorFlag)) &&
1060                                ((I2S0->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S0->TCSR & kSAI_FIFOErrorInterruptEnable)))
1061 #endif
1062     {
1063         s_saiTxIsr(I2S0, s_saiHandle[0][0]);
1064     }
1065 }
1066 
I2S0_Tx_DriverIRQHandler(void)1067 void I2S0_Tx_DriverIRQHandler(void)
1068 {
1069     assert(s_saiHandle[0][0]);
1070     s_saiTxIsr(I2S0, s_saiHandle[0][0]);
1071 }
1072 
I2S0_Rx_DriverIRQHandler(void)1073 void I2S0_Rx_DriverIRQHandler(void)
1074 {
1075     assert(s_saiHandle[0][1]);
1076     s_saiRxIsr(I2S0, s_saiHandle[0][1]);
1077 }
1078 #endif /* I2S0*/
1079 
1080 #if defined(I2S1)
I2S1_DriverIRQHandler(void)1081 void I2S1_DriverIRQHandler(void)
1082 {
1083 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1084     if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFORequestFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) &&
1085                                ((I2S1->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable)))
1086 #else
1087     if ((s_saiHandle[1][1]) && ((I2S1->RCSR & kSAI_FIFOWarningFlag) || (I2S1->RCSR & kSAI_FIFOErrorFlag)) &&
1088                                ((I2S1->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->RCSR & kSAI_FIFOErrorInterruptEnable)))
1089 #endif
1090     {
1091         s_saiRxIsr(I2S1, s_saiHandle[1][1]);
1092     }
1093 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1094     if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFORequestFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) &&
1095                                ((I2S1->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable)))
1096 #else
1097     if ((s_saiHandle[1][0]) && ((I2S1->TCSR & kSAI_FIFOWarningFlag) || (I2S1->TCSR & kSAI_FIFOErrorFlag)) &&
1098                                ((I2S1->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S1->TCSR & kSAI_FIFOErrorInterruptEnable)))
1099 #endif
1100     {
1101         s_saiTxIsr(I2S1, s_saiHandle[1][0]);
1102     }
1103 }
1104 
I2S1_Tx_DriverIRQHandler(void)1105 void I2S1_Tx_DriverIRQHandler(void)
1106 {
1107     assert(s_saiHandle[1][0]);
1108     s_saiTxIsr(I2S1, s_saiHandle[1][0]);
1109 }
1110 
I2S1_Rx_DriverIRQHandler(void)1111 void I2S1_Rx_DriverIRQHandler(void)
1112 {
1113     assert(s_saiHandle[1][1]);
1114     s_saiRxIsr(I2S1, s_saiHandle[1][1]);
1115 }
1116 #endif /* I2S1*/
1117 
1118 #if defined(I2S2)
I2S2_DriverIRQHandler(void)1119 void I2S2_DriverIRQHandler(void)
1120 {
1121 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1122     if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFORequestFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) &&
1123                                ((I2S2->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable)))
1124 #else
1125     if ((s_saiHandle[2][1]) && ((I2S2->RCSR & kSAI_FIFOWarningFlag) || (I2S2->RCSR & kSAI_FIFOErrorFlag)) &&
1126                                ((I2S2->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->RCSR & kSAI_FIFOErrorInterruptEnable)))
1127 #endif
1128     {
1129         s_saiRxIsr(I2S2, s_saiHandle[2][1]);
1130     }
1131 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1132     if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFORequestFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) &&
1133                                ((I2S2->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable)))
1134 #else
1135     if ((s_saiHandle[2][0]) && ((I2S2->TCSR & kSAI_FIFOWarningFlag) || (I2S2->TCSR & kSAI_FIFOErrorFlag)) &&
1136                                ((I2S2->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S2->TCSR & kSAI_FIFOErrorInterruptEnable)))
1137 #endif
1138     {
1139         s_saiTxIsr(I2S2, s_saiHandle[2][0]);
1140     }
1141 }
1142 
I2S2_Tx_DriverIRQHandler(void)1143 void I2S2_Tx_DriverIRQHandler(void)
1144 {
1145     assert(s_saiHandle[2][0]);
1146     s_saiTxIsr(I2S2, s_saiHandle[2][0]);
1147 }
1148 
I2S2_Rx_DriverIRQHandler(void)1149 void I2S2_Rx_DriverIRQHandler(void)
1150 {
1151     assert(s_saiHandle[2][1]);
1152     s_saiRxIsr(I2S2, s_saiHandle[2][1]);
1153 }
1154 #endif /* I2S2*/
1155 
1156 #if defined(I2S3)
I2S3_DriverIRQHandler(void)1157 void I2S3_DriverIRQHandler(void)
1158 {
1159 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1160     if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFORequestFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) &&
1161                                ((I2S3->RCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable)))
1162 #else
1163     if ((s_saiHandle[3][1]) && ((I2S3->RCSR & kSAI_FIFOWarningFlag) || (I2S3->RCSR & kSAI_FIFOErrorFlag)) &&
1164                                ((I2S3->RCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->RCSR & kSAI_FIFOErrorInterruptEnable)))
1165 #endif
1166     {
1167         s_saiRxIsr(I2S3, s_saiHandle[3][1]);
1168     }
1169 #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1)
1170     if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFORequestFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) &&
1171                                ((I2S3->TCSR & kSAI_FIFORequestInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable)))
1172 #else
1173     if ((s_saiHandle[3][0]) && ((I2S3->TCSR & kSAI_FIFOWarningFlag) || (I2S3->TCSR & kSAI_FIFOErrorFlag)) &&
1174                                ((I2S3->TCSR & kSAI_FIFOWarningInterruptEnable) || (I2S3->TCSR & kSAI_FIFOErrorInterruptEnable)))
1175 #endif
1176     {
1177         s_saiTxIsr(I2S3, s_saiHandle[3][0]);
1178     }
1179 }
1180 
I2S3_Tx_DriverIRQHandler(void)1181 void I2S3_Tx_DriverIRQHandler(void)
1182 {
1183     assert(s_saiHandle[3][0]);
1184     s_saiTxIsr(I2S3, s_saiHandle[3][0]);
1185 }
1186 
I2S3_Rx_DriverIRQHandler(void)1187 void I2S3_Rx_DriverIRQHandler(void)
1188 {
1189     assert(s_saiHandle[3][1]);
1190     s_saiRxIsr(I2S3, s_saiHandle[3][1]);
1191 }
1192 #endif /* I2S3*/
1193