From 3d5d0c939ea67148513ce08154fb3b8e0172bab8 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Mon, 28 Jul 2025 17:50:39 +0800 Subject: [PATCH 1/2] fix(i2s_pdm): fixed pdm multi slot clock issue Fixed the sample rate slow down issue when using more than 4 slots in pdm rx mode. --- components/driver/i2s/i2s_pdm.c | 12 +++++++++--- components/driver/i2s/i2s_private.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/components/driver/i2s/i2s_pdm.c b/components/driver/i2s/i2s_pdm.c index 4383c36d3f..506877c583 100644 --- a/components/driver/i2s/i2s_pdm.c +++ b/components/driver/i2s/i2s_pdm.c @@ -330,13 +330,19 @@ err: #if SOC_I2S_SUPPORTS_PDM_RX #define I2S_PDM_RX_BCLK_DIV_MIN 8 /*!< The minimum bclk_div for PDM RX mode */ +#define I2S_PDM_RX_CLK_LIMIT_COEFF 128 /*!< The coefficient for the clock limitation */ static esp_err_t i2s_pdm_rx_calculate_clock(i2s_chan_handle_t handle, const i2s_pdm_rx_clk_config_t *clk_cfg, i2s_hal_clock_info_t *clk_info) { + i2s_pdm_rx_slot_config_t *slot_cfg = &((i2s_pdm_rx_config_t *)(handle->mode_info))->slot_cfg; + uint32_t slot_num = __builtin_popcount(slot_cfg->slot_mask); + uint32_t rate = clk_cfg->sample_rate_hz; i2s_pdm_rx_clk_config_t *pdm_rx_clk = (i2s_pdm_rx_clk_config_t *)clk_cfg; - - clk_info->bclk = rate * I2S_LL_PDM_BCK_FACTOR * (pdm_rx_clk->dn_sample_mode == I2S_PDM_DSR_16S ? 2 : 1); - clk_info->bclk_div = clk_cfg->bclk_div < I2S_PDM_RX_BCLK_DIV_MIN ? I2S_PDM_RX_BCLK_DIV_MIN : clk_cfg->bclk_div; + uint32_t dn_sample_factor = I2S_LL_PDM_BCK_FACTOR * (pdm_rx_clk->dn_sample_mode == I2S_PDM_DSR_16S ? 2 : 1); + clk_info->bclk = rate * dn_sample_factor; + /* Hardware limitation: bclk_div * dn_sample_factor / slot_num >= 96 */ + uint32_t bclk_limit = (I2S_PDM_RX_CLK_LIMIT_COEFF * slot_num + dn_sample_factor - 1) / dn_sample_factor; + clk_info->bclk_div = MAX(MAX(bclk_limit, I2S_PDM_RX_BCLK_DIV_MIN), clk_cfg->bclk_div); clk_info->mclk = clk_info->bclk * clk_info->bclk_div; clk_info->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk); clk_info->mclk_div = clk_info->sclk / clk_info->mclk; diff --git a/components/driver/i2s/i2s_private.h b/components/driver/i2s/i2s_private.h index 332e66f39e..c6c922cd41 100644 --- a/components/driver/i2s/i2s_private.h +++ b/components/driver/i2s/i2s_private.h @@ -52,6 +52,7 @@ extern "C" { #endif #define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL") +#define MAX(a, b) ((a) > (b) ? (a) : (b)) /** * @brief i2s channel state for checking if the operation in under right driver state From 3b034c6886bba0f23a05782e193f483287a3e60d Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Fri, 1 Aug 2025 11:39:36 +0800 Subject: [PATCH 2/2] feat(i2s): add PLL240M clock source on S3 and C6 Closes https://github.com/espressif/esp-idf/issues/17056 --- components/hal/esp32c6/include/hal/i2s_ll.h | 6 ++++++ components/hal/esp32s3/include/hal/i2s_ll.h | 6 ++++++ components/soc/esp32c6/include/soc/clk_tree_defs.h | 3 ++- components/soc/esp32s3/include/soc/clk_tree_defs.h | 7 +++++-- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index f8bad2feb1..349638bbf8 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -220,6 +220,9 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0; break; + case I2S_CLK_SRC_PLL_240M: + PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 2; break; @@ -246,6 +249,9 @@ static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0; break; + case I2S_CLK_SRC_PLL_240M: + PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 2; break; diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 82677b556d..7899839e09 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -233,6 +233,9 @@ static inline void i2s_ll_tx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->tx_clkm_conf.tx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_240M: + hw->tx_clkm_conf.tx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->tx_clkm_conf.tx_clk_sel = 2; break; @@ -258,6 +261,9 @@ static inline void i2s_ll_rx_clk_set_src(i2s_dev_t *hw, i2s_clock_src_t src) case I2S_CLK_SRC_XTAL: hw->rx_clkm_conf.rx_clk_sel = 0; break; + case I2S_CLK_SRC_PLL_240M: + hw->rx_clkm_conf.rx_clk_sel = 1; + break; case I2S_CLK_SRC_PLL_160M: hw->rx_clkm_conf.rx_clk_sel = 2; break; diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index 69c9619162..7a5ba2b44c 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -295,13 +295,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of I2S */ -#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} +#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F240M, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} /** * @brief I2S clock source enum */ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */ + I2S_CLK_SRC_PLL_240M = SOC_MOD_CLK_PLL_F240M, /*!< Select PLL_F240M as the source clock */ I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index f38395fb19..5915b49f7e 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -280,16 +280,19 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of I2S */ -#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} +#define SOC_I2S_CLKS {SOC_MOD_CLK_PLL_F240M, SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_XTAL, I2S_CLK_SRC_EXTERNAL} /** * @brief I2S clock source enum */ typedef enum { I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */ + I2S_CLK_SRC_PLL_240M = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 as the source clock. + It is default to 240MHz while PLL is 480MHz, + but it will be 160MHz if PLL is 320MHz */ I2S_CLK_SRC_PLL_160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */ I2S_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ - I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ + I2S_CLK_SRC_EXTERNAL = -1, /*!< Select external clock as source clock */ } soc_periph_i2s_clk_src_t; /////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////