Skip to content

Commit faf28c0

Browse files
nordic-seglnordicjm
authored andcommitted
[nrf fromtree] drivers: audio: dmic_nrfx: improvements to driver
Added queue for memory slab addresses to ensure that they are released in correct order. Improved formula for frequency scaling for nRF54H20. Fixed alternative channel mapping. Signed-off-by: Michał Stasiak <[email protected]> Signed-off-by: Sebastian Głąb <[email protected]> (cherry picked from commit 8260e1f)
1 parent a676c71 commit faf28c0

File tree

1 file changed

+47
-19
lines changed

1 file changed

+47
-19
lines changed

drivers/audio/dmic_nrfx_pdm.c

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,20 @@
1616
LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);
1717

1818
#if CONFIG_SOC_SERIES_NRF54HX
19-
#define DMIC_NRFX_CLOCK_FREQ 8*1000*1000UL
19+
#define DMIC_NRFX_CLOCK_FREQ MHZ(16)
20+
#define DMIC_NRFX_CLOCK_FACTOR 8192
2021
#else
21-
#define DMIC_NRFX_CLOCK_FREQ 32*1000*1000UL
22+
#define DMIC_NRFX_CLOCK_FREQ MHZ(32)
23+
#define DMIC_NRFX_CLOCK_FACTOR 4096
2224
#endif
2325

2426
struct dmic_nrfx_pdm_drv_data {
2527
const nrfx_pdm_t *pdm;
2628
struct onoff_manager *clk_mgr;
2729
struct onoff_client clk_cli;
2830
struct k_mem_slab *mem_slab;
29-
void *mem_slab_buffer;
3031
uint32_t block_size;
32+
struct k_msgq mem_slab_queue;
3133
struct k_msgq rx_queue;
3234
bool request_clock : 1;
3335
bool configured : 1;
@@ -47,10 +49,10 @@ struct dmic_nrfx_pdm_drv_cfg {
4749
void *mem_reg;
4850
};
4951

50-
static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data)
52+
static void free_buffer(struct dmic_nrfx_pdm_drv_data *drv_data, void *buffer)
5153
{
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+
k_mem_slab_free(drv_data->mem_slab, buffer);
55+
LOG_DBG("Freed buffer %p", buffer);
5456
}
5557

5658
static void stop_pdm(struct dmic_nrfx_pdm_drv_data *drv_data)
@@ -65,20 +67,29 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
6567
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config;
6668
int ret;
6769
bool stop = false;
70+
void *mem_slab_buffer;
6871

