@@ -21,7 +21,6 @@ LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
2121
2222#if CONFIG_SOC_SERIES_NRF54HX
2323#define DMIC_NRFX_CLOCK_FREQ MHZ(16)
24- #define DMIC_NRFX_CLOCK_FACTOR 8192
2524#define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(NODE_AUDIOPLL, frequency, 0)
2625#elif DT_NODE_HAS_STATUS_OKAY (NODE_AUDIO_AUXPLL )
2726#define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP(NODE_AUDIO_AUXPLL, nordic_frequency)
@@ -31,7 +30,6 @@ BUILD_ASSERT((DMIC_NRFX_AUDIO_CLOCK_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K) ||
3130#define DMIC_NRFX_CLOCK_FREQ MHZ(32)
3231#else
3332#define DMIC_NRFX_CLOCK_FREQ MHZ(32)
34- #define DMIC_NRFX_CLOCK_FACTOR 4096
3533#define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(DT_NODELABEL(aclk), clock_frequency, \
3634 DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0))
3735#endif
@@ -202,220 +200,6 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
202200 }
203201}
204202
205- static bool is_in_freq_range (uint32_t freq , const struct dmic_cfg * pdm_cfg )
206- {
207- return freq >= pdm_cfg -> io .min_pdm_clk_freq && freq <= pdm_cfg -> io .max_pdm_clk_freq ;
208- }
209-
210- static bool is_better (uint32_t freq ,
211- uint8_t ratio ,
212- uint32_t req_rate ,
213- uint32_t * best_diff ,
214- uint32_t * best_rate ,
215- uint32_t * best_freq )
216- {
217- uint32_t act_rate = freq / ratio ;
218- uint32_t diff = act_rate >= req_rate ? (act_rate - req_rate )
219- : (req_rate - act_rate );
220-
221- LOG_DBG ("Freq %u, ratio %u, act_rate %u" , freq , ratio , act_rate );
222-
223- if (diff < * best_diff ) {
224- * best_diff = diff ;
225- * best_rate = act_rate ;
226- * best_freq = freq ;
227- return true;
228- }
229-
230- return false;
231- }
232-
233- static bool check_pdm_frequencies (const struct dmic_nrfx_pdm_drv_cfg * drv_cfg ,
234- nrfx_pdm_config_t * config ,
235- const struct dmic_cfg * pdm_cfg ,
236- uint8_t ratio ,
237- uint32_t * best_diff ,
238- uint32_t * best_rate ,
239- uint32_t * best_freq )
240- {
241- uint32_t req_rate = pdm_cfg -> streams [0 ].pcm_rate ;
242- bool better_found = false;
243- const uint32_t src_freq =
244- (NRF_PDM_HAS_SELECTABLE_CLOCK && drv_cfg -> clk_src == ACLK )
245- ? DMIC_NRFX_AUDIO_CLOCK_FREQ
246- : DMIC_NRFX_CLOCK_FREQ ;
247- #if NRF_PDM_HAS_PRESCALER
248- uint32_t req_freq = req_rate * ratio ;
249- uint32_t prescaler = src_freq / req_freq ;
250- uint32_t act_freq = src_freq / prescaler ;
251-
252- if (is_in_freq_range (act_freq , pdm_cfg ) &&
253- is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
254- config -> prescaler = prescaler ;
255-
256- better_found = true;
257- }
258-
259- /* Stop if an exact rate match is found. */
260- if (* best_diff == 0 ) {
261- return true;
262- }
263-
264- /* Prescaler value is rounded down by default,
265- * thus value rounded up should be checked as well.
266- */
267- prescaler += 1 ;
268- act_freq = src_freq / prescaler ;
269-
270- if (is_in_freq_range (act_freq , pdm_cfg ) &&
271- is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
272- config -> prescaler = prescaler ;
273-
274- better_found = true;
275- }
276- #else
277- if (IS_ENABLED (CONFIG_SOC_SERIES_NRF53X ) || IS_ENABLED (CONFIG_SOC_SERIES_NRF54HX )) {
278- uint32_t req_freq = req_rate * ratio ;
279- /* As specified in the nRF5340 PS:
280- *
281- * PDMCLKCTRL = 4096 * floor(f_pdm * 1048576 /
282- * (f_source + f_pdm / 2))
283- * f_actual = f_source / floor(1048576 * 4096 / PDMCLKCTRL)
284- */
285- uint32_t clk_factor = (uint32_t )((req_freq * 1048576ULL ) /
286- (src_freq + req_freq / 2 ));
287- uint32_t act_freq = src_freq / (1048576 / clk_factor );
288-
289- if (is_in_freq_range (act_freq , pdm_cfg ) &&
290- is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
291- config -> clock_freq = clk_factor * DMIC_NRFX_CLOCK_FACTOR ;
292-
293- better_found = true;
294- }
295- } else { /* -> !IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) */
296- static const struct {
297- uint32_t freq_val ;
298- nrf_pdm_freq_t freq_enum ;
299- } freqs [] = {
300- { 1000000 , NRF_PDM_FREQ_1000K },
301- { 1032000 , NRF_PDM_FREQ_1032K },
302- { 1067000 , NRF_PDM_FREQ_1067K },
303- #if defined(PDM_PDMCLKCTRL_FREQ_1231K )
304- { 1231000 , NRF_PDM_FREQ_1231K },
305- #endif
306- #if defined(PDM_PDMCLKCTRL_FREQ_1280K )
307- { 1280000 , NRF_PDM_FREQ_1280K },
308- #endif
309- #if defined(PDM_PDMCLKCTRL_FREQ_1333K )
310- { 1333000 , NRF_PDM_FREQ_1333K }
311- #endif
312- };
313-
314- for (int i = 0 ; i < ARRAY_SIZE (freqs ); ++ i ) {
315- uint32_t freq_val = freqs [i ].freq_val ;
316-
317- if (freq_val < pdm_cfg -> io .min_pdm_clk_freq ) {
318- continue ;
319- }
320- if (freq_val > pdm_cfg -> io .max_pdm_clk_freq ) {
321- break ;
322- }
323-
324- if (is_better (freq_val , ratio , req_rate ,
325- best_diff , best_rate , best_freq )) {
326- config -> clock_freq = freqs [i ].freq_enum ;
327-
328- /* Stop if an exact rate match is found. */
329- if (* best_diff == 0 ) {
330- return true;
331- }
332-
333- better_found = true;
334- }
335-
336- /* Since frequencies are in ascending order, stop
337- * checking next ones for the current ratio after
338- * resulting PCM rate goes above the one requested.
339- */
340- if ((freq_val / ratio ) > req_rate ) {
341- break ;
342- }
343- }
344- }
345- #endif /* NRF_PDM_HAS_PRESCALER */
346-
347- return better_found ;
348- }
349-
350- /* Finds clock settings that give the PCM output rate closest to that requested,
351- * taking into account the hardware limitations.
352- */
353- static bool find_suitable_clock (const struct dmic_nrfx_pdm_drv_cfg * drv_cfg ,
354- nrfx_pdm_config_t * config ,
355- const struct dmic_cfg * pdm_cfg )
356- {
357- uint32_t best_diff = UINT32_MAX ;
358- uint32_t best_rate ;
359- uint32_t best_freq ;
360-
361- #if NRF_PDM_HAS_RATIO_CONFIG
362- static const struct {
363- uint8_t ratio_val ;
364- nrf_pdm_ratio_t ratio_enum ;
365- } ratios [] = {
366- #if defined(PDM_RATIO_RATIO_Ratio32 )
367- { 32 , NRF_PDM_RATIO_32X },
368- #endif
369- #if defined(PDM_RATIO_RATIO_Ratio48 )
370- { 48 , NRF_PDM_RATIO_48X },
371- #endif
372- #if defined(PDM_RATIO_RATIO_Ratio50 )
373- { 50 , NRF_PDM_RATIO_50X },
374- #endif
375- { 64 , NRF_PDM_RATIO_64X },
376- { 80 , NRF_PDM_RATIO_80X },
377- #if defined(PDM_RATIO_RATIO_Ratio96 )
378- { 96 , NRF_PDM_RATIO_96X },
379- #endif
380- #if defined(PDM_RATIO_RATIO_Ratio100 )
381- { 100 , NRF_PDM_RATIO_100X },
382- #endif
383- #if defined(PDM_RATIO_RATIO_Ratio128 )
384- { 128 , NRF_PDM_RATIO_128X }
385- #endif
386- };
387-
388- for (int r = 0 ; best_diff != 0 && r < ARRAY_SIZE (ratios ); ++ r ) {
389- uint8_t ratio = ratios [r ].ratio_val ;
390-
391- if (check_pdm_frequencies (drv_cfg , config , pdm_cfg , ratio ,
392- & best_diff , & best_rate , & best_freq )) {
393- config -> ratio = ratios [r ].ratio_enum ;
394-
395- /* Look no further if a configuration giving the exact
396- * PCM rate is found.
397- */
398- if (best_diff == 0 ) {
399- break ;
400- }
401- }
402- }
403- #else
404- uint8_t ratio = 64 ;
405-
406- (void )check_pdm_frequencies (drv_cfg , config , pdm_cfg , ratio ,
407- & best_diff , & best_rate , & best_freq );
408- #endif
409-
410- if (best_diff == UINT32_MAX ) {
411- return false;
412- }
413-
414- LOG_INF ("PDM clock frequency: %u, actual PCM rate: %u" ,
415- best_freq , best_rate );
416- return true;
417- }
418-
419203static int dmic_nrfx_pdm_configure (const struct device * dev ,
420204 struct dmic_cfg * config )
421205{
@@ -499,7 +283,16 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
499283 ? NRF_PDM_MCLKSRC_ACLK
500284 : NRF_PDM_MCLKSRC_PCLK32M ;
501285#endif
502- if (!find_suitable_clock (drv_cfg , & nrfx_cfg , config )) {
286+ nrfx_pdm_output_t output_config = {
287+ .base_clock_freq = (NRF_PDM_HAS_SELECTABLE_CLOCK && drv_cfg -> clk_src == ACLK )
288+ ? DMIC_NRFX_AUDIO_CLOCK_FREQ
289+ : DMIC_NRFX_CLOCK_FREQ ,
290+ .sampling_rate = config -> streams [0 ].pcm_rate ,
291+ .output_freq_min = config -> io .min_pdm_clk_freq ,
292+ .output_freq_max = config -> io .max_pdm_clk_freq
293+ };
294+
295+ if (nrfx_pdm_prescalers_calc (& output_config , & nrfx_cfg .prescalers ) != NRFX_SUCCESS ) {
503296 LOG_ERR ("Cannot find suitable PDM clock configuration." );
504297 return - EINVAL ;
505298 }
0 commit comments