@@ -18,14 +18,21 @@ LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
1818#if CONFIG_SOC_SERIES_NRF54HX
1919#define DMIC_NRFX_CLOCK_FREQ MHZ(16)
2020#define DMIC_NRFX_CLOCK_FACTOR 8192
21+ #define DMIC_NRFX_AUDIO_CLOCK_FREQ DT_PROP_OR(DT_NODELABEL(audiopll), frequency, 0)
2122#else
2223#define DMIC_NRFX_CLOCK_FREQ MHZ(32)
2324#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))
2427#endif
2528
2629struct dmic_nrfx_pdm_drv_data {
2730 const nrfx_pdm_t * pdm ;
31+ #if CONFIG_CLOCK_CONTROL_NRF
2832 struct onoff_manager * clk_mgr ;
33+ #elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
34+ const struct device * audiopll_dev ;
35+ #endif
2936 struct onoff_client clk_cli ;
3037 struct k_mem_slab * mem_slab ;
3138 uint32_t block_size ;
@@ -61,6 +68,35 @@ static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
6168 nrfx_pdm_stop (drv_data -> pdm );
6269}
6370
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+
64100static void event_handler (const struct device * dev , const nrfx_pdm_evt_t * evt )
65101{
66102 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)
119155
120156 if (drv_data -> active ) {
121157 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 ;
124162 }
125163 }
126164 } else if (evt -> buffer_released ) {
@@ -191,9 +229,11 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
191229{
192230 uint32_t req_rate = pdm_cfg -> streams [0 ].pcm_rate ;
193231 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 ;
195236#if NRF_PDM_HAS_PRESCALER
196- uint32_t src_freq = 32 * 1000 * 1000UL ;
197237 uint32_t req_freq = req_rate * ratio ;
198238 uint32_t prescaler = src_freq / req_freq ;
199239 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,
224264 }
225265#else
226266 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 ;
245267 uint32_t req_freq = req_rate * ratio ;
246268 /* As specified in the nRF5340 PS:
247269 *
@@ -461,7 +483,7 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
461483 nrfx_cfg .edge = NRF_PDM_EDGE_LEFTRISING ;
462484 channel -> act_chan_map_lo = alt_map ;
463485 }
464- #if NRF_PDM_HAS_MCLKCONFIG
486+ #if NRF_PDM_HAS_SELECTABLE_CLOCK
465487 nrfx_cfg .mclksrc = drv_cfg -> clk_src == ACLK
466488 ? NRF_PDM_MCLKSRC_ACLK
467489 : NRF_PDM_MCLKSRC_PCLK32M ;
@@ -489,8 +511,10 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
489511 * (which is always available without any additional actions),
490512 * it is required to request the proper clock to be running
491513 * before starting the transfer itself.
514+ * Targets using CLKSELECT register to select clock source
515+ * do not need to request audio clock.
492516 */
493- drv_data -> request_clock = (drv_cfg -> clk_src != PCLK32M );
517+ drv_data -> request_clock = (drv_cfg -> clk_src != PCLK32M && ! NRF_PDM_HAS_CLKSELECT );
494518 drv_data -> configured = true;
495519 return 0 ;
496520}
@@ -508,8 +532,10 @@ static int start_transfer(struct dmic_nrfx_pdm_drv_data *drv_data)
508532 LOG_ERR ("Failed to start PDM: 0x%08x" , err );
509533 ret = - EIO ;
510534
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 ;
513539 }
514540
515541 drv_data -> active = false;
@@ -529,7 +555,12 @@ static void clock_started_callback(struct onoff_manager *mgr,
529555 * the actual transfer in such case.
530556 */
531557 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+ }
533564 } else {
534565 (void )start_transfer (drv_data );
535566 }
@@ -548,7 +579,7 @@ static int trigger_start(const struct device *dev)
548579 if (drv_data -> request_clock ) {
549580 sys_notify_init_callback (& drv_data -> clk_cli .notify ,
550581 clock_started_callback );
551- ret = onoff_request (drv_data -> clk_mgr , & drv_data -> clk_cli );
582+ ret = request_clock (drv_data );
552583 if (ret < 0 ) {
553584 drv_data -> active = false;
554585
@@ -624,12 +655,11 @@ static int dmic_nrfx_pdm_read(const struct device *dev,
624655 return ret ;
625656}
626657
627- #if CONFIG_CLOCK_CONTROL_NRF
628658static void init_clock_manager (const struct device * dev )
629659{
630- struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
660+ #if CONFIG_CLOCK_CONTROL_NRF
631661 clock_control_subsys_t subsys ;
632-
662+ struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
633663#if NRF_CLOCK_HAS_HFCLKAUDIO
634664 const struct dmic_nrfx_pdm_drv_cfg * drv_cfg = dev -> config ;
635665
@@ -643,8 +673,12 @@ static void init_clock_manager(const struct device *dev)
643673
644674 drv_data -> clk_mgr = z_nrf_clock_control_get_onoff (subsys );
645675 __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 ));
647680#endif
681+ }
648682
649683static const struct _dmic_ops dmic_ops = {
650684 .configure = dmic_nrfx_pdm_configure ,
@@ -677,8 +711,7 @@ static const struct _dmic_ops dmic_ops = {
677711 k_msgq_init(&dmic_nrfx_pdm_data##idx.mem_slab_queue, \
678712 (char *)mem_slab_msgs##idx, sizeof(void *), \
679713 ARRAY_SIZE(mem_slab_msgs##idx)); \
680- IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
681- (init_clock_manager(dev);)) \
714+ init_clock_manager(dev); \
682715 return 0; \
683716 } \
684717 static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
@@ -695,13 +728,20 @@ static const struct _dmic_ops dmic_ops = {
695728 .clk_src = PDM_CLK_SRC(idx), \
696729 .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
697730 }; \
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, \
699733 "Clock source ACLK is not available."); \
700734 BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \
701735 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), \
703741 "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"); \
705745 DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \
706746 &dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \
707747 POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
0 commit comments