6972
if (evt->buffer_requested) {
7073
void *buffer;
7174
nrfx_err_t err;
7275

73-
ret = k_mem_slab_alloc(drv_data->mem_slab, &drv_data->mem_slab_buffer, K_NO_WAIT);
76+
ret = k_mem_slab_alloc(drv_data->mem_slab, &mem_slab_buffer, K_NO_WAIT);
7477
if (ret < 0) {
7578
LOG_ERR("Failed to allocate buffer: %d", ret);
7679
stop = true;
7780
} else {
78-
ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
81+
ret = dmm_buffer_in_prepare(drv_cfg->mem_reg, mem_slab_buffer,
7982
drv_data->block_size, &buffer);
8083
if (ret < 0) {
8184
LOG_ERR("Failed to prepare buffer: %d", ret);
85+
free_buffer(drv_data, mem_slab_buffer);
86+
stop_pdm(drv_data);
87+
return;
88+
}
89+
ret = k_msgq_put(&drv_data->mem_slab_queue, &mem_slab_buffer, K_NO_WAIT);
90+
if (ret < 0) {
91+
LOG_ERR("Unable to put mem slab in queue");
92+
free_buffer(drv_data, mem_slab_buffer);
8293
stop_pdm(drv_data);
8394
return;
8495
}
@@ -92,14 +103,18 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
92103

93104
if (drv_data->stopping) {
94105
if (evt->buffer_released) {
95-
ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
106+
ret = k_msgq_get(&drv_data->mem_slab_queue, &mem_slab_buffer, K_NO_WAIT);
107+
if (ret < 0) {
108+
LOG_ERR("No buffers to free");
109+
return;
110+
}
111+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, mem_slab_buffer,
96112
drv_data->block_size, evt->buffer_released);
97113
if (ret < 0) {
98114
LOG_ERR("Failed to release buffer: %d", ret);
99-
stop_pdm(drv_data);
100115
return;
101116
}
102-
free_buffer(drv_data);
117+
free_buffer(drv_data, mem_slab_buffer);
103118
}
104119

105120
if (drv_data->active) {
@@ -109,20 +124,26 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
109124
}
110125
}
111126
} else if (evt->buffer_released) {
112-
ret = dmm_buffer_in_release(drv_cfg->mem_reg, drv_data->mem_slab_buffer,
127+
ret = k_msgq_get(&drv_data->mem_slab_queue, &mem_slab_buffer, K_NO_WAIT);
128+
if (ret < 0) {
129+
LOG_ERR("No buffers to free");
130+
stop_pdm(drv_data);
131+
return;
132+
}
133+
ret = dmm_buffer_in_release(drv_cfg->mem_reg, mem_slab_buffer,
113134
drv_data->block_size, evt->buffer_released);
114135
if (ret < 0) {
115136
LOG_ERR("Failed to release buffer: %d", ret);
116137
stop_pdm(drv_data);
117138
return;
118139
}
119140
ret = k_msgq_put(&drv_data->rx_queue,
120-
&drv_data->mem_slab_buffer,
141+
&mem_slab_buffer,
121142
K_NO_WAIT);
122143
if (ret < 0) {
123144
LOG_ERR("No room in RX queue");
124145
stop = true;
125-
free_buffer(drv_data);
146+
free_buffer(drv_data, mem_slab_buffer);
126147
} else {
127148
LOG_DBG("Queued buffer %p", evt->buffer_released);
128149
}
@@ -234,7 +255,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
234255

235256
if (is_in_freq_range(act_freq, pdm_cfg) &&
236257
is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
237-
config->clock_freq = clk_factor * 4096;
258+
config->clock_freq = clk_factor * DMIC_NRFX_CLOCK_FACTOR;
238259

239260
better_found = true;
240261
}
@@ -403,7 +424,6 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
403424

404425
channel->act_num_streams = 1;
405426
channel->act_chan_map_hi = 0;
406-
channel->act_chan_map_lo = def_map;
407427

408428
if (channel->req_num_streams != 1 ||
409429
channel->req_num_chan > 2 ||
@@ -434,9 +454,13 @@ static int dmic_nrfx_pdm_configure(const struct device *dev,
434454
nrfx_cfg.mode = channel->req_num_chan == 1
435455
? NRF_PDM_MODE_MONO
436456
: NRF_PDM_MODE_STEREO;
437-
nrfx_cfg.edge = channel->req_chan_map_lo == def_map
438-
? NRF_PDM_EDGE_LEFTFALLING
439-
: NRF_PDM_EDGE_LEFTRISING;
457+
if (channel->req_chan_map_lo == def_map) {
458+
nrfx_cfg.edge = NRF_PDM_EDGE_LEFTFALLING;
459+
channel->act_chan_map_lo = def_map;
460+
} else {
461+
nrfx_cfg.edge = NRF_PDM_EDGE_LEFTRISING;
462+
channel->act_chan_map_lo = alt_map;
463+
}
440464
#if NRF_PDM_HAS_MCLKCONFIG
441465
nrfx_cfg.mclksrc = drv_cfg->clk_src == ACLK
442466
? NRF_PDM_MCLKSRC_ACLK
@@ -633,6 +657,7 @@ static const struct _dmic_ops dmic_ops = {
633657

634658
#define PDM_NRFX_DEVICE(idx) \
635659
static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
660+
static void *mem_slab_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
636661
static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \
637662
static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \
638663
static int pdm_nrfx_init##idx(const struct device *dev) \
@@ -649,6 +674,9 @@ static const struct _dmic_ops dmic_ops = {
649674
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
650675
(char *)rx_msgs##idx, sizeof(void *), \
651676
ARRAY_SIZE(rx_msgs##idx)); \
677+
k_msgq_init(&dmic_nrfx_pdm_data##idx.mem_slab_queue, \
678+
(char *)mem_slab_msgs##idx, sizeof(void *), \
679+
ARRAY_SIZE(mem_slab_msgs##idx)); \
652680
IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
653681
(init_clock_manager(dev);)) \
654682
return 0; \

0 commit comments

Comments
 (0)