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