Browse Source

Merge branch 'bugfix/i2s_apll_fixed_clock' into 'master'

i2s: fix apll bug introduced in 'refactor/i2s_driver'

Closes IDFGH-5824

See merge request espressif/esp-idf!15109
Kevin (Lao Kaiyao) 4 năm trước cách đây
mục cha
commit
a287f34f88

+ 88 - 86
components/driver/i2s.c

@@ -155,7 +155,7 @@ static int _i2s_adc_channel = -1;
   -------------------------------------------------------------
                    I2S clock operation
   -------------------------------------------------------------
-   - [helper]   i2s_get_source_clock
+   - [helper]   i2s_config_source_clock
    - [helper]   i2s_calculate_adc_dac_clock
    - [helper]   i2s_calculate_pdm_tx_clock
    - [helper]   i2s_calculate_pdm_rx_clock
@@ -889,6 +889,28 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
                    I2S clock operation
   -------------------------------------------------------------*/
 #if SOC_I2S_SUPPORTS_APLL
+/**
+ * @brief Get APLL frequency
+ */
+static float i2s_apll_get_freq(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir)
+{
+    int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
+
+#if CONFIG_IDF_TARGET_ESP32
+    /* ESP32 rev0 silicon issue for APLL range/accuracy, please see ESP32 ECO document for more information on this */
+    if (esp_efuse_get_chip_ver() == 0) {
+        sdm0 = 0;
+        sdm1 = 0;
+    }
+#endif
+    float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4);
+    if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) {
+        return SOC_I2S_APLL_MAX_FREQ;
+    }
+    float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1)
+    return fpll / 2;
+}
+
 /**
  * @brief     APLL calculate function, was described by following:
  *            APLL Output frequency is given by the formula:
@@ -919,30 +941,6 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num)
  * @param[out]      sdm1             The sdm 1
  * @param[out]      sdm2             The sdm 2
  * @param[out]      odir             The odir
- *
- * @return     ESP_ERR_INVALID_ARG or ESP_OK
- */
-static float i2s_apll_get_division_coefficient(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir)
-{
-    int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
-
-#if CONFIG_IDF_TARGET_ESP32
-    /* ESP32 rev0 silicon issue for APLL range/accuracy, please see ESP32 ECO document for more information on this */
-    if (esp_efuse_get_chip_ver() == 0) {
-        sdm0 = 0;
-        sdm1 = 0;
-    }
-#endif
-    float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4);
-    if (fout < SOC_I2S_APLL_MIN_FREQ || fout > SOC_I2S_APLL_MAX_FREQ) {
-        return SOC_I2S_APLL_MAX_FREQ;
-    }
-    float fpll = fout / (2 * (odir + 2)); //== fi2s (N=1, b=0, a=1)
-    return fpll / 2;
-}
-
-/**
- * @brief Calculate APLL parameters to get a closest frequency
  */
 static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
 {
@@ -957,8 +955,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
     min_diff = SOC_I2S_APLL_MAX_FREQ;
 
     for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
-        max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, _sdm2, 0);
-        min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, _sdm2, 31);
+        max_rate = i2s_apll_get_freq(bits_per_sample, 255, 255, _sdm2, 0);
+        min_rate = i2s_apll_get_freq(bits_per_sample, 0, 0, _sdm2, 31);
         avg = (max_rate + min_rate) / 2;
         if (abs(avg - rate) < min_diff) {
             min_diff = abs(avg - rate);
@@ -967,8 +965,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
     }
     min_diff = SOC_I2S_APLL_MAX_FREQ;
     for (_odir = 0; _odir < 32; _odir ++) {
-        max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, *sdm2, _odir);
-        min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, *sdm2, _odir);
+        max_rate = i2s_apll_get_freq(bits_per_sample, 255, 255, *sdm2, _odir);
+        min_rate = i2s_apll_get_freq(bits_per_sample, 0, 0, *sdm2, _odir);
         avg = (max_rate + min_rate) / 2;
         if (abs(avg - rate) < min_diff) {
             min_diff = abs(avg - rate);
@@ -977,8 +975,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
     }
     min_diff = SOC_I2S_APLL_MAX_FREQ;
     for (_sdm2 = 4; _sdm2 < 9; _sdm2 ++) {
-        max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, 255, _sdm2, *odir);
-        min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, 0, _sdm2, *odir);
+        max_rate = i2s_apll_get_freq(bits_per_sample, 255, 255, _sdm2, *odir);
+        min_rate = i2s_apll_get_freq(bits_per_sample, 0, 0, _sdm2, *odir);
         avg = (max_rate + min_rate) / 2;
         if (abs(avg - rate) < min_diff) {
             min_diff = abs(avg - rate);
@@ -988,8 +986,8 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
 
     min_diff = SOC_I2S_APLL_MAX_FREQ;
     for (_sdm1 = 0; _sdm1 < 256; _sdm1 ++) {
-        max_rate = i2s_apll_get_division_coefficient(bits_per_sample, 255, _sdm1, *sdm2, *odir);
-        min_rate = i2s_apll_get_division_coefficient(bits_per_sample, 0, _sdm1, *sdm2, *odir);
+        max_rate = i2s_apll_get_freq(bits_per_sample, 255, _sdm1, *sdm2, *odir);
+        min_rate = i2s_apll_get_freq(bits_per_sample, 0, _sdm1, *sdm2, *odir);
         avg = (max_rate + min_rate) / 2;
         if (abs(avg - rate) < min_diff) {
             min_diff = abs(avg - rate);
@@ -999,7 +997,7 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
 
     min_diff = SOC_I2S_APLL_MAX_FREQ;
     for (_sdm0 = 0; _sdm0 < 256; _sdm0 ++) {
-        avg = i2s_apll_get_division_coefficient(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir);
+        avg = i2s_apll_get_freq(bits_per_sample, _sdm0, *sdm1, *sdm2, *odir);
         if (abs(avg - rate) < min_diff) {
             min_diff = abs(avg - rate);
             *sdm0 = _sdm0;
@@ -1009,15 +1007,17 @@ static void i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, in
 #endif
 
 /**
- * @brief   Get I2S source clock
+ * @brief   Config I2S source clock and get its frequency
  *
  * @param   i2s_num         I2S device number
  * @param   use_apll        Whether use apll, only take effect when chip supports
- * @param   fixed_mclk      Whether use apll, only take effect when 'use_apll' is true
+ * @param   mclk            module clock
+ *
  * @return
- *      - Clock frequency
+ *      - 0                 use I2S_CLK_APLL as clock source, no I2S system clock to set
+ *      - I2S_LL_BASE_CLK   use I2S_CLK_D2CLK as clock source, return APB clock frequency
  */
-static uint32_t i2s_get_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t fixed_mclk)
+static uint32_t i2s_config_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t mclk)
 {
 #if SOC_I2S_SUPPORTS_APLL
     if (use_apll) {
@@ -1025,20 +1025,18 @@ static uint32_t i2s_get_source_clock(i2s_port_t i2s_num, bool use_apll, uint32_t
         int sdm1 = 0;
         int sdm2 = 0;
         int odir = 0;
-        if (fixed_mclk == 0) {
-            ESP_LOGI(TAG, "fixed_mclk is not set, set to 128 MHz as default");
-            fixed_mclk = 128000000;
-        }else if ((fixed_mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / 16) < SOC_I2S_APLL_MIN_RATE) {
-            ESP_LOGW(TAG, "fixed_mclk is too small, use I2S_CLK_D2CLK as default clock source");
-            goto err;
+        if ((mclk / p_i2s[i2s_num]->hal_cfg.chan_bits / p_i2s[i2s_num]->hal_cfg.total_chan) < SOC_I2S_APLL_MIN_RATE) {
+            ESP_LOGE(TAG, "mclk is too small");
+            return 0;
         }
-        i2s_apll_calculate_fi2s(p_i2s[i2s_num]->hal_cfg.sample_rate, p_i2s[i2s_num]->hal_cfg.sample_bits,
-                                &sdm0, &sdm1, &sdm2, &odir);
+        i2s_apll_calculate_fi2s(mclk, p_i2s[i2s_num]->hal_cfg.sample_bits, &sdm0, &sdm1, &sdm2, &odir);
         ESP_LOGI(TAG, "APLL Enabled, coefficient: sdm0=%d, sdm1=%d, sdm2=%d, odir=%d", sdm0, sdm1, sdm2, odir);
         rtc_clk_apll_enable(true, sdm0, sdm1, sdm2, odir);
-        return fixed_mclk;
+        /* Set I2S_APLL as I2S module clock source */
+        i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_APLL);
+        /* In APLL mode, there is no sclk but only mclk, so return 0 here to indicate APLL mode */
+        return 0;
     }
-err:
     /* Set I2S_D2CLK (160M) as default I2S module clock source */
     i2s_hal_set_clock_src(&(p_i2s[i2s_num]->hal), I2S_CLK_D2CLK);
     return I2S_LL_BASE_CLK;
@@ -1067,20 +1065,22 @@ static esp_err_t i2s_calculate_adc_dac_clock(int i2s_num, i2s_hal_clock_cfg_t *c
     ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL");
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN), ESP_ERR_INVALID_ARG, TAG, "current mode is not built-in ADC/DAC");
 
-    /* Set I2S module clock */
-    clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk);
-    /* Set I2S bit clock default division */
-    clk_cfg->bclk_div = I2S_LL_AD_BCK_FACTOR;
     /* Set I2S bit clock */
     clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_AD_BCK_FACTOR * 2;
-    /* Get I2S master clock, mclk = bclk * bclk_div */
-    clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Set I2S bit clock default division */
+    clk_cfg->bclk_div = I2S_LL_AD_BCK_FACTOR;
+    /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */
+    clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
+                    p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Calculate bclk_div = mclk / bclk */
+    clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk;
+    /* Get I2S system clock by config source clock */
+    clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk);
     /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */
     clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk;
 
     /* Check if the configuration is correct */
-    ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module get clock failed");
-    ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
+    ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
 
     return ESP_OK;
 }
@@ -1101,23 +1101,24 @@ static esp_err_t i2s_calculate_pdm_tx_clock(int i2s_num, i2s_hal_clock_cfg_t *cl
     ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL");
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM");
 
-    /* Set I2S module clock */
-    clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk);
-    /* Set I2S bit clock default division */
-    clk_cfg->bclk_div = 8;
-
     int fp = i2s_hal_get_tx_pdm_fp(&(p_i2s[i2s_num]->hal));
     int fs = i2s_hal_get_tx_pdm_fs(&(p_i2s[i2s_num]->hal));
     /* Set I2S bit clock */
     clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * fp / fs;
-    /* Get I2S master clock, mclk = bclk * bclk_div */
-    clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Set I2S bit clock default division */
+    clk_cfg->bclk_div = 8;
+    /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */
+    clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
+                    p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Calculate bclk_div = mclk / bclk */
+    clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk;
+    /* Get I2S system clock by config source clock */
+    clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk);
     /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */
     clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk;
 
     /* Check if the configuration is correct */
