@@ -18,14 +18,21 @@ LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
18
18
#if CONFIG_SOC_SERIES_NRF54HX
19
19
#define DMIC_NRFX_CLOCK_FREQ MHZ(16)
20
20
#define DMIC_NRFX_CLOCK_FACTOR 8192
21
+ #define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(DT_NODELABEL(audiopll), frequency, 0)
21
22
#else
22
23
#define DMIC_NRFX_CLOCK_FREQ MHZ(32)
23
24
#define DMIC_NRFX_CLOCK_FACTOR 4096
25
+ #define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(DT_NODELABEL(aclk), clock_frequency, \
26
+ DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0))
24
27
#endif
25
28
26
29
struct dmic_nrfx_pdm_drv_data {
27
30
const nrfx_pdm_t * pdm ;
31
+ #if CONFIG_CLOCK_CONTROL_NRF
28
32
struct onoff_manager * clk_mgr ;
33
+ #elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
34
+ const struct device * audiopll_dev ;
35
+ #endif
29
36
struct onoff_client clk_cli ;
30
37
struct k_mem_slab * mem_slab ;
31
38
uint32_t block_size ;
@@ -61,6 +68,35 @@ static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
61
68
nrfx_pdm_stop (drv_data -> pdm );
62
69
}
63
70
71
+ static int request_clock (struct dmic_nrfx_pdm_drv_data * drv_data )
72
+ {
73
+ if (!drv_data -> request_clock ) {
74
+ return 0 ;
75
+ }
76
+ #if CONFIG_CLOCK_CONTROL_NRF
77
+ return onoff_request (drv_data -> clk_mgr , & drv_data -> clk_cli );
78
+ #elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
79
+ return nrf_clock_control_request (drv_data -> audiopll_dev , NULL , & drv_data -> clk_cli );
80
+ #else
81
+ return - ENOTSUP ;
82
+ #endif
83
+ }
84
+
85
+ static int release_clock (struct dmic_nrfx_pdm_drv_data * drv_data )
86
+ {
87
+ if (!drv_data -> request_clock ) {
88
+ return 0 ;
89
+ }
90
+
91
+ #if CONFIG_CLOCK_CONTROL_NRF
92
+ return onoff_release (drv_data -> clk_mgr );
93
+ #elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
94
+ return nrf_clock_control_release (drv_data -> audiopll_dev , NULL );
95
+ #else
96
+ return - ENOTSUP ;
97
+ #endif
98
+ }
99
+
64
100
static void event_handler (const struct device * dev , const nrfx_pdm_evt_t * evt )
65
101
{
66
102
struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
@@ -119,8 +155,10 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
119
155
120
156
if (drv_data -> active ) {
121
157
drv_data -> active = false;
122
- if (drv_data -> request_clock ) {
123
- (void )onoff_release (drv_data -> clk_mgr );
158
+ ret = release_clock (drv_data );
159
+ if (ret < 0 ) {
160
+ LOG_ERR ("Failed to release clock: %d" , ret );
161
+ return ;
124
162
}
125
163
}
126
164
} else if (evt -> buffer_released ) {
@@ -191,9 +229,11 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
191
229
{
192
230
uint32_t req_rate = pdm_cfg -> streams [0 ].pcm_rate ;
193
231
bool better_found = false;
194
-
232
+ const uint32_t src_freq =
233
+ (NRF_PDM_HAS_SELECTABLE_CLOCK && drv_cfg -> clk_src == ACLK )
234
+ ? DMIC_NRFX_AUDIO_CLOCK_FREQ
235
+ : DMIC_NRFX_CLOCK_FREQ ;
195
236
#if NRF_PDM_HAS_PRESCALER
196
- uint32_t src_freq = 32 * 1000 * 1000UL ;
197
237
uint32_t req_freq = req_rate * ratio ;
198
238
uint32_t prescaler = src_freq / req_freq ;
199
239
uint32_t act_freq = src_freq / prescaler ;
@@ -224,24 +264,6 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
224
264
}
225
265
#else
226
266
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
267
uint32_t req_freq = req_rate * ratio ;
246
268
/* As specified in the nRF5340 PS:
247
269
*
@@ -461,7 +483,7 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
461
483
nrfx_cfg .edge = NRF_PDM_EDGE_LEFTRISING ;
462
484
channel -> act_chan_map_lo = alt_map ;
463
485
}
464
- #if NRF_PDM_HAS_MCLKCONFIG
486
+ #if NRF_PDM_HAS_SELECTABLE_CLOCK
465
487
nrfx_cfg .mclksrc = drv_cfg -> clk_src == ACLK
466
488
? NRF_PDM_MCLKSRC_ACLK
467
489
: NRF_PDM_MCLKSRC_PCLK32M ;
@@ -489,8 +511,10 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
489
511
* (which is always available without any additional actions),
490
512
* it is required to request the proper clock to be running
491
513
* before starting the transfer itself.
514
+ * Targets using CLKSELECT register to select clock source
515
+ * do not need to request audio clock.
492
516
*/
493
- drv_data -> request_clock = (drv_cfg -> clk_src != PCLK32M );
517
+ drv_data -> request_clock = (drv_cfg -> clk_src != PCLK32M && ! NRF_PDM_HAS_CLKSELECT );
494
518
drv_data -> configured = true;
495
519
return 0 ;
496
520
}
@@ -508,8 +532,10 @@ static int start_transfer(struct dmic_nrfx_pdm_drv_data *drv_data)
508
532
LOG_ERR ("Failed to start PDM: 0x%08x" , err );
509
533
ret = - EIO ;
510
534
511
- if (drv_data -> request_clock ) {
512
- (void )onoff_release (drv_data -> clk_mgr );
535
+ ret = release_clock (drv_data );
536
+ if (ret < 0 ) {
537
+ LOG_ERR ("Failed to release clock: %d" , ret );
538
+ return ret ;
513
539
}
514
540
515
541
drv_data -> active = false;
@@ -529,7 +555,12 @@ static void clock_started_callback(struct onoff_manager *mgr,
529
555
* the actual transfer in such case.
530
556
*/
531
557
if (!drv_data -> active ) {
532
- (void )onoff_release (drv_data -> clk_mgr );
558
+ int ret = release_clock (drv_data );
559
+
560
+ if (ret < 0 ) {
561
+ LOG_ERR ("Failed to release clock: %d" , ret );
562
+ return ;
563
+ }
533
564
} else {
534
565
(void )start_transfer (drv_data );
535
566
}
@@ -548,7 +579,7 @@ static int trigger_start(const struct device *dev)
548
579
if (drv_data -> request_clock ) {
549
580
sys_notify_init_callback (& drv_data -> clk_cli .notify ,
550
581
clock_started_callback );
551
- ret = onoff_request (drv_data -> clk_mgr , & drv_data -> clk_cli );
582
+ ret = request_clock (drv_data );
552
583
if (ret < 0 ) {
553
584
drv_data -> active = false;
554
585
@@ -624,12 +655,11 @@ static int dmic_nrfx_pdm_read(const struct device *dev,
624
655
return ret ;
625
656
}
626
657
627
- #if CONFIG_CLOCK_CONTROL_NRF
628
658
static void init_clock_manager (const struct device * dev )
629
659
{
630
- struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
660
+ #if CONFIG_CLOCK_CONTROL_NRF
631
661
clock_control_subsys_t subsys ;
632
-
662
+ struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
633
663
#if NRF_CLOCK_HAS_HFCLKAUDIO
634
664
const struct dmic_nrfx_pdm_drv_cfg * drv_cfg = dev -> config ;
635
665
@@ -643,8 +673,12 @@ static void init_clock_manager(const struct device *dev)
643
673
644
674
drv_data -> clk_mgr = z_nrf_clock_control_get_onoff (subsys );
645
675
__ASSERT_NO_MSG (drv_data -> clk_mgr != NULL );
646
- }
676
+ #elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
677
+ struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
678
+
679
+ drv_data -> audiopll_dev = DEVICE_DT_GET (DT_NODELABEL (audiopll ));
647
680
#endif
681
+ }
648
682
649
683
static const struct _dmic_ops dmic_ops = {
650
684
.configure = dmic_nrfx_pdm_configure ,
@@ -677,8 +711,7 @@ static const struct _dmic_ops dmic_ops = {
677
711
k_msgq_init(&dmic_nrfx_pdm_data##idx.mem_slab_queue, \
678
712
(char *)mem_slab_msgs##idx, sizeof(void *), \
679
713
ARRAY_SIZE(mem_slab_msgs##idx)); \
680
- IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
681
- (init_clock_manager(dev);)) \
714
+ init_clock_manager(dev); \
682
715
return 0; \
683
716
} \
684
717
static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
@@ -695,13 +728,20 @@ static const struct _dmic_ops dmic_ops = {
695
728
.clk_src = PDM_CLK_SRC(idx), \
696
729
.mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
697
730
}; \
698
- BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
731
+ BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \
732
+ NRF_PDM_HAS_SELECTABLE_CLOCK, \
699
733
"Clock source ACLK is not available."); \
700
734
BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \
701
735
DT_NODE_HAS_PROP(DT_NODELABEL(clock), \
702
- hfclkaudio_frequency), \
736
+ hfclkaudio_frequency) || \
737
+ DT_NODE_HAS_PROP(DT_NODELABEL(aclk), \
738
+ clock_frequency) || \
739
+ DT_NODE_HAS_PROP(DT_NODELABEL(audiopll), \
740
+ frequency), \
703
741
"Clock source ACLK requires the hfclkaudio-frequency " \
704
- "property to be defined in the nordic,nrf-clock node."); \
742
+ "property to be defined in the nordic,nrf-clock node " \
743
+ "or clock-frequency property to be defined in aclk node" \
744
+ "or frequency property to be defined in audiopll node"); \
705
745
DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \
706
746
&dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \
707
747
POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
0 commit comments