mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
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 <cursoragent@cursor.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user