8
8
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
9
9
#include <zephyr/drivers/pinctrl.h>
10
10
#include <soc.h>
11
+ #include <dmm.h>
11
12
#include <nrfx_pdm.h>
12
13
13
14
#include <zephyr/logging/log.h>
14
15
#include <zephyr/irq.h>
15
16
LOG_MODULE_REGISTER (dmic_nrfx_pdm , CONFIG_AUDIO_DMIC_LOG_LEVEL );
16
17
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
+
17
24
struct dmic_nrfx_pdm_drv_data {
18
25
const nrfx_pdm_t * pdm ;
19
26
struct onoff_manager * clk_mgr ;
20
27
struct onoff_client clk_cli ;
21
28
struct k_mem_slab * mem_slab ;
29
+ void * mem_slab_buffer ;
22
30
uint32_t block_size ;
23
31
struct k_msgq rx_queue ;
24
32
bool request_clock : 1 ;
@@ -36,29 +44,44 @@ struct dmic_nrfx_pdm_drv_cfg {
36
44
PCLK32M_HFXO ,
37
45
ACLK
38
46
} clk_src ;
47
+ void * mem_reg ;
39
48
};
40
49
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 )
42
57
{
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 );
45
60
}
46
61
47
62
static void event_handler (const struct device * dev , const nrfx_pdm_evt_t * evt )
48
63
{
49
64
struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
65
+ const struct dmic_nrfx_pdm_drv_cfg * drv_cfg = dev -> config ;
50
66
int ret ;
51
67
bool stop = false;
52
68
53
69
if (evt -> buffer_requested ) {
54
70
void * buffer ;
55
71
nrfx_err_t err ;
56
72
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 );
58
74
if (ret < 0 ) {
59
75
LOG_ERR ("Failed to allocate buffer: %d" , ret );
60
76
stop = true;
61
77
} 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
+ }
62
85
err = nrfx_pdm_buffer_set (drv_data -> pdm , buffer , drv_data -> block_size / 2 );
63
86
if (err != NRFX_SUCCESS ) {
64
87
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)
69
92
70
93
if (drv_data -> stopping ) {
71
94
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 );
73
103
}
74
104
75
105
if (drv_data -> active ) {
@@ -79,22 +109,26 @@ static void event_handler(const struct device *dev, const nrfx_pdm_evt_t *evt)
79
109
}
80
110
}
81
111
} 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
+ }
82
119
ret = k_msgq_put (& drv_data -> rx_queue ,
83
- & evt -> buffer_released ,
120
+ & drv_data -> mem_slab_buffer ,
84
121
K_NO_WAIT );
85
122
if (ret < 0 ) {
86
123
LOG_ERR ("No room in RX queue" );
87
124
stop = true;
88
-
89
- free_buffer (drv_data , evt -> buffer_released );
125
+ free_buffer (drv_data );
90
126
} else {
91
127
LOG_DBG ("Queued buffer %p" , evt -> buffer_released );
92
128
}
93
129
}
94
-
95
130
if (stop ) {
96
- drv_data -> stopping = true;
97
- nrfx_pdm_stop (drv_data -> pdm );
131
+ stop_pdm (drv_data );
98
132
}
99
133
}
100
134
@@ -168,7 +202,7 @@ static bool check_pdm_frequencies(const struct dmic_nrfx_pdm_drv_cfg *drv_cfg,
168
202
better_found = true;
169
203
}
170
204
#else
171
- if (IS_ENABLED (CONFIG_SOC_SERIES_NRF53X )) {
205
+ if (IS_ENABLED (CONFIG_SOC_SERIES_NRF53X ) || IS_ENABLED ( CONFIG_SOC_SERIES_NRF54HX ) ) {
172
206
const uint32_t src_freq =
173
207
(NRF_PDM_HAS_MCLKCONFIG && drv_cfg -> clk_src == ACLK )
174
208
/* 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,
180
214
* not defined (this expression will be eventually
181
215
* optimized away then).
182
216
*/
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
+ */
183
221
? DT_PROP_OR (DT_NODELABEL (clock ), hfclkaudio_frequency ,
184
222
0 )
185
- : 32 * 1000 * 1000UL ;
223
+ : DMIC_NRFX_CLOCK_FREQ ;
186
224
uint32_t req_freq = req_rate * ratio ;
187
225
/* As specified in the nRF5340 PS:
188
226
*
@@ -562,6 +600,7 @@ static int dmic_nrfx_pdm_read(const struct device *dev,
562
600
return ret ;
563
601
}
564
602
603
+ #if CONFIG_CLOCK_CONTROL_NRF
565
604
static void init_clock_manager (const struct device * dev )
566
605
{
567
606
struct dmic_nrfx_pdm_drv_data * drv_data = dev -> data ;
@@ -581,6 +620,7 @@ static void init_clock_manager(const struct device *dev)
581
620
drv_data -> clk_mgr = z_nrf_clock_control_get_onoff (subsys );
582
621
__ASSERT_NO_MSG (drv_data -> clk_mgr != NULL );
583
622
}
623
+ #endif
584
624
585
625
static const struct _dmic_ops dmic_ops = {
586
626
.configure = dmic_nrfx_pdm_configure ,
@@ -609,7 +649,8 @@ static const struct _dmic_ops dmic_ops = {
609
649
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
610
650
(char *)rx_msgs##idx, sizeof(void *), \
611
651
ARRAY_SIZE(rx_msgs##idx)); \
612
- init_clock_manager(dev); \
652
+ IF_ENABLED(CONFIG_CLOCK_CONTROL_NRF, \
653
+ (init_clock_manager(dev);)) \
613
654
return 0; \
614
655
} \
615
656
static void event_handler##idx(const nrfx_pdm_evt_t *evt) \
@@ -624,6 +665,7 @@ static const struct _dmic_ops dmic_ops = {
624
665
.nrfx_def_cfg.skip_psel_cfg = true, \
625
666
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \
626
667
.clk_src = PDM_CLK_SRC(idx), \
668
+ .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \
627
669
}; \
628
670
BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \
629
671
"Clock source ACLK is not available."); \
0 commit comments