-    ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0");
-    ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
+    ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
 
     return ESP_OK;
 }
@@ -1138,23 +1139,24 @@ static esp_err_t i2s_calculate_pdm_rx_clock(int i2s_num, i2s_hal_clock_cfg_t *cl
     ESP_RETURN_ON_FALSE(clk_cfg, ESP_ERR_INVALID_ARG, TAG, "input clk_cfg is NULL");
     ESP_RETURN_ON_FALSE(p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_PDM, ESP_ERR_INVALID_ARG, TAG, "current mode is not PDM");
 
-    /* Set I2S module clock */
-    clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk);
-    /* Set I2S bit clock default division */
-    clk_cfg->bclk_div = 8;
-
     i2s_pdm_dsr_t dsr;
     i2s_hal_get_rx_pdm_dsr(&(p_i2s[i2s_num]->hal), &dsr);
     /* Set I2S bit clock */
     clk_cfg->bclk = p_i2s[i2s_num]->hal_cfg.sample_rate * I2S_LL_PDM_BCK_FACTOR * (dsr == I2S_PDM_DSR_16S ? 2 : 1);
-    /* Get I2S master clock, mclk = bclk * bclk_div */
-    clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Set I2S bit clock default division */
+    clk_cfg->bclk_div = 8;
+    /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */
+    clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
+                    p_i2s[i2s_num]->fixed_mclk : clk_cfg->bclk * clk_cfg->bclk_div;
+    /* Calculate bclk_div = mclk / bclk */
+    clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk;
+    /* Get I2S system clock by config source clock */
+    clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk);
     /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */
     clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk;
 
     /* Check if the configuration is correct */
