mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 10:00:57 +02:00
Merge branch 'bugfix/fix_multi_pdm_rx_slot_clock_issue_v5.2' into 'release/v5.2'
fix(i2s_pdm): fixed pdm multi slot clock issue (v5.2) See merge request espressif/esp-idf!41181
This commit is contained in:
@@ -330,13 +330,19 @@ err:
|
|||||||
|
|
||||||
#if SOC_I2S_SUPPORTS_PDM_RX
|
#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_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)
|
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;
|
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;
|
i2s_pdm_rx_clk_config_t *pdm_rx_clk = (i2s_pdm_rx_clk_config_t *)clk_cfg;
|
||||||
|
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 * I2S_LL_PDM_BCK_FACTOR * (pdm_rx_clk->dn_sample_mode == I2S_PDM_DSR_16S ? 2 : 1);
|
clk_info->bclk = rate * dn_sample_factor;
|
||||||
clk_info->bclk_div = clk_cfg->bclk_div < I2S_PDM_RX_BCLK_DIV_MIN ? I2S_PDM_RX_BCLK_DIV_MIN : clk_cfg->bclk_div;
|
/* 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->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->sclk = i2s_get_source_clk_freq(clk_cfg->clk_src, clk_info->mclk);
|
||||||
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
|
clk_info->mclk_div = clk_info->sclk / clk_info->mclk;
|
||||||
|
@@ -52,6 +52,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define I2S_NULL_POINTER_CHECK(tag, p) ESP_RETURN_ON_FALSE((p), ESP_ERR_INVALID_ARG, tag, "input parameter '"#p"' is NULL")
|
#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
|
* @brief i2s channel state for checking if the operation in under right driver state
|
||||||
|
@@ -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:
|
case I2S_CLK_SRC_XTAL:
|
||||||
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0;
|
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 0;
|
||||||
break;
|
break;
|
||||||
|
case I2S_CLK_SRC_PLL_240M:
|
||||||
|
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 1;
|
||||||
|
break;
|
||||||
case I2S_CLK_SRC_PLL_160M:
|
case I2S_CLK_SRC_PLL_160M:
|
||||||
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 2;
|
PCR.i2s_tx_clkm_conf.i2s_tx_clkm_sel = 2;
|
||||||
break;
|
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:
|
case I2S_CLK_SRC_XTAL:
|
||||||
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0;
|
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 0;
|
||||||
break;
|
break;
|
||||||
|
case I2S_CLK_SRC_PLL_240M:
|
||||||
|
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 1;
|
||||||
|
break;
|
||||||
case I2S_CLK_SRC_PLL_160M:
|
case I2S_CLK_SRC_PLL_160M:
|
||||||
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 2;
|
PCR.i2s_rx_clkm_conf.i2s_rx_clkm_sel = 2;
|
||||||
break;
|
break;
|
||||||
|
@@ -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:
|
case I2S_CLK_SRC_XTAL:
|
||||||
hw->tx_clkm_conf.tx_clk_sel = 0;
|
hw->tx_clkm_conf.tx_clk_sel = 0;
|
||||||
break;
|
break;
|
||||||
|
case I2S_CLK_SRC_PLL_240M:
|
||||||
|
hw->tx_clkm_conf.tx_clk_sel = 1;
|
||||||
|
break;
|
||||||
case I2S_CLK_SRC_PLL_160M:
|
case I2S_CLK_SRC_PLL_160M:
|
||||||
hw->tx_clkm_conf.tx_clk_sel = 2;
|
hw->tx_clkm_conf.tx_clk_sel = 2;
|
||||||
break;
|
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:
|
case I2S_CLK_SRC_XTAL:
|
||||||
hw->rx_clkm_conf.rx_clk_sel = 0;
|
hw->rx_clkm_conf.rx_clk_sel = 0;
|
||||||
break;
|
break;
|
||||||
|
case I2S_CLK_SRC_PLL_240M:
|
||||||
|
hw->rx_clkm_conf.rx_clk_sel = 1;
|
||||||
|
break;
|
||||||
case I2S_CLK_SRC_PLL_160M:
|
case I2S_CLK_SRC_PLL_160M:
|
||||||
hw->rx_clkm_conf.rx_clk_sel = 2;
|
hw->rx_clkm_conf.rx_clk_sel = 2;
|
||||||
break;
|
break;
|
||||||
|
@@ -295,13 +295,14 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* @brief Array initializer for all supported clock sources of I2S
|
* @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
|
* @brief I2S clock source enum
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */
|
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_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_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 */
|
||||||
|
@@ -280,16 +280,19 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* @brief Array initializer for all supported clock sources of I2S
|
* @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
|
* @brief I2S clock source enum
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2S_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default source clock */
|
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_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_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;
|
} soc_periph_i2s_clk_src_t;
|
||||||
|
|
||||||
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////I2C////////////////////////////////////////////////////////////////////
|
||||||
|
Reference in New Issue
Block a user