diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c index 47951b53589d..928e1a6acdcd 100644 --- a/components/driver/deprecated/i2s_legacy.c +++ b/components/driver/deprecated/i2s_legacy.c @@ -349,14 +349,22 @@ static esp_err_t i2s_dma_intr_init(i2s_port_t i2s_num, int intr_flag) gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; switch (i2s_num) { +#if SOC_I2S_NUM > 2 + case I2S_NUM_2: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2; + break; +#endif #if SOC_I2S_NUM > 1 case I2S_NUM_1: trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1; break; #endif - default: + case I2S_NUM_0: trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; break; + default: + ESP_LOGE(TAG, "Unsupported I2S port number"); + return ESP_ERR_NOT_SUPPORTED; } /* Set GDMA config */ diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index d145a49004aa..8306d0fcb5db 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -697,6 +697,7 @@ static void IRAM_ATTR i2s_dma_tx_callback(void *arg) */ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) { + esp_err_t ret = ESP_OK; i2s_port_t port_id = handle->controller->id; ESP_RETURN_ON_FALSE((port_id >= 0) && (port_id < SOC_I2S_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid handle"); #if SOC_GDMA_SUPPORTED @@ -704,14 +705,22 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) gdma_trigger_t trig = {.periph = GDMA_TRIG_PERIPH_I2S}; switch (port_id) { +#if SOC_I2S_NUM > 2 + case I2S_NUM_2: + trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S2; + break; +#endif #if SOC_I2S_NUM > 1 case I2S_NUM_1: trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S1; break; #endif - default: + case I2S_NUM_0: trig.instance_id = SOC_GDMA_TRIG_PERIPH_I2S0; break; + default: + ESP_LOGE(TAG, "Unsupported I2S port number"); + return ESP_ERR_NOT_SUPPORTED; } /* Set GDMA config */ @@ -720,18 +729,18 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) dma_cfg.direction = GDMA_CHANNEL_DIRECTION_TX; /* Register a new GDMA tx channel */ ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register tx dma channel error"); - ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect tx dma channel error"); + ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect tx dma channel error"); gdma_tx_event_callbacks_t cb = {.on_trans_eof = i2s_dma_tx_callback}; /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ - gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle); + ESP_GOTO_ON_ERROR(gdma_register_tx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register tx callback failed"); } else { dma_cfg.direction = GDMA_CHANNEL_DIRECTION_RX; /* Register a new GDMA rx channel */ ESP_RETURN_ON_ERROR(gdma_new_channel(&dma_cfg, &handle->dma.dma_chan), TAG, "Register rx dma channel error"); - ESP_RETURN_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), TAG, "Connect rx dma channel error"); + ESP_GOTO_ON_ERROR(gdma_connect(handle->dma.dma_chan, trig), err1, TAG, "Connect rx dma channel error"); gdma_rx_event_callbacks_t cb = {.on_recv_eof = i2s_dma_rx_callback}; /* Set callback function for GDMA, the interrupt is triggered by GDMA, then the GDMA ISR will call the callback function */ - gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle); + ESP_GOTO_ON_ERROR(gdma_register_rx_event_callbacks(handle->dma.dma_chan, &cb, handle), err2, TAG, "Register rx callback failed"); } #else intr_flag |= handle->intr_prio_flags; @@ -748,7 +757,15 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) /* Start DMA */ i2s_ll_enable_dma(handle->controller->hal.dev, true); #endif // SOC_GDMA_SUPPORTED - return ESP_OK; + return ret; +#if SOC_GDMA_SUPPORTED +err2: + gdma_disconnect(handle->dma.dma_chan); +err1: + gdma_del_channel(handle->dma.dma_chan); + handle->dma.dma_chan = NULL; + return ret; +#endif } static uint64_t s_i2s_get_pair_chan_gpio_mask(i2s_chan_handle_t handle) diff --git a/components/esp_driver_i2s/include/driver/i2s_types.h b/components/esp_driver_i2s/include/driver/i2s_types.h index 2135124389cd..9f103f0718c8 100644 --- a/components/esp_driver_i2s/include/driver/i2s_types.h +++ b/components/esp_driver_i2s/include/driver/i2s_types.h @@ -22,6 +22,9 @@ typedef enum { I2S_NUM_0 = 0, /*!< I2S controller port 0 */ #if SOC_I2S_NUM > 1 I2S_NUM_1 = 1, /*!< I2S controller port 1 */ +#endif +#if SOC_I2S_NUM > 2 + I2S_NUM_2 = 2, /*!< I2S controller port 2 */ #endif I2S_NUM_AUTO, /*!< Select whichever port is available */ } i2s_port_t; diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c index e0e69c551b35..7cac0ebcd3b4 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s.c @@ -191,7 +191,20 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]") TEST_ESP_OK(i2s_channel_enable(tx_handle)); TEST_ESP_OK(i2s_channel_disable(tx_handle)); TEST_ESP_OK(i2s_del_channel(tx_handle)); - TEST_ASSERT(i2s_channel_get_info(tx_handle, &chan_info) == ESP_ERR_NOT_FOUND); + TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_channel_get_info(tx_handle, &chan_info)); + + /* Exhaust test */ + i2s_chan_handle_t tx_ex[SOC_I2S_NUM] = {}; + for (int i = 0; i < SOC_I2S_NUM; i++) { + TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_ex[i], NULL)); + TEST_ESP_OK(i2s_channel_init_std_mode(tx_ex[i], &std_cfg)); + TEST_ESP_OK(i2s_channel_enable(tx_ex[i])); + } + TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, NULL)); + for (int i = 0; i < SOC_I2S_NUM; i++) { + TEST_ESP_OK(i2s_channel_disable(tx_ex[i])); + TEST_ESP_OK(i2s_del_channel(tx_ex[i])); + } /* Duplex channel basic test */ chan_cfg.id = I2S_NUM_0; // Specify port id to I2S port 0 @@ -209,7 +222,7 @@ TEST_CASE("I2S_basic_channel_allocation_reconfig_deleting_test", "[i2s]") /* Hold the occupation */ TEST_ESP_OK(i2s_platform_acquire_occupation(I2S_NUM_0, "test_i2s")); - TEST_ASSERT(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle) == ESP_ERR_NOT_FOUND); + TEST_ESP_ERR(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle)); TEST_ESP_OK(i2s_platform_release_occupation(I2S_NUM_0)); TEST_ESP_OK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle)); TEST_ESP_OK(i2s_del_channel(tx_handle)); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c index 3e4e6a1323dc..73f7e06af171 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i2s.c @@ -184,7 +184,6 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc // enable I2S LCD master mode (refer to I2S TRM) i2s_ll_enable_lcd(bus->hal.dev, true); i2s_ll_tx_stop_on_fifo_empty(bus->hal.dev, true); - i2s_ll_tx_bypass_pcm(bus->hal.dev, true); i2s_ll_tx_set_slave_mod(bus->hal.dev, false); i2s_ll_tx_set_bits_mod(bus->hal.dev, bus_config->bus_width); i2s_ll_tx_select_std_slot(bus->hal.dev, I2S_STD_SLOT_BOTH, true); // copy mono diff --git a/components/hal/esp32/include/hal/i2s_ll.h b/components/hal/esp32/include/hal/i2s_ll.h index f56f2fe6c1fa..9ce5dbec7887 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 */ @@ -74,7 +74,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 @@ -695,17 +695,6 @@ static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en) hw->conf1.tx_stop_en = en; } -/** - * @brief Set whether to bypass the internal PCM module - * - * @param hw Peripheral I2S hardware instance address. - * @param bypass whether to bypass the PCM module - */ -static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass) -{ - hw->conf1.tx_pcm_bypass = bypass; -} - /** * @brief Enable I2S DMA * @@ -932,7 +921,7 @@ static inline void i2s_ll_share_bck_ws(i2s_dev_t *hw, bool loopback_en) * @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) { @@ -1080,11 +1069,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) { @@ -1092,11 +1081,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) { diff --git a/components/hal/esp32s2/include/hal/i2s_ll.h b/components/hal/esp32s2/include/hal/i2s_ll.h index 2c97bf157a54..8ae76c41cd20 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 */ @@ -72,7 +72,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 @@ -997,17 +997,6 @@ static inline void i2s_ll_tx_stop_on_fifo_empty(i2s_dev_t *hw, bool en) hw->conf1.tx_stop_en = en; } -/** - * @brief Set whether to bypass the internal PCM module - * - * @param hw Peripheral I2S hardware instance address. - * @param bypass whether to bypass the PCM module - */ -static inline void i2s_ll_tx_bypass_pcm(i2s_dev_t *hw, bool bypass) -{ - hw->conf1.tx_pcm_bypass = bypass; -} - #ifdef __cplusplus } #endif diff --git a/components/soc/esp32s2/include/soc/i2s_reg.h b/components/soc/esp32s2/include/soc/i2s_reg.h index ed73a93aac0c..af207e0f36ba 100644 --- a/components/soc/esp32s2/include/soc/i2s_reg.h +++ b/components/soc/esp32s2/include/soc/i2s_reg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -723,26 +723,6 @@ extern "C" { #define I2S_TX_BCK_IN_DELAY_S 0 #define I2S_FIFO_CONF_REG(i) (REG_I2S_BASE(i) + 0x0020) -/* I2S_TX_24MSB_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */ -/*description: Only useful in tx 24bit mode. 1: the high 24 bits are effective - in i2s fifo 0: the low 24 bits are effective in i2s fifo*/ -#define I2S_TX_24MSB_EN (BIT(23)) -#define I2S_TX_24MSB_EN_M (BIT(23)) -#define I2S_TX_24MSB_EN_V 0x1 -#define I2S_TX_24MSB_EN_S 23 -/* I2S_RX_24MSB_EN : R/W ;bitpos:[22] ;default: 1'b0 ; */ -/*description: Only useful in rx 24bit mode. 1: the high 24 bits are effective - in i2s fifo 0: the low 24 bits are effective in i2s fifo*/ -#define I2S_RX_24MSB_EN (BIT(22)) -#define I2S_RX_24MSB_EN_M (BIT(22)) -#define I2S_RX_24MSB_EN_V 0x1 -#define I2S_RX_24MSB_EN_S 22 -/* I2S_RX_FIFO_SYNC : R/W ;bitpos:[21] ;default: 1'b0 ; */ -/*description: force write back rx data to memory*/ -#define I2S_RX_FIFO_SYNC (BIT(21)) -#define I2S_RX_FIFO_SYNC_M (BIT(21)) -#define I2S_RX_FIFO_SYNC_V 0x1 -#define I2S_RX_FIFO_SYNC_S 21 /* I2S_RX_FIFO_MOD_FORCE_EN : R/W ;bitpos:[20] ;default: 1'b0 ; */ /*description: The bit should always be set to 1*/ #define I2S_RX_FIFO_MOD_FORCE_EN (BIT(20)) @@ -1192,45 +1172,13 @@ extern "C" { #define I2S_LC_FIFO_TIMEOUT_S 0 #define I2S_CONF1_REG(i) (REG_I2S_BASE(i) + 0x00a0) -/* I2S_TX_ZEROS_RM_EN : R/W ;bitpos:[9] ;default: 1'd0 ; */ -/*description: don't use*/ -#define I2S_TX_ZEROS_RM_EN (BIT(9)) -#define I2S_TX_ZEROS_RM_EN_M (BIT(9)) -#define I2S_TX_ZEROS_RM_EN_V 0x1 -#define I2S_TX_ZEROS_RM_EN_S 9 /* I2S_TX_STOP_EN : R/W ;bitpos:[8] ;default: 1'd0 ; */ /*description: Set this bit to stop disable output BCK signal and WS signal - when tx FIFO is emtpy*/ + when tx FIFO is empty*/ #define I2S_TX_STOP_EN (BIT(8)) #define I2S_TX_STOP_EN_M (BIT(8)) #define I2S_TX_STOP_EN_V 0x1 #define I2S_TX_STOP_EN_S 8 -/* I2S_RX_PCM_BYPASS : R/W ;bitpos:[7] ;default: 1'h1 ; */ -/*description: Set this bit to bypass Compress/Decompress module for received data.*/ -#define I2S_RX_PCM_BYPASS (BIT(7)) -#define I2S_RX_PCM_BYPASS_M (BIT(7)) -#define I2S_RX_PCM_BYPASS_V 0x1 -#define I2S_RX_PCM_BYPASS_S 7 -/* I2S_RX_PCM_CONF : R/W ;bitpos:[6:4] ;default: 3'h0 ; */ -/*description: Compress/Decompress module configuration bits. 0: decompress - received data 1:compress received data*/ -#define I2S_RX_PCM_CONF 0x00000007 -#define I2S_RX_PCM_CONF_M ((I2S_RX_PCM_CONF_V)<<(I2S_RX_PCM_CONF_S)) -#define I2S_RX_PCM_CONF_V 0x7 -#define I2S_RX_PCM_CONF_S 4 -/* I2S_TX_PCM_BYPASS : R/W ;bitpos:[3] ;default: 1'h1 ; */ -/*description: Set this bit to bypass Compress/Decompress module for transmitted data.*/ -#define I2S_TX_PCM_BYPASS (BIT(3)) -#define I2S_TX_PCM_BYPASS_M (BIT(3)) -#define I2S_TX_PCM_BYPASS_V 0x1 -#define I2S_TX_PCM_BYPASS_S 3 -/* I2S_TX_PCM_CONF : R/W ;bitpos:[2:0] ;default: 3'h1 ; */ -/*description: Compress/Decompress module configuration bits. 0: decompress - transmitted data 1:compress transmitted data*/ -#define I2S_TX_PCM_CONF 0x00000007 -#define I2S_TX_PCM_CONF_M ((I2S_TX_PCM_CONF_V)<<(I2S_TX_PCM_CONF_S)) -#define I2S_TX_PCM_CONF_V 0x7 -#define I2S_TX_PCM_CONF_S 0 #define I2S_PD_CONF_REG(i) (REG_I2S_BASE(i) + 0x00a4) /* I2S_DMA_RAM_CLK_FO : R/W ;bitpos:[6] ;default: 1'h0 ; */ diff --git a/components/soc/esp32s2/include/soc/i2s_struct.h b/components/soc/esp32s2/include/soc/i2s_struct.h index 30edc7a31dad..038b0f662d5c 100644 --- a/components/soc/esp32s2/include/soc/i2s_struct.h +++ b/components/soc/esp32s2/include/soc/i2s_struct.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -175,10 +175,7 @@ typedef volatile struct i2s_dev_s { uint32_t rx_fifo_mod: 3; /*Receiver FIFO mode configuration bits*/ uint32_t tx_fifo_mod_force_en: 1; /*The bit should always be set to 1*/ uint32_t rx_fifo_mod_force_en: 1; /*The bit should always be set to 1*/ - uint32_t rx_fifo_sync: 1; /*force write back rx data to memory*/ - uint32_t rx_24msb_en: 1; /*Only useful in rx 24bit mode. 1: the high 24 bits are effective in i2s fifo 0: the low 24 bits are effective in i2s fifo*/ - uint32_t tx_24msb_en: 1; /*Only useful in tx 24bit mode. 1: the high 24 bits are effective in i2s fifo 0: the low 24 bits are effective in i2s fifo*/ - uint32_t reserved24: 8; + uint32_t reserved21: 11; }; uint32_t val; } fifo_conf; @@ -314,13 +311,9 @@ typedef volatile struct i2s_dev_s { uint32_t reserved_9c; union { struct { - uint32_t tx_pcm_conf: 3; /*Compress/Decompress module configuration bits. 0: decompress transmitted data 1:compress transmitted data*/ - uint32_t tx_pcm_bypass: 1; /*Set this bit to bypass Compress/Decompress module for transmitted data.*/ - uint32_t rx_pcm_conf: 3; /*Compress/Decompress module configuration bits. 0: decompress received data 1:compress received data*/ - uint32_t rx_pcm_bypass: 1; /*Set this bit to bypass Compress/Decompress module for received data.*/ - uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is emtpy*/ - uint32_t tx_zeros_rm_en: 1; /*don't use*/ - uint32_t reserved10: 22; + uint32_t reserved0: 8; + uint32_t tx_stop_en: 1; /*Set this bit to stop disable output BCK signal and WS signal when tx FIFO is empty*/ + uint32_t reserved9: 23; }; uint32_t val; } conf1;