1 /*
2  * Copyright 2017-2020 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_spdif.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.spdif"
14 #endif
15 
16 /*******************************************************************************
17  * Definitations
18  ******************************************************************************/
19 /*! @brief spdif transfer state. */
20 enum
21 {
22     kSPDIF_Busy = 0x0U, /*!< SPDIF is busy */
23     kSPDIF_Idle,        /*!< Transfer is done. */
24     kSPDIF_Error        /*!< Transfer error occurred. */
25 };
26 
27 /*! @brief Typedef for spdif tx interrupt handler. */
28 typedef void (*spdif_isr_t)(SPDIF_Type *base, spdif_handle_t *handle);
29 /*******************************************************************************
30  * Prototypes
31  ******************************************************************************/
32 
33 /*******************************************************************************
34  * Variables
35  ******************************************************************************/
36 /* Base pointer array */
37 static SPDIF_Type *const s_spdifBases[] = SPDIF_BASE_PTRS;
38 /*! @brief SPDIF handle pointer */
39 static spdif_handle_t *s_spdifHandle[ARRAY_SIZE(s_spdifBases)][2];
40 /* IRQ number array */
41 static const IRQn_Type s_spdifIRQ[] = SPDIF_IRQS;
42 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
43 /* Clock name array */
44 static const clock_ip_name_t s_spdifClock[] = SPDIF_CLOCKS;
45 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
46 /*! @brief Pointer to IRQ handler for each instance. */
47 static spdif_isr_t s_spdifTxIsr;
48 /*! @brief Pointer to IRQ handler for each instance. */
49 static spdif_isr_t s_spdifRxIsr;
50 /*! @brief Used for spdif gain */
51 static uint8_t s_spdif_gain[8]         = {24U, 16U, 12U, 8U, 6U, 4U, 3U, 1U};
52 static uint8_t s_spdif_tx_watermark[4] = {16, 12, 8, 4};
53 static uint8_t s_spdif_rx_watermark[4] = {1, 4, 8, 16};
54 
55 /*******************************************************************************
56  * Code
57  ******************************************************************************/
SPDIF_GetInstance(SPDIF_Type * base)58 uint32_t SPDIF_GetInstance(SPDIF_Type *base)
59 {
60     uint32_t instance;
61 
62     /* Find the instance index from base address mappings. */
63     for (instance = 0; instance < ARRAY_SIZE(s_spdifBases); instance++)
64     {
65         if (s_spdifBases[instance] == base)
66         {
67             break;
68         }
69     }
70 
71     assert(instance < ARRAY_SIZE(s_spdifBases));
72 
73     return instance;
74 }
75 
76 /*!
77  * brief Initializes the SPDIF peripheral.
78  *
79  * Ungates the SPDIF clock, resets the module, and configures SPDIF with a configuration structure.
80  * The configuration structure can be custom filled or set with default values by
81  * SPDIF_GetDefaultConfig().
82  *
83  * note  This API should be called at the beginning of the application to use
84  * the SPDIF driver. Otherwise, accessing the SPDIF module can cause a hard fault
85  * because the clock is not enabled.
86  *
87  * param base SPDIF base pointer
88  * param config SPDIF configuration structure.
89  */
SPDIF_Init(SPDIF_Type * base,const spdif_config_t * config)90 void SPDIF_Init(SPDIF_Type *base, const spdif_config_t *config)
91 {
92     uint32_t val = 0;
93 
94 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
95     /* Enable the SPDIF clock */
96     CLOCK_EnableClock(s_spdifClock[SPDIF_GetInstance(base)]);
97 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
98 
99     /* Reset the internal logic */
100     base->SCR |= SPDIF_SCR_SOFT_RESET_MASK;
101 
102     /* Waiting for reset finish */
103     while ((base->SCR & SPDIF_SCR_SOFT_RESET_MASK) != 0x00U)
104     {
105     }
106 
107     /* Setting the SPDIF settings */
108     base->SCR = SPDIF_SCR_RXFIFOFULL_SEL(config->rxFullSelect) | SPDIF_SCR_RXAUTOSYNC(config->isRxAutoSync) |
109                 SPDIF_SCR_TXAUTOSYNC(config->isRxAutoSync) | SPDIF_SCR_TXFIFOEMPTY_SEL(config->txFullSelect) |
110                 SPDIF_SCR_TXFIFO_CTRL(1U) | SPDIF_SCR_VALCTRL(config->validityConfig) |
111                 SPDIF_SCR_TXSEL(config->txSource) | SPDIF_SCR_USRC_SEL(config->uChannelSrc);
112 
113     /* Set DPLL clock source */
114     base->SRPC = SPDIF_SRPC_CLKSRC_SEL(config->DPLLClkSource) | SPDIF_SRPC_GAINSEL(config->gain);
115 
116     /* Set SPDIF tx clock source */
117     val = base->STC & ~SPDIF_STC_TXCLK_SOURCE_MASK;
118     val |= SPDIF_STC_TXCLK_SOURCE(config->txClkSource);
119     base->STC = val;
120 
121     /* clear and diable all the interrupt */
122     base->SIC = (uint32_t)kSPDIF_AllInterrupt;
123     base->SIE &= ~(uint32_t)kSPDIF_AllInterrupt;
124 }
125 
126 /*!
127  * brief De-initializes the SPDIF peripheral.
128  *
129  * This API gates the SPDIF clock. The SPDIF module can't operate unless SPDIF_Init is called to enable the clock.
130  *
131  * param base SPDIF base pointer
132  */
SPDIF_Deinit(SPDIF_Type * base)133 void SPDIF_Deinit(SPDIF_Type *base)
134 {
135     SPDIF_TxEnable(base, false);
136     SPDIF_RxEnable(base, false);
137 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
138     CLOCK_DisableClock(s_spdifClock[SPDIF_GetInstance(base)]);
139 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
140 }
141 
142 /*!
143  * brief  Sets the SPDIF configuration structure to default values.
144  *
145  * This API initializes the configuration structure for use in SPDIF_Init.
146  * The initialized structure can remain unchanged in SPDIF_Init, or it can be modified
147  *  before calling SPDIF_Init.
148  * This is an example.
149    code
150    spdif_config_t config;
151    SPDIF_GetDefaultConfig(&config);
152    endcode
153  *
154  * param config pointer to master configuration structure
155  */
SPDIF_GetDefaultConfig(spdif_config_t * config)156 void SPDIF_GetDefaultConfig(spdif_config_t *config)
157 {
158     /* Initializes the configure structure to zero. */
159     (void)memset(config, 0, sizeof(*config));
160 
161     config->isTxAutoSync   = true;
162     config->isRxAutoSync   = true;
163     config->DPLLClkSource  = 1;
164     config->txClkSource    = 1;
165     config->rxFullSelect   = kSPDIF_RxFull8Samples;
166     config->txFullSelect   = kSPDIF_TxEmpty8Samples;
167     config->uChannelSrc    = kSPDIF_UChannelFromTx;
168     config->txSource       = kSPDIF_txNormal;
169     config->validityConfig = kSPDIF_validityFlagAlwaysClear;
170     config->gain           = kSPDIF_GAIN_8;
171 }
172 
173 /*!
174  * brief Enables/disables the SPDIF Tx.
175  *
176  * param base SPDIF base pointer
177  * param enable True means enable SPDIF Tx, false means disable.
178  */
SPDIF_TxEnable(SPDIF_Type * base,bool enable)179 void SPDIF_TxEnable(SPDIF_Type *base, bool enable)
180 {
181     uint32_t val = 0;
182 
183     if (enable)
184     {
185         /* Open Tx FIFO */
186         val = base->SCR & (~SPDIF_SCR_TXFIFO_CTRL_MASK);
187         val |= SPDIF_SCR_TXFIFO_CTRL(1U);
188         base->SCR = val;
189         /* Enable transfer clock */
190         base->STC |= SPDIF_STC_TX_ALL_CLK_EN_MASK;
191     }
192     else
193     {
194         base->SCR &= ~(SPDIF_SCR_TXFIFO_CTRL_MASK | SPDIF_SCR_TXSEL_MASK);
195         /* Disable transfer clock */
196         base->STC &= ~SPDIF_STC_TX_ALL_CLK_EN_MASK;
197     }
198 }
199 
200 /*!
201  * brief Configures the SPDIF Tx sample rate.
202  *
203  * The audio format can be changed at run-time. This function configures the sample rate.
204  *
205  * param base SPDIF base pointer.
206  * param sampleRate_Hz SPDIF sample rate frequency in Hz.
207  * param sourceClockFreq_Hz SPDIF tx clock source frequency in Hz.
208  */
SPDIF_TxSetSampleRate(SPDIF_Type * base,uint32_t sampleRate_Hz,uint32_t sourceClockFreq_Hz)209 void SPDIF_TxSetSampleRate(SPDIF_Type *base, uint32_t sampleRate_Hz, uint32_t sourceClockFreq_Hz)
210 {
211     uint32_t clkDiv     = sourceClockFreq_Hz / (sampleRate_Hz * 64U);
212     uint32_t mod        = sourceClockFreq_Hz % (sampleRate_Hz * 64U);
213     uint32_t val        = 0;
214     uint8_t clockSource = (uint8_t)(((base->STC) & SPDIF_STC_TXCLK_SOURCE_MASK) >> SPDIF_STC_TXCLK_SOURCE_SHIFT);
215 
216     /* Compute the nearest divider */
217     if (mod > ((sampleRate_Hz * 64U) / 2U))
218     {
219         clkDiv += 1U;
220     }
221 
222     /* If use divided systeme clock */
223     if (clockSource == 5U)
224     {
225         if (clkDiv > 256U)
226         {
227             val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
228             val |= SPDIF_STC_SYSCLK_DF((clkDiv / 128U) - 1U) | SPDIF_STC_TXCLK_DF(127U);
229             base->STC = val;
230         }
231         else
232         {
233             val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
234             val |= SPDIF_STC_SYSCLK_DF(1U) | SPDIF_STC_TXCLK_DF(clkDiv - 1U);
235             base->STC = val;
236         }
237     }
238     else
239     {
240         /* Other clock only uses txclk div */
241         val = base->STC & (~(SPDIF_STC_TXCLK_DF_MASK | SPDIF_STC_SYSCLK_DF_MASK));
242         val |= SPDIF_STC_TXCLK_DF(clkDiv - 1U);
243         base->STC = val;
244     }
245 }
246 
247 /*!
248  * brief Configures the SPDIF Rx audio format.
249  *
250  * The audio format can be changed at run-time. This function configures the sample rate and audio data
251  * format to be transferred.
252  *
253  * param base SPDIF base pointer.
254  * param clockSourceFreq_Hz SPDIF system clock frequency in hz.
255  */
SPDIF_GetRxSampleRate(SPDIF_Type * base,uint32_t clockSourceFreq_Hz)256 uint32_t SPDIF_GetRxSampleRate(SPDIF_Type *base, uint32_t clockSourceFreq_Hz)
257 {
258     uint64_t gain       = s_spdif_gain[((base->SRPC & SPDIF_SRPC_GAINSEL_MASK) >> SPDIF_SRPC_GAINSEL_SHIFT)];
259     uint32_t measure    = 0;
260     uint32_t sampleRate = 0;
261     uint64_t temp       = 0;
262 
263     /* Wait the DPLL locked */
264     while ((base->SRPC & SPDIF_SRPC_LOCK_MASK) == 0U)
265     {
266     }
267 
268     /* Get the measure value */
269     measure = base->SRFM;
270     temp    = (uint64_t)measure * (uint64_t)clockSourceFreq_Hz;
271     temp /= 1024U * 1024U * 128U * gain;
272     sampleRate = (uint32_t)temp;
273 
274     return sampleRate;
275 }
276 
277 /*!
278  * brief Sends data using a blocking method.
279  *
280  * note This function blocks by polling until data is ready to be sent.
281  *
282  * param base SPDIF base pointer.
283  * param buffer Pointer to the data to be written.
284  * param size Bytes to be written.
285  */
SPDIF_WriteBlocking(SPDIF_Type * base,uint8_t * buffer,uint32_t size)286 void SPDIF_WriteBlocking(SPDIF_Type *base, uint8_t *buffer, uint32_t size)
287 {
288     assert(buffer != NULL);
289     assert((size % 6U) == 0U);
290 
291     uint32_t i = 0, j = 0, data = 0;
292 
293     while (i < size)
294     {
295         /* Wait until it can write data */
296         while ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_TxFIFOEmpty) == 0x00U)
297         {
298         }
299 
300         /* Write left channel data */
301         for (j = 0; j < 3U; j++)
302         {
303             data |= ((uint32_t)(*buffer) << (j * 8U));
304             buffer++;
305         }
306         SPDIF_WriteLeftData(base, data);
307 
308         /* Write right channel data */
309         data = 0;
310         for (j = 0; j < 3U; j++)
311         {
312             data |= ((uint32_t)(*buffer) << (j * 8U));
313             buffer++;
314         }
315         SPDIF_WriteRightData(base, data);
316 
317         i += 6U;
318     }
319 }
320 
321 /*!
322  * brief Receives data using a blocking method.
323  *
324  * note This function blocks by polling until data is ready to be sent.
325  *
326  * param base SPDIF base pointer.
327  * param buffer Pointer to the data to be read.
328  * param size Bytes to be read.
329  */
SPDIF_ReadBlocking(SPDIF_Type * base,uint8_t * buffer,uint32_t size)330 void SPDIF_ReadBlocking(SPDIF_Type *base, uint8_t *buffer, uint32_t size)
331 {
332     assert(buffer != NULL);
333     assert((size % 6U) == 0U);
334 
335     uint32_t i = 0, j = 0, data = 0;
336 
337     while (i < size)
338     {
339         /* Wait until it can write data */
340         while ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxFIFOFull) == 0x00U)
341         {
342         }
343 
344         /* Write left channel data */
345         data = SPDIF_ReadLeftData(base);
346         for (j = 0; j < 3U; j++)
347         {
348             *buffer = ((uint8_t)(data >> (j * 8U)) & 0xFFU);
349             buffer++;
350         }
351 
352         /* Write right channel data */
353         data = SPDIF_ReadRightData(base);
354         for (j = 0; j < 3U; j++)
355         {
356             *buffer = ((uint8_t)(data >> (j * 8U)) & 0xFFU);
357             buffer++;
358         }
359 
360         i += 6U;
361     }
362 }
363 
364 /*!
365  * brief Initializes the SPDIF Tx handle.
366  *
367  * This function initializes the Tx handle for the SPDIF Tx transactional APIs. Call
368  * this function once to get the handle initialized.
369  *
370  * param base SPDIF base pointer
371  * param handle SPDIF handle pointer.
372  * param callback Pointer to the user callback function.
373  * param userData User parameter passed to the callback function
374  */
SPDIF_TransferTxCreateHandle(SPDIF_Type * base,spdif_handle_t * handle,spdif_transfer_callback_t callback,void * userData)375 void SPDIF_TransferTxCreateHandle(SPDIF_Type *base,
376                                   spdif_handle_t *handle,
377                                   spdif_transfer_callback_t callback,
378                                   void *userData)
379 {
380     assert(handle != NULL);
381 
382     /* Zero the handle */
383     (void)memset(handle, 0, sizeof(*handle));
384 
385     s_spdifHandle[SPDIF_GetInstance(base)][0] = handle;
386 
387     handle->callback = callback;
388     handle->userData = userData;
389     handle->watermark =
390         s_spdif_tx_watermark[(base->SCR & SPDIF_SCR_TXFIFOEMPTY_SEL_MASK) >> SPDIF_SCR_TXFIFOEMPTY_SEL_SHIFT];
391 
392     /* Set the isr pointer */
393     s_spdifTxIsr = SPDIF_TransferTxHandleIRQ;
394 
395     /* Enable Tx irq */
396     (void)EnableIRQ(s_spdifIRQ[SPDIF_GetInstance(base)]);
397 }
398 
399 /*!
400  * brief Initializes the SPDIF Rx handle.
401  *
402  * This function initializes the Rx handle for the SPDIF Rx transactional APIs. Call
403  * this function once to get the handle initialized.
404  *
405  * param base SPDIF base pointer.
406  * param handle SPDIF handle pointer.
407  * param callback Pointer to the user callback function.
408  * param userData User parameter passed to the callback function.
409  */
SPDIF_TransferRxCreateHandle(SPDIF_Type * base,spdif_handle_t * handle,spdif_transfer_callback_t callback,void * userData)410 void SPDIF_TransferRxCreateHandle(SPDIF_Type *base,
411                                   spdif_handle_t *handle,
412                                   spdif_transfer_callback_t callback,
413                                   void *userData)
414 {
415     assert(handle != NULL);
416 
417     /* Zero the handle */
418     (void)memset(handle, 0, sizeof(*handle));
419 
420     s_spdifHandle[SPDIF_GetInstance(base)][1] = handle;
421 
422     handle->callback = callback;
423     handle->userData = userData;
424     handle->watermark =
425         s_spdif_rx_watermark[(base->SCR & SPDIF_SCR_RXFIFOFULL_SEL_MASK) >> SPDIF_SCR_RXFIFOFULL_SEL_SHIFT];
426 
427     /* Set the isr pointer */
428     s_spdifRxIsr = SPDIF_TransferRxHandleIRQ;
429 
430     /* Enable Rx irq */
431     (void)EnableIRQ(s_spdifIRQ[SPDIF_GetInstance(base)]);
432 }
433 
434 /*!
435  * brief Performs an interrupt non-blocking send transfer on SPDIF.
436  *
437  * note This API returns immediately after the transfer initiates.
438  * Call the SPDIF_TxGetTransferStatusIRQ to poll the transfer status and check whether
439  * the transfer is finished. If the return status is not kStatus_SPDIF_Busy, the transfer
440  * is finished.
441  *
442  * param base SPDIF base pointer.
443  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
444  * param xfer Pointer to the spdif_transfer_t structure.
445  * retval kStatus_Success Successfully started the data receive.
446  * retval kStatus_SPDIF_TxBusy Previous receive still not finished.
447  * retval kStatus_InvalidArgument The input parameter is invalid.
448  */
SPDIF_TransferSendNonBlocking(SPDIF_Type * base,spdif_handle_t * handle,spdif_transfer_t * xfer)449 status_t SPDIF_TransferSendNonBlocking(SPDIF_Type *base, spdif_handle_t *handle, spdif_transfer_t *xfer)
450 {
451     assert(handle != NULL);
452 
453     /* Check if the queue is full */
454     if (handle->spdifQueue[handle->queueUser].data != NULL)
455     {
456         return kStatus_SPDIF_QueueFull;
457     }
458 
459     /* Add into queue */
460     handle->transferSize[handle->queueUser]        = xfer->dataSize;
461     handle->spdifQueue[handle->queueUser].data     = xfer->data;
462     handle->spdifQueue[handle->queueUser].dataSize = xfer->dataSize;
463     handle->queueUser                              = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
464 
465     /* Set the state to busy */
466     handle->state = kSPDIF_Busy;
467 
468     /* Enable interrupt */
469     SPDIF_EnableInterrupts(base, kSPDIF_TxFIFOEmpty);
470 
471     /* Enable Tx transfer */
472     SPDIF_TxEnable(base, true);
473 
474     return kStatus_Success;
475 }
476 
477 /*!
478  * brief Performs an interrupt non-blocking receive transfer on SPDIF.
479  *
480  * note This API returns immediately after the transfer initiates.
481  * Call the SPDIF_RxGetTransferStatusIRQ to poll the transfer status and check whether
482  * the transfer is finished. If the return status is not kStatus_SPDIF_Busy, the transfer
483  * is finished.
484  *
485  * param base SPDIF base pointer
486  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
487  * param xfer Pointer to the spdif_transfer_t structure.
488  * retval kStatus_Success Successfully started the data receive.
489  * retval kStatus_SPDIF_RxBusy Previous receive still not finished.
490  * retval kStatus_InvalidArgument The input parameter is invalid.
491  */
SPDIF_TransferReceiveNonBlocking(SPDIF_Type * base,spdif_handle_t * handle,spdif_transfer_t * xfer)492 status_t SPDIF_TransferReceiveNonBlocking(SPDIF_Type *base, spdif_handle_t *handle, spdif_transfer_t *xfer)
493 {
494     assert(handle != NULL);
495 
496     uint32_t enableInterrupts = (uint32_t)kSPDIF_RxFIFOFull | (uint32_t)kSPDIF_RxControlChannelChange;
497 
498     /* Check if the queue is full */
499     if (handle->spdifQueue[handle->queueUser].data != NULL)
500     {
501         return kStatus_SPDIF_QueueFull;
502     }
503 
504     /* Add into queue */
505     handle->transferSize[handle->queueUser]        = xfer->dataSize;
506     handle->spdifQueue[handle->queueUser].data     = xfer->data;
507     handle->spdifQueue[handle->queueUser].dataSize = xfer->dataSize;
508     handle->spdifQueue[handle->queueUser].udata    = xfer->udata;
509     handle->spdifQueue[handle->queueUser].qdata    = xfer->qdata;
510     handle->queueUser                              = (handle->queueUser + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
511 
512     /* Set state to busy */
513     handle->state = kSPDIF_Busy;
514 
515     if (xfer->qdata != NULL)
516     {
517         enableInterrupts |= (uint32_t)kSPDIF_QChannelReceiveRegisterFull;
518     }
519 
520     if (xfer->udata != NULL)
521     {
522         enableInterrupts |= (uint32_t)kSPDIF_UChannelReceiveRegisterFull;
523     }
524 
525     /* Enable interrupt */
526     SPDIF_EnableInterrupts(base, enableInterrupts);
527 
528     /* Enable Rx transfer */
529     SPDIF_RxEnable(base, true);
530 
531     return kStatus_Success;
532 }
533 
534 /*!
535  * brief Gets a set byte count.
536  *
537  * param base SPDIF base pointer.
538  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
539  * param count Bytes count sent.
540  * retval kStatus_Success Succeed get the transfer count.
541  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
542  */
SPDIF_TransferGetSendCount(SPDIF_Type * base,spdif_handle_t * handle,size_t * count)543 status_t SPDIF_TransferGetSendCount(SPDIF_Type *base, spdif_handle_t *handle, size_t *count)
544 {
545     assert(handle != NULL);
546 
547     status_t status     = kStatus_Success;
548     uint8_t queueDriver = handle->queueDriver;
549 
550     if (handle->state != (uint32_t)kSPDIF_Busy)
551     {
552         status = kStatus_NoTransferInProgress;
553     }
554     else
555     {
556         *count = (handle->transferSize[queueDriver] - handle->spdifQueue[queueDriver].dataSize);
557     }
558 
559     return status;
560 }
561 
562 /*!
563  * brief Gets a received byte count.
564  *
565  * param base SPDIF base pointer.
566  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
567  * param count Bytes count received.
568  * retval kStatus_Success Succeed get the transfer count.
569  * retval kStatus_NoTransferInProgress There is not a non-blocking transaction currently in progress.
570  */
SPDIF_TransferGetReceiveCount(SPDIF_Type * base,spdif_handle_t * handle,size_t * count)571 status_t SPDIF_TransferGetReceiveCount(SPDIF_Type *base, spdif_handle_t *handle, size_t *count)
572 {
573     assert(handle != NULL);
574 
575     status_t status     = kStatus_Success;
576     uint8_t queueDriver = handle->queueDriver;
577 
578     if (handle->state != (uint32_t)kSPDIF_Busy)
579     {
580         status = kStatus_NoTransferInProgress;
581     }
582     else
583     {
584         *count = (handle->transferSize[queueDriver] - handle->spdifQueue[queueDriver].dataSize);
585     }
586 
587     return status;
588 }
589 
590 /*!
591  * brief Aborts the current send.
592  *
593  * note This API can be called any time when an interrupt non-blocking transfer initiates
594  * to abort the transfer early.
595  *
596  * param base SPDIF base pointer.
597  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
598  */
SPDIF_TransferAbortSend(SPDIF_Type * base,spdif_handle_t * handle)599 void SPDIF_TransferAbortSend(SPDIF_Type *base, spdif_handle_t *handle)
600 {
601     assert(handle != NULL);
602 
603     /* Use FIFO request interrupt and fifo error */
604     SPDIF_DisableInterrupts(base, kSPDIF_TxFIFOEmpty);
605 
606     handle->state = kSPDIF_Idle;
607 
608     /* Clear the queue */
609     (void)memset(handle->spdifQueue, 0, sizeof(spdif_transfer_t) * SPDIF_XFER_QUEUE_SIZE);
610     handle->queueDriver = 0;
611     handle->queueUser   = 0;
612 }
613 
614 /*!
615  * brief Aborts the current IRQ receive.
616  *
617  * note This API can be called when an interrupt non-blocking transfer initiates
618  * to abort the transfer early.
619  *
620  * param base SPDIF base pointer
621  * param handle Pointer to the spdif_handle_t structure which stores the transfer state.
622  */
SPDIF_TransferAbortReceive(SPDIF_Type * base,spdif_handle_t * handle)623 void SPDIF_TransferAbortReceive(SPDIF_Type *base, spdif_handle_t *handle)
624 {
625     assert(handle != NULL);
626 
627     /* Disable interrupt */
628     SPDIF_DisableInterrupts(base, (uint32_t)kSPDIF_UChannelReceiveRegisterFull |
629                                       (uint32_t)kSPDIF_QChannelReceiveRegisterFull | (uint32_t)kSPDIF_RxFIFOFull |
630                                       (uint32_t)kSPDIF_RxControlChannelChange);
631 
632     handle->state = kSPDIF_Idle;
633 
634     /* Clear the queue */
635     (void)memset(handle->spdifQueue, 0, sizeof(spdif_transfer_t) * SPDIF_XFER_QUEUE_SIZE);
636     handle->queueDriver = 0;
637     handle->queueUser   = 0;
638 }
639 
640 /*!
641  * brief Tx interrupt handler.
642  *
643  * param base SPDIF base pointer.
644  * param handle Pointer to the spdif_handle_t structure.
645  */
SPDIF_TransferTxHandleIRQ(SPDIF_Type * base,spdif_handle_t * handle)646 void SPDIF_TransferTxHandleIRQ(SPDIF_Type *base, spdif_handle_t *handle)
647 {
648     assert(handle != NULL);
649 
650     uint8_t *buffer  = handle->spdifQueue[handle->queueDriver].data;
651     uint8_t dataSize = 0;
652     uint32_t i = 0, j = 0, data = 0;
653 
654     /* Do Transfer */
655     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_TxFIFOEmpty) != 0x00U) &&
656         ((base->SIE & (uint32_t)kSPDIF_TxFIFOEmpty) != 0x00U))
657     {
658         dataSize = handle->watermark;
659         while (i < dataSize)
660         {
661             data = 0;
662             /* Write left channel data */
663             for (j = 0; j < 3U; j++)
664             {
665                 data |= ((uint32_t)(*buffer) << (j * 8U));
666                 buffer++;
667             }
668             SPDIF_WriteLeftData(base, data);
669 
670             /* Write right channel data */
671             data = 0;
672             for (j = 0; j < 3U; j++)
673             {
674                 data |= ((uint32_t)(*buffer) << (j * 8U));
675                 buffer++;
676             }
677             SPDIF_WriteRightData(base, data);
678 
679             i++;
680         }
681         handle->spdifQueue[handle->queueDriver].dataSize -= (uint32_t)dataSize * 6U;
682         handle->spdifQueue[handle->queueDriver].data += dataSize * 6U;
683 
684         /* If finished a block, call the callback function */
685         if (handle->spdifQueue[handle->queueDriver].dataSize == 0U)
686         {
687             (void)memset(&handle->spdifQueue[handle->queueDriver], 0, sizeof(spdif_transfer_t));
688             handle->queueDriver = (handle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
689             if (handle->callback != NULL)
690             {
691                 (handle->callback)(base, handle, kStatus_SPDIF_TxIdle, handle->userData);
692             }
693         }
694 
695         /* If all data finished, just stop the transfer */
696         if (handle->spdifQueue[handle->queueDriver].data == NULL)
697         {
698             SPDIF_TransferAbortSend(base, handle);
699         }
700     }
701 }
702 
703 /*!
704  * brief Tx interrupt handler.
705  *
706  * param base SPDIF base pointer.
707  * param handle Pointer to the spdif_handle_t structure.
708  */
SPDIF_TransferRxHandleIRQ(SPDIF_Type * base,spdif_handle_t * handle)709 void SPDIF_TransferRxHandleIRQ(SPDIF_Type *base, spdif_handle_t *handle)
710 {
711     assert(handle != NULL);
712 
713     uint8_t *buffer  = NULL;
714     uint8_t dataSize = 0;
715     uint32_t i = 0, j = 0, data = 0;
716 
717     /* Handle Cnew flag */
718     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxControlChannelChange) != 0x00U)
719     {
720         /* Clear the interrupt flag */
721         SPDIF_ClearStatusFlags(base, SPDIF_SIE_CNEW_MASK);
722         if (handle->callback != NULL)
723         {
724             (handle->callback)(base, handle, kStatus_SPDIF_RxCnew, handle->userData);
725         }
726     }
727 
728     /* Handle illegal symbol */
729     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxIllegalSymbol) != 0x00U)
730     {
731         SPDIF_ClearStatusFlags(base, kSPDIF_RxIllegalSymbol);
732         if (handle->callback != NULL)
733         {
734             (handle->callback)(base, handle, kStatus_SPDIF_RxIllegalSymbol, handle->userData);
735         }
736     }
737 
738     /* Handle Parity Bit Error */
739     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxParityBitError) != 0x00U)
740     {
741         SPDIF_ClearStatusFlags(base, kSPDIF_RxParityBitError);
742         if (handle->callback != NULL)
743         {
744             (handle->callback)(base, handle, kStatus_SPDIF_RxParityBitError, handle->userData);
745         }
746     }
747 
748     /* Handle DPlocked */
749     if ((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxDPLLLocked) != 0x00U)
750     {
751         SPDIF_ClearStatusFlags(base, kSPDIF_RxDPLLLocked);
752         if (handle->callback != NULL)
753         {
754             (handle->callback)(base, handle, kStatus_SPDIF_RxDPLLLocked, handle->userData);
755         }
756     }
757 
758     /* Handle Q channel full flag */
759     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_QChannelReceiveRegisterFull) != 0x00U) &&
760         ((base->SIE & (uint32_t)kSPDIF_QChannelReceiveRegisterFull) != 0x00U))
761     {
762         buffer = handle->spdifQueue[handle->queueDriver].qdata;
763         if (buffer != NULL)
764         {
765             data      = SPDIF_ReadQChannel(base);
766             buffer[0] = (uint8_t)data & 0xFFU;
767             buffer[1] = (uint8_t)(data >> 8U) & 0xFFU;
768             buffer[2] = (uint8_t)(data >> 16U) & 0xFFU;
769         }
770     }
771 
772     /* Handle U channel full flag */
773     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_UChannelReceiveRegisterFull) != 0x00U) &&
774         ((base->SIE & (uint32_t)kSPDIF_UChannelReceiveRegisterFull) != 0x00U))
775     {
776         buffer = handle->spdifQueue[handle->queueDriver].udata;
777         if (buffer != NULL)
778         {
779             data      = SPDIF_ReadUChannel(base);
780             buffer[0] = (uint8_t)data & 0xFFU;
781             buffer[1] = (uint8_t)(data >> 8U) & 0xFFU;
782             buffer[2] = (uint8_t)(data >> 16U) & 0xFFU;
783         }
784     }
785 
786     /* Handle audio data transfer */
787     if (((SPDIF_GetStatusFlag(base) & (uint32_t)kSPDIF_RxFIFOFull) != 0x00U) &&
788         ((base->SIE & (uint32_t)kSPDIF_RxFIFOFull) != 0x00U))
789     {
790         dataSize = handle->watermark;
791         buffer   = handle->spdifQueue[handle->queueDriver].data;
792         while (i < dataSize)
793         {
794             /* Read left channel data */
795             data = SPDIF_ReadLeftData(base);
796             for (j = 0; j < 3U; j++)
797             {
798                 *buffer = (uint8_t)((data >> (j * 8U)) & 0xFFU);
799                 buffer++;
800             }
801 
802             /* Read right channel data */
803             data = SPDIF_ReadRightData(base);
804             for (j = 0; j < 3U; j++)
805             {
806                 *buffer = (uint8_t)((data >> (j * 8U)) & 0xFFU);
807                 buffer++;
808             }
809 
810             i++;
811         }
812         handle->spdifQueue[handle->queueDriver].dataSize -= (uint32_t)dataSize * 6U;
813         handle->spdifQueue[handle->queueDriver].data += dataSize * 6U;
814 
815         /* If finished a block, call the callback function */
816         if (handle->spdifQueue[handle->queueDriver].dataSize == 0x00U)
817         {
818             (void)memset(&handle->spdifQueue[handle->queueDriver], 0, sizeof(spdif_transfer_t));
819             handle->queueDriver = (handle->queueDriver + 0x01U) % SPDIF_XFER_QUEUE_SIZE;
820             if (handle->callback != NULL)
821             {
822                 (handle->callback)(base, handle, kStatus_SPDIF_RxIdle, handle->userData);
823             }
824         }
825 
826         /* If all data finished, just stop the transfer */
827         if (handle->spdifQueue[handle->queueDriver].data == NULL)
828         {
829             SPDIF_TransferAbortReceive(base, handle);
830         }
831     }
832 }
833 
834 #if defined(SPDIF)
835 void SPDIF_DriverIRQHandler(void);
SPDIF_DriverIRQHandler(void)836 void SPDIF_DriverIRQHandler(void)
837 {
838     if ((s_spdifHandle[0][0] != NULL) && (s_spdifTxIsr != NULL))
839     {
840         s_spdifTxIsr(SPDIF, s_spdifHandle[0][0]);
841     }
842 
843     if ((s_spdifHandle[0][1] != NULL) && (s_spdifRxIsr != NULL))
844     {
845         s_spdifRxIsr(SPDIF, s_spdifHandle[0][1]);
846     }
847     SDK_ISR_EXIT_BARRIER;
848 }
849 #endif
850