Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions drivers/audio/Kconfig.dmic_pdm_nrfx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ config AUDIO_DMIC_NRFX_PDM
default y
depends on DT_HAS_NORDIC_NRF_PDM_ENABLED
select NRFX_PDM0 if HAS_HW_NRF_PDM0
select NRFX_PDM20 if HAS_HW_NRF_PDM20
select NRFX_PDM21 if HAS_HW_NRF_PDM21
select PINCTRL
help
Enable support for nrfx PDM driver for nRF MCU series.
96 changes: 80 additions & 16 deletions drivers/audio/dmic_nrfx_pdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
LOG_MODULE_REGISTER(dmic_nrfx_pdm, CONFIG_AUDIO_DMIC_LOG_LEVEL);

struct dmic_nrfx_pdm_drv_data {
const nrfx_pdm_t *pdm;
struct onoff_manager *clk_mgr;
struct onoff_client clk_cli;
struct k_mem_slab *mem_slab;
Expand Down Expand Up @@ -58,8 +59,7 @@
LOG_ERR("Failed to allocate buffer: %d", ret);
stop = true;
} else {
err = nrfx_pdm_buffer_set(buffer,
drv_data->block_size / 2);
err = nrfx_pdm_buffer_set(drv_data->pdm, buffer, drv_data->block_size / 2);
if (err != NRFX_SUCCESS) {
LOG_ERR("Failed to set buffer: 0x%08x", err);
stop = true;
Expand Down Expand Up @@ -94,10 +94,15 @@

if (stop) {
drv_data->stopping = true;
nrfx_pdm_stop();
nrfx_pdm_stop(drv_data->pdm);
}
}

static bool is_in_freq_range(uint32_t freq, const struct dmic_cfg *pdm_cfg)
{
return freq >= pdm_cfg->io.min_pdm_clk_freq && freq <= pdm_cfg->io.max_pdm_clk_freq;
}

static bool is_better(uint32_t freq,
uint8_t ratio,
uint32_t req_rate,
Expand Down Expand Up @@ -132,6 +137,37 @@
uint32_t req_rate = pdm_cfg->streams[0].pcm_rate;
bool better_found = false;

#if NRF_PDM_HAS_PRESCALER
uint32_t src_freq = 32 * 1000 * 1000UL;
uint32_t req_freq = req_rate * ratio;
uint32_t prescaler = src_freq / req_freq;
uint32_t act_freq = src_freq / prescaler;

if (is_in_freq_range(act_freq, pdm_cfg) &&
is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
config->prescaler = prescaler;

better_found = true;
}

/* Stop if an exact rate match is found. */
if (*best_diff == 0) {
return true;
}

/* Prescaler value is rounded down by default,
* thus value rounded up should be checked as well.
*/
prescaler += 1;
act_freq = src_freq / prescaler;

Check notice on line 163 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:163 - act_freq = src_freq / prescaler; + act_freq = src_freq / prescaler;
if (is_in_freq_range(act_freq, pdm_cfg) &&
is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
config->prescaler = prescaler;

better_found = true;
}
#else
if (IS_ENABLED(CONFIG_SOC_SERIES_NRF53X)) {
const uint32_t src_freq =
(NRF_PDM_HAS_MCLKCONFIG && drv_cfg->clk_src == ACLK)
Expand All @@ -158,10 +194,8 @@
(src_freq + req_freq / 2));
uint32_t act_freq = src_freq / (1048576 / clk_factor);

if (act_freq >= pdm_cfg->io.min_pdm_clk_freq &&
act_freq <= pdm_cfg->io.max_pdm_clk_freq &&
is_better(act_freq, ratio, req_rate,
best_diff, best_rate, best_freq)) {
if (is_in_freq_range(act_freq, pdm_cfg) &&
is_better(act_freq, ratio, req_rate, best_diff, best_rate, best_freq)) {
config->clock_freq = clk_factor * 4096;

better_found = true;
Expand Down Expand Up @@ -216,6 +250,7 @@
}
}
}
#endif /* NRF_PDM_HAS_PRESCALER */

return better_found;
}
Expand All @@ -236,8 +271,26 @@
uint8_t ratio_val;
nrf_pdm_ratio_t ratio_enum;
} ratios[] = {
{ 64, NRF_PDM_RATIO_64X },
{ 80, NRF_PDM_RATIO_80X }
#if defined(PDM_RATIO_RATIO_Ratio32)
{ 32, NRF_PDM_RATIO_32X },
#endif
#if defined(PDM_RATIO_RATIO_Ratio48)
{ 48, NRF_PDM_RATIO_48X },
#endif
#if defined(PDM_RATIO_RATIO_Ratio50)
{ 50, NRF_PDM_RATIO_50X },
#endif
{ 64, NRF_PDM_RATIO_64X },
{ 80, NRF_PDM_RATIO_80X },
#if defined(PDM_RATIO_RATIO_Ratio96)
{ 96, NRF_PDM_RATIO_96X },
#endif
#if defined(PDM_RATIO_RATIO_Ratio100)
{ 100, NRF_PDM_RATIO_100X },
#endif
#if defined(PDM_RATIO_RATIO_Ratio128)
{ 128, NRF_PDM_RATIO_128X }
#endif

Check notice on line 293 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:293 - { 32, NRF_PDM_RATIO_32X }, + {32, NRF_PDM_RATIO_32X}, #endif #if defined(PDM_RATIO_RATIO_Ratio48) - { 48, NRF_PDM_RATIO_48X }, + {48, NRF_PDM_RATIO_48X}, #endif #if defined(PDM_RATIO_RATIO_Ratio50) - { 50, NRF_PDM_RATIO_50X }, -#endif - { 64, NRF_PDM_RATIO_64X }, - { 80, NRF_PDM_RATIO_80X }, + {50, NRF_PDM_RATIO_50X}, +#endif + {64, NRF_PDM_RATIO_64X}, {80, NRF_PDM_RATIO_80X}, #if defined(PDM_RATIO_RATIO_Ratio96) - { 96, NRF_PDM_RATIO_96X }, + {96, NRF_PDM_RATIO_96X}, #endif #if defined(PDM_RATIO_RATIO_Ratio100) - { 100, NRF_PDM_RATIO_100X }, + {100, NRF_PDM_RATIO_100X}, #endif #if defined(PDM_RATIO_RATIO_Ratio128) - { 128, NRF_PDM_RATIO_128X } + {128, NRF_PDM_RATIO_128X}
};

