Skip to content

Commit bd370f9

Browse files
[nrf fromlist] drivers: audio: dmic_nrfx: add support for audio clocks on nRF54
Added support for audio clock for nRF54L20 and AudioPLL for nRF54H20 in DMIC PDM driver. Upstream PR #: 87105 Signed-off-by: Michał Stasiak <[email protected]>
1 parent 35805e2 commit bd370f9

File tree

1 file changed

+76
-36
lines changed

1 file changed

+76
-36
lines changed

drivers/audio/dmic_nrfx_pdm.c

+76-36
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,23 @@ 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 \
26+
COND_CODE_1(CONFIG_SOC_NRF54L20, \
27+
(DT_PROP_OR(DT_NODELABEL(aclk), clock_frequency, 0)), \
28+
(DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency, 0)))
2429
#endif
2530

2631
struct dmic_nrfx_pdm_drv_data {
2732
const nrfx_pdm_t *pdm;
33+
#if CONFIG_CLOCK_CONTROL_NRF
2834
struct onoff_manager *clk_mgr;
35+
#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
36+
const struct device *audiopll_dev;
37+
#endif
2938
struct onoff_client clk_cli;
3039
struct k_mem_slab *mem_slab;
3140
uint32_t block_size;
@@ -61,6 +70,35 @@ static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
6170
nrfx_pdm_stop(drv_data->pdm);
6271
}
6372

73+
static int request_clock(struct dmic_nrfx_pdm_drv_data *drv_data)
74+
{
75+
if (!drv_data->request_clock) {
76+
return 0;
77+
}
78+
#if CONFIG_CLOCK_CONTROL_NRF
79+
return onoff_request(drv_data->clk_mgr, &drv_data->clk_cli);
80+
#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
81+
return nrf_clock_control_request(drv_data->audiopll_dev, NULL, &drv_data->clk_cli);
82+
#else
83+
return 0;
84+
#endif
85+
}
86+
87+
static int release_clock(struct dmic_nrfx_pdm_drv_data *drv_data)
88+
{
89+
if (!drv_data->request_clock) {
90+
return 0;
91+
}
92+
93+
#if CONFIG_CLOCK_CONTROL_NRF
94+
return onoff_release(drv_data->clk_mgr);
95+
#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL
96+
return nrf_clock_control_release(drv_data->audiopll_dev, NULL);
97+
#else
98+
return 0;
99+
#endif
100+
}
101+
64102
static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
65103
{
66104
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
@@ -119,8 +157,10 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
119157

120158
if (drv_data->active) {
121159
drv_data->active = false;
122-
if (drv_data->request_clock) {
123-
(void)onoff_release(drv_data->clk_mgr);
160+
ret = release_clock(drv_data);
161+
if (ret < 0) {
162+
LOG_ERR("Failed to release clock: %d", ret);
163+
return;
124164
}
125165
}
126166
} else if (evt->buffer_released) {
@@ -191,9 +231,11 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
191231
{
192232
uint32_t req_rate = pdm_cfg->streams[0].pcm_rate;
193233
bool better_found = false;
194-
234+
const uint32_t src_freq =
235+
(NRF_PDM_HAS_SELECTABLE_CLOCK && drv_cfg->clk_src == ACLK)
236+
? DMIC_NRFX_AUDIO_CLOCK_FREQ
237+
: DMIC_NRFX_CLOCK_FREQ;
195238
#if NRF_PDM_HAS_PRESCALER
196-
uint32_t src_freq = 32 * 1000 * 1000UL;
197239
uint32_t req_freq = req_rate * ratio;
198240
uint32_t prescaler = src_freq / req_freq;
199241
uint32_t act_freq = src_freq / prescaler;
@@ -224,24 +266,6 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
224266
}
225267
#else
226268
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;
245269
uint32_t req_freq = req_rate * ratio;
246270
/* As specified in the nRF5340 PS:
247271
*
@@ -461,7 +485,7 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
461485
nrfx_cfg.edge = NRF_PDM_EDGE_LEFTRISING;
462486
channel->act_chan_map_lo = alt_map;
463487
}
464-
#if NRF_PDM_HAS_MCLKCONFIG
488+
#if NRF_PDM_HAS_SELECTABLE_CLOCK
465489
nrfx_cfg.mclksrc = drv_cfg->clk_src == ACLK
466490
? NRF_PDM_MCLKSRC_ACLK
467491
: NRF_PDM_MCLKSRC_PCLK32M;
@@ -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
628658
static 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

649683
static 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

Comments
 (0)