diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index 5f33bf4277..552cde83c8 100644 --- a/components/hal/esp32/include/hal/i2s_ll.h +++ b/components/hal/esp32/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -81,7 +81,7 @@ static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en) } /** - * @brief I2S DMA generate EOF event on data in FIFO poped out + * @brief I2S DMA generate EOF event on data in FIFO popped out * * @param hw Peripheral I2S hardware instance address. * @param en True to enable, False to disable @@ -314,11 +314,6 @@ static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uin */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that unlike to calculate from the regular decimal */ - i2s_ll_set_raw_mclk_div(hw, 7, 47, 3); i2s_ll_set_raw_mclk_div(hw, mclk_div->integ, mclk_div->denom, mclk_div->numer); } @@ -623,7 +618,7 @@ static inline void i2s_ll_tx_set_bits_mod(i2s_dev_t *hw, uint32_t val) } /** - * @brief Congfigure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit + * @brief Configure TX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -636,7 +631,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit + * @brief Configure RX chan bit and audio data bit, on ESP32, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width diff --git a/components/hal/esp32c3/include/hal/i2s_ll.h b/components/hal/esp32c3/include/hal/i2s_ll.h index e007248f49..c64682a567 100644 --- a/components/hal/esp32c3/include/hal/i2s_ll.h +++ b/components/hal/esp32c3/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -258,15 +258,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, 2); + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = yn1; + hw->tx_clkm_div_conf.tx_clkm_div_z = z; + hw->tx_clkm_div_conf.tx_clkm_div_y = y; + hw->tx_clkm_div_conf.tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->tx_clkm_div_conf) div = {}; - div.tx_clkm_div_x = x; - div.tx_clkm_div_y = y; - div.tx_clkm_div_z = z; - div.tx_clkm_div_yn1 = yn1; - hw->tx_clkm_div_conf.val = div.val; } /** @@ -281,15 +287,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, 2); + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = yn1; + hw->rx_clkm_div_conf.rx_clkm_div_z = z; + hw->rx_clkm_div_conf.rx_clkm_div_y = y; + hw->rx_clkm_div_conf.rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->rx_clkm_div_conf) div = {}; - div.rx_clkm_div_x = x; - div.rx_clkm_div_y = y; - div.rx_clkm_div_z = z; - div.rx_clkm_div_yn1 = yn1; - hw->rx_clkm_div_conf.val = div.val; } /** @@ -300,12 +312,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -340,12 +346,6 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -440,7 +440,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit + * @brief Configure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -453,7 +453,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit + * @brief Configure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -853,11 +853,11 @@ static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM fp configuration paramater + * @brief Get I2S TX PDM fp configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fp configuration paramater + * - fp configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { @@ -865,11 +865,11 @@ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) } /** - * @brief Get I2S TX PDM fs configuration paramater + * @brief Get I2S TX PDM fs configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fs configuration paramater + * - fs configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { @@ -895,7 +895,7 @@ static inline void i2s_ll_rx_enable_pdm(i2s_dev_t *hw, bool pdm_enable) * @brief Configura TX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -907,7 +907,7 @@ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_ * @brief Configure RX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -1079,7 +1079,7 @@ static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) * @param is_copy Whether the un-selected slot copies the data from the selected one * If not, the un-selected slot will transmit the data from 'conf_single_data' - * @param mask The slot mask to selet the slot + * @param mask The slot mask to select the slot */ static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) { diff --git a/components/hal/esp32c6/include/hal/i2s_ll.h b/components/hal/esp32c6/include/hal/i2s_ll.h index c36e5d7ea6..5eea14b0af 100644 --- a/components/hal/esp32c6/include/hal/i2s_ll.h +++ b/components/hal/esp32c6/include/hal/i2s_ll.h @@ -270,13 +270,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, 2); + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = 1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = z; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = y; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; } /** @@ -292,13 +300,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, 2); + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = 1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = z; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = y; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; } /** @@ -309,12 +325,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -349,12 +359,6 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; diff --git a/components/hal/esp32h2/include/hal/i2s_ll.h b/components/hal/esp32h2/include/hal/i2s_ll.h index 2d7b4fce29..7ff1c1df58 100644 --- a/components/hal/esp32h2/include/hal/i2s_ll.h +++ b/components/hal/esp32h2/include/hal/i2s_ll.h @@ -277,13 +277,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, 2); + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = 1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = 0; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_yn1 = yn1; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_z = z; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_y = y; + PCR.i2s_tx_clkm_div_conf.i2s_tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_tx_clkm_conf, i2s_tx_clkm_div_num, div_int); - typeof(PCR.i2s_tx_clkm_div_conf) div = {}; - div.i2s_tx_clkm_div_x = x; - div.i2s_tx_clkm_div_y = y; - div.i2s_tx_clkm_div_z = z; - div.i2s_tx_clkm_div_yn1 = yn1; - PCR.i2s_tx_clkm_div_conf.val = div.val; } /** @@ -299,13 +307,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { (void)hw; + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, 2); + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = 1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = 0; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_yn1 = yn1; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_z = z; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_y = y; + PCR.i2s_rx_clkm_div_conf.i2s_rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.i2s_rx_clkm_conf, i2s_rx_clkm_div_num, div_int); - typeof(PCR.i2s_rx_clkm_div_conf) div = {}; - div.i2s_rx_clkm_div_x = x; - div.i2s_rx_clkm_div_y = y; - div.i2s_rx_clkm_div_z = z; - div.i2s_rx_clkm_div_yn1 = yn1; - PCR.i2s_rx_clkm_div_conf.val = div.val; } /** @@ -316,12 +332,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 8, 1, 1, 73, 1); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -356,12 +366,6 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 8, 1, 1, 73, 1); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 1329c9e5c6..eb12347cb0 100644 --- a/components/hal/esp32s2/include/hal/i2s_ll.h +++ b/components/hal/esp32s2/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -78,7 +78,7 @@ static inline void i2s_ll_dma_enable_auto_write_back(i2s_dev_t *hw, bool en) } /** - * @brief I2S DMA generate EOF event on data in FIFO poped out + * @brief I2S DMA generate EOF event on data in FIFO popped out * * @param hw Peripheral I2S hardware instance address. * @param en True to enable, False to disable @@ -305,11 +305,6 @@ static inline void i2s_ll_set_raw_mclk_div(i2s_dev_t *hw, uint32_t mclk_div, uin */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that unlike to calculate from the regular decimal */ - i2s_ll_set_raw_mclk_div(hw, 7, 47, 3); i2s_ll_set_raw_mclk_div(hw, mclk_div->integ, mclk_div->denom, mclk_div->numer); } @@ -646,7 +641,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, uint32_t eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit + * @brief Configure TX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -659,7 +654,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit + * @brief Configure RX chan bit and audio data bit, on ESP32-S2, sample_bit should equals to data_bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width diff --git a/components/hal/esp32s3/include/hal/i2s_ll.h b/components/hal/esp32s3/include/hal/i2s_ll.h index 02de004fbe..3a00494435 100644 --- a/components/hal/esp32s3/include/hal/i2s_ll.h +++ b/components/hal/esp32s3/include/hal/i2s_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -258,15 +258,21 @@ static inline void i2s_ll_tx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, 2); + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = 0; + hw->tx_clkm_div_conf.tx_clkm_div_y = 1; + hw->tx_clkm_div_conf.tx_clkm_div_z = 0; + hw->tx_clkm_div_conf.tx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->tx_clkm_div_conf.tx_clkm_div_yn1 = yn1; + hw->tx_clkm_div_conf.tx_clkm_div_z = z; + hw->tx_clkm_div_conf.tx_clkm_div_y = y; + hw->tx_clkm_div_conf.tx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->tx_clkm_conf, tx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->tx_clkm_div_conf) div = {}; - div.tx_clkm_div_x = x; - div.tx_clkm_div_y = y; - div.tx_clkm_div_z = z; - div.tx_clkm_div_yn1 = yn1; - hw->tx_clkm_div_conf.val = div.val; } /** @@ -281,15 +287,21 @@ static inline void i2s_ll_tx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, uint32_t x, uint32_t y, uint32_t z, uint32_t yn1) { - /* Set the integer part of mclk division */ + /* Workaround for the double division issue. + * The division coefficients must be set in particular sequence. + * And it has to switch to a small division first before setting the target division. */ + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, 2); + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = 0; + hw->rx_clkm_div_conf.rx_clkm_div_y = 1; + hw->rx_clkm_div_conf.rx_clkm_div_z = 0; + hw->rx_clkm_div_conf.rx_clkm_div_x = 0; + + /* Set the target mclk division coefficients */ + hw->rx_clkm_div_conf.rx_clkm_div_yn1 = yn1; + hw->rx_clkm_div_conf.rx_clkm_div_z = z; + hw->rx_clkm_div_conf.rx_clkm_div_y = y; + hw->rx_clkm_div_conf.rx_clkm_div_x = x; HAL_FORCE_MODIFY_U32_REG_FIELD(hw->rx_clkm_conf, rx_clkm_div_num, div_int); - /* Set the decimal part of the mclk division */ - typeof(hw->rx_clkm_div_conf) div = {}; - div.rx_clkm_div_x = x; - div.rx_clkm_div_y = y; - div.rx_clkm_div_z = z; - div.rx_clkm_div_yn1 = yn1; - hw->rx_clkm_div_conf.val = div.val; } /** @@ -300,12 +312,6 @@ static inline void i2s_ll_rx_set_raw_clk_div(i2s_dev_t *hw, uint32_t div_int, ui */ static inline void i2s_ll_tx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_tx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -340,12 +346,6 @@ static inline void i2s_ll_rx_set_bck_div_num(i2s_dev_t *hw, uint32_t val) */ static inline void i2s_ll_rx_set_mclk(i2s_dev_t *hw, const i2s_ll_mclk_div_t *mclk_div) { - /* Workaround for inaccurate clock while switching from a relatively low sample rate to a high sample rate - * Set to particular coefficients first then update to the target coefficients, - * otherwise the clock division might be inaccurate. - * the general idea is to set a value that impossible to calculate from the regular decimal */ - i2s_ll_rx_set_raw_clk_div(hw, 7, 317, 7, 3, 0); - uint32_t div_x = 0; uint32_t div_y = 0; uint32_t div_z = 0; @@ -441,7 +441,7 @@ static inline void i2s_ll_rx_set_eof_num(i2s_dev_t *hw, int eof_num) } /** - * @brief Congfigure TX chan bit and audio data bit + * @brief Configure TX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -454,7 +454,7 @@ static inline void i2s_ll_tx_set_sample_bit(i2s_dev_t *hw, uint8_t chan_bit, int } /** - * @brief Congfigure RX chan bit and audio data bit + * @brief Configure RX chan bit and audio data bit * * @param hw Peripheral I2S hardware instance address. * @param chan_bit The chan bit width @@ -757,11 +757,11 @@ static inline void i2s_ll_tx_set_pdm_fpfs(i2s_dev_t *hw, uint32_t fp, uint32_t f } /** - * @brief Get I2S TX PDM fp configuration paramater + * @brief Get I2S TX PDM fp configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fp configuration paramater + * - fp configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) { @@ -769,11 +769,11 @@ static inline uint32_t i2s_ll_tx_get_pdm_fp(i2s_dev_t *hw) } /** - * @brief Get I2S TX PDM fs configuration paramater + * @brief Get I2S TX PDM fs configuration parameter * * @param hw Peripheral I2S hardware instance address. * @return - * - fs configuration paramater + * - fs configuration parameter */ static inline uint32_t i2s_ll_tx_get_pdm_fs(i2s_dev_t *hw) { @@ -894,7 +894,7 @@ static inline void i2s_ll_tx_set_pdm_sd_dither2(i2s_dev_t *hw, uint32_t dither2) * @brief Configure RX PDM downsample * * @param hw Peripheral I2S hardware instance address. - * @param dsr PDM downsample configuration paramater + * @param dsr PDM downsample configuration parameter */ static inline void i2s_ll_rx_set_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t dsr) { @@ -916,7 +916,7 @@ static inline void i2s_ll_rx_get_pdm_dsr(i2s_dev_t *hw, i2s_pdm_dsr_t *dsr) * @brief Configura TX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -928,7 +928,7 @@ static inline void i2s_ll_tx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_ * @brief Configure RX a/u-law decompress or compress * * @param hw Peripheral I2S hardware instance address. - * @param pcm_cfg PCM configuration paramater + * @param pcm_cfg PCM configuration parameter */ static inline void i2s_ll_rx_set_pcm_type(i2s_dev_t *hw, i2s_pcm_compress_t pcm_cfg) { @@ -1100,7 +1100,7 @@ static inline void i2s_ll_tx_pdm_dma_take_mode(i2s_dev_t *hw, bool is_mono, bool * @param is_mono The DMA data only has one slot (mono) or contains two slots (stereo) * @param is_copy Whether the un-selected slot copies the data from the selected one * If not, the un-selected slot will transmit the data from 'conf_single_data' - * @param mask The slot mask to selet the slot + * @param mask The slot mask to select the slot */ static inline void i2s_ll_tx_pdm_slot_mode(i2s_dev_t *hw, bool is_mono, bool is_copy, i2s_pdm_slot_mask_t mask) {