1 /*
2 * Copyright (c) 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_dmic.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.dmic"
14 #endif
15
16 /*******************************************************************************
17 * Variables
18 ******************************************************************************/
19
20 /* Array of DMIC peripheral base address. */
21 static DMIC_Type *const s_dmicBases[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_BASE_PTRS;
22
23 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
24 /* Array of DMIC clock name. */
25 static const clock_ip_name_t s_dmicClock[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_CLOCKS;
26 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
27
28 /* Array of DMIC IRQ number. */
29 static const IRQn_Type s_dmicIRQ[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_IRQS;
30
31 /*! @brief Callback function array for DMIC(s). */
32 static dmic_callback_t s_dmicCallback[FSL_FEATURE_SOC_DMIC_COUNT];
33
34 /* Array of HWVAD IRQ number. */
35 static const IRQn_Type s_dmicHwvadIRQ[FSL_FEATURE_SOC_DMIC_COUNT] = DMIC_HWVAD_IRQS;
36
37 /*! @brief Callback function array for HWVAD(s). */
38 static dmic_hwvad_callback_t s_dmicHwvadCallback[FSL_FEATURE_SOC_DMIC_COUNT];
39
40 /*******************************************************************************
41 * Prototypes
42 ******************************************************************************/
43 /*!
44 * @brief Get the DMIC instance from peripheral base address.
45 *
46 * @param base DMIC peripheral base address.
47 * @return DMIC instance.
48 */
49 /*!
50 * brief Get the DMIC instance from peripheral base address.
51 *
52 * param base DMIC peripheral base address.
53 * return DMIC instance.
54 */
DMIC_GetInstance(DMIC_Type * base)55 uint32_t DMIC_GetInstance(DMIC_Type *base)
56 {
57 uint32_t instance;
58
59 /* Find the instance index from base address mappings. */
60 for (instance = 0; instance < ARRAY_SIZE(s_dmicBases); instance++)
61 {
62 if (s_dmicBases[instance] == base)
63 {
64 break;
65 }
66 }
67
68 assert(instance < ARRAY_SIZE(s_dmicBases));
69
70 return instance;
71 }
72
73 /*!
74 * brief Turns DMIC Clock on
75 * param base : DMIC base
76 * return Nothing
77 */
DMIC_Init(DMIC_Type * base)78 void DMIC_Init(DMIC_Type *base)
79 {
80 assert(base != NULL);
81
82 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
83 /* Enable the clock. */
84 CLOCK_EnableClock(s_dmicClock[DMIC_GetInstance(base)]);
85 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
86
87 #if !(defined(FSL_SDK_DISABLE_DRIVER_RESET_CONTROL) && FSL_SDK_DISABLE_DRIVER_RESET_CONTROL)
88 /* Reset the module. */
89 RESET_PeripheralReset(kDMIC_RST_SHIFT_RSTn);
90 #endif /* FSL_SDK_DISABLE_DRIVER_RESET_CONTROL */
91
92 /* reset FIFO configuration */
93 base->CHANNEL[0].FIFO_CTRL = 0U;
94 base->CHANNEL[1].FIFO_CTRL = 0U;
95 #if defined(FSL_FEATURE_DMIC_CHANNEL_NUM) && (FSL_FEATURE_DMIC_CHANNEL_NUM > 2U)
96 base->CHANNEL[2].FIFO_CTRL = 0U;
97 base->CHANNEL[3].FIFO_CTRL = 0U;
98 #endif
99 #if defined(FSL_FEATURE_DMIC_CHANNEL_NUM) && (FSL_FEATURE_DMIC_CHANNEL_NUM > 4U)
100 base->CHANNEL[4].FIFO_CTRL = 0U;
101 base->CHANNEL[5].FIFO_CTRL = 0U;
102 base->CHANNEL[6].FIFO_CTRL = 0U;
103 base->CHANNEL[7].FIFO_CTRL = 0U;
104 #endif
105 }
106
107 /*!
108 * brief Turns DMIC Clock off
109 * param base : DMIC base
110 * return Nothing
111 */
DMIC_DeInit(DMIC_Type * base)112 void DMIC_DeInit(DMIC_Type *base)
113 {
114 assert(base != NULL);
115
116 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
117 /* Disable the clock. */
118 CLOCK_DisableClock(s_dmicClock[DMIC_GetInstance(base)]);
119 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
120 }
121
122 #if !(defined(FSL_FEATURE_DMIC_HAS_NO_IOCFG) && FSL_FEATURE_DMIC_HAS_NO_IOCFG)
123 /*!
124 * brief Configure DMIC io
125 * @deprecated Do not use this function. It has been superceded by @ref DMIC_SetIOCFG
126 * param base : The base address of DMIC interface
127 * param config : DMIC io configuration
128 * return Nothing
129 */
DMIC_ConfigIO(DMIC_Type * base,dmic_io_t config)130 void DMIC_ConfigIO(DMIC_Type *base, dmic_io_t config)
131 {
132 base->IOCFG = (uint32_t)config;
133 }
134 #endif
135
136 /*!
137 * brief Set DMIC operating mode
138 * deprecated Do not use this function. It has been superceded by @ref
139 * DMIC_EnableChannelInterrupt/DMIC_EnableChannelDma
140 * param base : The base address of DMIC interface
141 * param mode : DMIC mode
142 * return Nothing
143 */
DMIC_SetOperationMode(DMIC_Type * base,operation_mode_t mode)144 void DMIC_SetOperationMode(DMIC_Type *base, operation_mode_t mode)
145 {
146 if (mode == kDMIC_OperationModeInterrupt)
147 {
148 /* Enable DMIC interrupt. */
149 base->CHANNEL[0].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
150 base->CHANNEL[1].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
151 }
152 if (mode == kDMIC_OperationModeDma)
153 {
154 /* enable DMA request*/
155 base->CHANNEL[0].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
156 base->CHANNEL[1].FIFO_CTRL |= DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
157 }
158 }
159
160 /*!
161 * brief Configure DMIC channel
162 *
163 * param base : The base address of DMIC interface
164 * param channel : DMIC channel
165 * param side : stereo_side_t, choice of left or right
166 * param channel_config : Channel configuration
167 * return Nothing
168 */
DMIC_ConfigChannel(DMIC_Type * base,dmic_channel_t channel,stereo_side_t side,dmic_channel_config_t * channel_config)169 void DMIC_ConfigChannel(DMIC_Type *base,
170 dmic_channel_t channel,
171 stereo_side_t side,
172 dmic_channel_config_t *channel_config)
173 {
174 base->CHANNEL[channel].DIVHFCLK = (uint32_t)channel_config->divhfclk;
175 base->CHANNEL[channel].OSR = channel_config->osr;
176 base->CHANNEL[channel].GAINSHIFT = (uint32_t)channel_config->gainshft;
177 base->CHANNEL[channel].PREAC2FSCOEF = (uint32_t)channel_config->preac2coef;
178 base->CHANNEL[channel].PREAC4FSCOEF = (uint32_t)channel_config->preac4coef;
179 base->CHANNEL[channel].PHY_CTRL =
180 DMIC_CHANNEL_PHY_CTRL_PHY_FALL(side) | DMIC_CHANNEL_PHY_CTRL_PHY_HALF(channel_config->sample_rate);
181 base->CHANNEL[channel].DC_CTRL = DMIC_CHANNEL_DC_CTRL_DCPOLE(channel_config->dc_cut_level) |
182 DMIC_CHANNEL_DC_CTRL_DCGAIN(channel_config->post_dc_gain_reduce) |
183 DMIC_CHANNEL_DC_CTRL_SATURATEAT16BIT(channel_config->saturate16bit);
184
185 #if defined(FSL_FEATURE_DMIC_CHANNEL_HAS_SIGNEXTEND) && (FSL_FEATURE_DMIC_CHANNEL_HAS_SIGNEXTEND)
186 base->CHANNEL[channel].DC_CTRL |= DMIC_CHANNEL_DC_CTRL_SIGNEXTEND(channel_config->enableSignExtend);
187 #endif
188 }
189
190 /*!
191 * brief Configure DMIC channel
192 * param base : The base address of DMIC interface
193 * param channel : DMIC channel
194 * param dc_cut_level : dc_removal_t, Cut off Frequency
195 * param post_dc_gain_reduce : Fine g!y!9
196 * param saturate16bit : If selects 16-bit saturation.
197 */
DMIC_CfgChannelDc(DMIC_Type * base,dmic_channel_t channel,dc_removal_t dc_cut_level,uint32_t post_dc_gain_reduce,bool saturate16bit)198 void DMIC_CfgChannelDc(DMIC_Type *base,
199 dmic_channel_t channel,
200 dc_removal_t dc_cut_level,
201 uint32_t post_dc_gain_reduce,
202 bool saturate16bit)
203 {
204 base->CHANNEL[channel].DC_CTRL = DMIC_CHANNEL_DC_CTRL_DCPOLE(dc_cut_level) |
205 DMIC_CHANNEL_DC_CTRL_DCGAIN(post_dc_gain_reduce) |
206 DMIC_CHANNEL_DC_CTRL_SATURATEAT16BIT(saturate16bit);
207 }
208
209 /*!
210 * brief Configure Clock scaling
211 * param base : The base address of DMIC interface
212 * param use2fs : clock scaling
213 * return Nothing
214 */
DMIC_Use2fs(DMIC_Type * base,bool use2fs)215 void DMIC_Use2fs(DMIC_Type *base, bool use2fs)
216 {
217 base->USE2FS = (use2fs) ? 0x1UL : 0x0UL;
218 }
219
220 /*!
221 * brief Enable a particualr channel
222 * param base : The base address of DMIC interface
223 * param channelmask : Channel selection
224 * return Nothing
225 */
DMIC_EnableChannnel(DMIC_Type * base,uint32_t channelmask)226 void DMIC_EnableChannnel(DMIC_Type *base, uint32_t channelmask)
227 {
228 base->CHANEN |= channelmask;
229 }
230
231 /*!
232 * brief Configure fifo settings for DMIC channel
233 * param base : The base address of DMIC interface
234 * param channel : DMIC channel
235 * param trig_level : FIFO trigger level
236 * param enable : FIFO level
237 * param resetn : FIFO reset
238 * return Nothing
239 */
DMIC_FifoChannel(DMIC_Type * base,uint32_t channel,uint32_t trig_level,uint32_t enable,uint32_t resetn)240 void DMIC_FifoChannel(DMIC_Type *base, uint32_t channel, uint32_t trig_level, uint32_t enable, uint32_t resetn)
241 {
242 base->CHANNEL[channel].FIFO_CTRL =
243 ((base->CHANNEL[channel].FIFO_CTRL & (DMIC_CHANNEL_FIFO_CTRL_INTEN_MASK | DMIC_CHANNEL_FIFO_CTRL_DMAEN_MASK)) |
244 DMIC_CHANNEL_FIFO_CTRL_TRIGLVL(trig_level) | DMIC_CHANNEL_FIFO_CTRL_ENABLE(enable) |
245 DMIC_CHANNEL_FIFO_CTRL_RESETN(resetn));
246 }
247
248 #if defined(FSL_FEATURE_DMIC_HAS_DECIMATOR_RESET_FUNC) && FSL_FEATURE_DMIC_HAS_DECIMATOR_RESET_FUNC
249 /*!
250 * brief DMIC channel Decimator reset
251 * param base : The base address of DMIC interface
252 * param channelMask : DMIC channel mask, reference _dmic_channel_mask
253 * param reset : true is reset decimator, false is release decimator.
254 */
DMIC_ResetChannelDecimator(DMIC_Type * base,uint32_t channelMask,bool reset)255 void DMIC_ResetChannelDecimator(DMIC_Type *base, uint32_t channelMask, bool reset)
256 {
257 uint32_t decReset = 0U;
258
259 if ((channelMask & ((uint32_t)kDMIC_EnableChannel1 | (uint32_t)kDMIC_EnableChannel0)) != 0U)
260 {
261 decReset |= 1U;
262 }
263 #if defined(FSL_FEATURE_DMIC_CHANNEL_NUM) && (FSL_FEATURE_DMIC_CHANNEL_NUM > 2U)
264 if ((channelMask & ((uint32_t)kDMIC_EnableChannel3 | (uint32_t)kDMIC_EnableChannel2)) != 0U)
265 {
266 decReset |= 2U;
267 }
268 #endif
269 #if defined(FSL_FEATURE_DMIC_CHANNEL_NUM) && (FSL_FEATURE_DMIC_CHANNEL_NUM > 4U)
270 if ((channelMask & ((uint32_t)kDMIC_EnableChannel5 | (uint32_t)kDMIC_EnableChannel4)) != 0U)
271 {
272 decReset |= 4U;
273 }
274
275 if ((channelMask & ((uint32_t)kDMIC_EnableChannel7 | (uint32_t)kDMIC_EnableChannel6)) != 0U)
276 {
277 decReset |= 8U;
278 }
279 #endif
280
281 if (reset)
282 {
283 base->DECRESET |= decReset;
284 }
285 else
286 {
287 base->DECRESET &= ~decReset;
288 }
289 }
290 #endif
291
292 /*!
293 * brief Enable callback.
294
295 * This function enables the interrupt for the selected DMIC peripheral.
296 * The callback function is not enabled until this function is called.
297 *
298 * param base Base address of the DMIC peripheral.
299 * param cb callback Pointer to store callback function.
300 * retval None.
301 */
DMIC_EnableIntCallback(DMIC_Type * base,dmic_callback_t cb)302 void DMIC_EnableIntCallback(DMIC_Type *base, dmic_callback_t cb)
303 {
304 uint32_t instance;
305
306 instance = DMIC_GetInstance(base);
307 NVIC_ClearPendingIRQ(s_dmicIRQ[instance]);
308 /* Save callback pointer */
309 s_dmicCallback[instance] = cb;
310 (void)EnableIRQ(s_dmicIRQ[instance]);
311 }
312
313 /*!
314 * brief Disable callback.
315
316 * This function disables the interrupt for the selected DMIC peripheral.
317 *
318 * param base Base address of the DMIC peripheral.
319 * param cb callback Pointer to store callback function..
320 * retval None.
321 */
DMIC_DisableIntCallback(DMIC_Type * base,dmic_callback_t cb)322 void DMIC_DisableIntCallback(DMIC_Type *base, dmic_callback_t cb)
323 {
324 uint32_t instance;
325
326 instance = DMIC_GetInstance(base);
327 (void)DisableIRQ(s_dmicIRQ[instance]);
328 s_dmicCallback[instance] = NULL;
329 NVIC_ClearPendingIRQ(s_dmicIRQ[instance]);
330 }
331
332 /*!
333 * brief Enable hwvad callback.
334
335 * This function enables the hwvad interrupt for the selected DMIC peripheral.
336 * The callback function is not enabled until this function is called.
337 *
338 * param base Base address of the DMIC peripheral.
339 * param vadcb callback Pointer to store callback function.
340 * retval None.
341 */
DMIC_HwvadEnableIntCallback(DMIC_Type * base,dmic_hwvad_callback_t vadcb)342 void DMIC_HwvadEnableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb)
343 {
344 uint32_t instance;
345
346 instance = DMIC_GetInstance(base);
347 NVIC_ClearPendingIRQ(s_dmicHwvadIRQ[instance]);
348 /* Save callback pointer */
349 s_dmicHwvadCallback[instance] = vadcb;
350 (void)EnableIRQ(s_dmicHwvadIRQ[instance]);
351 }
352
353 /*!
354 * brief Disable callback.
355
356 * This function disables the hwvad interrupt for the selected DMIC peripheral.
357 *
358 * param base Base address of the DMIC peripheral.
359 * param vadcb callback Pointer to store callback function..
360 * retval None.
361 */
DMIC_HwvadDisableIntCallback(DMIC_Type * base,dmic_hwvad_callback_t vadcb)362 void DMIC_HwvadDisableIntCallback(DMIC_Type *base, dmic_hwvad_callback_t vadcb)
363 {
364 uint32_t instance;
365
366 instance = DMIC_GetInstance(base);
367 (void)DisableIRQ(s_dmicHwvadIRQ[instance]);
368 s_dmicHwvadCallback[instance] = NULL;
369 NVIC_ClearPendingIRQ(s_dmicHwvadIRQ[instance]);
370 }
371
372 /* IRQ handler functions overloading weak symbols in the startup */
373 #if defined(DMIC0)
374 /*DMIC0 IRQ handler */
375 void DMIC0_DriverIRQHandler(void);
DMIC0_DriverIRQHandler(void)376 void DMIC0_DriverIRQHandler(void)
377 {
378 if (s_dmicCallback[0] != NULL)
379 {
380 s_dmicCallback[0]();
381 }
382 SDK_ISR_EXIT_BARRIER;
383 }
384 /*DMIC0 HWVAD IRQ handler */
385 void HWVAD0_DriverIRQHandler(void);
HWVAD0_DriverIRQHandler(void)386 void HWVAD0_DriverIRQHandler(void)
387 {
388 if (s_dmicHwvadCallback[0] != NULL)
389 {
390 s_dmicHwvadCallback[0]();
391 }
392 SDK_ISR_EXIT_BARRIER;
393 }
394 #endif
395