-    ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0");
-    ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
+    ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
 
     return ESP_OK;
 }
@@ -1177,10 +1179,8 @@ static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *cl
     uint32_t chan_num = p_i2s[i2s_num]->hal_cfg.total_chan < 2 ? 2 : p_i2s[i2s_num]->hal_cfg.total_chan;
     uint32_t chan_bit = p_i2s[i2s_num]->hal_cfg.chan_bits;
     uint32_t multi;
-    /* Set I2S module clock */
-    clk_cfg->sclk = i2s_get_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, p_i2s[i2s_num]->fixed_mclk);
     /* Calculate multiple */
-    if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_MASTER) {
+    if (p_i2s[i2s_num]->hal_cfg.mode & I2S_MODE_MASTER || p_i2s[i2s_num]->use_apll) {
         multi = p_i2s[i2s_num]->mclk_multiple ? p_i2s[i2s_num]->mclk_multiple : I2S_MCLK_MULTIPLE_256;
     } else {
         /* Only need to set the multiple of mclk to sample rate for MASTER mode,
@@ -1194,23 +1194,25 @@ static esp_err_t i2s_calculate_common_clock(int i2s_num, i2s_hal_clock_cfg_t *cl
          * Here use 'SOC_I2S_SUPPORTS_TDM' to differentialize other chips with ESP32 and ESP32S2.
          */
 #if SOC_I2S_SUPPORTS_TDM
-        multi = clk_cfg->sclk / rate;
+        multi = I2S_LL_BASE_CLK / rate;
 #else
         multi =  64 * chan_bit;
 #endif
     }
     /* Set I2S bit clock */
     clk_cfg->bclk = rate * chan_num * chan_bit;
-    /* Set I2S bit clock division according to the sample rate and multiple of mclk */
-    clk_cfg->bclk_div = rate * multi / clk_cfg->bclk;
-    /* Get I2S master clock, mclk = bclk * bclk_div = rate * multiple */
-    clk_cfg->mclk = clk_cfg->bclk * clk_cfg->bclk_div;
+    /* If fixed_mclk and use_apll are set, use fixed_mclk as mclk frequency, otherwise calculate by mclk = sample_rate * multiple */
+    clk_cfg->mclk = (p_i2s[i2s_num]->use_apll && p_i2s[i2s_num]->fixed_mclk) ?
+                    p_i2s[i2s_num]->fixed_mclk : (rate * multi);
+    /* Calculate bclk_div = mclk / bclk */
+    clk_cfg->bclk_div = clk_cfg->mclk / clk_cfg->bclk;
+    /* Get I2S system clock by config source clock */
+    clk_cfg->sclk = i2s_config_source_clock(i2s_num, p_i2s[i2s_num]->use_apll, clk_cfg->mclk);
     /* Get I2S master clock rough division, later will calculate the fine division parameters in HAL */
     clk_cfg->mclk_div = clk_cfg->sclk / clk_cfg->mclk;
 
     /* Check if the configuration is correct */
-    ESP_RETURN_ON_FALSE(clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "I2S module clock is 0");
-    ESP_RETURN_ON_FALSE(clk_cfg->bclk * clk_cfg->bclk_div <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
+    ESP_RETURN_ON_FALSE(!clk_cfg->sclk || clk_cfg->mclk <= clk_cfg->sclk, ESP_ERR_INVALID_ARG, TAG, "sample rate is too large");
 
     return ESP_OK;
 }
@@ -1904,6 +1906,7 @@ static esp_err_t i2s_dma_object_init(i2s_port_t i2s_num)
  *     - ESP_OK              Success
  *     - ESP_ERR_INVALID_ARG Parameter error
  *     - ESP_ERR_NO_MEM      Out of memory
+ *     - ESP_ERR_INVALID_STATE  Current I2S port is in use
  */
 esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)
 {
@@ -1924,7 +1927,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
     if (ret != ESP_OK) {
         free(pre_alloc_i2s_obj);
         ESP_LOGE(TAG, "register I2S object to platform failed");
-        return ret;
+        return ESP_ERR_INVALID_STATE;
     }
 
     /* Step 3: Initialize I2S object, assign configarations */
@@ -1965,7 +1968,6 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
     /* Step 6: Initialise i2s event queue if user needs */
     if (i2s_queue) {
         pre_alloc_i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t));
