1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/audio/dmic.h>
8 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
9 #include <zephyr/drivers/pinctrl.h>
10 #include <soc.h>
11 #include <dmm.h>
12 #include <nrfx_pdm.h>
13
14 #include <zephyr/logging/log.h>
15 #include <zephyr/irq.h>
16 LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
17
18 #if CONFIG_SOC_SERIES_NRF54HX
19 #define DMIC_NRFX_CLOCK_FREQ 8*1000*1000UL
20 #else
21 #define DMIC_NRFX_CLOCK_FREQ 32*1000*1000UL
22 #endif
23
24 struct dmic_nrfx_pdm_drv_data {
25 const nrfx_pdm_t *pdm;
26 struct onoff_manager *clk_mgr;
27 struct onoff_client clk_cli;
28 struct k_mem_slab *mem_slab;
29 void *mem_slab_buffer;
30 uint32_t block_size;
31 struct k_msgq rx_queue;
32 bool request_clock : 1;
33 bool configured : 1;
34 volatile bool active;
35 volatile bool stopping;
36 };
37
38 struct dmic_nrfx_pdm_drv_cfg {
39 nrfx_pdm_event_handler_t event_handler;
40 nrfx_pdm_config_t nrfx_def_cfg;
41 const struct pinctrl_dev_config *pcfg;
42 enum clock_source {
43 PCLK32M,
44 PCLK32M_HFXO,
45 ACLK
46 } clk_src;
47 void *mem_reg;
48 };
49
free_buffer(struct dmic_nrfx_pdm_drv_data * drv_data)50 static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data)
51 {
52 k_mem_slab_free(drv_data->mem_slab, drv_data->mem_slab_buffer);
53 LOG_DBG("Freed buffer %p", drv_data->mem_slab_buffer);
54 }
55
stop_pdm(struct dmic_nrfx_pdm_drv_data * drv_data)56 static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
57 {
58 drv_data->stopping = true;
59 nrfx_pdm_stop(drv_data->pdm);
60 }
61
event_handler(const struct device * dev,const nrfx_pdm_evt_t * evt)62 static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
63 {
64 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
65 const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
66 int ret;
67 bool stop = false;
68
69 if (evt->buffer_requested) {
70 void *buffer;
71 nrfx_err_t err;
72
73 ret = k_mem_slab_alloc(drv_data->mem_slab, &drv_data->mem_slab_buffer, K_NO_WAIT);
74 if (ret < 0) {
75 LOG_ERR("Failed to allocate buffer: %d", ret);
76 stop = true;
77 } else {
78 ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
79 drv_data->block_size, &buffer);
80 if (ret < 0) {
81 LOG_ERR("Failed to prepare buffer: %d", ret);
82 stop_pdm(drv_data);
83 return;
84 }
85 err = nrfx_pdm_buffer_set(drv_data->pdm, buffer, drv_data->block_size / 2);
86 if (err != NRFX_SUCCESS) {
87 LOG_ERR("Failed to set buffer: 0x%08x", err);
88 stop = true;
89 }
90 }
91 }
92
93 if (drv_data->stopping) {
94 if (evt->buffer_released) {
95 ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
96 drv_data->block_size, evt->buffer_released);
97 if (ret < 0) {
98 LOG_ERR("Failed to release buffer: %d", ret);
99 stop_pdm(drv_data);
100 return;
101 }
102 free_buffer(drv_data);
103 }
104
105 if (drv_data->active) {
106 drv_data->active = false;
107 if (drv_data->request_clock) {
108 (void)onoff_release(drv_data->clk_mgr);
109 }
110 }
111 } else if (evt->buffer_released) {
112 ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
113 drv_data->block_size, evt->buffer_released);
114 if (ret < 0) {
115 LOG_ERR("Failed to release buffer: %d", ret);
116 stop_pdm(drv_data);
117 return;
118 }
119 ret = k_msgq_put(&drv_data->rx_queue,
120 &drv_data->mem_slab_buffer,
121 K_NO_WAIT);
122 if (ret < 0) {
123 LOG_ERR("No room in RX queue");
124 stop = true;
125 free_buffer(drv_data);
126 } else {
127 LOG_DBG("Queued buffer %p", evt->buffer_released);
128 }
129 }
130 if (stop) {
131 stop_pdm(drv_data);
132 }
133 }
134
is_in_freq_range(uint32_t freq,const struct dmic_cfg * pdm_cfg)135 static bool is_in_freq_range(uint32_t freq, const struct dmic_cfg *pdm_cfg)
136 {
137 return freq >= pdm_cfg->io.min_pdm_clk_freq && freq <= pdm_cfg->io.max_pdm_clk_freq;
138 }
139
is_better(uint32_t freq,uint8_t ratio,uint32_t req_rate,uint32_t * best_diff,uint32_t * best_rate,uint32_t * best_freq)140 static bool is_better(uint32_t freq,
141 uint8_t ratio,
142 uint32_t req_rate,
143 uint32_t *best_diff,
144 uint32_t *best_rate,
145 uint32_t *best_freq)
146 {
147 uint32_t act_rate = freq / ratio;
148 uint32_t diff = act_rate >= req_rate ? (act_rate - req_rate)
149 : (req_rate - act_rate);
150
151 LOG_DBG("Freq %u, ratio %u, act_rate %u", freq, ratio, act_rate);
152
153 if (diff < *best_diff) {
154 *best_diff = diff;
155 *best_rate = act_rate;
156 *best_freq = freq;
157 return true;
158 }
159
160 return false;
161 }
162
check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg * drv_cfg,nrfx_pdm_config_t * config,const struct dmic_cfg * pdm_cfg,uint8_t ratio,uint32_t * best_diff,uint32_t * best_rate,uint32_t * best_freq)163 static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
164 nrfx_pdm_config_t *config,
165 const struct dmic_cfg *pdm_cfg,
166 uint8_t ratio,
167 uint32_t *best_diff,
168 uint32_t *best_rate,
169 uint32_t *best_freq)
170 {
171 uint32_t req_rate = pdm_cfg->streams[0].pcm_rate;
172 bool better_found = false;
173
174 #if NRF_PDM_HAS_PRESCALER
175 uint32_t src_freq = 32 * 1000 * 1000UL;
176 uint32_t req_freq = req_rate * ratio;
177 uint32_t prescaler = src_freq / req_freq;
178 uint32_t act_freq = src_freq / prescaler;
179
180 if (is_in_freq_range(act_freq, pdm_cfg) &&
181 is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
182 config->prescaler = prescaler;
183
184 better_found = true;
185 }
186
187 /* Stop if an exact rate match is found. */
188 if (*best_diff == 0) {
189 return true;
190 }
191
192 /* Prescaler value is rounded down by default,
193 * thus value rounded up should be checked as well.
194 */
195 prescaler += 1;
196 act_freq = src_freq / prescaler;
197
198 if (is_in_freq_range(act_freq, pdm_cfg) &&
199 is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
200 config->prescaler = prescaler;
201
202 better_found = true;
203 }
204 #else
205 if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X) || IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX)) {
206 const uint32_t src_freq =
207 (NRF_PDM_HAS_MCLKCONFIG && drv_cfg->clk_src == ACLK)
208 /* The DMIC_NRFX_PDM_DEVICE() macro contains build
209 * assertions that make sure that the ACLK clock
210 * source is only used when it is available and only
211 * with the "hfclkaudio-frequency" property defined,
212 * but the default value of 0 here needs to be used
213 * to prevent compilation errors when the property is
214 * not defined (this expression will be eventually
215 * optimized away then).
216 */
217 /* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK.
218 * Assume that master clock source frequency is 8 MHz. Remove once
219 * correct formula is found.
220 */
221 ? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency,
222 0)
223 : DMIC_NRFX_CLOCK_FREQ;
224 uint32_t req_freq = req_rate * ratio;
225 /* As specified in the nRF5340 PS:
226 *
227 * PDMCLKCTRL = 4096 * floor(f_pdm * 1048576 /
228 * (f_source + f_pdm / 2))
229 * f_actual = f_source / floor(1048576 * 4096 / PDMCLKCTRL)
230 */
231 uint32_t clk_factor = (uint32_t)((req_freq * 1048576ULL) /
232 (src_freq + req_freq / 2));
233 uint32_t act_freq = src_freq / (1048576 / clk_factor);
234
235 if (is_in_freq_range(act_freq, pdm_cfg) &&
236 is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
237 config->clock_freq = clk_factor * 4096;
238
239 better_found = true;
240 }
241 } else { /* -> !IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) */
242 static const struct {
243 uint32_t freq_val;
244 nrf_pdm_freq_t freq_enum;
245 } freqs[] = {
246 { 1000000, NRF_PDM_FREQ_1000K },
247 { 1032000, NRF_PDM_FREQ_1032K },
248 { 1067000, NRF_PDM_FREQ_1067K },
249 #if defined(PDM_PDMCLKCTRL_FREQ_1231K)
250 { 1231000, NRF_PDM_FREQ_1231K },
251 #endif
252 #if defined(PDM_PDMCLKCTRL_FREQ_1280K)
253 { 1280000, NRF_PDM_FREQ_1280K },
254 #endif
255 #if defined(PDM_PDMCLKCTRL_FREQ_1333K)
256 { 1333000, NRF_PDM_FREQ_1333K }
257 #endif
258 };
259
260 for (int i = 0; i < ARRAY_SIZE(freqs); ++i) {
261 uint32_t freq_val = freqs[i].freq_val;
262
263 if (freq_val < pdm_cfg->io.min_pdm_clk_freq) {
264 continue;
265 }
266 if (freq_val > pdm_cfg->io.max_pdm_clk_freq) {
267 break;
268 }
269
270 if (is_better(freq_val, ratio, req_rate,
271 best_diff, best_rate, best_freq)) {
272 config->clock_freq = freqs[i].freq_enum;
273
274 /* Stop if an exact rate match is found. */
275 if (*best_diff == 0) {
276 return true;
277 }
278
279 better_found = true;
280 }
281
282 /* Since frequencies are in ascending order, stop
283 * checking next ones for the current ratio after
284 * resulting PCM rate goes above the one requested.
285 */
286 if ((freq_val / ratio) > req_rate) {
287 break;
288 }
289 }
290 }
291 #endif /* NRF_PDM_HAS_PRESCALER */
292
293 return better_found;
294 }
295
296 /* Finds clock settings that give the PCM output rate closest to that requested,
297 * taking into account the hardware limitations.
298 */
find_suitable_clock(const struct dmic_nrfx_pdm_drv_cfg * drv_cfg,nrfx_pdm_config_t * config,const struct dmic_cfg * pdm_cfg)299 static bool find_suitable_clock(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
300 nrfx_pdm_config_t *config,
301 const struct dmic_cfg *pdm_cfg)
302 {
303 uint32_t best_diff = UINT32_MAX;
304 uint32_t best_rate;
305 uint32_t best_freq;
306
307 #if NRF_PDM_HAS_RATIO_CONFIG
308 static const struct {
309 uint8_t ratio_val;
310 nrf_pdm_ratio_t ratio_enum;
311 } ratios[] = {
312 #if defined(PDM_RATIO_RATIO_Ratio32)
313 { 32, NRF_PDM_RATIO_32X },
314 #endif
315 #if defined(PDM_RATIO_RATIO_Ratio48)
316 { 48, NRF_PDM_RATIO_48X },
317 #endif
318 #if defined(PDM_RATIO_RATIO_Ratio50)
319 { 50, NRF_PDM_RATIO_50X },
320 #endif
321 { 64, NRF_PDM_RATIO_64X },
322 { 80, NRF_PDM_RATIO_80X },
323 #if defined(PDM_RATIO_RATIO_Ratio96)
324 { 96, NRF_PDM_RATIO_96X },
325 #endif
326 #if defined(PDM_RATIO_RATIO_Ratio100)
327 { 100, NRF_PDM_RATIO_100X },
328 #endif
329 #if defined(PDM_RATIO_RATIO_Ratio128)
330 { 128, NRF_PDM_RATIO_128X }
331 #endif
332 };
333
334 for (int r = 0; best_diff != 0 && r < ARRAY_SIZE(ratios); ++r) {
335 uint8_t ratio = ratios[r].ratio_val;
336
337 if (check_pdm_frequencies(drv_cfg, config, pdm_cfg, ratio,
338 &best_diff, &best_rate, &best_freq)) {
339 config->ratio = ratios[r].ratio_enum;
340
341 /* Look no further if a configuration giving the exact
342 * PCM rate is found.
343 */
344 if (best_diff == 0) {
345 break;
346 }
347 }
348 }
349 #else
350 uint8_t ratio = 64;
351
352 (void)check_pdm_frequencies(drv_cfg, config, pdm_cfg, ratio,
353 &best_diff, &best_rate, &best_freq);
354 #endif
355
356 if (best_diff == UINT32_MAX) {
357 return false;
358 }
359
360 LOG_INF("PDM clock frequency: %u, actual PCM rate: %u",
361 best_freq, best_rate);
362 return true;
363 }
364
dmic_nrfx_pdm_configure(const struct device * dev,struct dmic_cfg * config)365 static int dmic_nrfx_pdm_configure(const struct device *dev,
366 struct dmic_cfg *config)
367 {
368 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
369 const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
370 struct pdm_chan_cfg *channel = &config->channel;
371 struct pcm_stream_cfg *stream = &config->streams[0];
372 uint32_t def_map, alt_map;
373 nrfx_pdm_config_t nrfx_cfg;
374 nrfx_err_t err;
375
376 if (drv_data->active) {
377 LOG_ERR("Cannot configure device while it is active");
378 return -EBUSY;
379 }
380
381 /*
382 * This device supports only one stream and can be configured to return
383 * 16-bit samples for two channels (Left+Right samples) or one channel
384 * (only Left samples). Left and Right samples can be optionally swapped
385 * by changing the PDM_CLK edge on which the sampling is done
386 * Provide the valid channel maps for both the above configurations
387 * (to inform the requester what is available) and check if what is
388 * requested can be actually configured.
389 */
390 if (channel->req_num_chan == 1) {
391 def_map = dmic_build_channel_map(0, 0, PDM_CHAN_LEFT);
392 alt_map = dmic_build_channel_map(0, 0, PDM_CHAN_RIGHT);
393
394 channel->act_num_chan = 1;
395 } else {
396 def_map = dmic_build_channel_map(0, 0, PDM_CHAN_LEFT)
397 | dmic_build_channel_map(1, 0, PDM_CHAN_RIGHT);
398 alt_map = dmic_build_channel_map(0, 0, PDM_CHAN_RIGHT)
399 | dmic_build_channel_map(1, 0, PDM_CHAN_LEFT);
400
401 channel->act_num_chan = 2;
402 }
403
404 channel->act_num_streams = 1;
405 channel->act_chan_map_hi = 0;
406 channel->act_chan_map_lo = def_map;
407
408 if (channel->req_num_streams != 1 ||
409 channel->req_num_chan > 2 ||
410 channel->req_num_chan < 1 ||
411 (channel->req_chan_map_lo != def_map &&
412 channel->req_chan_map_lo != alt_map) ||
413 channel->req_chan_map_hi != channel->act_chan_map_hi) {
414 LOG_ERR("Requested configuration is not supported");
415 return -EINVAL;
416 }
417
418 /* If either rate or width is 0, the stream is to be disabled. */
419 if (stream->pcm_rate == 0 || stream->pcm_width == 0) {
420 if (drv_data->configured) {
421 nrfx_pdm_uninit(drv_data->pdm);
422 drv_data->configured = false;
423 }
424
425 return 0;
426 }
427
428 if (stream->pcm_width != 16) {
429 LOG_ERR("Only 16-bit samples are supported");
430 return -EINVAL;
431 }
432
433 nrfx_cfg = drv_cfg->nrfx_def_cfg;
434 nrfx_cfg.mode = channel->req_num_chan == 1
435 ? NRF_PDM_MODE_MONO
436 : NRF_PDM_MODE_STEREO;
437 nrfx_cfg.edge = channel->req_chan_map_lo == def_map
438 ? NRF_PDM_EDGE_LEFTFALLING
439 : NRF_PDM_EDGE_LEFTRISING;
440 #if NRF_PDM_HAS_MCLKCONFIG
441 nrfx_cfg.mclksrc = drv_cfg->clk_src == ACLK
442 ? NRF_PDM_MCLKSRC_ACLK
443 : NRF_PDM_MCLKSRC_PCLK32M;
444 #endif
445 if (!find_suitable_clock(drv_cfg, &nrfx_cfg, config)) {
446 LOG_ERR("Cannot find suitable PDM clock configuration.");
447 return -EINVAL;
448 }
449
450 if (drv_data->configured) {
451 nrfx_pdm_uninit(drv_data->pdm);
452 drv_data->configured = false;
453 }
454
455 err = nrfx_pdm_init(drv_data->pdm, &nrfx_cfg, drv_cfg->event_handler);
456 if (err != NRFX_SUCCESS) {
457 LOG_ERR("Failed to initialize PDM: 0x%08x", err);
458 return -EIO;
459 }
460
461 drv_data->block_size = stream->block_size;
462 drv_data->mem_slab = stream->mem_slab;
463
464 /* Unless the PCLK32M source is used with the HFINT oscillator
465 * (which is always available without any additional actions),
466 * it is required to request the proper clock to be running
467 * before starting the transfer itself.
468 */
469 drv_data->request_clock = (drv_cfg->clk_src != PCLK32M);
470 drv_data->configured = true;
471 return 0;
472 }
473
start_transfer(struct dmic_nrfx_pdm_drv_data * drv_data)474 static int start_transfer(struct dmic_nrfx_pdm_drv_data *drv_data)
475 {
476 nrfx_err_t err;
477 int ret;
478
479 err = nrfx_pdm_start(drv_data->pdm);
480 if (err == NRFX_SUCCESS) {
481 return 0;
482 }
483
484 LOG_ERR("Failed to start PDM: 0x%08x", err);
485 ret = -EIO;
486
487 if (drv_data->request_clock) {
488 (void)onoff_release(drv_data->clk_mgr);
489 }
490
491 drv_data->active = false;
492 return ret;
493 }
494
clock_started_callback(struct onoff_manager * mgr,struct onoff_client * cli,uint32_t state,int res)495 static void clock_started_callback(struct onoff_manager *mgr,
496 struct onoff_client *cli,
497 uint32_t state,
498 int res)
499 {
500 struct dmic_nrfx_pdm_drv_data *drv_data =
501 CONTAINER_OF(cli, struct dmic_nrfx_pdm_drv_data, clk_cli);
502
503 /* The driver can turn out to be inactive at this point if the STOP
504 * command was triggered before the clock has started. Do not start
505 * the actual transfer in such case.
506 */
507 if (!drv_data->active) {
508 (void)onoff_release(drv_data->clk_mgr);
509 } else {
510 (void)start_transfer(drv_data);
511 }
512 }
513
trigger_start(const struct device * dev)514 static int trigger_start(const struct device *dev)
515 {
516 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
517 int ret;
518
519 drv_data->active = true;
520
521 /* If it is required to use certain HF clock, request it to be running
522 * first. If not, start the transfer directly.
523 */
524 if (drv_data->request_clock) {
525 sys_notify_init_callback(&drv_data->clk_cli.notify,
526 clock_started_callback);
527 ret = onoff_request(drv_data->clk_mgr, &drv_data->clk_cli);
528 if (ret < 0) {
529 drv_data->active = false;
530
531 LOG_ERR("Failed to request clock: %d", ret);
532 return -EIO;
533 }
534 } else {
535 ret = start_transfer(drv_data);
536 if (ret < 0) {
537 return ret;
538 }
539 }
540
541 return 0;
542 }
543
dmic_nrfx_pdm_trigger(const struct device * dev,enum dmic_trigger cmd)544 static int dmic_nrfx_pdm_trigger(const struct device *dev,
545 enum dmic_trigger cmd)
546 {
547 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
548
549 switch (cmd) {
550 case DMIC_TRIGGER_PAUSE:
551 case DMIC_TRIGGER_STOP:
552 if (drv_data->active) {
553 drv_data->stopping = true;
554 nrfx_pdm_stop(drv_data->pdm);
555 }
556 break;
557
558 case DMIC_TRIGGER_RELEASE:
559 case DMIC_TRIGGER_START:
560 if (!drv_data->configured) {
561 LOG_ERR("Device is not configured");
562 return -EIO;
563 } else if (!drv_data->active) {
564 drv_data->stopping = false;
565 return trigger_start(dev);
566 }
567 break;
568
569 default:
570 LOG_ERR("Invalid command: %d", cmd);
571 return -EINVAL;
572 }
573
574 return 0;
575 }
576
dmic_nrfx_pdm_read(const struct device * dev,uint8_t stream,void ** buffer,size_t * size,int32_t timeout)577 static int dmic_nrfx_pdm_read(const struct device *dev,
578 uint8_t stream,
579 void **buffer, size_t *size, int32_t timeout)
580 {
581 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
582 int ret;
583
584 ARG_UNUSED(stream);
585
586 if (!drv_data->configured) {
587 LOG_ERR("Device is not configured");
588 return -EIO;
589 }
590
591 ret = k_msgq_get(&drv_data->rx_queue, buffer, SYS_TIMEOUT_MS(timeout));
592 if (ret != 0) {
593 LOG_DBG("No audio data to be read");
594 } else {
595 LOG_DBG("Released buffer %p", *buffer);
596
597 *size = drv_data->block_size;
598 }
599
600 return ret;
601 }
602
603 #if CONFIG_CLOCK_CONTROL_NRF
init_clock_manager(const struct device * dev)604 static void init_clock_manager(const struct device *dev)
605 {
606 struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
607 clock_control_subsys_t subsys;
608
609 #if NRF_CLOCK_HAS_HFCLKAUDIO
610 const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
611
612 if (drv_cfg->clk_src == ACLK) {
613 subsys = CLOCK_CONTROL_NRF_SUBSYS_HFAUDIO;
614 } else
615 #endif
616 {
617 subsys = CLOCK_CONTROL_NRF_SUBSYS_HF;
618 }
619
620 drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys);
621 __ASSERT_NO_MSG(drv_data->clk_mgr != NULL);
622 }
623 #endif
624
625 static const struct _dmic_ops dmic_ops = {
626 .configure = dmic_nrfx_pdm_configure,
627 .trigger = dmic_nrfx_pdm_trigger,
628 .read = dmic_nrfx_pdm_read,
629 };
630
631 #define PDM(idx) DT_NODELABEL(pdm##idx)
632 #define PDM_CLK_SRC(idx) DT_STRING_TOKEN(PDM(idx), clock_source)
633
634 #define PDM_NRFX_DEVICE(idx) \
635 static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
636 static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \
637 static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \
638 static int pdm_nrfx_init##idx(const struct device *dev) \
639 { \
640 IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \
641 nrfx_isr, nrfx_pdm_##idx##_irq_handler, 0); \
642 const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \
643 int err = pinctrl_apply_state(drv_cfg->pcfg, \
644 PINCTRL_STATE_DEFAULT); \
645 if (err < 0) { \
646 return err; \
647 } \
648 dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \
649 k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
650 (char *)rx_msgs##idx, sizeof(void *), \
651 ARRAY_SIZE(rx_msgs##idx)); \
652 IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
653 (init_clock_manager(dev);)) \
654 return 0; \
655 } \
656 static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
657 { \
658 event_handler(DEVICE_DT_GET(PDM(idx)), evt); \
659 } \
660 PINCTRL_DT_DEFINE(PDM(idx)); \
661 static const struct dmic_nrfx_pdm_drv_cfg dmic_nrfx_pdm_cfg##idx = { \
662 .event_handler = event_handler##idx, \
663 .nrfx_def_cfg = NRFX_PDM_DEFAULT_CONFIG(0, 0), \
664 .nrfx_def_cfg.skip_gpio_cfg = true, \
665 .nrfx_def_cfg.skip_psel_cfg = true, \
666 .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \
667 .clk_src = PDM_CLK_SRC(idx), \
668 .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
669 }; \
670 BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
671 "Clock source ACLK is not available."); \
672 BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \
673 DT_NODE_HAS_PROP(DT_NODELABEL(clock), \
674 hfclkaudio_frequency), \
675 "Clock source ACLK requires the hfclkaudio-frequency " \
676 "property to be defined in the nordic,nrf-clock node."); \
677 DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \
678 &dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \
679 POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
680 &dmic_ops);
681
682 #ifdef CONFIG_HAS_HW_NRF_PDM0
683 PDM_NRFX_DEVICE(0);
684 #endif
685
686 #ifdef CONFIG_HAS_HW_NRF_PDM20
687 PDM_NRFX_DEVICE(20);
688 #endif
689
690 #ifdef CONFIG_HAS_HW_NRF_PDM21
691 PDM_NRFX_DEVICE(21);
692 #endif
693