From ef6b7b742f7150dba29dd7c52691b25249bffc78 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 27 Jul 2026 18:40:04 +0800 Subject: [PATCH] refactor(lcdcam): move shared core clock setup to drivers Configure the shared LCDCAM core clock through guarded LCD and CAM LL APIs, and unify LCD functional clock LL calls around group IDs across supported targets. Co-authored-by: Cursor --- .../dvp/src/esp_cam_ctlr_dvp_cam.c | 9 ++- .../esp_hal_cam/esp32s31/include/hal/cam_ll.h | 62 ++++++++++++++-- .../esp32s31/include/hal/clk_gate_ll.h | 8 --- .../esp_hal_lcd/esp32p4/include/hal/lcd_ll.h | 10 +-- .../esp_hal_lcd/esp32s3/include/hal/lcd_ll.h | 10 +-- .../esp_hal_lcd/esp32s31/include/hal/lcd_ll.h | 70 ++++++++++++++++--- components/esp_lcd/i80/esp_lcd_panel_io_i80.c | 21 +++--- components/esp_lcd/rgb/esp_lcd_panel_rgb.c | 25 +++---- .../soc/esp32s31/include/soc/clk_tree_defs.h | 20 ++++++ 9 files changed, 183 insertions(+), 52 deletions(-) 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 2b2bcd5735e..cb65826f4c2 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 @@ -348,14 +348,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 } } @@ -471,7 +474,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 2bb647532f4..e395a509481 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 c37fa64fa20..a2fd9f5b4c4 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 @@ -149,14 +149,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 17b55930846..cc9fb2a0047 100644 --- a/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32p4/include/hal/lcd_ll.h @@ -125,11 +125,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; @@ -157,14 +158,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 e687e1619d6..68282d3adb6 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 8ce33c63b45..013163ebe22 100644 --- a/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h +++ b/components/esp_hal_lcd/esp32s31/include/hal/lcd_ll.h @@ -69,7 +69,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 @@ -82,7 +82,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) /** @@ -106,6 +106,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 * @@ -121,12 +175,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; @@ -147,15 +201,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 a368e3a525f..2912956581d 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -124,7 +124,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 @@ -159,6 +159,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 @@ -185,9 +189,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); @@ -273,8 +276,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 @@ -301,7 +304,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 = soc_i80_lcd_retention_info[bus_id].retention_module; @@ -655,9 +658,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 e2aba452077..dc0d7ca7b84 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -173,9 +173,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; // hook fields esp_lcd_panel_draw_bitmap_hook_t draw_bitmap_hook; // Draw bitmap hook function @@ -254,9 +252,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) { @@ -406,6 +404,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 } } @@ -414,9 +416,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); @@ -650,7 +651,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); @@ -1129,7 +1130,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 @@ -1491,7 +1492,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 6c5119db2fc..1a34e82a93e 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 */