diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index a648990312..434f0589ab 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -56,7 +56,7 @@ static esp_err_t i2s_pdm_tx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); ESP_RETURN_ON_FALSE(clk_info->mclk_div < 256, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); #if SOC_I2S_SUPPORTS_PCM2PDM if (!handle->is_raw_pdm) { @@ -385,7 +385,8 @@ static esp_err_t i2s_pdm_rx_calculate_clock(i2s_chan_handle_t handle, const i2s_ clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * 1.99, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); #if SOC_I2S_SUPPORTS_PDM2PCM if (!handle->is_raw_pdm) { /* Set down-sampling configuration */ diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index e567f75f2d..f2743b9f20 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -43,8 +43,12 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std ESP_LOGW(TAG, "the current mclk multiple cannot perform integer division (slot_num: %"PRIu32", slot_bits: %"PRIu32")", handle->total_slot, slot_bits); } } else { - /* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */ - clk_info->bclk_div = 8; + if (clk_cfg->bclk_div < 8) { + ESP_LOGW(TAG, "the current bclk division is too small, adjust the bclk division to 8"); + clk_info->bclk_div = 8; + } else { + clk_info->bclk_div = clk_cfg->bclk_div; + } clk_info->bclk = rate * handle->total_slot * slot_bits; clk_info->mclk = clk_info->bclk * clk_info->bclk_div; } @@ -60,7 +64,8 @@ static esp_err_t i2s_std_calculate_clock(i2s_chan_handle_t handle, const i2s_std clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); return ESP_OK; } diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index 61ed2a5f2c..e5d3f7892a 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -66,7 +66,8 @@ static esp_err_t i2s_tdm_calculate_clock(i2s_chan_handle_t handle, const i2s_tdm clk_info->mclk_div = clk_info->sclk / clk_info->mclk; /* Check if the configuration is correct. Use float for check in case the mclk division might be carried up in the fine division calculation */ - ESP_RETURN_ON_FALSE(clk_info->sclk / (float)clk_info->mclk > min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate or mclk_multiple is too large for the current clock source"); + ESP_RETURN_ON_FALSE((float)clk_info->sclk > clk_info->mclk * min_mclk_div, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large"); + ESP_RETURN_ON_FALSE(clk_info->mclk_div < I2S_LL_CLK_FRAC_DIV_N_MAX, ESP_ERR_INVALID_ARG, TAG, "sample rate is too small"); return ESP_OK; } diff --git a/components/esp_driver_i2s/include/driver/i2s_std.h b/components/esp_driver_i2s/include/driver/i2s_std.h index 038ff2825a..d41af89418 100644 --- a/components/esp_driver_i2s/include/driver/i2s_std.h +++ b/components/esp_driver_i2s/include/driver/i2s_std.h @@ -204,6 +204,7 @@ extern "C" { .sample_rate_hz = rate, \ .clk_src = I2S_CLK_SRC_DEFAULT, \ .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ + .bclk_div = 8, \ } #else /** @@ -217,6 +218,7 @@ extern "C" { .clk_src = I2S_CLK_SRC_DEFAULT, \ .ext_clk_freq_hz = 0, \ .mclk_multiple = I2S_MCLK_MULTIPLE_256, \ + .bclk_div = 8, \ } #endif @@ -265,6 +267,7 @@ typedef struct { * but please set this field a multiple of `3` (like 384) when using 24-bit data width, * otherwise the sample rate might be inaccurate */ + uint32_t bclk_div; /*!< The division from MCLK to BCLK, only take effect for slave role, it shouldn't be smaller than 8. Increase this field when data sent by slave lag behind */ } i2s_std_clk_config_t; /**