Skip to content

Commit a7781f3

Browse files
committed
Merge branch 'feat/rgb_lcd_increase_pclk_v5.3' into 'release/v5.3'
feat(lcd): increase the upper limit of pclk frequency for RGB LCD (v5.3) See merge request espressif/esp-idf!35929
2 parents 73a155f + 4d5d5de commit a7781f3

File tree

5 files changed

+25
-31
lines changed

5 files changed

+25
-31
lines changed

components/esp_lcd/rgb/esp_lcd_panel_rgb.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ struct esp_rgb_panel_t {
134134
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
135135
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
136136
portMUX_TYPE spinlock; // to protect panel specific resource from concurrent access (e.g. between task and ISR)
137-
int lcd_clk_flags; // LCD clock calculation flags
138137
int rotate_mask; // panel rotate_mask mask, Or'ed of `panel_rotate_mask_t`
139138
struct {
140139
uint32_t disp_en_level: 1; // The level which can turn on the screen by `disp_gpio_num`
@@ -330,11 +329,6 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
330329
// reset peripheral and FIFO after we select a correct clock source
331330
lcd_ll_fifo_reset(rgb_panel->hal.dev);
332331
lcd_ll_reset(rgb_panel->hal.dev);
333-
// set minimal PCLK divider
334-
// A limitation in the hardware, if the LCD_PCLK == LCD_CLK, then the PCLK polarity can't be adjustable
335-
if (!(rgb_panel_config->timings.flags.pclk_active_neg || rgb_panel_config->timings.flags.pclk_idle_high)) {
336-
rgb_panel->lcd_clk_flags |= LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK;
337-
}
338332
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
339333
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
340334
ret = esp_intr_alloc_intrstatus(lcd_periph_rgb_signals.panels[panel_id].irq_id, isr_flags,
@@ -543,7 +537,7 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel)
543537
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
544538
// set pixel clock frequency
545539
hal_utils_clk_div_t lcd_clk_div = {};
546-
rgb_panel->timings.pclk_hz = lcd_hal_cal_pclk_freq(&rgb_panel->hal, rgb_panel->src_clk_hz, rgb_panel->timings.pclk_hz, rgb_panel->lcd_clk_flags, &lcd_clk_div);
540+
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);
547541
LCD_CLOCK_SRC_ATOMIC() {
548542
lcd_ll_set_group_clock_coeff(rgb_panel->hal.dev, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator);
549543
}
@@ -1183,7 +1177,7 @@ IRAM_ATTR static void lcd_rgb_panel_try_update_pclk(esp_rgb_panel_t *rgb_panel)
11831177
portENTER_CRITICAL_ISR(&rgb_panel->spinlock);
11841178
if (unlikely(rgb_panel->flags.need_update_pclk)) {
11851179
rgb_panel->flags.need_update_pclk = false;
1186-
rgb_panel->timings.pclk_hz = lcd_hal_cal_pclk_freq(&rgb_panel->hal, rgb_panel->src_clk_hz, rgb_panel->timings.pclk_hz, rgb_panel->lcd_clk_flags, &lcd_clk_div);
1180+
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);
11871181
LCD_CLOCK_SRC_ATOMIC() {
11881182
lcd_ll_set_group_clock_coeff(rgb_panel->hal.dev, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator);
11891183
}

components/hal/esp32p4/include/hal/lcd_ll.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,8 @@ __attribute__((always_inline))
130130
static inline void lcd_ll_set_group_clock_coeff(lcd_cam_dev_t *dev, int div_num, int div_a, int div_b)
131131
{
132132
// lcd_clk = module_clock_src / (div_num + div_b / div_a)
133-
HAL_ASSERT(div_num >= 2 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX);
134-
// dic_num == 0 means LCD_LL_CLK_FRAC_DIV_N_MAX divider in hardware
135-
if (div_num >= LCD_LL_CLK_FRAC_DIV_N_MAX) {
136-
div_num = 0;
137-
}
138-
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl110, reg_lcd_clk_div_num, div_num);
133+
HAL_ASSERT(div_num > 0 && div_num <= LCD_LL_CLK_FRAC_DIV_N_MAX);
134+
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl110, reg_lcd_clk_div_num, div_num - 1);
139135
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl110, reg_lcd_clk_div_denominator, div_a);
140136
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl110, reg_lcd_clk_div_numerator, div_b);
141137
}
@@ -177,7 +173,7 @@ static inline void lcd_ll_set_pixel_clock_edge(lcd_cam_dev_t *dev, bool active_o
177173
__attribute__((always_inline))
178174
static inline void lcd_ll_set_pixel_clock_prescale(lcd_cam_dev_t *dev, uint32_t prescale)
179175
{
180-
HAL_ASSERT(prescale <= LCD_LL_PCLK_DIV_MAX);
176+
HAL_ASSERT(prescale > 0 && prescale <= LCD_LL_PCLK_DIV_MAX);
181177
// Formula: pixel_clk = lcd_clk / (1 + clkcnt_n)
182178
// clkcnt_n can't be zero
183179
uint32_t scale = 1;

components/hal/esp32s3/include/hal/lcd_ll.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static inline void lcd_ll_set_pixel_clock_edge(lcd_cam_dev_t *dev, bool active_o
161161
__attribute__((always_inline))
162162
static inline void lcd_ll_set_pixel_clock_prescale(lcd_cam_dev_t *dev, uint32_t prescale)
163163
{
164-
HAL_ASSERT(prescale <= LCD_LL_PCLK_DIV_MAX);
164+
HAL_ASSERT(prescale > 0 && prescale <= LCD_LL_PCLK_DIV_MAX);
165165
// Formula: pixel_clk = lcd_clk / (1 + clkcnt_n)
166166
// clkcnt_n can't be zero
167167
uint32_t scale = 1;
@@ -571,7 +571,7 @@ static inline void lcd_ll_set_command(lcd_cam_dev_t *dev, uint32_t data_width, u
571571
}
572572

573573
/**
574-
* @brief Wether to enable RGB interface
574+
* @brief Whether to enable RGB interface
575575
*
576576
* @param dev LCD register base address
577577
* @param en True to enable RGB interface, False to disable RGB interface
@@ -594,7 +594,7 @@ static inline void lcd_ll_enable_auto_next_frame(lcd_cam_dev_t *dev, bool en)
594594
}
595595

596596
/**
597-
* @brief Wether to output HSYNC signal in porch resion
597+
* @brief Whether to output HSYNC signal in porch resion
598598
*
599599
* @param dev LCD register base address
600600
* @param en True to enable, False to disable
@@ -726,7 +726,7 @@ static inline uint32_t lcd_ll_get_interrupt_status(lcd_cam_dev_t *dev)
726726
* @brief Clear interrupt status by mask
727727
*
728728
* @param dev LCD register base address
729-
* @param mask Interupt status mask
729+
* @param mask Interrupt status mask
730730
*/
731731
__attribute__((always_inline))
732732
static inline void lcd_ll_clear_interrupt_status(lcd_cam_dev_t *dev, uint32_t mask)

components/hal/include/hal/lcd_hal.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -34,20 +34,17 @@ typedef struct {
3434
*/
3535
void lcd_hal_init(lcd_hal_context_t *hal, int id);
3636

37-
#define LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK (1 << 0)
38-
3937
/**
4038
* @brief LCD PCLK clock calculation
4139
* @note Currently this function is only used by RGB LCD driver, I80 driver still uses a fixed clock division
4240
*
4341
* @param hal LCD HAL layer context
4442
* @param src_freq_hz LCD source clock frequency in Hz
4543
* @param expect_pclk_freq_hz Expected LCD PCLK frequency in Hz
46-
* @param lcd_clk_flags Extra flags to control LCD PCLK clock calculation, supported flags are prefixed with LCD_HAL_PCLK_FLAG_
4744
* @param lcd_clk_div Returned LCD clock divider parameter
4845
* @return Actual LCD PCLK frequency in Hz
4946
*/
50-
uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uint32_t expect_pclk_freq_hz, int lcd_clk_flags, hal_utils_clk_div_t* lcd_clk_div);
47+
uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uint32_t expect_pclk_freq_hz, hal_utils_clk_div_t* lcd_clk_div);
5148

5249
#ifdef __cplusplus
5350
}

components/hal/lcd_hal.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -13,14 +13,14 @@ void lcd_hal_init(lcd_hal_context_t *hal, int id)
1313
hal->dev = LCD_LL_GET_HW(id);
1414
}
1515

16-
uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uint32_t expect_pclk_freq_hz, int lcd_clk_flags, hal_utils_clk_div_t* lcd_clk_div)
16+
uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uint32_t expect_pclk_freq_hz, hal_utils_clk_div_t* lcd_clk_div)
1717
{
18+
// formula:
1819
// lcd_clk = module_clock_src / (n + b / a)
1920
// pixel_clk = lcd_clk / mo
20-
uint32_t mo = src_freq_hz / expect_pclk_freq_hz / LCD_LL_CLK_FRAC_DIV_N_MAX + 1;
21-
if (mo == 1 && !(lcd_clk_flags & LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK)) {
22-
mo = 2;
23-
}
21+
22+
// due to some unstable hardware issue, we prefer to start with mo=2 first
23+
uint32_t mo = 2;
2424
hal_utils_clk_info_t lcd_clk_info = {
2525
.src_freq_hz = src_freq_hz,
2626
.exp_freq_hz = expect_pclk_freq_hz * mo,
@@ -29,8 +29,15 @@ uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uin
2929
.max_fract = LCD_LL_CLK_FRAC_DIV_AB_MAX,
3030
};
3131
uint32_t real_freq = hal_utils_calc_clk_div_frac_fast(&lcd_clk_info, lcd_clk_div);
32-
HAL_EARLY_LOGD("lcd_hal", "n=%"PRIu32",a=%"PRIu32",b=%"PRIu32",mo=%"PRIu32, lcd_clk_div->integer, lcd_clk_div->denominator, lcd_clk_div->numerator, mo);
3332

33+
if (!real_freq) {
34+
// if mo=2 can't achieve the target frequency, try others
35+
mo = src_freq_hz / expect_pclk_freq_hz / LCD_LL_CLK_FRAC_DIV_N_MAX + 1;
36+
lcd_clk_info.exp_freq_hz = expect_pclk_freq_hz * mo;
37+
real_freq = hal_utils_calc_clk_div_frac_fast(&lcd_clk_info, lcd_clk_div);
38+
}
39+
40+
HAL_EARLY_LOGD("lcd_hal", "n=%"PRIu32",a=%"PRIu32",b=%"PRIu32",mo=%"PRIu32, lcd_clk_div->integer, lcd_clk_div->denominator, lcd_clk_div->numerator, mo);
3441
lcd_ll_set_pixel_clock_prescale(hal->dev, mo);
3542
return real_freq / mo;
3643
}

0 commit comments

Comments
 (0)