2021-08-18 07:45:51 -04:00
/*
2024-04-02 02:57:00 -04:00
* SPDX - FileCopyrightText : 2022 - 2024 Espressif Systems ( Shanghai ) CO LTD
2021-08-18 07:45:51 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
# include <string.h>
2022-04-07 03:32:46 -04:00
2021-08-18 07:45:51 -04:00
# include "freertos/FreeRTOS.h"
# include "freertos/semphr.h"
2022-04-07 03:32:46 -04:00
# include "sdkconfig.h"
# if CONFIG_I2S_ENABLE_DEBUG_LOG
// The local log level must be defined before including esp_log.h
// Set the maximum log level for this source file
# define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
# endif
2021-08-18 07:45:51 -04:00
# include "hal/i2s_hal.h"
# include "driver/gpio.h"
# include "driver/i2s_std.h"
# include "i2s_private.h"
# include "clk_ctrl_os.h"
# include "esp_intr_alloc.h"
# include "esp_check.h"
2022-04-07 03:32:46 -04:00
const static char * TAG = " i2s_std " ;
2021-08-18 07:45:51 -04:00
static esp_err_t i2s_std_calculate_clock ( i2s_chan_handle_t handle , const i2s_std_clk_config_t * clk_cfg , i2s_hal_clock_info_t * clk_info )
{
uint32_t rate = clk_cfg - > sample_rate_hz ;
i2s_std_slot_config_t * slot_cfg = & ( ( i2s_std_config_t * ) ( handle - > mode_info ) ) - > slot_cfg ;
uint32_t slot_bits = ( slot_cfg - > slot_bit_width = = I2S_SLOT_BIT_WIDTH_AUTO ) | |
( ( int ) slot_cfg - > slot_bit_width < ( int ) slot_cfg - > data_bit_width ) ?
slot_cfg - > data_bit_width : slot_cfg - > slot_bit_width ;
/* Calculate multiple
* Fmclk = bck_div * fbck = fsclk / ( mclk_div + b / a ) */
if ( handle - > role = = I2S_ROLE_MASTER ) {
clk_info - > bclk = rate * handle - > total_slot * slot_bits ;
clk_info - > mclk = rate * clk_cfg - > mclk_multiple ;
clk_info - > bclk_div = clk_info - > mclk / clk_info - > bclk ;
2024-08-27 23:05:08 -04:00
if ( clk_info - > mclk % clk_info - > bclk ! = 0 ) {
ESP_LOGW ( TAG , " the current mclk multiple cannot perform integer division (slot_num: % " PRIu32 " , slot_bits: % " PRIu32 " ) " , handle - > total_slot , slot_bits ) ;
}
2021-08-18 07:45:51 -04:00
} else {
/* For slave mode, mclk >= bclk * 8, so fix bclk_div to 2 first */
clk_info - > bclk_div = 8 ;
clk_info - > bclk = rate * handle - > total_slot * slot_bits ;
clk_info - > mclk = clk_info - > bclk * clk_info - > bclk_div ;
}
2023-07-20 05:00:48 -04:00
# if SOC_I2S_HW_VERSION_2
clk_info - > sclk = clk_cfg - > clk_src = = I2S_CLK_SRC_EXTERNAL ?
clk_cfg - > ext_clk_freq_hz : i2s_get_source_clk_freq ( clk_cfg - > clk_src , clk_info - > mclk ) ;
# else
2022-09-15 05:27:57 -04:00
clk_info - > sclk = i2s_get_source_clk_freq ( clk_cfg - > clk_src , clk_info - > mclk ) ;
2023-07-20 05:00:48 -04:00
# endif
2021-08-18 07:45:51 -04:00
clk_info - > mclk_div = clk_info - > sclk / clk_info - > mclk ;
/* Check if the configuration is correct */
2023-07-20 05:00:48 -04:00
ESP_RETURN_ON_FALSE ( clk_info - > mclk_div , ESP_ERR_INVALID_ARG , TAG , " sample rate is too large for the current clock source " ) ;
2021-08-18 07:45:51 -04:00
return ESP_OK ;
}
static esp_err_t i2s_std_set_clock ( i2s_chan_handle_t handle , const i2s_std_clk_config_t * clk_cfg )
{
esp_err_t ret = ESP_OK ;
i2s_std_config_t * std_cfg = ( i2s_std_config_t * ) ( handle - > mode_info ) ;
2023-04-26 03:23:58 -04:00
i2s_data_bit_width_t real_slot_bit = ( int ) std_cfg - > slot_cfg . slot_bit_width < ( int ) std_cfg - > slot_cfg . data_bit_width ?
std_cfg - > slot_cfg . data_bit_width : std_cfg - > slot_cfg . slot_bit_width ;
ESP_RETURN_ON_FALSE ( real_slot_bit ! = I2S_DATA_BIT_WIDTH_24BIT | |
2022-07-04 23:22:27 -04:00
( clk_cfg - > mclk_multiple % 3 = = 0 ) , ESP_ERR_INVALID_ARG , TAG ,
" The 'mclk_multiple' should be the multiple of 3 while using 24-bit data width " ) ;
2021-08-18 07:45:51 -04:00
i2s_hal_clock_info_t clk_info ;
/* Calculate clock parameters */
ESP_RETURN_ON_ERROR ( i2s_std_calculate_clock ( handle , clk_cfg , & clk_info ) , TAG , " clock calculate failed " ) ;
2022-08-04 01:08:48 -04:00
ESP_LOGD ( TAG , " Clock division info: [sclk] % " PRIu32 " Hz [mdiv] %d [mclk] % " PRIu32 " Hz [bdiv] %d [bclk] % " PRIu32 " Hz " ,
2022-04-07 03:32:46 -04:00
clk_info . sclk , clk_info . mclk_div , clk_info . mclk , clk_info . bclk_div , clk_info . bclk ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
portENTER_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
/* Set clock configurations in HAL*/
2023-09-05 22:55:47 -04:00
I2S_CLOCK_SRC_ATOMIC ( ) {
2023-08-02 07:21:54 -04:00
if ( handle - > dir = = I2S_DIR_TX ) {
i2s_hal_set_tx_clock ( & handle - > controller - > hal , & clk_info , clk_cfg - > clk_src ) ;
} else {
i2s_hal_set_rx_clock ( & handle - > controller - > hal , & clk_info , clk_cfg - > clk_src ) ;
}
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portEXIT_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
/* Update the mode info: clock configuration */
memcpy ( & ( std_cfg - > clk_cfg ) , clk_cfg , sizeof ( i2s_std_clk_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ret ;
}
static esp_err_t i2s_std_set_slot ( i2s_chan_handle_t handle , const i2s_std_slot_config_t * slot_cfg )
{
2022-04-02 09:31:35 -04:00
/* Update the total slot num and active slot num */
handle - > total_slot = 2 ;
handle - > active_slot = slot_cfg - > slot_mode = = I2S_SLOT_MODE_MONO ? 1 : 2 ;
2021-08-18 07:45:51 -04:00
uint32_t buf_size = i2s_get_buf_size ( handle , slot_cfg - > data_bit_width , handle - > dma . frame_num ) ;
/* The DMA buffer need to re-allocate if the buffer size changed */
if ( handle - > dma . buf_size ! = buf_size ) {
handle - > dma . buf_size = buf_size ;
ESP_RETURN_ON_ERROR ( i2s_free_dma_desc ( handle ) , TAG , " failed to free the old dma descriptor " ) ;
ESP_RETURN_ON_ERROR ( i2s_alloc_dma_desc ( handle , handle - > dma . desc_num , buf_size ) ,
TAG , " allocate memory for dma descriptor failed " ) ;
}
bool is_slave = handle - > role = = I2S_ROLE_SLAVE ;
/* Share bck and ws signal in full-duplex mode */
2022-04-07 03:32:46 -04:00
if ( handle - > controller - > full_duplex ) {
i2s_ll_share_bck_ws ( handle - > controller - > hal . dev , true ) ;
2021-08-18 07:45:51 -04:00
/* Since bck and ws are shared, only tx or rx can be master
Force to set rx as slave to avoid conflict of clock signal */
if ( handle - > dir = = I2S_DIR_RX ) {
is_slave = true ;
}
} else {
2022-04-07 03:32:46 -04:00
i2s_ll_share_bck_ws ( handle - > controller - > hal . dev , false ) ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portENTER_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
/* Configure the hardware to apply STD format */
if ( handle - > dir = = I2S_DIR_TX ) {
2022-04-07 03:32:46 -04:00
i2s_hal_std_set_tx_slot ( & ( handle - > controller - > hal ) , is_slave , ( i2s_hal_slot_config_t * ) slot_cfg ) ;
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_hal_std_set_rx_slot ( & ( handle - > controller - > hal ) , is_slave , ( i2s_hal_slot_config_t * ) slot_cfg ) ;
2021-08-18 07:45:51 -04:00
}
2022-04-07 03:32:46 -04:00
portEXIT_CRITICAL ( & g_i2s . spinlock ) ;
2021-08-18 07:45:51 -04:00
2022-04-02 09:31:35 -04:00
/* Update the mode info: slot configuration */
2022-04-07 03:32:46 -04:00
i2s_std_config_t * std_cfg = ( i2s_std_config_t * ) ( handle - > mode_info ) ;
2022-04-02 09:31:35 -04:00
memcpy ( & ( std_cfg - > slot_cfg ) , slot_cfg , sizeof ( i2s_std_slot_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ESP_OK ;
}
static esp_err_t i2s_std_set_gpio ( i2s_chan_handle_t handle , const i2s_std_gpio_config_t * gpio_cfg )
{
2022-04-07 03:32:46 -04:00
int id = handle - > controller - > id ;
2021-08-18 07:45:51 -04:00
/* Check validity of selected pins */
ESP_RETURN_ON_FALSE ( ( gpio_cfg - > bclk = = - 1 | | GPIO_IS_VALID_GPIO ( gpio_cfg - > bclk ) ) ,
ESP_ERR_INVALID_ARG , TAG , " bclk invalid " ) ;
ESP_RETURN_ON_FALSE ( ( gpio_cfg - > ws = = - 1 | | GPIO_IS_VALID_GPIO ( gpio_cfg - > ws ) ) ,
ESP_ERR_INVALID_ARG , TAG , " ws invalid " ) ;
2022-04-07 03:32:46 -04:00
i2s_std_config_t * std_cfg = ( i2s_std_config_t * ) ( handle - > mode_info ) ;
2022-04-02 09:31:35 -04:00
/* Loopback if dout = din */
2023-11-07 08:06:07 -05:00
if ( gpio_cfg - > dout ! = - 1 & & gpio_cfg - > dout = = gpio_cfg - > din ) {
2024-04-02 02:57:00 -04:00
i2s_gpio_loopback_set ( handle , gpio_cfg - > dout , i2s_periph_signal [ id ] . data_out_sig , i2s_periph_signal [ id ] . data_in_sig ) ;
2022-04-07 03:32:46 -04:00
} else if ( handle - > dir = = I2S_DIR_TX ) {
/* Set data output GPIO */
2024-04-02 02:57:00 -04:00
i2s_gpio_check_and_set ( handle , gpio_cfg - > dout , i2s_periph_signal [ id ] . data_out_sig , false , false ) ;
2022-04-07 03:32:46 -04:00
} else {
/* Set data input GPIO */
2024-04-02 02:57:00 -04:00
i2s_gpio_check_and_set ( handle , gpio_cfg - > din , i2s_periph_signal [ id ] . data_in_sig , true , false ) ;
2022-04-02 09:31:35 -04:00
}
2021-08-18 07:45:51 -04:00
2023-07-20 05:00:48 -04:00
/* Set mclk pin */
2024-04-02 02:57:00 -04:00
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 " ) ;
2023-07-20 05:00:48 -04:00
2021-08-18 07:45:51 -04:00
if ( handle - > role = = I2S_ROLE_SLAVE ) {
/* For "tx + slave" mode, select TX signal index for ws and bck */
2022-04-07 03:32:46 -04:00
if ( handle - > dir = = I2S_DIR_TX & & ! handle - > controller - > full_duplex ) {
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
2023-12-22 06:39:31 -05:00
I2S_CLOCK_SRC_ATOMIC ( ) {
2023-12-21 02:25:39 -05:00
i2s_ll_mclk_bind_to_tx_clk ( handle - > controller - > hal . dev ) ;
}
2021-08-18 07:45:51 -04:00
# endif
2024-04-02 02:57:00 -04:00
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 ) ;
2022-04-07 03:32:46 -04:00
/* For "tx + rx + slave" or "rx + slave" mode, select RX signal index for ws and bck */
2021-08-18 07:45:51 -04:00
} else {
2024-04-02 02:57:00 -04:00
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 ) ;
2021-08-18 07:45:51 -04:00
}
} else {
/* For "rx + master" mode, select RX signal index for ws and bck */
2022-04-07 03:32:46 -04:00
if ( handle - > dir = = I2S_DIR_RX & & ! handle - > controller - > full_duplex ) {
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
2023-12-22 06:39:31 -05:00
I2S_CLOCK_SRC_ATOMIC ( ) {
2023-12-21 02:25:39 -05:00
i2s_ll_mclk_bind_to_rx_clk ( handle - > controller - > hal . dev ) ;
}
2021-08-18 07:45:51 -04:00
# endif
2024-04-02 02:57:00 -04:00
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 ) ;
2022-04-07 03:32:46 -04:00
/* For "tx + rx + master" or "tx + master" mode, select TX signal index for ws and bck */
2021-08-18 07:45:51 -04:00
} else {
2024-04-02 02:57:00 -04:00
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 ) ;
2021-08-18 07:45:51 -04:00
}
}
2022-04-02 09:31:35 -04:00
/* Update the mode info: gpio configuration */
memcpy ( & ( std_cfg - > gpio_cfg ) , gpio_cfg , sizeof ( i2s_std_gpio_config_t ) ) ;
2021-08-18 07:45:51 -04:00
return ESP_OK ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_init_std_mode ( i2s_chan_handle_t handle , const i2s_std_config_t * std_cfg )
2021-08-18 07:45:51 -04:00
{
2022-04-07 03:32:46 -04:00
# if CONFIG_I2S_ENABLE_DEBUG_LOG
esp_log_level_set ( TAG , ESP_LOG_DEBUG ) ;
# endif
2021-08-18 07:45:51 -04:00
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-04-02 09:31:35 -04:00
handle - > mode = I2S_COMM_MODE_STD ;
/* Allocate memory for storing the configurations of standard mode */
if ( handle - > mode_info ) {
free ( handle - > mode_info ) ;
}
handle - > mode_info = calloc ( 1 , sizeof ( i2s_std_config_t ) ) ;
ESP_GOTO_ON_FALSE ( handle - > mode_info , ESP_ERR_NO_MEM , err , TAG , " no memory for storing the configurations " ) ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_FALSE ( handle - > state = = I2S_CHAN_STATE_REGISTER , ESP_ERR_INVALID_STATE , err , TAG , " the channel has initialized already " ) ;
2022-04-07 03:32:46 -04:00
/* i2s_set_std_slot should be called before i2s_set_std_clock while initializing, because clock is relay on the slot */
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_std_set_slot ( handle , & std_cfg - > slot_cfg ) , err , TAG , " initialize channel failed while setting slot " ) ;
2022-04-02 09:31:35 -04:00
# if SOC_I2S_SUPPORTS_APLL
/* Enable APLL and acquire its lock when the clock source is APLL */
2022-04-07 03:32:46 -04:00
if ( std_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_acquire ( ) ;
handle - > apll_en = true ;
}
# endif
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_std_set_clock ( handle , & std_cfg - > clk_cfg ) , err , TAG , " initialize channel failed while setting clock " ) ;
2023-07-20 05:00:48 -04:00
/* i2s_std_set_gpio should be called after i2s_std_set_clock as mclk relies on the clock source */
ESP_GOTO_ON_ERROR ( i2s_std_set_gpio ( handle , & std_cfg - > gpio_cfg ) , err , TAG , " initialize channel failed while setting gpio pins " ) ;
2023-03-20 08:15:12 -04:00
ESP_GOTO_ON_ERROR ( i2s_init_dma_intr ( handle , I2S_INTR_ALLOC_FLAGS ) , err , TAG , " initialize dma interrupt failed " ) ;
2021-08-18 07:45:51 -04:00
# if SOC_I2S_HW_VERSION_2
/* Enable clock to start outputting mclk signal. Some codecs will reset once mclk stop */
if ( handle - > dir = = I2S_DIR_TX ) {
2022-04-07 03:32:46 -04:00
i2s_ll_tx_enable_std ( handle - > controller - > hal . dev ) ;
2021-08-18 07:45:51 -04:00
} else {
2022-04-07 03:32:46 -04:00
i2s_ll_rx_enable_std ( handle - > controller - > hal . dev ) ;
2021-08-18 07:45:51 -04:00
}
# endif
2022-04-07 03:32:46 -04:00
# ifdef CONFIG_PM_ENABLE
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX ;
# if SOC_I2S_SUPPORTS_APLL
if ( std_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
pm_type = ESP_PM_NO_LIGHT_SLEEP ;
}
# endif // SOC_I2S_SUPPORTS_APLL
ESP_RETURN_ON_ERROR ( esp_pm_lock_create ( pm_type , 0 , " i2s_driver " , & handle - > pm_lock ) , TAG , " I2S pm lock create failed " ) ;
# endif
2021-08-18 07:45:51 -04:00
/* Initialization finished, mark state as ready */
handle - > state = I2S_CHAN_STATE_READY ;
xSemaphoreGive ( handle - > mutex ) ;
2022-06-20 08:30:31 -04:00
ESP_LOGD ( TAG , " The %s channel on I2S%d has been initialized to STD mode successfully " ,
handle - > dir = = I2S_DIR_TX ? " tx " : " rx " , handle - > controller - > id ) ;
2021-08-18 07:45:51 -04:00
return ret ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_std_clock ( i2s_chan_handle_t handle , const i2s_std_clk_config_t * clk_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , clk_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_STD , ESP_ERR_INVALID_ARG , err , TAG , " this handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
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 clock " ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
i2s_std_config_t * std_cfg = ( i2s_std_config_t * ) handle - > mode_info ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_FALSE ( std_cfg , ESP_ERR_INVALID_STATE , err , TAG , " initialization not complete " ) ;
2022-04-07 03:32:46 -04:00
# if SOC_I2S_SUPPORTS_APLL
2022-04-02 09:31:35 -04:00
/* Enable APLL and acquire its lock when the clock source is changed to APLL */
2022-04-07 03:32:46 -04:00
if ( clk_cfg - > clk_src = = I2S_CLK_SRC_APLL & & std_cfg - > clk_cfg . clk_src ! = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_acquire ( ) ;
handle - > apll_en = true ;
}
/* Disable APLL and release its lock when clock source is changed to 160M_PLL */
2022-04-07 03:32:46 -04:00
if ( clk_cfg - > clk_src ! = I2S_CLK_SRC_APLL & & std_cfg - > clk_cfg . clk_src = = I2S_CLK_SRC_APLL ) {
2022-04-02 09:31:35 -04:00
periph_rtc_apll_release ( ) ;
handle - > apll_en = false ;
}
# endif
ESP_GOTO_ON_ERROR ( i2s_std_set_clock ( handle , clk_cfg ) , err , TAG , " update clock failed " ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
# ifdef CONFIG_PM_ENABLE
// Create/Re-create power management lock
if ( std_cfg - > clk_cfg . clk_src ! = clk_cfg - > clk_src ) {
ESP_GOTO_ON_ERROR ( esp_pm_lock_delete ( handle - > pm_lock ) , err , TAG , " I2S delete old pm lock failed " ) ;
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX ;
# if SOC_I2S_SUPPORTS_APLL
if ( clk_cfg - > clk_src = = I2S_CLK_SRC_APLL ) {
pm_type = ESP_PM_NO_LIGHT_SLEEP ;
}
# endif // SOC_I2S_SUPPORTS_APLL
ESP_GOTO_ON_ERROR ( esp_pm_lock_create ( pm_type , 0 , " i2s_driver " , & handle - > pm_lock ) , err , TAG , " I2S pm lock create failed " ) ;
}
# endif //CONFIG_PM_ENABLE
2021-08-18 07:45:51 -04:00
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_std_slot ( i2s_chan_handle_t handle , const i2s_std_slot_config_t * slot_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , slot_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_STD , ESP_ERR_INVALID_ARG , err , TAG , " this handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
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 slot " ) ;
2021-08-18 07:45:51 -04:00
2022-04-07 03:32:46 -04:00
i2s_std_config_t * std_cfg = ( i2s_std_config_t * ) handle - > mode_info ;
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_FALSE ( std_cfg , ESP_ERR_INVALID_STATE , err , TAG , " initialization not complete " ) ;
ESP_GOTO_ON_ERROR ( i2s_std_set_slot ( handle , slot_cfg ) , err , TAG , " set i2s standard slot failed " ) ;
/* If the slot bit width changed, then need to update the clock */
uint32_t slot_bits = slot_cfg - > slot_bit_width = = I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg - > data_bit_width : slot_cfg - > slot_bit_width ;
if ( std_cfg - > slot_cfg . slot_bit_width = = slot_bits ) {
ESP_GOTO_ON_ERROR ( i2s_std_set_clock ( handle , & std_cfg - > clk_cfg ) , err , TAG , " update clock failed " ) ;
}
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}
2022-04-07 03:32:46 -04:00
esp_err_t i2s_channel_reconfig_std_gpio ( i2s_chan_handle_t handle , const i2s_std_gpio_config_t * gpio_cfg )
2021-08-18 07:45:51 -04:00
{
I2S_NULL_POINTER_CHECK ( TAG , handle ) ;
I2S_NULL_POINTER_CHECK ( TAG , gpio_cfg ) ;
esp_err_t ret = ESP_OK ;
xSemaphoreTake ( handle - > mutex , portMAX_DELAY ) ;
2022-12-22 02:16:26 -05:00
ESP_GOTO_ON_FALSE ( handle - > mode = = I2S_COMM_MODE_STD , ESP_ERR_INVALID_ARG , err , TAG , " This handle is not working in standard mode " ) ;
2022-04-07 03:32:46 -04:00
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 " ) ;
2021-08-18 07:45:51 -04:00
2024-04-02 02:57:00 -04:00
if ( handle - > reserve_gpio_mask ) {
i2s_output_gpio_revoke ( handle , handle - > reserve_gpio_mask ) ;
}
2021-08-18 07:45:51 -04:00
ESP_GOTO_ON_ERROR ( i2s_std_set_gpio ( handle , gpio_cfg ) , err , TAG , " set i2s standard slot failed " ) ;
xSemaphoreGive ( handle - > mutex ) ;
return ESP_OK ;
err :
xSemaphoreGive ( handle - > mutex ) ;
return ret ;
}