15
15
LOG_MODULE_REGISTER (dmic_nrfx_pdm , CONFIG_AUDIO_DMIC_LOG_LEVEL );
16
16
17
17
struct dmic_nrfx_pdm_drv_data {
18
+ const nrfx_pdm_t * pdm ;
18
19
struct onoff_manager * clk_mgr ;
19
20
struct onoff_client clk_cli ;
20
21
struct k_mem_slab * mem_slab ;
@@ -58,8 +59,7 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
58
59
LOG_ERR ("Failed to allocate buffer: %d" , ret );
59
60
stop = true;
60
61
} 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 );
63
63
if (err != NRFX_SUCCESS ) {
64
64
LOG_ERR ("Failed to set buffer: 0x%08x" , err );
65
65
stop = true;
@@ -94,10 +94,15 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
94
94
95
95
if (stop ) {
96
96
drv_data -> stopping = true;
97
- nrfx_pdm_stop ();
97
+ nrfx_pdm_stop (drv_data -> pdm );
98
98
}
99
99
}
100
100
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
+
101
106
static bool is_better (uint32_t freq ,
102
107
uint8_t ratio ,
103
108
uint32_t req_rate ,
@@ -132,6 +137,37 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
132
137
uint32_t req_rate = pdm_cfg -> streams [0 ].pcm_rate ;
133
138
bool better_found = false;
134
139
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
135
171
if (IS_ENABLED (CONFIG_SOC_SERIES_NRF53X )) {
136
172
const uint32_t src_freq =
137
173
(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,
158
194
(src_freq + req_freq / 2 ));
159
195
uint32_t act_freq = src_freq / (1048576 / clk_factor );
160
196
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 )) {
165
199
config -> clock_freq = clk_factor * 4096 ;
166
200
167
201
better_found = true;
@@ -216,6 +250,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
216
250
}
217
251
}
218
252
}
253
+ #endif /* NRF_PDM_HAS_PRESCALER */
219
254
220
255
return better_found ;
221
256
}
@@ -236,8 +271,26 @@ static bool find_suitable_clock(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
236
271
uint8_t ratio_val ;
237
272
nrf_pdm_ratio_t ratio_enum ;
238
273
} 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
241
294
};
242
295
243
296
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,
327
380
/* If either rate or width is 0, the stream is to be disabled. */
328
381
if (stream -> pcm_rate == 0 || stream -> pcm_width == 0 ) {
329
382
if (drv_data -> configured ) {
330
- nrfx_pdm_uninit ();
383
+ nrfx_pdm_uninit (drv_data -> pdm );
331
384
drv_data -> configured = false;
332
385
}
333
386
@@ -357,11 +410,11 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
357
410
}
358
411
359
412
if (drv_data -> configured ) {
360
- nrfx_pdm_uninit ();
413
+ nrfx_pdm_uninit (drv_data -> pdm );
361
414
drv_data -> configured = false;
362
415
}
363
416
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 );
365
418
if (err != NRFX_SUCCESS ) {
366
419
LOG_ERR ("Failed to initialize PDM: 0x%08x" , err );
367
420
return - EIO ;
@@ -385,7 +438,7 @@ static int start_transfer(struct dmic_nrfx_pdm_drv_data *drv_data)
385
438
nrfx_err_t err ;
386
439
int ret ;
387
440
388
- err = nrfx_pdm_start ();
441
+ err = nrfx_pdm_start (drv_data -> pdm );
389
442
if (err == NRFX_SUCCESS ) {
390
443
return 0 ;
391
444
}
@@ -460,7 +513,7 @@ static int dmic_nrfx_pdm_trigger(const struct device *dev,
460
513
case DMIC_TRIGGER_STOP :
461
514
if (drv_data -> active ) {
462
515
drv_data -> stopping = true;
463
- nrfx_pdm_stop ();
516
+ nrfx_pdm_stop (drv_data -> pdm );
464
517
}
465
518
break ;
466
519
@@ -541,16 +594,18 @@ static const struct _dmic_ops dmic_ops = {
541
594
#define PDM_NRFX_DEVICE (idx ) \
542
595
static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
543
596
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); \
544
598
static int pdm_nrfx_init##idx(const struct device *dev) \
545
599
{ \
546
600
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); \
548
602
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \
549
603
int err = pinctrl_apply_state(drv_cfg->pcfg, \
550
604
PINCTRL_STATE_DEFAULT); \
551
605
if (err < 0) { \
552
606
return err; \
553
607
} \
608
+ dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \
554
609
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
555
610
(char *)rx_msgs##idx, sizeof(void *), \
556
611
ARRAY_SIZE(rx_msgs##idx)); \
@@ -582,5 +637,14 @@ static const struct _dmic_ops dmic_ops = {
582
637
POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
583
638
&dmic_ops);
584
639
585
- /* Existing SoCs only have one PDM instance. */
640
+ #ifdef CONFIG_HAS_HW_NRF_PDM0
586
641
PDM_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