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