mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'refactor/lcd_cam_core_clock_init_v6.1' into 'release/v6.1'
refactor(lcdcam): move shared core clock setup to drivers (v6.1) See merge request espressif/esp-idf!52452
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