From e4f28fcb7f897b42569e4bdb5f09de420c8d0a03 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 2 Apr 2024 14:57:00 +0800 Subject: [PATCH] feat(i2s): support i2s gpio reservation --- components/esp_driver_i2s/i2s_common.c | 52 ++++++++++++++++++++++--- components/esp_driver_i2s/i2s_pdm.c | 28 +++++++------ components/esp_driver_i2s/i2s_private.h | 29 ++++++++++++-- components/esp_driver_i2s/i2s_std.c | 30 +++++++------- components/esp_driver_i2s/i2s_tdm.c | 29 +++++++------- 5 files changed, 121 insertions(+), 47 deletions(-) diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index e3042695f2..7bd6cddd6d 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -283,6 +283,7 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir, new_chan->dma.curr_desc = NULL; new_chan->start = NULL; new_chan->stop = NULL; + new_chan->reserve_gpio_mask = 0; if (dir == I2S_DIR_TX) { if (i2s_obj->tx_chan) { @@ -749,7 +750,42 @@ esp_err_t i2s_init_dma_intr(i2s_chan_handle_t handle, int intr_flag) return ESP_OK; } -void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool is_invert) +static uint64_t s_i2s_get_pair_chan_gpio_mask(i2s_chan_handle_t handle) +{ + if (handle->dir == I2S_DIR_TX) { + return handle->controller->rx_chan ? handle->controller->rx_chan->reserve_gpio_mask : 0; + } + return handle->controller->tx_chan ? handle->controller->tx_chan->reserve_gpio_mask : 0; +} + +void i2s_output_gpio_reserve(i2s_chan_handle_t handle, int gpio_num) +{ + bool used_by_pair_chan = false; + /* If the gpio is used by the pair channel do not show warning for this case */ + if (handle->controller->full_duplex) { + used_by_pair_chan = !!(s_i2s_get_pair_chan_gpio_mask(handle) & BIT64(gpio_num)); + } + /* reserve the GPIO output path, because we don't expect another peripheral to signal to the same GPIO */ + if (!used_by_pair_chan && (esp_gpio_reserve(BIT64(gpio_num)) & BIT64(gpio_num))) { + ESP_LOGW(TAG, "GPIO %d is not usable, maybe conflict with others", gpio_num); + } + handle->reserve_gpio_mask |= BIT64(gpio_num); +} + +void i2s_output_gpio_revoke(i2s_chan_handle_t handle, uint64_t gpio_mask) +{ + uint64_t revoke_mask = gpio_mask; + /* If the gpio is used by the pair channel do not show warning for this case */ + if (handle->controller->full_duplex) { + uint64_t pair_chan_gpio_mask = s_i2s_get_pair_chan_gpio_mask(handle); + /* Only revoke the gpio which is not used by the pair channel */ + revoke_mask = (pair_chan_gpio_mask ^ gpio_mask) & gpio_mask; + } + esp_gpio_revoke(revoke_mask); + handle->reserve_gpio_mask &= ~gpio_mask; +} + +void i2s_gpio_check_and_set(i2s_chan_handle_t handle, int gpio, uint32_t signal_idx, bool is_input, bool is_invert) { /* Ignore the pin if pin = I2S_GPIO_UNUSED */ if (gpio != (int)I2S_GPIO_UNUSED) { @@ -759,15 +795,17 @@ void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool i gpio_set_direction(gpio, GPIO_MODE_INPUT); esp_rom_gpio_connect_in_signal(gpio, signal_idx, is_invert); } else { + i2s_output_gpio_reserve(handle, gpio); gpio_set_direction(gpio, GPIO_MODE_OUTPUT); esp_rom_gpio_connect_out_signal(gpio, signal_idx, is_invert, 0); } } } -void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx) +void i2s_gpio_loopback_set(i2s_chan_handle_t handle, int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx) { if (gpio != (int)I2S_GPIO_UNUSED) { + i2s_output_gpio_reserve(handle, gpio); gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO); gpio_set_direction(gpio, GPIO_MODE_INPUT_OUTPUT); esp_rom_gpio_connect_out_signal(gpio, out_sig_idx, 0, 0); @@ -775,7 +813,7 @@ void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx) } } -esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert) +esp_err_t i2s_check_set_mclk(i2s_chan_handle_t handle, i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert) { if (gpio_num == (int)I2S_GPIO_UNUSED) { return ESP_OK; @@ -784,6 +822,7 @@ esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_sr bool is_i2s0 = id == I2S_NUM_0; bool is_apll = clk_src == I2S_CLK_SRC_APLL; if (g_i2s.controller[id]->mclk_out_hdl == NULL) { + i2s_output_gpio_reserve(handle, gpio_num); soc_clkout_sig_id_t clkout_sig = is_apll ? CLKOUT_SIG_APLL : (is_i2s0 ? CLKOUT_SIG_I2S0 : CLKOUT_SIG_I2S1); ESP_RETURN_ON_ERROR(esp_clock_output_start(clkout_sig, gpio_num, &(g_i2s.controller[id]->mclk_out_hdl)), TAG, "mclk configure failed"); } @@ -791,11 +830,11 @@ esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_sr ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "mck_io_num invalid"); #if SOC_I2S_HW_VERSION_2 if (clk_src == I2S_CLK_SRC_EXTERNAL) { - i2s_gpio_check_and_set(gpio_num, i2s_periph_signal[id].mck_in_sig, true, is_invert); + i2s_gpio_check_and_set(handle, gpio_num, i2s_periph_signal[id].mck_in_sig, true, is_invert); } else #endif // SOC_I2S_HW_VERSION_2 { - i2s_gpio_check_and_set(gpio_num, i2s_periph_signal[id].mck_out_sig, false, is_invert); + i2s_gpio_check_and_set(handle, gpio_num, i2s_periph_signal[id].mck_out_sig, false, is_invert); } #endif // CONFIG_IDF_TARGET_ESP32 ESP_LOGD(TAG, "MCLK is pinned to GPIO%d on I2S%d", gpio_num, id); @@ -930,6 +969,9 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) esp_pm_lock_delete(handle->pm_lock); } #endif + if (handle->reserve_gpio_mask) { + i2s_output_gpio_revoke(handle, handle->reserve_gpio_mask); + } if (handle->mode_info) { free(handle->mode_info); } diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index c358d6b5cd..9d10058af4 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -132,23 +132,23 @@ static esp_err_t i2s_pdm_tx_set_gpio(i2s_chan_handle_t handle, const i2s_pdm_tx_ ESP_ERR_INVALID_ARG, TAG, "dout gpio is invalid"); i2s_pdm_tx_config_t *pdm_tx_cfg = (i2s_pdm_tx_config_t *)handle->mode_info; /* Set data output GPIO */ - i2s_gpio_check_and_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); + i2s_gpio_check_and_set(handle, gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); #if SOC_I2S_PDM_MAX_TX_LINES > 1 if (pdm_tx_cfg->slot_cfg.line_mode == I2S_PDM_TX_TWO_LINE_DAC) { - i2s_gpio_check_and_set(gpio_cfg->dout2, i2s_periph_signal[id].data_out_sigs[1], false, false); + i2s_gpio_check_and_set(handle, gpio_cfg->dout2, i2s_periph_signal[id].data_out_sigs[1], false, false); } #endif if (handle->role == I2S_ROLE_SLAVE) { /* For "tx + slave" mode, select TX signal index for ws and bck */ if (!handle->controller->full_duplex) { - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); /* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */ } else { - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); } } else { - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); } #if SOC_I2S_HW_VERSION_2 I2S_CLOCK_SRC_ATOMIC() { @@ -311,6 +311,9 @@ esp_err_t i2s_channel_reconfig_pdm_tx_gpio(i2s_chan_handle_t handle, const i2s_p ESP_GOTO_ON_FALSE(handle->mode == I2S_COMM_MODE_PDM, ESP_ERR_INVALID_ARG, err, TAG, "This handle is not working in standard mode"); ESP_GOTO_ON_FALSE(handle->state == I2S_CHAN_STATE_READY, ESP_ERR_INVALID_STATE, err, TAG, "Invalid state, I2S should be disabled before reconfiguring the gpio"); + if (handle->reserve_gpio_mask) { + i2s_output_gpio_revoke(handle, handle->reserve_gpio_mask); + } ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_gpio(handle, gpio_cfg), err, TAG, "set i2s standard slot failed"); xSemaphoreGive(handle->mutex); @@ -422,21 +425,21 @@ static esp_err_t i2s_pdm_rx_set_gpio(i2s_chan_handle_t handle, const i2s_pdm_rx_ #if SOC_I2S_PDM_MAX_RX_LINES > 1 for (int i = 0; i < SOC_I2S_PDM_MAX_RX_LINES; i++) { if (pdm_rx_cfg->slot_cfg.slot_mask & (0x03 << (i * 2))) { - i2s_gpio_check_and_set(gpio_cfg->dins[i], i2s_periph_signal[id].data_in_sigs[i], true, false); + i2s_gpio_check_and_set(handle, gpio_cfg->dins[i], i2s_periph_signal[id].data_in_sigs[i], true, false); } } #else - i2s_gpio_check_and_set(gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); + i2s_gpio_check_and_set(handle, gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); #endif if (handle->role == I2S_ROLE_SLAVE) { /* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */ - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.clk_inv); } else { if (!handle->controller->full_duplex) { - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); } else { - i2s_gpio_check_and_set(gpio_cfg->clk, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->clk, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.clk_inv); } } #if SOC_I2S_HW_VERSION_2 @@ -595,6 +598,9 @@ esp_err_t i2s_channel_reconfig_pdm_rx_gpio(i2s_chan_handle_t handle, const i2s_p ESP_GOTO_ON_FALSE(handle->mode == I2S_COMM_MODE_PDM, ESP_ERR_INVALID_ARG, err, TAG, "This handle is not working in standard mode"); ESP_GOTO_ON_FALSE(handle->state == I2S_CHAN_STATE_READY, ESP_ERR_INVALID_STATE, err, TAG, "Invalid state, I2S should be disabled before reconfiguring the gpio"); + if (handle->reserve_gpio_mask) { + i2s_output_gpio_revoke(handle, handle->reserve_gpio_mask); + } ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_gpio(handle, gpio_cfg), err, TAG, "set i2s standard slot failed"); xSemaphoreGive(handle->mutex); diff --git a/components/esp_driver_i2s/i2s_private.h b/components/esp_driver_i2s/i2s_private.h index 65c483b6b7..0f6e388e8c 100644 --- a/components/esp_driver_i2s/i2s_private.h +++ b/components/esp_driver_i2s/i2s_private.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ #include "esp_private/gdma.h" #endif #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_gpio_reserve.h" #include "esp_pm.h" #include "esp_err.h" #include "sdkconfig.h" @@ -146,6 +147,7 @@ struct i2s_channel_obj_t { esp_pm_lock_handle_t pm_lock; /*!< Power management lock, to avoid apb clock frequency changes while i2s is working */ #endif QueueHandle_t msg_queue; /*!< Message queue handler, used for transporting data between interrupt and read/write task */ + uint64_t reserve_gpio_mask; /*!< The gpio mask that has been reserved by I2S */ i2s_event_callbacks_internal_t callbacks; /*!< Callback functions */ void *user_data; /*!< User data for callback functions */ void (*start)(i2s_chan_handle_t); /*!< start tx/rx channel */ @@ -224,16 +226,18 @@ uint32_t i2s_get_source_clk_freq(i2s_clock_src_t clk_src, uint32_t mclk_freq_hz) /** * @brief Check gpio validity and attach to corresponding signal * + * @param handle I2S channel handle * @param gpio GPIO number * @param signal_idx Signal index * @param is_input Is input gpio * @param is_invert Is invert gpio */ -void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool is_invert); +void i2s_gpio_check_and_set(i2s_chan_handle_t handle, int gpio, uint32_t signal_idx, bool is_input, bool is_invert); /** * @brief Check gpio validity and output mclk signal * + * @param handle I2S channel handle * @param id I2S port id * @param gpio_num GPIO number * @param clk_src The clock source of this I2S port @@ -242,16 +246,33 @@ void i2s_gpio_check_and_set(int gpio, uint32_t signal_idx, bool is_input, bool i * - ESP_OK Set mclk output gpio success * - ESP_ERR_INVALID_ARG Invalid GPIO number */ -esp_err_t i2s_check_set_mclk(i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert); +esp_err_t i2s_check_set_mclk(i2s_chan_handle_t handle, i2s_port_t id, int gpio_num, i2s_clock_src_t clk_src, bool is_invert); /** * @brief Attach data out signal and data in signal to a same gpio * + * @param handle I2S channel handle * @param gpio GPIO number * @param out_sig_idx Data out signal index * @param in_sig_idx Data in signal index */ -void i2s_gpio_loopback_set(int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx); +void i2s_gpio_loopback_set(i2s_chan_handle_t handle, int gpio, uint32_t out_sig_idx, uint32_t in_sig_idx); + +/** + * @brief Reserve the GPIO that configured as I2S output signal + * + * @param handle I2S channel handle + * @param gpio_num The output gpio number to be reserved + */ +void i2s_output_gpio_reserve(i2s_chan_handle_t handle, int gpio_num); + +/** + * @brief Revoke the GPIO that configured as I2S output signal + * + * @param handle I2S channel handle + * @param gpio_mask The output gpio mask to be revoked + */ +void i2s_output_gpio_revoke(i2s_chan_handle_t handle, uint64_t gpio_mask); #ifdef __cplusplus } diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index 1594b04ee0..c3ef0c0469 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -145,20 +145,19 @@ static esp_err_t i2s_std_set_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_c ESP_RETURN_ON_FALSE((gpio_cfg->ws == -1 || GPIO_IS_VALID_GPIO(gpio_cfg->ws)), ESP_ERR_INVALID_ARG, TAG, "ws invalid"); i2s_std_config_t *std_cfg = (i2s_std_config_t *)(handle->mode_info); - /* Loopback if dout = din */ if (gpio_cfg->dout != -1 && gpio_cfg->dout == gpio_cfg->din) { - i2s_gpio_loopback_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig); + i2s_gpio_loopback_set(handle, gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig); } else if (handle->dir == I2S_DIR_TX) { /* Set data output GPIO */ - i2s_gpio_check_and_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); + i2s_gpio_check_and_set(handle, gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); } else { /* Set data input GPIO */ - i2s_gpio_check_and_set(gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); + i2s_gpio_check_and_set(handle, gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); } /* Set mclk pin */ - ESP_RETURN_ON_ERROR(i2s_check_set_mclk(id, gpio_cfg->mclk, std_cfg->clk_cfg.clk_src, gpio_cfg->invert_flags.mclk_inv), TAG, "mclk config failed"); + ESP_RETURN_ON_ERROR(i2s_check_set_mclk(handle, id, gpio_cfg->mclk, std_cfg->clk_cfg.clk_src, gpio_cfg->invert_flags.mclk_inv), TAG, "mclk config failed"); if (handle->role == I2S_ROLE_SLAVE) { /* For "tx + slave" mode, select TX signal index for ws and bck */ @@ -168,12 +167,12 @@ static esp_err_t i2s_std_set_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_c i2s_ll_mclk_bind_to_tx_clk(handle->controller->hal.dev); } #endif - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].s_tx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].s_tx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); /* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */ } else { - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].s_rx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].s_rx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); } } else { /* For "rx + master" mode, select RX signal index for ws and bck */ @@ -183,12 +182,12 @@ static esp_err_t i2s_std_set_gpio(i2s_chan_handle_t handle, const i2s_std_gpio_c i2s_ll_mclk_bind_to_rx_clk(handle->controller->hal.dev); } #endif - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].m_rx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].m_rx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); /* For "tx + rx + master" or "tx + master" mode, select TX signal index for ws and bck */ } else { - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].m_tx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].m_tx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); } } /* Update the mode info: gpio configuration */ @@ -349,6 +348,9 @@ esp_err_t i2s_channel_reconfig_std_gpio(i2s_chan_handle_t handle, const i2s_std_ ESP_GOTO_ON_FALSE(handle->mode == I2S_COMM_MODE_STD, ESP_ERR_INVALID_ARG, err, TAG, "This handle is not working in standard mode"); ESP_GOTO_ON_FALSE(handle->state == I2S_CHAN_STATE_READY, ESP_ERR_INVALID_STATE, err, TAG, "Invalid state, I2S should be disabled before reconfiguring the gpio"); + if (handle->reserve_gpio_mask) { + i2s_output_gpio_revoke(handle, handle->reserve_gpio_mask); + } ESP_GOTO_ON_ERROR(i2s_std_set_gpio(handle, gpio_cfg), err, TAG, "set i2s standard slot failed"); xSemaphoreGive(handle->mutex); diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index 5dcdb50114..584e75881c 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -153,17 +153,17 @@ static esp_err_t i2s_tdm_set_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_c /* Loopback if dout = din */ if (gpio_cfg->dout != -1 && gpio_cfg->dout == gpio_cfg->din) { - i2s_gpio_loopback_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig); + i2s_gpio_loopback_set(handle, gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, i2s_periph_signal[id].data_in_sig); } else if (handle->dir == I2S_DIR_TX) { /* Set data output GPIO */ - i2s_gpio_check_and_set(gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); + i2s_gpio_check_and_set(handle, gpio_cfg->dout, i2s_periph_signal[id].data_out_sig, false, false); } else { /* Set data input GPIO */ - i2s_gpio_check_and_set(gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); + i2s_gpio_check_and_set(handle, gpio_cfg->din, i2s_periph_signal[id].data_in_sig, true, false); } /* Set mclk pin */ - ESP_RETURN_ON_ERROR(i2s_check_set_mclk(id, gpio_cfg->mclk, tdm_cfg->clk_cfg.clk_src, gpio_cfg->invert_flags.mclk_inv), TAG, "mclk config failed"); + ESP_RETURN_ON_ERROR(i2s_check_set_mclk(handle, id, gpio_cfg->mclk, tdm_cfg->clk_cfg.clk_src, gpio_cfg->invert_flags.mclk_inv), TAG, "mclk config failed"); if (handle->role == I2S_ROLE_SLAVE) { /* For "tx + slave" mode, select TX signal index for ws and bck */ @@ -173,12 +173,12 @@ static esp_err_t i2s_tdm_set_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_c i2s_ll_mclk_bind_to_tx_clk(handle->controller->hal.dev); } #endif - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].s_tx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].s_tx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].s_tx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); /* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */ } else { - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].s_rx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].s_rx_ws_sig, true, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].s_rx_bck_sig, true, gpio_cfg->invert_flags.bclk_inv); } } else { /* For "rx + master" mode, select RX signal index for ws and bck */ @@ -188,12 +188,12 @@ static esp_err_t i2s_tdm_set_gpio(i2s_chan_handle_t handle, const i2s_tdm_gpio_c i2s_ll_mclk_bind_to_rx_clk(handle->controller->hal.dev); } #endif - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].m_rx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].m_rx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].m_rx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); /* For "tx + rx + master" or "tx + master" mode, select TX signal index for ws and bck */ } else { - i2s_gpio_check_and_set(gpio_cfg->ws, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); - i2s_gpio_check_and_set(gpio_cfg->bclk, i2s_periph_signal[id].m_tx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->ws, i2s_periph_signal[id].m_tx_ws_sig, false, gpio_cfg->invert_flags.ws_inv); + i2s_gpio_check_and_set(handle, gpio_cfg->bclk, i2s_periph_signal[id].m_tx_bck_sig, false, gpio_cfg->invert_flags.bclk_inv); } } /* Update the mode info: gpio configuration */ @@ -357,6 +357,9 @@ esp_err_t i2s_channel_reconfig_tdm_gpio(i2s_chan_handle_t handle, const i2s_tdm_ ESP_GOTO_ON_FALSE(handle->mode == I2S_COMM_MODE_TDM, ESP_ERR_INVALID_ARG, err, TAG, "This handle is not working in standard mode"); ESP_GOTO_ON_FALSE(handle->state == I2S_CHAN_STATE_READY, ESP_ERR_INVALID_STATE, err, TAG, "Invalid state, I2S should be disabled before reconfiguring the gpio"); + if (handle->reserve_gpio_mask) { + i2s_output_gpio_revoke(handle, handle->reserve_gpio_mask); + } ESP_GOTO_ON_ERROR(i2s_tdm_set_gpio(handle, gpio_cfg), err, TAG, "set i2s standard slot failed"); xSemaphoreGive(handle->mutex);