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