Skip to content

Commit 645c6fc

Browse files
[nrf fromlist] drivers: audio: dmic_nrfx: Add DMM support to driver
Added support for DMM in PDM drivers in order to use it with nRF54H20. Upstream PR #: 81588 Signed-off-by: Michał Stasiak <[email protected]>
1 parent f095ceb commit 645c6fc

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

drivers/audio/dmic_nrfx_pdm.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@
88
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
99
#include <zephyr/drivers/pinctrl.h>
1010
#include <soc.h>
11+
#include <dmm.h>
1112
#include <nrfx_pdm.h>
1213

1314
#include <zephyr/logging/log.h>
1415
#include <zephyr/irq.h>
1516
LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
1617

18+
#if CONFIG_SOC_SERIES_NRF54HX
19+
#define DMIC_NRFX_CLOCK_FREQ 8*1000*1000UL
20+
#else
21+
#define DMIC_NRFX_CLOCK_FREQ 32*1000*1000UL
22+
#endif
23+
1724
struct dmic_nrfx_pdm_drv_data {
1825
const nrfx_pdm_t *pdm;
1926
struct onoff_manager *clk_mgr;
@@ -36,6 +43,7 @@ struct dmic_nrfx_pdm_drv_cfg {
3643
PCLK32M_HFXO,
3744
ACLK
3845
} clk_src;
46+
void *mem_reg;
3947
};
4048

4149
static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data, void *buffer)
@@ -44,9 +52,16 @@ static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data, void *buffer)
4452
LOG_DBG("Freed buffer %p", buffer);
4553
}
4654

55+
static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
56+
{
57+
drv_data->stopping = true;
58+
nrfx_pdm_stop(drv_data->pdm);
59+
}
60+
4761
static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
4862
{
4963
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
64+
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
5065
int ret;
5166
bool stop = false;
5267

@@ -59,6 +74,14 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
5974
LOG_ERR("Failed to allocate buffer: %d", ret);
6075
stop = true;
6176
} else {
77+
ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, &buffer,
78+
drv_data->block_size,
79+
(void *)drv_data->mem_slab->buffer);
80+
if (ret) {
81+
LOG_ERR("Failed to prepare buffer: %d", ret);
82+
stop_pdm(drv_data);
83+
return;
84+
}
6285
err = nrfx_pdm_buffer_set(drv_data->pdm, buffer, drv_data->block_size / 2);
6386
if (err != NRFX_SUCCESS) {
6487
LOG_ERR("Failed to set buffer: 0x%08x", err);
@@ -69,6 +92,14 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
6992

7093
if (drv_data->stopping) {
7194
if (evt->buffer_released) {
95+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, evt->buffer_released,
96+
drv_data->block_size,
97+
(void *)drv_data->mem_slab->buffer);
98+
if (ret) {
99+
LOG_ERR("Failed to release buffer: %d", ret);
100+
stop_pdm(drv_data);
101+
return;
102+
}
72103
free_buffer(drv_data, evt->buffer_released);
73104
}
74105

@@ -85,16 +116,21 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
85116
if (ret < 0) {
86117
LOG_ERR("No room in RX queue");
87118
stop = true;
88-
119+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, evt->buffer_released,
120+
drv_data->block_size,
121+
(void *)drv_data->mem_slab->buffer);
122+
if (ret) {
123+
LOG_ERR("Failed to release buffer: %d", ret);
124+
stop_pdm(drv_data);
125+
return;
126+
}
89127
free_buffer(drv_data, evt->buffer_released);
90128
} else {
91129
LOG_DBG("Queued buffer %p", evt->buffer_released);
92130
}
93131
}
94-
95132
if (stop) {
96-
drv_data->stopping = true;
97-
nrfx_pdm_stop(drv_data->pdm);
133+
stop_pdm(drv_data);
98134
}
99135
}
100136

@@ -168,7 +204,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
168204
better_found = true;
169205
}
170206
#else
171-
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) {
207+
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X) || IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX)) {
172208
const uint32_t src_freq =
173209
(NRF_PDM_HAS_MCLKCONFIG && drv_cfg->clk_src == ACLK)
174210
/* The DMIC_NRFX_PDM_DEVICE() macro contains build
@@ -180,9 +216,13 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
180216
* not defined (this expression will be eventually
181217
* optimized away then).
182218
*/
219+
/* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK.
220+
* Assume that master clock source frequency is 8 MHz. Remove once
221+
* correct formula is found.
222+
*/
183223
? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency,
184224
0)
185-
: 32*1000*1000UL;
225+
: DMIC_NRFX_CLOCK_FREQ;
186226
uint32_t req_freq = req_rate * ratio;
187227
/* As specified in the nRF5340 PS:
188228
*
@@ -562,6 +602,7 @@ static int dmic_nrfx_pdm_read(const struct device *dev,
562602
return ret;
563603
}
564604

605+
#if CONFIG_CLOCK_CONTROL_NRF
565606
static void init_clock_manager(const struct device *dev)
566607
{
567608
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
@@ -581,6 +622,7 @@ static void init_clock_manager(const struct device *dev)
581622
drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys);
582623
__ASSERT_NO_MSG(drv_data->clk_mgr != NULL);
583624
}
625+
#endif
584626

585627
static const struct _dmic_ops dmic_ops = {
586628
.configure = dmic_nrfx_pdm_configure,
@@ -609,7 +651,8 @@ static const struct _dmic_ops dmic_ops = {
609651
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
610652
(char *)rx_msgs##idx, sizeof(void *), \
611653
ARRAY_SIZE(rx_msgs##idx)); \
612-
init_clock_manager(dev); \
654+
IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
655+
(init_clock_manager(dev);)) \
613656
return 0; \
614657
} \
615658
static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
@@ -624,6 +667,7 @@ static const struct _dmic_ops dmic_ops = {
624667
.nrfx_def_cfg.skip_psel_cfg = true, \
625668
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \
626669
.clk_src = PDM_CLK_SRC(idx), \
670+
.mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
627671
}; \
628672
BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
629673
"Clock source ACLK is not available."); \

0 commit comments

Comments
 (0)