1515LOG_MODULE_REGISTER (dmic_nrfx_pdm , CONFIG_AUDIO_DMIC_LOG_LEVEL );
1616
1717struct dmic_nrfx_pdm_drv_data {
18+ const nrfx_pdm_t * pdm ;
1819 struct onoff_manager * clk_mgr ;
1920 struct onoff_client clk_cli ;
2021 struct k_mem_slab * mem_slab ;
@@ -58,8 +59,7 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
5859 LOG_ERR ("Failed to allocate buffer: %d" , ret );
5960 stop = true;
6061 } else {
61- err = nrfx_pdm_buffer_set (buffer ,
62- drv_data -> block_size / 2 );
62+ err = nrfx_pdm_buffer_set (drv_data -> pdm , buffer , drv_data -> block_size / 2 );
6363 if (err != NRFX_SUCCESS ) {
6464 LOG_ERR ("Failed to set buffer: 0x%08x" , err );
6565 stop = true;
@@ -94,10 +94,15 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
9494
9595 if (stop ) {
9696 drv_data -> stopping = true;
97- nrfx_pdm_stop ();
97+ nrfx_pdm_stop (drv_data -> pdm );
9898 }
9999}
100100
101+ static bool is_in_freq_range (uint32_t freq , const struct dmic_cfg * pdm_cfg )
102+ {
103+ return freq >= pdm_cfg -> io .min_pdm_clk_freq && freq <= pdm_cfg -> io .max_pdm_clk_freq ;
104+ }
105+
101106static bool is_better (uint32_t freq ,
102107 uint8_t ratio ,
103108 uint32_t req_rate ,
@@ -132,6 +137,37 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
132137 uint32_t req_rate = pdm_cfg -> streams [0 ].pcm_rate ;
133138 bool better_found = false;
134139
140+ #if NRF_PDM_HAS_PRESCALER
141+ uint32_t src_freq = 32 * 1000 * 1000UL ;
142+ uint32_t req_freq = req_rate * ratio ;
143+ uint32_t prescaler = src_freq / req_freq ;
144+ uint32_t act_freq = src_freq / prescaler ;
145+
146+ if (is_in_freq_range (act_freq , pdm_cfg ) &&
147+ is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
148+ config -> prescaler = prescaler ;
149+
150+ better_found = true;
151+ }
152+
153+ /* Stop if an exact rate match is found. */
154+ if (* best_diff == 0 ) {
155+ return true;
156+ }
157+
158+ /* Prescaler value is rounded down by default,
159+ * thus value rounded up should be checked as well.
160+ */
161+ prescaler += 1 ;
162+ act_freq = src_freq / prescaler ;
163+
164+ if (is_in_freq_range (act_freq , pdm_cfg ) &&
165+ is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
166+ config -> prescaler = prescaler ;
167+
168+ better_found = true;
169+ }
170+ #else
135171 if (IS_ENABLED (CONFIG_SOC_SERIES_NRF53X )) {
136172 const uint32_t src_freq =
137173 (NRF_PDM_HAS_MCLKCONFIG && drv_cfg -> clk_src == ACLK )
@@ -158,10 +194,8 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
158194 (src_freq + req_freq / 2 ));
159195 uint32_t act_freq = src_freq / (1048576 / clk_factor );
160196
161- if (act_freq >= pdm_cfg -> io .min_pdm_clk_freq &&
162- act_freq <= pdm_cfg -> io .max_pdm_clk_freq &&
163- is_better (act_freq , ratio , req_rate ,
164- best_diff , best_rate , best_freq )) {
197+ if (is_in_freq_range (act_freq , pdm_cfg ) &&
198+ is_better (act_freq , ratio , req_rate , best_diff , best_rate , best_freq )) {
165199 config -> clock_freq = clk_factor * 4096 ;
166200
167201 better_found = true;
@@ -216,6 +250,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
216250 }
217251 }
218252 }
253+ #endif /* NRF_PDM_HAS_PRESCALER */
219254
220255 return better_found ;
221256}
@@ -236,8 +271,26 @@ static bool find_suitable_clock(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
236271 uint8_t ratio_val ;
237272 nrf_pdm_ratio_t ratio_enum ;
238273 } ratios [] = {
239- { 64 , NRF_PDM_RATIO_64X },
240- { 80 , NRF_PDM_RATIO_80X }
274+ #if defined(PDM_RATIO_RATIO_Ratio32 )
275+ { 32 , NRF_PDM_RATIO_32X },
276+ #endif
277+ #if defined(PDM_RATIO_RATIO_Ratio48 )
278+ { 48 , NRF_PDM_RATIO_48X },
279+ #endif
280+ #if defined(PDM_RATIO_RATIO_Ratio50 )
281+ { 50 , NRF_PDM_RATIO_50X },
282+ #endif
283+ { 64 , NRF_PDM_RATIO_64X },
284+ { 80 , NRF_PDM_RATIO_80X },
285+ #if defined(PDM_RATIO_RATIO_Ratio96 )
286+ { 96 , NRF_PDM_RATIO_96X },
287+ #endif
288+ #if defined(PDM_RATIO_RATIO_Ratio100 )
289+ { 100 , NRF_PDM_RATIO_100X },
290+ #endif
291+ #if defined(PDM_RATIO_RATIO_Ratio128 )
292+ { 128 , NRF_PDM_RATIO_128X }
293+ #endif
241294 };
242295
243296 for (int r = 0 ; best_diff != 0 && r < ARRAY_SIZE (ratios ); ++ r ) {
@@ -327,7 +380,7 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
327380 /* If either rate or width is 0, the stream is to be disabled. */
328381 if (stream -> pcm_rate == 0 || stream -> pcm_width == 0 ) {
329382 if (drv_data -> configured ) {
330- nrfx_pdm_uninit ();
383+ nrfx_pdm_uninit (drv_data -> pdm );
331384 drv_data -> configured = false;
332385 }
333386
@@ -357,11 +410,11 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
357410 }
358411
359412 if (drv_data -> configured ) {
360- nrfx_pdm_uninit ();
413+ nrfx_pdm_uninit (drv_data -> pdm );
361414 drv_data -> configured = false;
362415 }
363416
364- err = nrfx_pdm_init (& nrfx_cfg , drv_cfg -> event_handler );
417+ err = nrfx_pdm_init (drv_data -> pdm , & nrfx_cfg , drv_cfg -> event_handler );
365418 if (err != NRFX_SUCCESS ) {
366419 LOG_ERR ("Failed to initialize PDM: 0x%08x" , err );
367420 return - EIO ;
@@ -385,7 +438,7 @@ static int start_transfer(struct dmic_nrfx_pdm_drv_data *drv_data)
385438 nrfx_err_t err ;
386439 int ret ;
387440
388- err = nrfx_pdm_start ();
441+ err = nrfx_pdm_start (drv_data -> pdm );
389442 if (err == NRFX_SUCCESS ) {
390443 return 0 ;
391444 }
@@ -460,7 +513,7 @@ static int dmic_nrfx_pdm_trigger(const struct device *dev,
460513 case DMIC_TRIGGER_STOP :
461514 if (drv_data -> active ) {
462515 drv_data -> stopping = true;
463- nrfx_pdm_stop ();
516+ nrfx_pdm_stop (drv_data -> pdm );
464517 }
465518 break ;
466519
@@ -541,16 +594,18 @@ static const struct _dmic_ops dmic_ops = {
541594#define PDM_NRFX_DEVICE (idx ) \
542595 static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
543596 static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \
597+ static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \
544598 static int pdm_nrfx_init##idx(const struct device *dev) \
545599 { \
546600 IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \
547- nrfx_isr, nrfx_pdm_irq_handler , 0); \
601+ nrfx_isr, nrfx_pdm_##idx##_irq_handler , 0); \
548602 const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \
549603 int err = pinctrl_apply_state(drv_cfg->pcfg, \
550604 PINCTRL_STATE_DEFAULT); \
551605 if (err < 0) { \
552606 return err; \
553607 } \
608+ dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \
554609 k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
555610 (char *)rx_msgs##idx, sizeof(void *), \
556611 ARRAY_SIZE(rx_msgs##idx)); \
@@ -582,5 +637,14 @@ static const struct _dmic_ops dmic_ops = {
582637 POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
583638 &dmic_ops);
584639
585- /* Existing SoCs only have one PDM instance. */
640+ #ifdef CONFIG_HAS_HW_NRF_PDM0
586641PDM_NRFX_DEVICE (0 );
642+ #endif
643+
644+ #ifdef CONFIG_HAS_HW_NRF_PDM20
645+ PDM_NRFX_DEVICE (20 );
646+ #endif
647+
648+ #ifdef CONFIG_HAS_HW_NRF_PDM21
649+ PDM_NRFX_DEVICE (21 );
650+ #endif
0 commit comments