diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c index 56a6252185f..23adf3d3f4b 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c @@ -347,14 +347,17 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e } #if CONFIG_IDF_TARGET_ESP32S31 - // PLL 120M was selected in esp_perip_clk_init on esp32s31. - ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true)); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)CAM_CORE_CLK_SRC_DEFAULT, true)); #endif PERIPH_RCC_ACQUIRE_ATOMIC(cam_periph_signals.buses[ctlr_id].module, ref_count) { if (ref_count == 0) { cam_ll_enable_bus_clock(ctlr_id, true); cam_ll_reset_register(ctlr_id); +#if CONFIG_IDF_TARGET_ESP32S31 + cam_ll_select_core_clk_src(ctlr_id, CAM_CORE_CLK_SRC_DEFAULT); + cam_ll_set_core_clock_divider(ctlr_id, 2, 0, 0); +#endif } } @@ -470,7 +473,7 @@ esp_err_t esp_cam_ctlr_dvp_deinit(int ctlr_id) } #if CONFIG_IDF_TARGET_ESP32S31 - esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false); + esp_clk_tree_enable_src((soc_module_clk_t)CAM_CORE_CLK_SRC_DEFAULT, false); #endif return ESP_OK; diff --git a/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h b/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h index 6043b2d4850..c2cd6b248b1 100644 --- a/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h +++ b/components/esp_hal_cam/esp32s31/include/hal/cam_ll.h @@ -29,7 +29,7 @@ extern "C" { * @param group_id Group ID * @param enable true to enable, false to disable */ -static inline void cam_ll_enable_bus_clock(int group_id, bool en) +static inline void _cam_ll_enable_bus_clock(int group_id, bool en) { (void)group_id; // the core clock is a shared clock for both LCD and CAM @@ -42,7 +42,7 @@ static inline void cam_ll_enable_bus_clock(int group_id, bool en) /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance #define cam_ll_enable_bus_clock(...) do { \ (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ - cam_ll_enable_bus_clock(__VA_ARGS__); \ + _cam_ll_enable_bus_clock(__VA_ARGS__); \ } while(0) /** @@ -50,7 +50,7 @@ static inline void cam_ll_enable_bus_clock(int group_id, bool en) * * @param group_id Group ID */ -static inline void cam_ll_reset_register(int group_id) +static inline void _cam_ll_reset_register(int group_id) { (void)group_id; HP_SYS_CLKRST.lcdcam_ctrl0.reg_lcdcam_apb_rst_en = 1; @@ -63,7 +63,61 @@ static inline void cam_ll_reset_register(int group_id) /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance #define cam_ll_reset_register(...) do { \ (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ - cam_ll_reset_register(__VA_ARGS__); \ + _cam_ll_reset_register(__VA_ARGS__); \ + } while(0) + +/** + * @brief Select shared core clock source for LCDCAM peripheral + * + * @param group_id Group ID + * @param src Core clock source + */ +static inline void _cam_ll_select_core_clk_src(int group_id, soc_periph_cam_core_clk_src_t src) +{ + (void)group_id; + switch (src) { + case CAM_CORE_CLK_SRC_XTAL: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 0; + break; + case CAM_CORE_CLK_SRC_PLL120M: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 1; + break; + case CAM_CORE_CLK_SRC_APLL: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 2; + break; + default: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 3; + break; + } +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define cam_ll_select_core_clk_src(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + _cam_ll_select_core_clk_src(__VA_ARGS__); \ + } while(0) + +/** + * @brief Set shared core clock divider for LCDCAM peripheral + * + * @param group_id Group ID + * @param div_num Integer part of the divider + * @param div_a Denominator of the fractional part; set to 0 to disable fractional division + * @param div_b Numerator of the fractional part; set to 0 to disable fractional division + */ +static inline void _cam_ll_set_core_clock_divider(int group_id, uint32_t div_num, uint32_t div_a, uint32_t div_b) +{ + (void)group_id; + HAL_ASSERT(div_num > 0 && div_num <= CAM_LL_CLK_FRAC_DIV_N_MAX); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_num, div_num - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_denominator, div_a); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_numerator, div_b); +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define cam_ll_set_core_clock_divider(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + _cam_ll_set_core_clock_divider(__VA_ARGS__); \ } while(0) /** diff --git a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h index a7be7133f3e..8acb981c5b1 100644 --- a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h @@ -164,14 +164,6 @@ static inline void periph_ll_clk_gate_set_default(soc_reset_reason_t rst_reason, HP_SYS_CLKRST.timergrp1_ctrl0.reg_timergrp1_t0_clk_en = 0; HP_SYS_CLKRST.timergrp1_ctrl0.reg_timergrp1_t1_clk_en = 0; HP_SYS_CLKRST.timergrp1_ctrl0.reg_timergrp1_wdt_clk_en = 0; - // LCDCAM - /* - * Default lcdcam_lcdcam_ctrl0: - * reg_lcdcam_clk_src_sel: 1 (BBPLL 120 MHz path, shared by LCD and CAM) - * reg_lcdcam_clk_div_num: 1 (divide by 2 → 60 MHz) - */ - HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 1; - HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_div_num = 1; // ASRC HP_SYS_CLKRST.ahb_asrc_ctrl0.reg_ahb_asrc_sys_clk_en = 0; // Flash diff --git a/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h b/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h index 2984647ff9e..1da1188fda0 100644 --- a/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h @@ -122,11 +122,12 @@ static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) /** * @brief Select clock source for LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param src Clock source */ -static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t src) +static inline void lcd_ll_select_clk_src(int group_id, lcd_clock_source_t src) { + (void)group_id; switch (src) { case LCD_CLK_SRC_XTAL: HP_SYS_CLKRST.peri_clk_ctrl19.reg_lcd_clk_src_sel = 0; @@ -154,14 +155,15 @@ static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t /** * @brief Set clock coefficient of LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param div_num Integer part of the divider * @param div_a denominator of the divider * @param div_b numerator of the divider */ __attribute__((always_inline)) -static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num, int div_a, int div_b) +static inline void lcd_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b) { + (void)group_id; // lcd_clk = module_clock_src / (div_num + div_b / div_a) HAL_ASSERT(div_num > 0 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX); HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl110, reg_lcd_clk_div_num, div_num - 1); diff --git a/components/esp_hal_lcd/esp32s3/include/hal/lcd_ll.h b/components/esp_hal_lcd/esp32s3/include/hal/lcd_ll.h index 001868f2484..ef467bf4076 100644 --- a/components/esp_hal_lcd/esp32s3/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32s3/include/hal/lcd_ll.h @@ -103,11 +103,12 @@ static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) /** * @brief Select clock source for LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param src Clock source */ -static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t src) +static inline void lcd_ll_select_clk_src(int group_id, lcd_clock_source_t src) { + lcd_cam_dev_t *dev = LCD_LL_GET_HW(group_id); switch (src) { case LCD_CLK_SRC_PLL160M: dev->lcd_clock.lcd_clk_sel = 3; @@ -129,14 +130,15 @@ static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t /** * @brief Set clock coefficient of LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param div_num Integer part of the divider * @param div_a denominator of the divider * @param div_b numerator of the divider */ __attribute__((always_inline)) -static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num, int div_a, int div_b) +static inline void lcd_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b) { + lcd_cam_dev_t *dev = LCD_LL_GET_HW(group_id); // lcd_clk = module_clock_src / (div_num + div_b / div_a) HAL_ASSERT(div_num >= 2 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX); // dic_num == 0 means LCD_LL_CLK_FRAC_DIV_N_MAX divider in hardware diff --git a/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h b/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h index ea2b43500ba..0e11836c3f0 100644 --- a/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h @@ -68,7 +68,7 @@ typedef enum { * @param group_id Group ID * @param enable true to enable, false to disable */ -static inline void lcd_ll_enable_bus_clock(int group_id, bool enable) +static inline void _lcd_ll_enable_bus_clock(int group_id, bool enable) { (void)group_id; // the core clock is a shared clock for both LCD and CAM @@ -81,7 +81,7 @@ static inline void lcd_ll_enable_bus_clock(int group_id, bool enable) /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance #define lcd_ll_enable_bus_clock(...) do { \ (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ - lcd_ll_enable_bus_clock(__VA_ARGS__); \ + _lcd_ll_enable_bus_clock(__VA_ARGS__); \ } while(0) /** @@ -105,6 +105,60 @@ static inline void _lcd_ll_reset_register(int group_id) _lcd_ll_reset_register(__VA_ARGS__); \ } while(0) +/** + * @brief Select shared core clock source for LCDCAM peripheral + * + * @param group_id Group ID + * @param src Core clock source + */ +static inline void _lcd_ll_select_core_clk_src(int group_id, soc_periph_lcd_core_clk_src_t src) +{ + (void)group_id; + switch (src) { + case LCD_CORE_CLK_SRC_XTAL: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 0; + break; + case LCD_CORE_CLK_SRC_PLL120M: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 1; + break; + case LCD_CORE_CLK_SRC_APLL: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 2; + break; + default: + HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0.reg_lcdcam_clk_src_sel = 3; + break; + } +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define lcd_ll_select_core_clk_src(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + _lcd_ll_select_core_clk_src(__VA_ARGS__); \ + } while(0) + +/** + * @brief Set shared core clock divider for LCDCAM peripheral + * + * @param group_id Group ID + * @param div_num Integer part of the divider + * @param div_a Denominator of the fractional part; set to 0 to disable fractional division + * @param div_b Numerator of the fractional part; set to 0 to disable fractional division + */ +static inline void _lcd_ll_set_core_clock_divider(int group_id, uint32_t div_num, uint32_t div_a, uint32_t div_b) +{ + (void)group_id; + HAL_ASSERT(div_num > 0 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_num, div_num - 1); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_denominator, div_a); + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcdcam_ctrl0, reg_lcdcam_clk_div_numerator, div_b); +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance +#define lcd_ll_set_core_clock_divider(...) do { \ + (void)__DECLARE_RCC_RC_ATOMIC_ENV; \ + _lcd_ll_set_core_clock_divider(__VA_ARGS__); \ + } while(0) + /** * @brief Enable clock gating * @@ -120,12 +174,12 @@ static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) /** * @brief Select clock source for LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param src Clock source */ -static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t src) +static inline void lcd_ll_select_clk_src(int group_id, lcd_clock_source_t src) { - (void)dev; + (void)group_id; switch (src) { case LCD_CLK_SRC_XTAL: HP_SYS_CLKRST.lcdcam_lcd_ctrl0.reg_lcd_clk_src_sel = 0; @@ -146,15 +200,15 @@ static inline void lcd_ll_select_clk_src(lcd_cam_dev_t *dev, lcd_clock_source_t /** * @brief Set clock coefficient of LCD peripheral * - * @param dev LCD register base address + * @param group_id Group ID * @param div_num Integer part of the divider * @param div_a denominator of the divider * @param div_b numerator of the divider */ __attribute__((always_inline)) -static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num, int div_a, int div_b) +static inline void lcd_ll_set_group_clock_coeff(int group_id, int div_num, int div_a, int div_b) { - (void)dev; + (void)group_id; // lcd_clk = module_clock_src / (div_num + div_b / div_a) HAL_ASSERT(div_num > 0 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX); HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.lcdcam_lcd_ctrl0, reg_lcd_clk_div_num, div_num - 1); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index 423d6aa2621..1fbc4ce9c21 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -125,7 +125,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc esp_err_t ret = ESP_OK; esp_lcd_i80_bus_t *bus = NULL; #if CONFIG_IDF_TARGET_ESP32S31 - bool pll_f120m_enabled = false; + bool core_clk_enabled = false; #endif ESP_RETURN_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); // although LCD_CAM can support up to 24 data lines, we restrict users to only use 8 or 16 bit width @@ -163,6 +163,10 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc if (ref_count == 0) { lcd_ll_enable_bus_clock(bus_id, true); lcd_ll_reset_register(bus_id); +#if CONFIG_IDF_TARGET_ESP32S31 + lcd_ll_select_core_clk_src(bus_id, LCD_CORE_CLK_SRC_DEFAULT); + lcd_ll_set_core_clock_divider(bus_id, 2, 0, 0); +#endif } } #if I80_USE_RETENTION_LINK @@ -189,9 +193,8 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc // initialize HAL layer, so we can call LL APIs later lcd_hal_init(&bus->hal, bus_id); #if CONFIG_IDF_TARGET_ESP32S31 - // PLL 120M was selected in esp_perip_clk_init on esp32s31. - ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true), err, TAG, "clock source enable failed"); - pll_f120m_enabled = true; + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)LCD_CORE_CLK_SRC_DEFAULT, true), err, TAG, "core clock source enable failed"); + core_clk_enabled = true; #endif PERIPH_RCC_ATOMIC() { lcd_ll_enable_clock(bus->hal.dev, true); @@ -277,8 +280,8 @@ err: bus->clk_src = SOC_MOD_CLK_INVALID; } #if CONFIG_IDF_TARGET_ESP32S31 - if (pll_f120m_enabled) { - esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false); + if (core_clk_enabled) { + esp_clk_tree_enable_src((soc_module_clk_t)LCD_CORE_CLK_SRC_DEFAULT, false); } #endif #if CONFIG_PM_ENABLE @@ -305,7 +308,7 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus) bus->clk_src = SOC_MOD_CLK_INVALID; } #if CONFIG_IDF_TARGET_ESP32S31 - ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false), err, TAG, "clock source disable failed"); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)LCD_CORE_CLK_SRC_DEFAULT, false), err, TAG, "core clock source disable failed"); #endif #if I80_USE_RETENTION_LINK const periph_retention_module_t module_id = lcd_i80_reg_retention_info[bus_id].retention_module; @@ -667,9 +670,9 @@ static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz), TAG, "get clock source frequency failed"); PERIPH_RCC_ATOMIC() { - lcd_ll_select_clk_src(bus->hal.dev, clk_src); + lcd_ll_select_clk_src(bus->bus_id, clk_src); // force to use integer division, as fractional division might lead to clock jitter - lcd_ll_set_group_clock_coeff(bus->hal.dev, LCD_PERIPH_CLOCK_PRE_SCALE, 0, 0); + lcd_ll_set_group_clock_coeff(bus->bus_id, LCD_PERIPH_CLOCK_PRE_SCALE, 0, 0); } // save the resolution of the i80 bus diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 9d5f5491d72..ef68a71565a 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -170,9 +170,7 @@ struct esp_rgb_panel_t { uint32_t fb_behind_cache: 1; // Whether the frame buffer is behind the cache uint32_t bb_behind_cache: 1; // Whether the bounce buffer is behind the cache uint32_t user_fb: 1; // Whether the frame buffer is provided by user -#if CONFIG_IDF_TARGET_ESP32S31 - uint32_t pll_f120m_enabled: 1; // Whether PLL_F120M was enabled for this panel instance -#endif + uint32_t core_clk_enabled: 1; // Whether the LCD core clock source was enabled for this panel instance } flags; }; @@ -261,9 +259,9 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel) lcd_ll_enable_clock(rgb_panel->hal.dev, false); } #if CONFIG_IDF_TARGET_ESP32S31 - if (rgb_panel->flags.pll_f120m_enabled) { - esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false); - rgb_panel->flags.pll_f120m_enabled = 0; + if (rgb_panel->flags.core_clk_enabled) { + esp_clk_tree_enable_src((soc_module_clk_t)LCD_CORE_CLK_SRC_DEFAULT, false); + rgb_panel->flags.core_clk_enabled = 0; } #endif if (rgb_panel->clk_src) { @@ -407,6 +405,10 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf if (ref_count == 0) { lcd_ll_enable_bus_clock(panel_id, true); lcd_ll_reset_register(panel_id); +#if CONFIG_IDF_TARGET_ESP32S31 + lcd_ll_select_core_clk_src(panel_id, LCD_CORE_CLK_SRC_DEFAULT); + lcd_ll_set_core_clock_divider(panel_id, 2, 0, 0); +#endif } } @@ -415,9 +417,8 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf lcd_hal_context_t *hal = &rgb_panel->hal; // enable clock #if CONFIG_IDF_TARGET_ESP32S31 - // PLL 120M was selected in esp_perip_clk_init on esp32s31. - ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true), err, TAG, "clock source enable failed"); - rgb_panel->flags.pll_f120m_enabled = 1; + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)LCD_CORE_CLK_SRC_DEFAULT, true), err, TAG, "core clock source enable failed"); + rgb_panel->flags.core_clk_enabled = 1; #endif PERIPH_RCC_ATOMIC() { lcd_ll_enable_clock(hal->dev, true); @@ -646,7 +647,7 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel) hal_utils_clk_div_t lcd_clk_div = {}; rgb_panel->timings.pclk_hz = lcd_hal_cal_pclk_freq(&rgb_panel->hal, rgb_panel->src_clk_hz, rgb_panel->timings.pclk_hz, &lcd_clk_div); PERIPH_RCC_ATOMIC() { - lcd_ll_set_group_clock_coeff(rgb_panel->hal.dev, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator); + lcd_ll_set_group_clock_coeff(rgb_panel->panel_id, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator); } // pixel clock phase and polarity lcd_ll_set_clock_idle_level(rgb_panel->hal.dev, rgb_panel->timings.flags.pclk_idle_high); @@ -1019,7 +1020,7 @@ static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *rgb_panel, lcd_ TAG, "get clock source frequency failed"); rgb_panel->src_clk_hz = src_clk_hz; PERIPH_RCC_ATOMIC() { - lcd_ll_select_clk_src(rgb_panel->hal.dev, clk_src); + lcd_ll_select_clk_src(rgb_panel->panel_id, clk_src); } // create pm lock based on different clock source @@ -1376,7 +1377,7 @@ IRAM_ATTR static void lcd_rgb_panel_try_update_pclk(esp_rgb_panel_t *rgb_panel) rgb_panel->flags.need_update_pclk = false; rgb_panel->timings.pclk_hz = lcd_hal_cal_pclk_freq(&rgb_panel->hal, rgb_panel->src_clk_hz, rgb_panel->timings.pclk_hz, &lcd_clk_div); PERIPH_RCC_ATOMIC() { - lcd_ll_set_group_clock_coeff(rgb_panel->hal.dev, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator); + lcd_ll_set_group_clock_coeff(rgb_panel->panel_id, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator); } } portEXIT_CRITICAL_ISR(&rgb_panel->spinlock); diff --git a/components/soc/esp32s31/include/soc/clk_tree_defs.h b/components/soc/esp32s31/include/soc/clk_tree_defs.h index 4504a342eef..98929643ad5 100644 --- a/components/soc/esp32s31/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s31/include/soc/clk_tree_defs.h @@ -169,6 +169,16 @@ typedef enum { //////////////////////////////////////////////////LCD/////////////////////////////////////////////////////////////////// +/** + * @brief Type of LCD core clock source + */ +typedef enum { + LCD_CORE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + LCD_CORE_CLK_SRC_PLL120M = SOC_MOD_CLK_PLL_F120M, /*!< Select PLL_F120M as the source clock */ + LCD_CORE_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */ + LCD_CORE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F120M, /*!< Select PLL_F120M as the default choice */ +} soc_periph_lcd_core_clk_src_t; + /** * @brief Array initializer for all supported clock sources of LCD */ @@ -186,6 +196,16 @@ typedef enum { //////////////////////////////////////////////////CAM/////////////////////////////////////////////////////////////////// +/** + * @brief Type of CAM core clock source + */ +typedef enum { + CAM_CORE_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL, /*!< Select XTAL as the source clock */ + CAM_CORE_CLK_SRC_PLL120M = SOC_MOD_CLK_PLL_F120M, /*!< Select PLL_F120M as the source clock */ + CAM_CORE_CLK_SRC_APLL = SOC_MOD_CLK_APLL, /*!< Select APLL as the source clock */ + CAM_CORE_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F120M, /*!< Select PLL_F120M as the default choice */ +} soc_periph_cam_core_clk_src_t; + /** * @brief Array initializer for all supported clock sources of CAM */