From 9c262ce065b4d0e1301cdbe6a79eacb771b381c8 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 21 Dec 2021 17:38:56 +0800 Subject: [PATCH 1/2] lcd: split gpio check for de and hv mode --- .../esp_lcd/include/esp_lcd_panel_rgb.h | 4 +-- components/esp_lcd/src/esp_lcd_rgb_panel.c | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/components/esp_lcd/include/esp_lcd_panel_rgb.h b/components/esp_lcd/include/esp_lcd_panel_rgb.h index 0c264545ee..f274625a31 100644 --- a/components/esp_lcd/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/include/esp_lcd_panel_rgb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,7 +64,7 @@ typedef struct { unsigned int hsync_idle_low: 1; /*!< The hsync signal is low in IDLE state */ unsigned int vsync_idle_low: 1; /*!< The vsync signal is low in IDLE state */ unsigned int de_idle_high: 1; /*!< The de signal is high in IDLE state */ - unsigned int pclk_active_neg: 1; /*!< The display will write data lines when there's a falling edge on PCLK */ + unsigned int pclk_active_neg: 1; /*!< Whether the display data is clocked out at the falling edge of PCLK */ unsigned int pclk_idle_high: 1; /*!< The PCLK stays at high level in IDLE phase */ } flags; } esp_lcd_rgb_timing_t; diff --git a/components/esp_lcd/src/esp_lcd_rgb_panel.c b/components/esp_lcd/src/esp_lcd_rgb_panel.c index c6f6356408..0d56370b7e 100644 --- a/components/esp_lcd/src/esp_lcd_rgb_panel.c +++ b/components/esp_lcd/src/esp_lcd_rgb_panel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -379,8 +379,11 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_ { int panel_id = panel->panel_id; // check validation of GPIO number - bool valid_gpio = (panel_config->hsync_gpio_num >= 0) && (panel_config->vsync_gpio_num >= 0) && - (panel_config->pclk_gpio_num >= 0); + bool valid_gpio = (panel_config->pclk_gpio_num >= 0); + if (panel_config->de_gpio_num < 0) { + // Hsync and Vsync are required in HV mode + valid_gpio = valid_gpio && (panel_config->hsync_gpio_num >= 0) && (panel_config->vsync_gpio_num >= 0); + } for (size_t i = 0; i < panel_config->data_width; i++) { valid_gpio = valid_gpio && (panel_config->data_gpio_nums[i] >= 0); } @@ -394,14 +397,18 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_ esp_rom_gpio_connect_out_signal(panel_config->data_gpio_nums[i], lcd_periph_signals.panels[panel_id].data_sigs[i], false, false); } - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->hsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->hsync_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(panel_config->hsync_gpio_num, - lcd_periph_signals.panels[panel_id].hsync_sig, false, false); - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->vsync_gpio_num], PIN_FUNC_GPIO); - gpio_set_direction(panel_config->vsync_gpio_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(panel_config->vsync_gpio_num, - lcd_periph_signals.panels[panel_id].vsync_sig, false, false); + if (panel_config->hsync_gpio_num >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->hsync_gpio_num], PIN_FUNC_GPIO); + gpio_set_direction(panel_config->hsync_gpio_num, GPIO_MODE_OUTPUT); + esp_rom_gpio_connect_out_signal(panel_config->hsync_gpio_num, + lcd_periph_signals.panels[panel_id].hsync_sig, false, false); + } + if (panel_config->vsync_gpio_num >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->vsync_gpio_num], PIN_FUNC_GPIO); + gpio_set_direction(panel_config->vsync_gpio_num, GPIO_MODE_OUTPUT); + esp_rom_gpio_connect_out_signal(panel_config->vsync_gpio_num, + lcd_periph_signals.panels[panel_id].vsync_sig, false, false); + } gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[panel_config->pclk_gpio_num], PIN_FUNC_GPIO); gpio_set_direction(panel_config->pclk_gpio_num, GPIO_MODE_OUTPUT); esp_rom_gpio_connect_out_signal(panel_config->pclk_gpio_num, From f6ab70339094f22aad500dfae2eca919de5df854 Mon Sep 17 00:00:00 2001 From: morris Date: Tue, 28 Dec 2021 10:36:03 +0800 Subject: [PATCH 2/2] lcd: alloc framebuffer in alignment --- components/esp_lcd/include/esp_lcd_panel_rgb.h | 2 ++ components/esp_lcd/src/esp_lcd_rgb_panel.c | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/components/esp_lcd/include/esp_lcd_panel_rgb.h b/components/esp_lcd/include/esp_lcd_panel_rgb.h index f274625a31..6f06deb816 100644 --- a/components/esp_lcd/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/include/esp_lcd_panel_rgb.h @@ -92,6 +92,8 @@ typedef struct { lcd_clock_source_t clk_src; /*!< Clock source for the RGB LCD peripheral */ esp_lcd_rgb_timing_t timings; /*!< RGB timing parameters */ size_t data_width; /*!< Number of data lines */ + size_t sram_trans_align; /*!< Alignment for framebuffer that allocated in SRAM */ + size_t psram_trans_align; /*!< Alignment for framebuffer that allocated in PSRAM */ int hsync_gpio_num; /*!< GPIO used for HSYNC signal */ int vsync_gpio_num; /*!< GPIO used for VSYNC signal */ int de_gpio_num; /*!< GPIO used for DE signal, set to -1 if it's not used */ diff --git a/components/esp_lcd/src/esp_lcd_rgb_panel.c b/components/esp_lcd/src/esp_lcd_rgb_panel.c index 0d56370b7e..60299aeb6a 100644 --- a/components/esp_lcd/src/esp_lcd_rgb_panel.c +++ b/components/esp_lcd/src/esp_lcd_rgb_panel.c @@ -65,6 +65,8 @@ struct esp_rgb_panel_t { int panel_id; // LCD panel ID lcd_hal_context_t hal; // Hal layer object size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16) + size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM + size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off" intr_handle_t intr; // LCD peripheral interrupt handle esp_pm_lock_handle_t pm_lock; // Power management lock @@ -125,12 +127,17 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf } #endif } + size_t psram_trans_align = rgb_panel_config->psram_trans_align ? rgb_panel_config->psram_trans_align : 64; + size_t sram_trans_align = rgb_panel_config->sram_trans_align ? rgb_panel_config->sram_trans_align : 4; if (alloc_from_psram) { - rgb_panel->fb = heap_caps_calloc(1, fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + // the low level malloc function will help check the validation of alignment + rgb_panel->fb = heap_caps_aligned_calloc(psram_trans_align, 1, fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { - rgb_panel->fb = heap_caps_calloc(1, fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); + rgb_panel->fb = heap_caps_aligned_calloc(sram_trans_align, 1, fb_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); } ESP_GOTO_ON_FALSE(rgb_panel->fb, ESP_ERR_NO_MEM, err, TAG, "no mem for frame buffer"); + rgb_panel->psram_trans_align = psram_trans_align; + rgb_panel->sram_trans_align = sram_trans_align; rgb_panel->fb_size = fb_size; rgb_panel->flags.fb_in_psram = alloc_from_psram; // semaphore indicates new frame trans done @@ -478,8 +485,8 @@ static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel) ESP_GOTO_ON_ERROR(ret, err, TAG, "alloc DMA channel failed"); gdma_connect(panel->dma_chan, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0)); gdma_transfer_ability_t ability = { - .psram_trans_align = 64, - .sram_trans_align = 4, + .psram_trans_align = panel->psram_trans_align, + .sram_trans_align = panel->sram_trans_align, }; gdma_set_transfer_ability(panel->dma_chan, &ability); // the start of DMA should be prior to the start of LCD engine