for (int r = 0; best_diff != 0 && r < ARRAY_SIZE(ratios); ++r) {
Expand Down Expand Up @@ -327,7 +380,7 @@
/* If either rate or width is 0, the stream is to be disabled. */
if (stream->pcm_rate == 0 || stream->pcm_width == 0) {
if (drv_data->configured) {
nrfx_pdm_uninit();
nrfx_pdm_uninit(drv_data->pdm);
drv_data->configured = false;
}

Expand Down Expand Up @@ -357,11 +410,11 @@
}

if (drv_data->configured) {
nrfx_pdm_uninit();
nrfx_pdm_uninit(drv_data->pdm);
drv_data->configured = false;
}

err = nrfx_pdm_init(&nrfx_cfg, drv_cfg->event_handler);
err = nrfx_pdm_init(drv_data->pdm, &nrfx_cfg, drv_cfg->event_handler);
if (err != NRFX_SUCCESS) {
LOG_ERR("Failed to initialize PDM: 0x%08x", err);
return -EIO;
Expand All @@ -385,7 +438,7 @@
nrfx_err_t err;
int ret;

err = nrfx_pdm_start();
err = nrfx_pdm_start(drv_data->pdm);
if (err == NRFX_SUCCESS) {
return 0;
}
Expand Down Expand Up @@ -460,7 +513,7 @@
case DMIC_TRIGGER_STOP:
if (drv_data->active) {
drv_data->stopping = true;
nrfx_pdm_stop();
nrfx_pdm_stop(drv_data->pdm);
}
break;

Expand Down Expand Up @@ -541,16 +594,18 @@
#define PDM_NRFX_DEVICE(idx) \
static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \
static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \
static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \
static int pdm_nrfx_init##idx(const struct device *dev) \
{ \
IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \
nrfx_isr, nrfx_pdm_irq_handler, 0); \
nrfx_isr, nrfx_pdm_##idx##_irq_handler, 0); \
const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \
int err = pinctrl_apply_state(drv_cfg->pcfg, \
PINCTRL_STATE_DEFAULT); \
if (err < 0) { \
return err; \
} \
dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \
k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \
(char *)rx_msgs##idx, sizeof(void *), \
ARRAY_SIZE(rx_msgs##idx)); \
Expand Down Expand Up @@ -580,7 +635,16 @@
DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \
&dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \
POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \
&dmic_ops);

Check notice on line 638 in drivers/audio/dmic_nrfx_pdm.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/audio/dmic_nrfx_pdm.c:638 -#define PDM_NRFX_DEVICE(idx) \ - static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ - static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ - static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ - static int pdm_nrfx_init##idx(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), \ - nrfx_isr, nrfx_pdm_##idx##_irq_handler, 0); \ - const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ - int err = pinctrl_apply_state(drv_cfg->pcfg, \ - PINCTRL_STATE_DEFAULT); \ - if (err < 0) { \ - return err; \ - } \ - dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ - k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, \ - (char *)rx_msgs##idx, sizeof(void *), \ - ARRAY_SIZE(rx_msgs##idx)); \ - init_clock_manager(dev); \ - return 0; \ - } \ - static void event_handler##idx(const nrfx_pdm_evt_t *evt) \ - { \ - event_handler(DEVICE_DT_GET(PDM(idx)), evt); \ - } \ - PINCTRL_DT_DEFINE(PDM(idx)); \ - static const struct dmic_nrfx_pdm_drv_cfg dmic_nrfx_pdm_cfg##idx = { \ - .event_handler = event_handler##idx, \ - .nrfx_def_cfg = NRFX_PDM_DEFAULT_CONFIG(0, 0), \ - .nrfx_def_cfg.skip_gpio_cfg = true, \ - .nrfx_def_cfg.skip_psel_cfg = true, \ - .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PDM(idx)), \ - .clk_src = PDM_CLK_SRC(idx), \ - }; \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || NRF_PDM_HAS_MCLKCONFIG, \ - "Clock source ACLK is not available."); \ - BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \ - DT_NODE_HAS_PROP(DT_NODELABEL(clock), \ - hfclkaudio_frequency), \ - "Clock source ACLK requires the hfclkaudio-frequency " \ - "property to be defined in the nordic,nrf-clock node."); \ - DEVICE_DT_DEFINE(PDM(idx), pdm_nrfx_init##idx, NULL, \ - &dmic_nrfx_pdm_data##idx, &dmic_nrfx_pdm_cfg##idx, \ - POST_KERNEL, CONFIG_AUDIO_DMIC_INIT_PRIORITY, \ +#define PDM_NRFX_DEVICE(idx) \ + static void *rx_msgs##idx[DT_PROP(PDM(idx), queue_size)]; \ + static struct dmic_nrfx_pdm_drv_data dmic_nrfx_pdm_data##idx; \ + static const nrfx_pdm_t dmic_nrfx_pdm##idx = NRFX_PDM_INSTANCE(idx); \ + static int pdm_nrfx_init##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_IRQN(PDM(idx)), DT_IRQ(PDM(idx), priority), nrfx_isr, \ + nrfx_pdm_##idx##_irq_handler, 0); \ + const struct dmic_nrfx_pdm_drv_cfg *drv_cfg = dev->config; \ + int err = pinctrl_apply_state(drv_cfg->pcfg, PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + dmic_nrfx_pdm_data##idx.pdm = &dmic_nrfx_pdm##idx; \ + k_msgq_init(&dmic_nrfx_pdm_data##idx.rx_queue, (char *)rx_msgs##idx, \ + sizeof(void *), ARRAY_SIZE(rx_msgs##idx)); \ + init_clock_manager(dev); \ + return 0; \ + } \ + static void event_handler##idx(const nrfx_pdm_evt_t *evt) \ + {

/* Existing SoCs only have one PDM instance. */
#ifdef CONFIG_HAS_HW_NRF_PDM0
PDM_NRFX_DEVICE(0);
#endif

#ifdef CONFIG_HAS_HW_NRF_PDM20
PDM_NRFX_DEVICE(20);
#endif

#ifdef CONFIG_HAS_HW_NRF_PDM21
PDM_NRFX_DEVICE(21);
#endif
10 changes: 10 additions & 0 deletions modules/hal_nordic/nrfx/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,16 @@ config NRFX_PDM0
depends on $(dt_nodelabel_has_compat,pdm0,$(DT_COMPAT_NORDIC_NRF_PDM))
select NRFX_PDM

config NRFX_PDM20
bool "PDM20 driver instance"
depends on $(dt_nodelabel_has_compat,pdm20,$(DT_COMPAT_NORDIC_NRF_PDM))
select NRFX_PDM

config NRFX_PDM21
bool "PDM21 driver instance"
depends on $(dt_nodelabel_has_compat,pdm21,$(DT_COMPAT_NORDIC_NRF_PDM))
select NRFX_PDM

config NRFX_POWER
bool "POWER driver"
depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_POWER))
Expand Down
10 changes: 8 additions & 2 deletions modules/hal_nordic/nrfx/nrfx_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,17 @@
#ifdef CONFIG_NRFX_PDM
#define NRFX_PDM_ENABLED 1
#endif
#ifdef CONFIG_NRFX_PDM_LOG
#define NRFX_PDM_CONFIG_LOG_ENABLED 1
#endif
#ifdef CONFIG_NRFX_PDM0
#define NRFX_PDM0_ENABLED 1
#endif
#ifdef CONFIG_NRFX_PDM_LOG
#define NRFX_PDM_CONFIG_LOG_ENABLED 1
#ifdef CONFIG_NRFX_PDM20
#define NRFX_PDM20_ENABLED 1
#endif
#ifdef CONFIG_NRFX_PDM21
#define NRFX_PDM21_ENABLED 1
#endif

