Skip to content

Commit a8ca36c

Browse files
mstasiaknordicrlubos
authored andcommitted
[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 5503683 commit a8ca36c

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

drivers/audio/dmic_nrfx_pdm.c

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,25 @@
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;
2027
struct onoff_client clk_cli;
2128
struct k_mem_slab *mem_slab;
29+
void *mem_slab_buffer;
2230
uint32_t block_size;
2331
struct k_msgq rx_queue;
2432
bool request_clock : 1;
@@ -36,29 +44,44 @@ struct dmic_nrfx_pdm_drv_cfg {
3644
PCLK32M_HFXO,
3745
ACLK
3846
} clk_src;
47+
void *mem_reg;
3948
};
4049

41-
static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data, void *buffer)
50+
static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data)
51+
{
52+
k_mem_slab_free(drv_data->mem_slab, drv_data->mem_slab_buffer);
53+
LOG_DBG("Freed buffer %p", drv_data->mem_slab_buffer);
54+
}
55+
56+
static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
4257
{
43-
k_mem_slab_free(drv_data->mem_slab, buffer);
44-
LOG_DBG("Freed buffer %p", buffer);
58+
drv_data->stopping = true;
59+
nrfx_pdm_stop(drv_data->pdm);
4560
}
4661

4762
static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
4863
{
4964
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
65+
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
5066
int ret;
5167
bool stop = false;
5268

5369
if (evt->buffer_requested) {
5470
void *buffer;
5571
nrfx_err_t err;
5672

57-
ret = k_mem_slab_alloc(drv_data->mem_slab, &buffer, K_NO_WAIT);
73+
ret = k_mem_slab_alloc(drv_data->mem_slab, &drv_data->mem_slab_buffer, K_NO_WAIT);
5874
if (ret < 0) {
5975
LOG_ERR("Failed to allocate buffer: %d", ret);
6076
stop = true;
6177
} else {
78+
ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
79+
drv_data->block_size, &buffer);
80+
if (ret < 0) {
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,7 +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) {
72-
free_buffer(drv_data, evt->buffer_released);
95+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
96+
drv_data->block_size, evt->buffer_released);
97+
if (ret < 0) {
98+
LOG_ERR("Failed to release buffer: %d", ret);
99+
stop_pdm(drv_data);
100+
return;
101+
}
102+
free_buffer(drv_data);
73103
}
74104

75105
if (drv_data->active) {
@@ -79,22 +109,26 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
79109
}
80110
}
81111
} else if (evt->buffer_released) {
112+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
113+
drv_data->block_size, evt->buffer_released);
114+
if (ret < 0) {
115+
LOG_ERR("Failed to release buffer: %d", ret);
116+
stop_pdm(drv_data);
117+
return;
118+
}
82119
ret = k_msgq_put(&drv_data->rx_queue,
83-
&evt->buffer_released,
120+
&drv_data->mem_slab_buffer,
84121
K_NO_WAIT);
85122
if (ret < 0) {
86123
LOG_ERR("No room in RX queue");
87124
stop = true;
88-
89-
free_buffer(drv_data, evt->buffer_released);
125+
free_buffer(drv_data);
90126
} else {
91127
LOG_DBG("Queued buffer %p", evt->buffer_released);
92128
}
93129
}
94-
95130
if (stop) {
96-
drv_data->stopping = true;
97-
nrfx_pdm_stop(drv_data->pdm);
131+
stop_pdm(drv_data);
98132
}
99133
}
100134

@@ -168,7 +202,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
168202
better_found = true;
169203
}
170204
#else
171-
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) {
205+
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X) || IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX)) {
172206
const uint32_t src_freq =
173207
(NRF_PDM_HAS_MCLKCONFIG && drv_cfg->clk_src == ACLK)
174208
/* The DMIC_NRFX_PDM_DEVICE() macro contains build
@@ -180,9 +214,13 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
180214
* not defined (this expression will be eventually
181215
* optimized away then).
182216
*/
217+
/* TODO : PS does not provide correct formula for nRF54H20 PDM_CLK.
218+
* Assume that master clock source frequency is 8 MHz. Remove once
219+
* correct formula is found.
220+
*/
183221
? DT_PROP_OR(DT_NODELABEL(clock), hfclkaudio_frequency,
184222
0)
185-
: 32*1000*1000UL;
223+
: DMIC_NRFX_CLOCK_FREQ;
186224
uint32_t req_freq = req_rate * ratio;
187225
/* As specified in the nRF5340 PS:
188226
*
@@ -562,6 +600,7 @@ static int dmic_nrfx_pdm_read(const struct device *dev,
562600
return ret;
563601
}
564602

603+
#if CONFIG_CLOCK_CONTROL_NRF
565604
static void init_clock_manager(const struct device *dev)
566605
{
567606
struct dmic_nrfx_pdm_drv_data *drv_data = dev->data;
@@ -581,6 +620,7 @@ static void init_clock_manager(const struct device *dev)
581620
drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys);
582621
__ASSERT_NO_MSG(drv_data->clk_mgr != NULL);
583622
}
623+
#endif
584624

585625
static const struct _dmic_ops dmic_ops = {
586626
.configure = dmic_nrfx_pdm_configure,
@@ -609,7 +649,8 @@ static const struct _dmic_ops dmic_ops = {
609649
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
610650
(char *)rx_msgs##idx, sizeof(void *), \
611651
ARRAY_SIZE(rx_msgs##idx)); \
612-
init_clock_manager(dev); \
652+
IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
653+
(init_clock_manager(dev);)) \
613654
return 0; \
614655
} \
615656
static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
@@ -624,6 +665,7 @@ static const struct _dmic_ops dmic_ops = {
624665
.nrfx_def_cfg.skip_psel_cfg = true, \
625666
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \
626667
.clk_src = PDM_CLK_SRC(idx), \
668+
.mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
627669
}; \
628670
BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
629671
"Clock source ACLK is not available."); \

0 commit comments

Comments
 (0)