1 /*
2  * Copyright 2019-2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_asrc.h"
9 #include "fsl_asrc_firmware.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.easrc"
14 #endif
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 /*! @brief asrc sample rate ratio format */
20 typedef enum _asrc_samplerate_ratio_format
21 {
22     kASRC_SampleRateRatio5Int39Frac = 32,  /*!< sample rate ratio 5 integer bits and 39 fractional bits */
23     kASRC_SampleRateRatio6Int38Frac = 64,  /*!< sample rate ratio 6 integer bits and 38 fractional bits */
24     kASRC_SampleRateRatio7Int37Frac = 128, /*!< sample rate ratio 7 integer bits and 37 fractional bits */
25 } asrc_samplerate_ratio_format_t;
26 
27 /*! @brief ASRC support maximum channel number */
28 #define ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMBER 32U
29 /*! @brief ASRC support maximum channel number of one context process pipe line */
30 #define ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER 8U
31 /*! @brief ASRC support maximum channel number of context */
32 #define ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER 4U
33 
34 /*! @brief ASRC macro to get register field value*/
35 #define ASRC_GET_SLOT0_CONTEXT_INDEX(context)                                            \
36     ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM_MASK) >> \
37      ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM_SHIFT)
38 #define ASRC_GET_SLOT0_CHANNEL_NUMBER(context)                                          \
39     ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH_MASK) >> \
40      ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH_SHIFT)
41 #define ASRC_GET_SLOT1_CONTEXT_INDEX(context)                                            \
42     ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM_MASK) >> \
43      ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM_SHIFT)
44 #define ASRC_GET_SLOT1_CHANNEL_NUMBER(context)                                          \
45     ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH_MASK) >> \
46      ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH_SHIFT)
47 #define ASRC_IS_CONTEXT_ENABLED(index) ((base->CTX_CTRL[index] & ASRC_CTX_CTRL_RUN_EN_MASK) != 0U)
48 #define ASRC_IS_SLOT0_ENABLED(context) \
49     ((base->PROC_CTRL_SLOT0_R0[context] & ASRC_PROC_CTRL_SLOT0_R0_SLOT0_EN_MASK) != 0U)
50 #define ASRC_IS_SLOT1_ENABLED(context) \
51     ((base->PROC_CTRL_SLOT1_R0[context] & ASRC_PROC_CTRL_SLOT1_R0_SLOT1_EN_MASK) != 0U)
52 
53 /*******************************************************************************
54  * Prototypes
55  ******************************************************************************/
56 /*!
57  * @brief ASRC get greatest common divisor between the input and output sample rate.
58  *
59  * @param inputSampleRate input sample rate.
60  * @param outputSampleRate output sample rate.
61  * @retval GCD between the input and output sample rate.
62  */
63 static uint32_t ASRC_GetSampleRateGCD(uint32_t inputSampleRate, uint32_t outputSampleRate);
64 
65 /*!
66  * @brief ASRC get available context slot channel.
67  *
68  * @param base ASRC base address.
69  * @param contextProcessor context processor number.
70  * @param slot0UsedChannel slot0 used channel number.
71  * @param slot1UsedChannel slot1 used channel number.
72  */
73 static void ASRC_GetAvailableContextSlot(ASRC_Type *base,
74                                          uint32_t contextProcessor,
75                                          uint32_t *slot0UsedChannel,
76                                          uint32_t *slot1UsedChannel);
77 
78 /*!
79  * @brief ASRC enable context slot.
80  *
81  * @param base ASRC base address.
82  * @param contextProcessor context processor number.
83  * @param slot slot number.
84  * @param channelNums channel number
85  * @param startChannel start channel number running on this slot.
86  * @param context context number running on this slot.
87  */
88 static void ASRC_EnableContextSlot(ASRC_Type *base,
89                                    uint32_t contextProcessor,
90                                    uint32_t slot,
91                                    uint32_t channelNums,
92                                    uint32_t startChannel,
93                                    asrc_context_t runningContext);
94 
95 /*!
96  * @brief ASRC config the sample rate ratio.
97  *
98  * @param base ASRC base address.
99  * @param context context number.
100  * @param inputSampleRate input sample rate.
101  * @param outputSampleRate output sample rate.
102  * @param format sample rate ratio format.
103  * @retval kStatus_Success, else configure failed.
104  */
105 static status_t ASRC_SetSampleRateRatioConfig(ASRC_Type *base,
106                                               asrc_context_t context,
107                                               uint32_t inputSampleRate,
108                                               uint32_t outputSampleRate,
109                                               asrc_samplerate_ratio_format_t format);
110 
111 /*!
112  * @brief ASRC load prefilter configuration.
113  *
114  * @param config prefilter pointer.
115  * @param inputSampleRate input sample rate.
116  * @param outputSampleRate output sample rate.
117  * @retval kStatus_Success, else configure failed.
118  */
119 static status_t ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t *config,
120                                         uint32_t inputSampleRate,
121                                         uint32_t outputSampleRate);
122 
123 /*!
124  * @brief ASRC load resample configuration.
125  *
126  * @param config resamplefilter pointer.
127  * @param interpolationTap resampler taps
128  * @retval kStatus_Success, else configure failed.
129  */
130 static status_t ASRC_GetResamplerConfig(asrc_context_resampler_config_t *config,
131                                         asrc_resampler_taps_t interpolationTap);
132 
133 /*!
134  * @brief ASRC reset prefilter coeff memory pointer reset.
135  *
136  * @param base ASRC base address.
137  * @param context context number.
138  */
139 static void ASRC_SetPrefilterCoeffMemReset(ASRC_Type *base, asrc_context_t context);
140 
141 /*!
142  * @brief ASRC set prefilter configuration.
143  *
144  * @param base ASRC base address.
145  * @param context context number.
146  * @param config prefilter configuration.
147  * @param filter filter configuration load from firmware.
148  * @retval kStatus_Success, else configure failed.
149  */
150 static status_t ASRC_SetPrefilterConfig(ASRC_Type *base,
151                                         asrc_context_t context,
152                                         asrc_context_prefilter_config_t *config);
153 
154 /*!
155  * @brief ASRC set resampler configuration.
156  *
157  * @param base ASRC base address.
158  * @param context context number.
159  * @param config resampler configuration.
160  * @param filter filter configuration load from firmware.
161  * @retval kStatus_Success, else configure failed.
162  */
163 static status_t ASRC_SetResamplerConfig(ASRC_Type *base,
164                                         asrc_context_t context,
165                                         asrc_context_resampler_config_t *config);
166 
167 /*!
168  * @brief ASRC set slot config.
169  *
170  * @param base ASRC base address.
171  * @param context context number.
172  * @param requestChannel request channel number need to run on this slot.
173  * @param filter filter configuration load from firmware.
174  * @retval kStatus_Success, else configure failed.
175  */
176 static status_t ASRC_SetSlotConfig(ASRC_Type *base,
177                                    asrc_context_t context,
178                                    uint32_t requestChannel,
179                                    asrc_context_prefilter_config_t *config);
180 
181 /*!
182  * @brief ASRC set context processor config.
183  *
184  * @param base ASRC base address.
185  * @param context context number.
186  * @param config context configuration.
187  * @retval kStatus_Success, else configure failed.
188  */
189 static status_t ASRC_SetContextProcessorConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config);
190 
191 /*******************************************************************************
192  * Variables
193  ******************************************************************************/
194 /* Base pointer array */
195 static ASRC_Type *const s_asrcBases[] = ASRC_BASE_PTRS;
196 
197 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
198 /* Clock name array */
199 static const clock_ip_name_t s_asrcClock[] = ASRC_CLOCKS;
200 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
201 /*! @brief ASRC filter firmware table */
202 static const uint32_t s_asrcFirmware[] = ASRC_FILTER_FIRMWARE;
203 /*******************************************************************************
204  * Code
205  ******************************************************************************/
ASRC_GetInstance(ASRC_Type * base)206 uint32_t ASRC_GetInstance(ASRC_Type *base)
207 {
208     uint32_t instance;
209 
210     /* Find the instance index from base address mappings. */
211     for (instance = 0; instance < ARRAY_SIZE(s_asrcBases); instance++)
212     {
213         if (s_asrcBases[instance] == base)
214         {
215             break;
216         }
217     }
218 
219     assert(instance < ARRAY_SIZE(s_asrcBases));
220 
221     return instance;
222 }
223 
ASRC_GetSampleRateGCD(uint32_t inputSampleRate,uint32_t outputSampleRate)224 static uint32_t ASRC_GetSampleRateGCD(uint32_t inputSampleRate, uint32_t outputSampleRate)
225 {
226     uint32_t temp = 0U, gcd = inputSampleRate;
227 
228     while (outputSampleRate != 0U)
229     {
230         temp             = outputSampleRate;
231         outputSampleRate = gcd % outputSampleRate;
232         gcd              = temp;
233     }
234 
235     return gcd;
236 }
237 
ASRC_GetAvailableContextSlot(ASRC_Type * base,uint32_t contextProcessor,uint32_t * slot0UsedChannel,uint32_t * slot1UsedChannel)238 static void ASRC_GetAvailableContextSlot(ASRC_Type *base,
239                                          uint32_t contextProcessor,
240                                          uint32_t *slot0UsedChannel,
241                                          uint32_t *slot1UsedChannel)
242 {
243     uint32_t contextIndex = 0U;
244 
245     /* looking for available context processor */
246     if (ASRC_IS_SLOT0_ENABLED(contextProcessor))
247     {
248         contextIndex = ASRC_GET_SLOT0_CONTEXT_INDEX(contextProcessor);
249         if (ASRC_IS_CONTEXT_ENABLED(contextIndex))
250         {
251             *slot0UsedChannel = ASRC_GET_SLOT0_CHANNEL_NUMBER(contextProcessor);
252         }
253     }
254 
255     if (ASRC_IS_SLOT1_ENABLED(contextProcessor))
256     {
257         contextIndex = ASRC_GET_SLOT1_CONTEXT_INDEX(contextProcessor);
258         if (ASRC_IS_CONTEXT_ENABLED(contextIndex))
259         {
260             *slot1UsedChannel = ASRC_GET_SLOT1_CHANNEL_NUMBER(contextProcessor);
261         }
262     }
263 }
264 
ASRC_EnableContextSlot(ASRC_Type * base,uint32_t contextProcessor,uint32_t slot,uint32_t channelNums,uint32_t startChannel,asrc_context_t runningContext)265 static void ASRC_EnableContextSlot(ASRC_Type *base,
266                                    uint32_t contextProcessor,
267                                    uint32_t slot,
268                                    uint32_t channelNums,
269                                    uint32_t startChannel,
270                                    asrc_context_t runningContext)
271 {
272     assert(channelNums <= ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER);
273 
274     if (slot == 0U)
275     {
276         base->PROC_CTRL_SLOT0_R0[contextProcessor] =
277             ASRC_PROC_CTRL_SLOT0_R0_SLOT0_EN_MASK | ASRC_PROC_CTRL_SLOT0_R0_SLOT0_CTX_NUM(runningContext) |
278             ASRC_PROC_CTRL_SLOT0_R0_SLOT0_NUM_CH(channelNums - 1U) |
279             ASRC_PROC_CTRL_SLOT0_R0_SLOT0_MIN_CH(startChannel) |
280             ASRC_PROC_CTRL_SLOT0_R0_SLOT0_MAX_CH(startChannel + channelNums - 1U);
281     }
282     else
283     {
284         base->PROC_CTRL_SLOT1_R0[contextProcessor] =
285             ASRC_PROC_CTRL_SLOT1_R0_SLOT1_EN_MASK | ASRC_PROC_CTRL_SLOT1_R0_SLOT1_CTX_NUM(runningContext) |
286             ASRC_PROC_CTRL_SLOT1_R0_SLOT1_NUM_CH(channelNums - 1U) |
287             ASRC_PROC_CTRL_SLOT1_R0_SLOT1_MIN_CH(startChannel) |
288             ASRC_PROC_CTRL_SLOT1_R0_SLOT1_MAX_CH(startChannel + channelNums - 1U);
289     }
290 }
291 
ASRC_SetSampleRateRatioConfig(ASRC_Type * base,asrc_context_t context,uint32_t inputSampleRate,uint32_t outputSampleRate,asrc_samplerate_ratio_format_t format)292 static status_t ASRC_SetSampleRateRatioConfig(ASRC_Type *base,
293                                               asrc_context_t context,
294                                               uint32_t inputSampleRate,
295                                               uint32_t outputSampleRate,
296                                               asrc_samplerate_ratio_format_t format)
297 {
298     uint64_t ratio    = 0U;
299     uint32_t fracBits = 0U;
300 
301     uint32_t gcd     = ASRC_GetSampleRateGCD(inputSampleRate, outputSampleRate);
302     uint32_t inRate  = inputSampleRate / gcd;
303     uint32_t outRate = outputSampleRate / gcd;
304 
305     if (format == kASRC_SampleRateRatio5Int39Frac)
306     {
307         fracBits = 39U;
308     }
309     else if (format == kASRC_SampleRateRatio6Int38Frac)
310     {
311         fracBits = 38U;
312     }
313     else
314     {
315         fracBits = 37U;
316     }
317 
318     ratio = ((uint64_t)inRate << fracBits) / outRate;
319 
320     base->RS_RATIO_LOW[context].RS_RATIO_LOW  = (uint32_t)ratio & 0xFFFFFFFFU;
321     base->RS_RATIO_LOW[context].RS_RATIO_HIGH = ((uint32_t)(ratio >> 32U)) & 0xFFFFFFFFU;
322 
323     return kStatus_Success;
324 }
325 
ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t * config,uint32_t inputSampleRate,uint32_t outputSampleRate)326 static status_t ASRC_GetPrefilterConfig(asrc_context_prefilter_config_t *config,
327                                         uint32_t inputSampleRate,
328                                         uint32_t outputSampleRate)
329 {
330     assert(config != NULL);
331 
332     uint32_t gcd           = ASRC_GetSampleRateGCD(inputSampleRate, outputSampleRate);
333     uint32_t inSampleRate  = inputSampleRate / gcd;
334     uint32_t outSampleRate = outputSampleRate / gcd;
335     uint32_t i = 0U, offset = 0U;
336     const uint32_t *firmware = s_asrcFirmware;
337 
338     /* while performing a up-conversion, the prefilter should be bypassed */
339     if (inputSampleRate <= outputSampleRate)
340     {
341         return kStatus_Success;
342     }
343 
344     offset = (ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN + 5U) * ASRC_FILTER_INTERPOLATION_FILTER_NUM;
345 
346     /* load interpolation filter */
347     for (i = 0U; i < ASRC_FILTER_PREFILTER_FILTER_NUM; i++)
348     {
349         if (firmware[offset] != ASRC_FILTER_FIRMWARE_HEAD)
350         {
351             return kStatus_InvalidArgument;
352         }
353 
354         if ((firmware[offset + ASRC_FILTER_PREFILTER_IN_SAMPLE_RATE_INDEX] == inSampleRate) &&
355             ((firmware[offset + ASRC_FILTER_PREFILTER_OUT_SAMPLE_RATE_INDEX] == outSampleRate)))
356         {
357             config->filterSt1Taps      = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_TAPS_INDEX];
358             config->filterSt2Taps      = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_2_TAPS_INDEX];
359             config->filterSt1Exp       = firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_EXPANSION_FACTOR_INDEX];
360             config->filterCoeffAddress = &firmware[offset + ASRC_FILTER_PREFILTER_STAGE_1_DATA_INDEX];
361             break;
362         }
363         offset += ASRC_FILTER_PREFILTER_FIRMWARE_LEN + ASRC_FILTER_PREFILTER_STAGE_1_DATA_INDEX;
364     }
365 
366     /* check if the interpolation filter firmware is founded */
367     if (config->filterCoeffAddress == NULL)
368     {
369         return kStatus_InvalidArgument;
370     }
371 
372     return kStatus_Success;
373 }
374 
ASRC_GetResamplerConfig(asrc_context_resampler_config_t * config,asrc_resampler_taps_t interpolationTap)375 static status_t ASRC_GetResamplerConfig(asrc_context_resampler_config_t *config, asrc_resampler_taps_t interpolationTap)
376 {
377     assert(config != NULL);
378 
379     uint32_t i = 0U, offset = 0U;
380     const uint32_t *firmware = s_asrcFirmware;
381 
382     /* load prefilter firmware */
383     for (i = 0U; i < ASRC_FILTER_INTERPOLATION_FILTER_NUM; i++)
384     {
385         if (firmware[offset] != ASRC_FILTER_FIRMWARE_HEAD)
386         {
387             return kStatus_InvalidArgument;
388         }
389 
390         if (firmware[offset + ASRC_FILTER_INTERPOLATION_TAP_INDEX] == ((uint32_t)interpolationTap + 1U))
391         {
392             config->filterPhases = firmware[offset + ASRC_FILTER_INTERPOLATION_PHASE_INDEX];
393             config->filterCenterTap =
394                 ((uint64_t)firmware[offset + 1U + ASRC_FILTER_INTERPOLATION_CENTER_TAP_INDEX] << 32U) +
395                 firmware[offset + ASRC_FILTER_INTERPOLATION_CENTER_TAP_INDEX];
396             config->filterCoeffAddress = &firmware[offset + +1U + ASRC_FILTER_INTERPOLATION_DATA_INDEX];
397             break;
398         }
399         offset += ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN + ASRC_FILTER_INTERPOLATION_DATA_INDEX + 1U;
400     }
401 
402     /* check if the interpolation filter firmware is founded */
403     if (config->filterCoeffAddress == NULL)
404     {
405         return kStatus_InvalidArgument;
406     }
407 
408     return kStatus_Success;
409 }
410 
ASRC_SetPrefilterCoeffMemReset(ASRC_Type * base,asrc_context_t context)411 static void ASRC_SetPrefilterCoeffMemReset(ASRC_Type *base, asrc_context_t context)
412 {
413     base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
414     base->CTX_CTRL_EXT1[context] |= ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
415     base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_MEM_RST_MASK;
416 }
417 
ASRC_SetPrefilterConfig(ASRC_Type * base,asrc_context_t context,asrc_context_prefilter_config_t * config)418 static status_t ASRC_SetPrefilterConfig(ASRC_Type *base,
419                                         asrc_context_t context,
420                                         asrc_context_prefilter_config_t *config)
421 {
422     uint32_t contextReg          = base->CTX_CTRL_EXT1[context];
423     const uint32_t *coeffPointer = config->filterCoeffAddress;
424     uint32_t i = 0U, j = 0U;
425 
426     if (coeffPointer == NULL)
427     {
428         return kStatus_InvalidArgument;
429     }
430 
431     contextReg &= ~(ASRC_CTX_CTRL_EXT1_PF_INIT_MODE_MASK | ASRC_CTX_CTRL_EXT1_PF_STOP_MODE_MASK |
432                     ASRC_CTX_CTRL_EXT1_PF_EXPANSION_FACTOR_MASK | ASRC_CTX_CTRL_EXT1_PF_ST1_WB_FLOAT_MASK |
433                     ASRC_CTX_CTRL_EXT1_PF_TWO_STAGE_EN_MASK);
434 
435     contextReg |= ASRC_CTX_CTRL_EXT1_PF_INIT_MODE(config->initMode) |
436                   ASRC_CTX_CTRL_EXT1_PF_STOP_MODE(config->stopMode) |
437                   ASRC_CTX_CTRL_EXT1_PF_EXPANSION_FACTOR(config->filterSt1Exp - 1U) |
438                   ASRC_CTX_CTRL_EXT1_PF_ST1_WB_FLOAT(config->stage1Result) |
439                   ASRC_CTX_CTRL_EXT1_PF_TWO_STAGE_EN(config->filterSt2Taps != 0U ? 1U : 0U);
440 
441     base->CTX_CTRL_EXT1[context] = contextReg;
442     base->CTX_CTRL_EXT2[context] = ASRC_CTX_CTRL_EXT2_ST1_NUM_TAPS(config->filterSt1Taps - 1U) |
443                                    ASRC_CTX_CTRL_EXT2_ST2_NUM_TAPS(config->filterSt2Taps - 1U);
444 
445     /* reset prefilter coefficient memory */
446     ASRC_SetPrefilterCoeffMemReset(base, context);
447     /* load stage1 */
448     base->CTX_CTRL_EXT1[context] &= ~ASRC_CTX_CTRL_EXT1_PF_COEFF_STAGE_WR_MASK;
449 
450     for (i = 0; i < ((config->filterSt1Taps + 1U) / 2U) * 2U; i++)
451     {
452         base->PRE_COEFF_FIFO[context] = coeffPointer[i];
453     }
454 
455     /* reset prefilter coefficient memory */
456     ASRC_SetPrefilterCoeffMemReset(base, context);
457     /* load stage2 */
458     if (config->filterSt2Taps != 0U)
459     {
460         base->CTX_CTRL_EXT1[context] |= ASRC_CTX_CTRL_EXT1_PF_COEFF_STAGE_WR_MASK;
461         for (j = 0; j < ((config->filterSt2Taps + 1U) / 2U) * 2U; j++)
462         {
463             base->PRE_COEFF_FIFO[context] = coeffPointer[i + j];
464         }
465     }
466 
467     return kStatus_Success;
468 }
469 
ASRC_SetResamplerConfig(ASRC_Type * base,asrc_context_t context,asrc_context_resampler_config_t * config)470 static status_t ASRC_SetResamplerConfig(ASRC_Type *base,
471                                         asrc_context_t context,
472                                         asrc_context_resampler_config_t *config)
473 {
474     uint32_t contextReg          = base->CTX_CTRL_EXT1[context];
475     uint32_t i                   = 0U;
476     const uint32_t *coeffPointer = config->filterCoeffAddress;
477 
478     contextReg &= ~(ASRC_CTX_CTRL_EXT1_RS_INIT_MODE_MASK | ASRC_CTX_CTRL_EXT1_RS_STOP_MODE_MASK);
479     contextReg |= ASRC_CTX_CTRL_EXT1_RS_INIT_MODE(config->initMode) | ASRC_CTX_CTRL_EXT1_RS_STOP_MODE(config->stopMode);
480     base->CTX_CTRL_EXT1[context] = contextReg;
481 
482     /* center tap */
483     base->RS_CT_LOW  = (uint32_t)config->filterCenterTap & 0xFFFFFFFFU;
484     base->RS_CT_HIGH = (uint32_t)(config->filterCenterTap >> 32U) & 0xFFFFFFFFU;
485 
486     /* resampler taps */
487     contextReg = base->CTX_RS_COEFF_CTRL;
488     contextReg &= ~ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS_MASK;
489 
490     if (config->tap == kASRC_ResamplerTaps_32)
491     {
492         contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(0);
493     }
494     else if (config->tap == kASRC_ResamplerTaps_64)
495     {
496         contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(1);
497     }
498     else
499     {
500         contextReg |= ASRC_CTX_RS_COEFF_CTRL_NUM_RES_TAPS(2);
501     }
502     base->CTX_RS_COEFF_CTRL = contextReg;
503 
504     /* load coefficient */
505     /* reset coefficient memory firstly */
506     base->CTX_RS_COEFF_CTRL &= ~ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
507     base->CTX_RS_COEFF_CTRL |= ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
508     base->CTX_RS_COEFF_CTRL &= ~ASRC_CTX_RS_COEFF_CTRL_RS_COEFF_PTR_RST_MASK;
509 
510     for (i = 0U; i < ASRC_FILTER_INTERPOLATION_FIRMWARE_LEN; i++)
511     {
512         base->CTX_RS_COEFF_MEM = coeffPointer[i];
513     }
514 
515     return kStatus_Success;
516 }
517 
ASRC_SetSlotConfig(ASRC_Type * base,asrc_context_t context,uint32_t requestChannel,asrc_context_prefilter_config_t * config)518 static status_t ASRC_SetSlotConfig(ASRC_Type *base,
519                                    asrc_context_t context,
520                                    uint32_t requestChannel,
521                                    asrc_context_prefilter_config_t *config)
522 {
523     uint32_t availableSlot = 0U, availableContext = 0U, availableChannel = 0U, startChannel = 0U;
524     uint32_t i                = 0U;
525     uint32_t slot0UsedChannel = 0U, slot1UsedChannel = 0U;
526     uint32_t stage1MemSize = 0U, stage1MemAddr = 0U, stage2MemSize = 0U, stage2MemAddr = 0U, stage1Exp = 0U;
527     uint32_t leftChannel = requestChannel;
528 
529     for (i = 0U; i < ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER; i++)
530     {
531         /* record start channel */
532         startChannel += availableChannel;
533 
534         ASRC_GetAvailableContextSlot(base, i, &slot0UsedChannel, &slot1UsedChannel);
535 
536         /* context is busy */
537         if ((slot0UsedChannel != 0U) && ((slot1UsedChannel != 0U)))
538         {
539             continue;
540         }
541         /* context is idle */
542         if ((slot0UsedChannel == 0U) && (slot1UsedChannel == 0U))
543         {
544             availableSlot    = 0U;
545             availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER;
546             availableContext = i;
547         }
548         /* context slot 0 is busy, slot 1 is idle */
549         else if (slot0UsedChannel != 0U)
550         {
551             availableSlot    = 1U;
552             availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER - slot0UsedChannel;
553             availableContext = i;
554         }
555         /* context slot0 is idle, slot 1 is busy, ((slot0UsedChannel == 0U) && (slot1UsedChannel != 0U))*/
556         else
557         {
558             availableSlot    = 0U;
559             availableChannel = ASRC_SUPPORT_CONTEXT_PROCESSOR_MAXIMUM_CHANNEL_NUMBER - slot1UsedChannel;
560             availableContext = i;
561         }
562 
563         availableChannel = availableChannel > leftChannel ? leftChannel : availableChannel;
564         leftChannel -= availableChannel;
565         /* enable the available slot */
566         ASRC_EnableContextSlot(base, availableContext, availableSlot, availableChannel, startChannel, context);
567 
568         if (availableSlot == 0U)
569         {
570             if (config->filterSt2Taps != 0U)
571             {
572                 stage1Exp = (config->filterSt1Exp - 1U) * availableChannel;
573                 stage1MemSize =
574                     (config->filterSt1Taps - 1U) * config->filterSt1Exp * availableChannel + availableChannel;
575                 stage1MemAddr = 0U;
576                 stage2MemSize = availableChannel * config->filterSt2Taps;
577                 stage2MemAddr = stage1MemSize;
578             }
579             else
580             {
581                 stage1MemSize = availableChannel * config->filterSt1Taps;
582                 stage1MemAddr = 0U;
583             }
584 
585             base->PROC_CTRL_SLOT0_R1[availableContext] = stage1Exp;
586             base->PROC_CTRL_SLOT0_R2[availableContext] = ASRC_PROC_CTRL_SLOT0_R2_SLOT0_ST1_ST_ADDR(stage1MemAddr) |
587                                                          ASRC_PROC_CTRL_SLOT0_R2_SLOT0_ST1_MEM_ALLOC(stage1MemSize);
588             base->PROC_CTRL_SLOT0_R3[availableContext] = ASRC_PROC_CTRL_SLOT0_R3_SLOT0_ST2_ST_ADDR(stage2MemAddr) |
589                                                          ASRC_PROC_CTRL_SLOT0_R3_SLOT0_ST2_MEM_ALLOC(stage2MemSize);
590         }
591         else
592         {
593             if (config->filterSt2Taps != 0U)
594             {
595                 stage1Exp = (config->filterSt1Exp - 1U) * availableChannel;
596                 stage1MemSize =
597                     (config->filterSt1Taps - 1U) * config->filterSt1Exp * availableChannel + availableChannel;
598                 stage1MemAddr = 0x1800U - stage1MemSize;
599                 stage2MemSize = availableChannel * config->filterSt2Taps;
600                 stage2MemAddr = 0x1800U - stage1MemSize - stage2MemSize;
601             }
602             else
603             {
604                 stage1MemSize = availableChannel * config->filterSt1Taps;
605                 stage1MemAddr = 0x1800U - stage1MemSize;
606             }
607 
608             base->PROC_CTRL_SLOT1_R1[availableContext] = stage1Exp;
609             base->PROC_CTRL_SLOT1_R2[availableContext] = ASRC_PROC_CTRL_SLOT1_R2_SLOT1_ST1_ST_ADDR(stage1MemAddr) |
610                                                          ASRC_PROC_CTRL_SLOT1_R2_SLOT1_ST1_MEM_ALLOC(stage1MemSize);
611             base->PROC_CTRL_SLOT1_R3[availableContext] = ASRC_PROC_CTRL_SLOT1_R3_SLOT1_ST2_ST_ADDR(stage2MemAddr) |
612                                                          ASRC_PROC_CTRL_SLOT1_R3_SLOT1_ST2_MEM_ALLOC(stage2MemSize);
613         }
614 
615         /* one context processor can satisfy the channel requirement*/
616         if (leftChannel == 0U)
617         {
618             return kStatus_Success;
619         }
620         /* multiple slot across context processor is required */
621         else
622         {
623             continue;
624         }
625     }
626 
627     return kStatus_Fail;
628 }
629 
ASRC_SetContextProcessorConfig(ASRC_Type * base,asrc_context_t context,asrc_context_config_t * config)630 static status_t ASRC_SetContextProcessorConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config)
631 {
632     assert(config != NULL);
633 
634     /* bypass resampler */
635     if (config->contextInput.sampleRate == config->contextOutput.sampleRate)
636     {
637         ASRC_EnableResamplerBypass(base, context, true);
638     }
639     else
640     {
641         /* ensure resampler is not bypassed */
642         ASRC_EnableResamplerBypass(base, context, false);
643 
644         if (config->contextResampler.filterCoeffAddress == NULL)
645         {
646             if (ASRC_GetResamplerConfig(&config->contextResampler, config->contextResampler.tap) != kStatus_Success)
647             {
648                 return kStatus_InvalidArgument;
649             }
650         }
651         /* resampler configuration */
652         if (ASRC_SetResamplerConfig(base, context, &config->contextResampler) != kStatus_Success)
653         {
654             return kStatus_ASRCResamplerConfigureFailed;
655         }
656     }
657 
658     /* up conversion should bypass the prefilter */
659     if (config->contextInput.sampleRate <= config->contextOutput.sampleRate)
660     {
661         /* prefilter bypass mode */
662         ASRC_EnablePreFilterBypass(base, context, true);
663     }
664     else
665     {
666         /* ensure prefilter not in bypass mode */
667         ASRC_EnablePreFilterBypass(base, context, false);
668         /* load default configuration if not assigned by application */
669         if (config->contextPrefilter.filterCoeffAddress == NULL)
670         {
671             if (ASRC_GetPrefilterConfig(&config->contextPrefilter, config->contextInput.sampleRate,
672                                         config->contextOutput.sampleRate) == kStatus_InvalidArgument)
673             {
674                 return kStatus_InvalidArgument;
675             }
676         }
677         if (ASRC_SetPrefilterConfig(base, context, &config->contextPrefilter) != kStatus_Success)
678         {
679             return kStatus_ASRCPrefilterConfigureFailed;
680         }
681     }
682 
683     /* set channel number in context */
684     ASRC_SetContextChannelNumber(base, context, config->contextChannelNums);
685 
686     return ASRC_SetSlotConfig(base, context, config->contextChannelNums, &config->contextPrefilter);
687 }
688 
689 /*!
690  * brief Initializes the asrc peripheral.
691  *
692  * This API gates the asrc clock. The asrc module can't operate unless ASRC_Init is called to enable the clock.
693  *
694  * param base asrc base pointer.
695  */
ASRC_Init(ASRC_Type * base)696 void ASRC_Init(ASRC_Type *base)
697 {
698 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
699     /* Enable the asrc clock */
700     CLOCK_EnableClock(s_asrcClock[ASRC_GetInstance(base)]);
701 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
702 
703     for (uint32_t i = 0U; i < ASRC_SUPPORT_MAXIMUM_CONTEXT_PROCESSOR_NUMBER; i++)
704     {
705         /* disable ASRC module and reset ASRC slot configurations*/
706         base->CTX_CTRL[i]           = 0U;
707         base->CTX_OUT_CTRL[i]       = 0U;
708         base->PROC_CTRL_SLOT0_R0[i] = 0U;
709         base->PROC_CTRL_SLOT1_R0[i] = 0U;
710     }
711 
712     /* disable all the interrupt */
713     base->IRQ_CTRL  = 0U;
714     base->IRQ_FLAGS = 0xFFFU;
715 }
716 
717 /*!
718  * brief De-initializes the ASRC peripheral.
719  *
720  * This API gates the ASRC clock and disable ASRC module. The ASRC module can't operate unless ASRC_Init
721  *
722  * param base ASRC base pointer.
723  */
ASRC_Deinit(ASRC_Type * base)724 void ASRC_Deinit(ASRC_Type *base)
725 {
726 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
727     CLOCK_DisableClock(s_asrcClock[ASRC_GetInstance(base)]);
728 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
729 }
730 
731 /*!
732  * brief ASRC configure context input.
733  *
734  * param base ASRC base pointer.
735  * param context index of asrc context, reference asrc_context_t.
736  * param config ASRC context input configuration pointer.
737  */
ASRC_SetContextInputConfig(ASRC_Type * base,asrc_context_t context,asrc_context_input_config_t * config)738 status_t ASRC_SetContextInputConfig(ASRC_Type *base, asrc_context_t context, asrc_context_input_config_t *config)
739 {
740     assert(config != NULL);
741 
742     uint32_t contextReg = base->CTX_CTRL[context];
743 
744     contextReg &= ~(ASRC_CTX_CTRL_SIGN_IN_MASK | ASRC_CTX_CTRL_FLOAT_FMT_MASK | ASRC_CTX_CTRL_BITS_PER_SAMPLE_MASK |
745                     ASRC_CTX_CTRL_BIT_REV_MASK | ASRC_CTX_CTRL_SAMPLE_POSITION_MASK | ASRC_CTX_CTRL_FIFO_WTMK_MASK);
746 
747     contextReg |= ASRC_CTX_CTRL_FIFO_WTMK(config->watermark);
748 
749     contextReg |= ASRC_CTX_CTRL_SIGN_IN(config->dataFormat.dataSign) |
750                   ASRC_CTX_CTRL_FLOAT_FMT(config->dataFormat.dataType) |
751                   ASRC_CTX_CTRL_BITS_PER_SAMPLE(config->dataFormat.dataWidth) |
752                   ASRC_CTX_CTRL_BIT_REV(config->dataFormat.dataEndianness) |
753                   ASRC_CTX_CTRL_SAMPLE_POSITION(config->dataFormat.dataPosition);
754 
755     base->CTX_CTRL[context] = contextReg;
756 
757     base->CTRL_IN_ACCESS[context] = ASRC_CTRL_IN_ACCESS_ACCESS_LENGTH(config->accessCtrl.accessLen) |
758                                     ASRC_CTRL_IN_ACCESS_ITERATIONS(config->accessCtrl.accessIterations) |
759                                     ASRC_CTRL_IN_ACCESS_GROUP_LENGTH(config->accessCtrl.accessGroupLen);
760 
761     return kStatus_Success;
762 }
763 
764 /*!
765  * brief ASRC configure context output.
766  *
767  * param base ASRC base pointer.
768  * param context index of asrc context, reference asrc_context_t.
769  * param config ASRC context output configuration pointer.
770  */
ASRC_SetContextOutputConfig(ASRC_Type * base,asrc_context_t context,asrc_context_output_config_t * config)771 status_t ASRC_SetContextOutputConfig(ASRC_Type *base, asrc_context_t context, asrc_context_output_config_t *config)
772 {
773     assert(config != NULL);
774 
775     uint32_t contextReg     = base->CTX_OUT_CTRL[context];
776     uint32_t samplePosition = config->dataFormat.dataPosition;
777 
778     contextReg &=
779         ~(ASRC_CTX_OUT_CTRL_SIGN_OUT_MASK | ASRC_CTX_OUT_CTRL_FLOAT_FMT_MASK | ASRC_CTX_OUT_CTRL_IEC_V_DATA_MASK |
780           ASRC_CTX_OUT_CTRL_DITHER_EN_MASK | ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_MASK | ASRC_CTX_OUT_CTRL_BIT_REV_MASK |
781           ASRC_CTX_OUT_CTRL_SAMPLE_POSITION_MASK | ASRC_CTX_OUT_CTRL_FIFO_WTMK_MASK);
782 
783     contextReg |= ASRC_CTX_OUT_CTRL_FIFO_WTMK(config->watermark);
784 
785     if (config->enableIEC60958)
786     {
787         if (config->dataFormat.dataWidth == kASRC_DataWidth16Bit)
788         {
789             samplePosition = 12U;
790         }
791         else if (config->dataFormat.dataWidth == kASRC_DataWidth20Bit)
792         {
793             samplePosition = 8U;
794         }
795         else if (config->dataFormat.dataWidth == kASRC_DataWidth24Bit)
796         {
797             samplePosition = 4U;
798         }
799         else
800         {
801             return kStatus_InvalidArgument;
802         }
803 
804         contextReg |= ASRC_CTX_OUT_CTRL_IEC_V_DATA_MASK;
805     }
806 
807     contextReg |= ASRC_CTX_OUT_CTRL_DITHER_EN(config->enableDither);
808 
809     contextReg |= ASRC_CTX_OUT_CTRL_SIGN_OUT(config->dataFormat.dataSign) |
810                   ASRC_CTX_OUT_CTRL_FLOAT_FMT(config->dataFormat.dataType) |
811                   ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE(config->dataFormat.dataWidth) |
812                   ASRC_CTX_OUT_CTRL_BIT_REV(config->dataFormat.dataEndianness) |
813                   ASRC_CTX_OUT_CTRL_SAMPLE_POSITION(samplePosition);
814 
815     base->CTX_OUT_CTRL[context] = contextReg;
816 
817     base->CTRL_OUT_ACCESS[context] = ASRC_CTRL_OUT_ACCESS_ACCESS_LENGTH(config->accessCtrl.accessLen) |
818                                      ASRC_CTRL_OUT_ACCESS_ITERATIONS(config->accessCtrl.accessIterations) |
819                                      ASRC_CTRL_OUT_ACCESS_GROUP_LENGTH(config->accessCtrl.accessGroupLen);
820 
821     return kStatus_Success;
822 }
823 
824 /*!
825  * brief ASRC get context default configuration.
826  *
827  * param config ASRC context configuration pointer.
828  * param channels input audio data channel numbers.
829  * param inSampleRate input sample rate.
830  * param outSampleRate output sample rate.
831  */
ASRC_GetContextDefaultConfig(asrc_context_config_t * config,uint32_t channels,uint32_t inSampleRate,uint32_t outSampleRate)832 void ASRC_GetContextDefaultConfig(asrc_context_config_t *config,
833                                   uint32_t channels,
834                                   uint32_t inSampleRate,
835                                   uint32_t outSampleRate)
836 {
837     assert(config != NULL);
838 
839     (void)memset(config, 0, sizeof(asrc_context_config_t));
840 
841     config->contextChannelNums = (uint8_t)channels;
842 
843     /* input configuration */
844     config->contextInput.sampleRate                  = inSampleRate;
845     config->contextInput.watermark                   = FSL_ASRC_INPUT_FIFO_DEPTH / 2U;
846     config->contextInput.accessCtrl.accessIterations = 1;
847     config->contextInput.accessCtrl.accessGroupLen   = (uint8_t)channels;
848     config->contextInput.accessCtrl.accessLen        = (uint8_t)channels;
849     config->contextInput.dataFormat.dataPosition     = 0U;
850     config->contextInput.dataFormat.dataEndianness   = kASRC_DataEndianLittle;
851     config->contextInput.dataFormat.dataWidth        = kASRC_DataWidth16Bit;
852     config->contextInput.dataFormat.dataType         = kASRC_DataTypeInteger;
853     config->contextInput.dataFormat.dataSign         = kASRC_DataSigned;
854     /* output configuration */
855     config->contextOutput.sampleRate                  = outSampleRate;
856     config->contextOutput.watermark                   = FSL_ASRC_OUTPUT_FIFO_DEPTH / 8U;
857     config->contextOutput.accessCtrl.accessIterations = 1;
858     config->contextOutput.accessCtrl.accessGroupLen   = (uint8_t)channels;
859     config->contextOutput.accessCtrl.accessLen        = (uint8_t)channels;
860     config->contextOutput.dataFormat.dataPosition     = 0;
861     config->contextOutput.dataFormat.dataEndianness   = kASRC_DataEndianLittle;
862     config->contextOutput.dataFormat.dataWidth        = kASRC_DataWidth16Bit;
863     config->contextOutput.dataFormat.dataType         = kASRC_DataTypeInteger;
864     config->contextOutput.dataFormat.dataSign         = kASRC_DataSigned;
865     config->contextOutput.enableDither                = false;
866     config->contextOutput.enableIEC60958              = false;
867     /* prefilter configuration */
868     config->contextPrefilter.initMode     = kASRC_SampleBufferFillZeroOnInit;
869     config->contextPrefilter.stopMode     = kASRC_SampleBufferFillLastSampleOnStop;
870     config->contextPrefilter.stage1Result = kASRC_PrefilterStage1ResultFloat;
871     /* resampler configuration */
872     config->contextResampler.initMode = kASRC_SampleBufferFillZeroOnInit;
873     config->contextResampler.stopMode = kASRC_SampleBufferFillLastSampleOnStop;
874     config->contextResampler.tap      = kASRC_ResamplerTaps_128;
875 }
876 
877 /*!
878  * brief ASRC configure context.
879  *
880  * param base ASRC base pointer.
881  * param context index of asrc context, reference asrc_context_t.
882  * param config ASRC context configuration pointer.
883  * retval kStatus_InvalidArgument invalid parameters.
884  *        kStatus_ASRCConfigureFailed context configure failed.
885  *        kStatus_Success context configure success.
886  */
ASRC_SetContextConfig(ASRC_Type * base,asrc_context_t context,asrc_context_config_t * config)887 status_t ASRC_SetContextConfig(ASRC_Type *base, asrc_context_t context, asrc_context_config_t *config)
888 {
889     assert(config != NULL);
890 
891     if ((config->contextChannelNums == 0U) || (config->contextChannelNums > ASRC_SUPPORT_MAXIMUM_CHANNEL_NUMBER))
892     {
893         return kStatus_InvalidArgument;
894     }
895 
896     if (((config->contextInput.sampleRate < (uint32_t)kASRC_SampleRate_8000) ||
897          (config->contextInput.sampleRate > (uint32_t)kASRC_SampleRate_768000)) ||
898         ((config->contextOutput.sampleRate < (uint32_t)kASRC_SampleRate_8000) ||
899          (config->contextOutput.sampleRate > (uint32_t)kASRC_SampleRate_768000)))
900     {
901         return kStatus_InvalidArgument;
902     }
903 
904     /* sampel ratio configure */
905     if (ASRC_SetSampleRateRatioConfig(base, context, config->contextInput.sampleRate, config->contextOutput.sampleRate,
906                                       (asrc_samplerate_ratio_format_t)config->contextResampler.tap) != kStatus_Success)
907     {
908         return kStatus_ASRCConfigureFailed;
909     }
910 
911     /* configure context input */
912     if (ASRC_SetContextInputConfig(base, context, &config->contextInput) != kStatus_Success)
913     {
914         return kStatus_ASRCConfigureFailed;
915     }
916 
917     /* allocate context processor */
918     if (ASRC_SetContextProcessorConfig(base, context, config) != kStatus_Success)
919     {
920         return kStatus_ASRCConfigureFailed;
921     }
922 
923     /* configure context output */
924     if (ASRC_SetContextOutputConfig(base, context, &config->contextOutput) != kStatus_Success)
925     {
926         return kStatus_ASRCConfigureFailed;
927     }
928 
929     return kStatus_Success;
930 }
931 
932 /*!
933  * brief ASRC get output sample count.
934  *
935  * param inSampleRate output sample rate.
936  * param inSamplesSize input sample rate.
937  * param inWidth input samples buffer size, the size of buffer should be converted to align with 4 byte .
938  * param outSampleRate input sample width.
939  * param outWidth Output width.
940  * retval output samples size.
941  */
ASRC_GetContextOutSampleSize(uint32_t inSampleRate,uint32_t inSamplesSize,uint32_t inWidth,uint32_t outSampleRate,uint32_t outWidth)942 uint32_t ASRC_GetContextOutSampleSize(
943     uint32_t inSampleRate, uint32_t inSamplesSize, uint32_t inWidth, uint32_t outSampleRate, uint32_t outWidth)
944 {
945     uint32_t reminder = (((uint64_t)inSamplesSize / inWidth) * outSampleRate % inSampleRate) == 0U ? 0U : 1U;
946     uint32_t quotient = (uint32_t)(((uint64_t)inSamplesSize / inWidth) * outSampleRate / inSampleRate);
947 
948     return (reminder + quotient) * outWidth;
949 }
950 
951 /*!
952  * brief Get the ASRC read fifo remained samples.
953  * Since the DMA request will be triggered only when the sample group in read fifo is bigger then the watermark, so when
954  * the data size cannot be divisible by the (watermark + 1), then part of sample will left in read fifo, application
955  * should call this api to get the left samples.
956  *
957  * param base ASRC base pointer.
958  * param context context id.
959  * param outAddr address to receive remained sample in read fifo.
960  * param outWidth output data width.
961  * param sampleCount specify the read sample count.
962  * retval sample counts actual read from output fifo.
963  */
ASRC_ReadFIFORemainedSample(ASRC_Type * base,asrc_context_t context,uint32_t * outAddr,uint32_t outWidth,uint32_t sampleCount)964 uint32_t ASRC_ReadFIFORemainedSample(
965     ASRC_Type *base, asrc_context_t context, uint32_t *outAddr, uint32_t outWidth, uint32_t sampleCount)
966 {
967     uint32_t remainSample = base->SAMPLE_FIFO_STATUS[context] & ASRC_SAMPLE_FIFO_STATUS_NUM_SAMPLE_GROUPS_OUT_MASK;
968     uint32_t channel      = (base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U;
969     uint32_t i = 0U, sizeToRead = remainSample * channel;
970 
971     if (sizeToRead == 0U)
972     {
973         return 0U;
974     }
975 
976     if (sampleCount < sizeToRead)
977     {
978         sizeToRead = sampleCount;
979     }
980 
981     for (i = 0U; i < sizeToRead; i++)
982     {
983         *outAddr = ASRC_ReadContextFifo(base, context);
984         outAddr  = (uint32_t *)((size_t)outAddr + outWidth);
985     }
986 
987     return sizeToRead;
988 }
989 
990 /*!
991  * brief ASRC blocking convert audio sample rate.
992  * This function depends on the configuration of input and output, so it should be called after the
993  * ASRC_SetContextConfig. The data format it supports:
994  * 1.16bit 16bit per sample in input buffer, input buffer size
995  * should be calculate as: samples 2U output buffer size can be calculated by call function
996  * ASRC_GetContextOutSampleSize, the parameter outWidth should be 2
997  * 2.20bit 24bit per sample in input buffer, input buffer size should be calculate as: samples 3U output buffer size can
998  * be calculated by call function ASRC_GetContextOutSampleSize, the outWidth should be 3. 3.24bit 24bit per sample in
999  * input buffer, input buffer size should be calculate as: samples * 3U output buffer size can be calculated by call
1000  * function ASRC_GetContextOutSampleSize, the outWidth should be 3. 4.32bit 32bit per sample in input buffer, input
1001  * buffer size should be calculate as: samples * 4U output buffer size can be calculated by call function
1002  * ASRC_GetContextOutSampleSize, the outWidth should be 4.
1003  *
1004  * param base ASRC base pointer.
1005  * param context context id.
1006  * param xfer .xfer configuration.
1007  * retval kStatus_Success.
1008  */
ASRC_TransferBlocking(ASRC_Type * base,asrc_context_t context,asrc_transfer_t * xfer)1009 status_t ASRC_TransferBlocking(ASRC_Type *base, asrc_context_t context, asrc_transfer_t *xfer)
1010 {
1011     assert((xfer->inDataAddr != NULL) && (xfer->outDataAddr != NULL));
1012     assert(xfer->inDataSize % sizeof(uint32_t) == 0U);
1013 
1014     uint32_t inWatermarkSamples =
1015         (((base->CTX_CTRL[context] & ASRC_CTX_CTRL_FIFO_WTMK_MASK) >> ASRC_CTX_CTRL_FIFO_WTMK_SHIFT) + 1U) *
1016         ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U);
1017     uint32_t outWatermarkSamples =
1018         (((base->CTX_OUT_CTRL[context] & ASRC_CTX_OUT_CTRL_FIFO_WTMK_MASK) >> ASRC_CTX_OUT_CTRL_FIFO_WTMK_SHIFT) + 1U) *
1019         ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_NUM_CH_EN_MASK) + 1U);
1020     uint32_t inWidth =
1021         ((base->CTX_CTRL[context] & ASRC_CTX_CTRL_BITS_PER_SAMPLE_MASK) >> ASRC_CTX_CTRL_BITS_PER_SAMPLE_SHIFT);
1022     uint32_t outWidth = ((base->CTX_OUT_CTRL[context] & ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_MASK) >>
1023                          ASRC_CTX_OUT_CTRL_BITS_PER_SAMPLE_SHIFT);
1024     uint32_t inMask =
1025         (inWidth == (uint32_t)kASRC_DataWidth32Bit ? 0xFFFFFFFFU :
1026                                                      inWidth == (uint32_t)kASRC_DataWidth24Bit ?
1027                                                      0xFFFFFFU :
1028                                                      inWidth == (uint32_t)kASRC_DataWidth20Bit ? 0xFFFFFU : 0xFFFFU);
1029     inWidth =
1030         (inWidth == (uint32_t)kASRC_DataWidth32Bit ?
1031              4U :
1032              inWidth == (uint32_t)kASRC_DataWidth24Bit ? 3U : inWidth == (uint32_t)kASRC_DataWidth20Bit ? 3U : 2U);
1033     outWidth =
1034         (outWidth == (uint32_t)kASRC_DataWidth32Bit ?
1035              4U :
1036              outWidth == (uint32_t)kASRC_DataWidth24Bit ? 3U : outWidth == (uint32_t)kASRC_DataWidth20Bit ? 3U : 2U);
1037     uint32_t inSamples     = xfer->inDataSize / inWidth;
1038     uint32_t outSamples    = xfer->outDataSize / outWidth;
1039     uint32_t *writePointer = xfer->inDataAddr;
1040     uint32_t *readPointer  = xfer->outDataAddr;
1041 
1042     uint32_t writtenSamples = 0U, readSamples = 0U, i = 0U, j = 0U;
1043     /* enable context run */
1044     ASRC_EnableContextRun(base, context, true);
1045     ASRC_EnableContextRunStop(base, context, false);
1046 
1047     while ((inSamples != 0U) || (outSamples != 0U))
1048     {
1049         if (inSamples != 0U)
1050         {
1051             if (inSamples < inWatermarkSamples)
1052             {
1053                 writtenSamples = inSamples;
1054             }
1055             else
1056             {
1057                 writtenSamples = inWatermarkSamples;
1058             }
1059 
1060             if ((ASRC_GetFifoStatus(base, context) & (uint32_t)kASRC_FifoStatusInputFifoWatermarkFlag) != 0U)
1061             {
1062                 for (i = 0U; i < writtenSamples; i++)
1063                 {
1064                     ASRC_WriteContextFifo(base, context, *writePointer & inMask);
1065                     writePointer = (uint32_t *)((size_t)writePointer + inWidth);
1066                 }
1067 
1068                 inSamples -= writtenSamples;
1069             }
1070         }
1071 
1072         if (outSamples <= outWatermarkSamples)
1073         {
1074             readSamples = ASRC_ReadFIFORemainedSample(base, context, readPointer, outWidth, outSamples);
1075             /* for the case that all the output samples have write to the output fifo and all the fifo samples has been
1076              * read */
1077             if (((ASRC_GetInterruptStatus(base) & ((uint32_t)kASRC_Context0RunStopDone << (uint32_t)context)) != 0U) &&
1078                 (readSamples == 0U))
1079             {
1080                 ASRC_ClearInterruptStatus(base, ((uint32_t)kASRC_Context0RunStopDone << (uint32_t)context));
1081                 break;
1082             }
1083             outSamples -= readSamples;
1084             continue;
1085         }
1086         else
1087         {
1088             readSamples = outWatermarkSamples;
1089         }
1090 
1091         if ((ASRC_GetFifoStatus(base, context) & (uint32_t)kASRC_FifoStatusOutputFifoWatermarkFlag) != 0U)
1092         {
1093             for (j = 0U; j < readSamples; j++)
1094             {
1095                 *readPointer = ASRC_ReadContextFifo(base, context);
1096                 readPointer  = (uint32_t *)((size_t)readPointer + outWidth);
1097             }
1098             outSamples -= readSamples;
1099         }
1100         else
1101         {
1102             /* flush all the samples out */
1103             if ((inSamples == 0U) && (outSamples > outWatermarkSamples))
1104             {
1105                 ASRC_EnableContextRunStop(base, context, true);
1106             }
1107         }
1108     }
1109 
1110     /* disable context run */
1111     ASRC_EnableContextRun(base, context, false);
1112     ASRC_EnableContextRunStop(base, context, false);
1113 
1114     return kStatus_Success;
1115 }
1116