#ifdef CONFIG_NRFX_POWER
Expand Down
2 changes: 1 addition & 1 deletion modules/hal_nordic/nrfx/nrfx_config_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

/** @brief Symbol specifying minor version of the nrfx API to be used. */
#ifndef NRFX_CONFIG_API_VER_MINOR
#define NRFX_CONFIG_API_VER_MINOR 6
#define NRFX_CONFIG_API_VER_MINOR 7
#endif

/** @brief Symbol specifying micro version of the nrfx API to be used. */
Expand Down
9 changes: 9 additions & 0 deletions modules/hal_nordic/nrfx/nrfx_config_nrf5340_application.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,15 @@
#define NRFX_PDM_CONFIG_LOG_LEVEL 3
#endif

/**
* @brief NRFX_PDM0_ENABLED
*
* Boolean. Accepted values 0 and 1.
*/
#ifndef NRFX_PDM0_ENABLED
#define NRFX_PDM0_ENABLED 0
#endif

/**
* @brief NRFX_POWER_ENABLED
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

&pinctrl {
pdm20_default_alt: pdm20_default_alt {
group1 {
psels = <NRF_PSEL(PDM_CLK, 1, 12)>,
<NRF_PSEL(PDM_DIN, 1, 13)>;
};
};
};

dmic_dev: &pdm20 {
status = "okay";
pinctrl-0 = <&pdm20_default_alt>;
pinctrl-names = "default";
clock-source = "PCLK32M";
};
1 change: 1 addition & 0 deletions samples/drivers/audio/dmic/sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tests:
integration_platforms:
- nrf52840dk/nrf52840
- nrf5340dk/nrf5340/cpuapp
- nrf54l15dk/nrf54l15/cpuapp
harness: console
harness_config:
type: multi_line
Expand Down
6 changes: 6 additions & 0 deletions soc/nordic/common/Kconfig.peripherals
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ config HAS_HW_NRF_OSCILLATORS
config HAS_HW_NRF_PDM0
def_bool $(dt_nodelabel_enabled_with_compat,pdm0,$(DT_COMPAT_NORDIC_NRF_PDM))

config HAS_HW_NRF_PDM20
def_bool $(dt_nodelabel_enabled_with_compat,pdm20,$(DT_COMPAT_NORDIC_NRF_PDM))

config HAS_HW_NRF_PDM21
def_bool $(dt_nodelabel_enabled_with_compat,pdm21,$(DT_COMPAT_NORDIC_NRF_PDM))

config HAS_HW_NRF_POWER
def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_POWER))

Expand Down
2 changes: 2 additions & 0 deletions soc/nordic/validate_base_addresses.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ CHECK_DT_REG(nfct, NRF_NFCT);
CHECK_DT_REG(nrf_mpu, NRF_MPU);
CHECK_DT_REG(oscillators, NRF_OSCILLATORS);
CHECK_DT_REG(pdm0, NRF_PDM0);
CHECK_DT_REG(pdm20, NRF_PDM20);
CHECK_DT_REG(pdm21, NRF_PDM21);
CHECK_DT_REG(power, NRF_POWER);
CHECK_DT_REG(ppi, NRF_PPI);
CHECK_DT_REG(pwm0, NRF_PWM0);
Expand Down
Loading