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