-        printf("queue handle %p\n", pre_alloc_i2s_obj->i2s_queue);
         ESP_GOTO_ON_FALSE(pre_alloc_i2s_obj->i2s_queue, ESP_ERR_NO_MEM, err, TAG, "I2S queue create failed");
         *((QueueHandle_t *) i2s_queue) = pre_alloc_i2s_obj->i2s_queue;
         ESP_LOGI(TAG, "queue free spaces: %d", uxQueueSpacesAvailable(pre_alloc_i2s_obj->i2s_queue));

+ 1 - 1
components/driver/include/driver/i2s.h

@@ -221,7 +221,7 @@ esp_err_t i2s_set_pdm_tx_up_sample(i2s_port_t i2s_num, const i2s_pdm_tx_upsample
  *     - ESP_OK              Success
  *     - ESP_ERR_INVALID_ARG Parameter error
  *     - ESP_ERR_NO_MEM      Out of memory
- *     - ESP_ERR_NOT_FOUND   I2S port is not found or has been installed by others (e.g. LCD i80)
+ *     - ESP_ERR_INVALID_STATE  Current I2S port is in use
  */
 esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue);
 

+ 66 - 2
components/driver/test/test_i2s.c

@@ -145,6 +145,14 @@ TEST_CASE("I2S basic driver install, uninstall, set pin test", "[i2s]")
         .dma_buf_len = 60,
         .use_apll = 0,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
 
     // normal  i2s
@@ -181,6 +189,14 @@ TEST_CASE("I2S Loopback test(master tx and rx)", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 0,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t master_pin_config = {
         .bck_io_num = MASTER_BCK_IO,
@@ -246,6 +262,14 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 0,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t master_pin_config = {
         .bck_io_num = MASTER_BCK_IO,
@@ -268,6 +292,14 @@ TEST_CASE("I2S write and read test(master tx and slave rx)", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 0,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t slave_pin_config = {
         .bck_io_num = SLAVE_BCK_IO,
@@ -332,6 +364,14 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 1,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t master_pin_config = {
         .bck_io_num = MASTER_BCK_IO,
@@ -354,6 +394,14 @@ TEST_CASE("I2S write and read test(master rx and slave tx)", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 1,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t slave_pin_config = {
         .bck_io_num = SLAVE_BCK_IO,
@@ -419,6 +467,14 @@ TEST_CASE("I2S memory leaking test", "[i2s]")
         .dma_buf_len = 100,
         .use_apll = 0,
         .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
     i2s_pin_config_t master_pin_config = {
         .bck_io_num = MASTER_BCK_IO,
@@ -442,6 +498,7 @@ TEST_CASE("I2S memory leaking test", "[i2s]")
     TEST_ASSERT(initial_size == esp_get_free_heap_size());
 }
 
+#if SOC_I2S_SUPPORTS_APLL
 /*
  *   The I2S APLL clock variation test used to test the difference between the different sample rates, different bits per sample
  *   and the APLL clock generate for it. The TEST_CASE passes PERCENT_DIFF variation from the provided sample rate in APLL generated clock
@@ -464,10 +521,16 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
         .communication_format = I2S_COMM_FORMAT_STAND_I2S,
         .dma_buf_count = 6,
         .dma_buf_len = 60,
-#if SOC_I2S_SUPPORTS_APLL
         .use_apll = true,
-#endif
         .intr_alloc_flags = 0,
+#if SOC_I2S_SUPPORTS_TDM
+        .chan_mask = I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1,
+        .total_chan = 2,
+        .left_align = false,
+        .big_edin = false,
+        .bit_order_msb = false,
+        .skip_msk = false
+#endif
     };
 
     TEST_ESP_OK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
@@ -494,6 +557,7 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
     vTaskDelay(100 / portTICK_PERIOD_MS);
     TEST_ASSERT(initial_size == esp_get_free_heap_size());
 }
+#endif
 
 #if SOC_I2S_SUPPORTS_ADC
 /* Only ESP32 need I2S adc/dac test */

+ 1 - 1
components/esp_lcd/test/test_i80_lcd_panel.c

@@ -595,7 +595,7 @@ TEST_CASE("i80 and i2s driver coexistance", "[lcd][i2s]")
         .dma_buf_len = 60,
     };
     // I2S driver won't be installed as the same I2S port has been used by LCD
-    TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, i2s_driver_install(0, &i2s_config, 0, NULL));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_install(0, &i2s_config, 0, NULL));
     TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
 }
 #endif // SOC_I2S_LCD_I80_VARIANT

+ 2 - 0
components/hal/i2s_hal.c

@@ -34,7 +34,9 @@ static void i2s_hal_mclk_div_decimal_cal(i2s_hal_clock_cfg_t *clk_cfg, i2s_ll_mc
     cal->mclk_div = clk_cfg->mclk_div;
     cal->a = 1;
     cal->b = 0;
+    /* If sclk = 0 means APLL clock applied, mclk_div should set to 1 */
     if (!clk_cfg->sclk) {
+        cal->mclk_div = 1;
         return;
     }
     uint32_t freq_diff = clk_cfg->sclk - clk_cfg->mclk * cal->mclk_div;