Преглед изворни кода

Merge branch 'bugfix/i80_pll240_esp32s3' into 'master'

lcd: support PLL240M as i80 clock source on esp32s3

See merge request espressif/esp-idf!22285
morris пре 2 година
родитељ
комит
18295bb2f5

+ 16 - 16
components/esp_lcd/src/esp_lcd_panel_io_i2s.c

@@ -36,6 +36,7 @@
 #include "hal/dma_types.h"
 #include "hal/gpio_hal.h"
 #include "driver/gpio.h"
+#include "clk_tree.h"
 #include "esp_private/periph_ctrl.h"
 #include "esp_private/i2s_platform.h"
 #include "soc/lcd_periph.h"
@@ -348,7 +349,7 @@ static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t
 {
     lcd_panel_io_i80_t *i80_device = __containerof(io, lcd_panel_io_i80_t, base);
 
-    if(i80_device->on_color_trans_done != NULL) {
+    if (i80_device->on_color_trans_done != NULL) {
         ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!");
     }
 
@@ -605,23 +606,22 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
 
 static esp_err_t i2s_lcd_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t src)
 {
-    esp_err_t ret = ESP_OK;
-    switch (src) {
-    case LCD_CLK_SRC_PLL160M:
-        bus->resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE;
-        i2s_ll_tx_clk_set_src(bus->hal.dev, I2S_CLK_SRC_PLL_160M);
+    // get clock source frequency
+    uint32_t src_clk_hz = 0;
+    ESP_RETURN_ON_ERROR(clk_tree_src_get_freq_hz((soc_module_clk_t)src, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz),
+                        TAG, "get clock source frequency failed");
+
+    i2s_ll_tx_clk_set_src(bus->hal.dev, I2S_CLK_SRC_PLL_160M);
+    i2s_ll_set_raw_mclk_div(bus->hal.dev, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0);
+    // save the resolution of the i80 bus
+    bus->resolution_hz = src_clk_hz / LCD_PERIPH_CLOCK_PRE_SCALE;
+
+    // create pm lock based on different clock source
+    // clock sources like PLL and XTAL will be turned off in light sleep
 #if CONFIG_PM_ENABLE
-        ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i2s_controller_lcd", &bus->pm_lock);
-        ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed");
-        ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock");
+    ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i80_bus_lcd", &bus->pm_lock), TAG, "create pm lock failed");
 #endif
-        break;
-    default:
-        ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", src);
-        break;
-    }
-    i2s_ll_set_raw_mclk_div(bus->hal.dev, LCD_PERIPH_CLOCK_PRE_SCALE, 1, 0);
-    return ret;
+    return ESP_OK;
 }
 
 static esp_err_t i2s_lcd_init_dma_link(esp_lcd_i80_bus_handle_t bus)

+ 15 - 19
components/esp_lcd/src/esp_lcd_panel_io_i80.c

@@ -25,7 +25,7 @@
 #include "esp_lcd_panel_io.h"
 #include "esp_rom_gpio.h"
 #include "soc/soc_caps.h"
-#include "esp_private/esp_clk.h"
+#include "clk_tree.h"
 #include "esp_memory_utils.h"
 #include "hal/dma_types.h"
 #include "hal/gpio_hal.h"
@@ -339,8 +339,8 @@ static esp_err_t panel_io_i80_register_event_callbacks(esp_lcd_panel_io_handle_t
 {
     lcd_panel_io_i80_t *i80_device = __containerof(io, lcd_panel_io_i80_t, base);
 
-    if(i80_device->on_color_trans_done != NULL) {
-        ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was owerwritten!");
+    if (i80_device->on_color_trans_done != NULL) {
+        ESP_LOGW(TAG, "Callback on_color_trans_done was already set and now it was overwritten!");
     }
 
     i80_device->on_color_trans_done = cbs->on_color_trans_done;
@@ -486,27 +486,23 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
 
 static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_clock_source_t clk_src)
 {
-    esp_err_t ret = ESP_OK;
+    // get clock source frequency
+    uint32_t src_clk_hz = 0;
+    ESP_RETURN_ON_ERROR(clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz),
+                        TAG, "get clock source frequency failed");
+
     // force to use integer division, as fractional division might lead to clock jitter
     lcd_ll_select_clk_src(bus->hal.dev, clk_src);
     lcd_ll_set_group_clock_coeff(bus->hal.dev, LCD_PERIPH_CLOCK_PRE_SCALE, 0, 0);
-    switch (clk_src) {
-    case LCD_CLK_SRC_PLL160M:
-        bus->resolution_hz = 160000000 / LCD_PERIPH_CLOCK_PRE_SCALE;
+
+    // save the resolution of the i80 bus
+    bus->resolution_hz = src_clk_hz / LCD_PERIPH_CLOCK_PRE_SCALE;
+    // create pm lock based on different clock source
+    // clock sources like PLL and XTAL will be turned off in light sleep
 #if CONFIG_PM_ENABLE
-        ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "i80_bus_lcd", &bus->pm_lock);
-        ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed");
-        ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock");
+    ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "i80_bus_lcd", &bus->pm_lock), TAG, "create pm lock failed");
 #endif
-        break;
-    case LCD_CLK_SRC_XTAL:
-        bus->resolution_hz = esp_clk_xtal_freq() / LCD_PERIPH_CLOCK_PRE_SCALE;
-        break;
-    default:
-        ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG,  "unsupported clock source: %d", clk_src);
-        break;
-    }
-    return ret;
+    return ESP_OK;
 }
 
 static esp_err_t lcd_i80_init_dma_link(esp_lcd_i80_bus_handle_t bus)

+ 15 - 25
components/esp_lcd/src/esp_lcd_panel_rgb.c

@@ -26,7 +26,7 @@
 #include "esp_lcd_panel_ops.h"
 #include "esp_rom_gpio.h"
 #include "soc/soc_caps.h"
-#include "esp_private/esp_clk.h"
+#include "clk_tree.h"
 #include "hal/dma_types.h"
 #include "hal/gpio_hal.h"
 #include "esp_private/gdma.h"
@@ -114,7 +114,7 @@ struct esp_rgb_panel_t {
     int y_gap;                      // Extra gap in y coordinate, it's used when calculate the flush window
     portMUX_TYPE spinlock;          // to protect panel specific resource from concurrent access (e.g. between task and ISR)
     int lcd_clk_flags;              // LCD clock calculation flags
-    int rotate_mask;                     // panel rotate_mask mask, Or'ed of `panel_rotate_mask_t`
+    int rotate_mask;                // panel rotate_mask mask, Or'ed of `panel_rotate_mask_t`
     struct {
         uint32_t disp_en_level: 1;       // The level which can turn on the screen by `disp_gpio_num`
         uint32_t stream_mode: 1;         // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
@@ -919,33 +919,23 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_
 
 static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src)
 {
-    esp_err_t ret = ESP_OK;
-    switch (clk_src) {
-    case LCD_CLK_SRC_PLL240M:
-        panel->src_clk_hz = 240000000;
-        break;
-    case LCD_CLK_SRC_PLL160M:
-        panel->src_clk_hz = 160000000;
-        break;
-    case LCD_CLK_SRC_XTAL:
-        panel->src_clk_hz = esp_clk_xtal_freq();
-        break;
-    default:
-        ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, TAG, "unsupported clock source: %d", clk_src);
-        break;
-    }
+    // get clock source frequency
+    uint32_t src_clk_hz = 0;
+    ESP_RETURN_ON_ERROR(clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz),
+                        TAG, "get clock source frequency failed");
+    panel->src_clk_hz = src_clk_hz;
     lcd_ll_select_clk_src(panel->hal.dev, clk_src);
 
-    if (clk_src == LCD_CLK_SRC_PLL240M || clk_src == LCD_CLK_SRC_PLL160M) {
+    // create pm lock based on different clock source
+    // clock sources like PLL and XTAL will be turned off in light sleep
 #if CONFIG_PM_ENABLE
-        ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "rgb_panel", &panel->pm_lock);
-        ESP_RETURN_ON_ERROR(ret, TAG, "create ESP_PM_APB_FREQ_MAX lock failed");
-        // hold the lock during the whole lifecycle of RGB panel
-        esp_pm_lock_acquire(panel->pm_lock);
-        ESP_LOGD(TAG, "installed ESP_PM_APB_FREQ_MAX lock and hold the lock during the whole panel lifecycle");
+    ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "rgb_panel", &panel->pm_lock), TAG, "create pm lock failed");
+    // hold the lock during the whole lifecycle of RGB panel
+    esp_pm_lock_acquire(panel->pm_lock);
+    ESP_LOGD(TAG, "installed pm lock and hold the lock during the whole panel lifecycle");
 #endif
-    }
-    return ret;
+
+    return ESP_OK;
 }
 
 static IRAM_ATTR bool lcd_rgb_panel_fill_bounce_buffer(esp_rgb_panel_t *panel, uint8_t *buffer)

+ 4 - 1
components/esp_lcd/test_apps/i2c_lcd/sdkconfig.defaults

@@ -1,2 +1,5 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+# CONFIG_ESP_TASK_WDT_INIT is not set
 CONFIG_FREERTOS_HZ=1000
-CONFIG_ESP_TASK_WDT=n

+ 4 - 1
components/esp_lcd/test_apps/i80_lcd/sdkconfig.defaults

@@ -1,2 +1,5 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+# CONFIG_ESP_TASK_WDT_INIT is not set
 CONFIG_FREERTOS_HZ=1000
-CONFIG_ESP_TASK_WDT=n

+ 4 - 1
components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults

@@ -1,2 +1,5 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+# CONFIG_ESP_TASK_WDT_INIT is not set
 CONFIG_FREERTOS_HZ=1000
-CONFIG_ESP_TASK_WDT=n

+ 4 - 1
components/esp_lcd/test_apps/spi_lcd/sdkconfig.defaults

@@ -1,2 +1,5 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+# CONFIG_ESP_TASK_WDT_INIT is not set
 CONFIG_FREERTOS_HZ=1000
-CONFIG_ESP_TASK_WDT=n

+ 3 - 5
components/soc/esp32/include/soc/clk_tree_defs.h

@@ -165,16 +165,14 @@ typedef enum {
 /**
  * @brief Array initializer for all supported clock sources of LCD
  */
-#define SOC_LCD_CLKS {SOC_MOD_CLK_PLL_D2, SOC_MOD_CLK_APLL, SOC_MOD_CLK_XTAL}
+#define SOC_LCD_CLKS {SOC_MOD_CLK_PLL_F160M}
 
 /**
  * @brief Type of LCD clock source
  */
 typedef enum {
-    LCD_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 (default to 160MHz) as the source clock */
-    LCD_CLK_SRC_APLL = SOC_MOD_CLK_APLL,      /*!< Select APLL as the source clock */
-    LCD_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,      /*!< Select XTAL as the source clock */
-    LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_D2, /*!< Select PLL_D2 (default to 160MHz) as the default choice */
+    LCD_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_160M as the source clock */
+    LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_160M as the default choice */
 } soc_periph_lcd_clk_src_t;
 
 //////////////////////////////////////////////////RMT///////////////////////////////////////////////////////////////////

+ 1 - 3
components/soc/esp32s2/include/soc/clk_tree_defs.h

@@ -165,15 +165,13 @@ typedef enum {
 /**
  * @brief Array initializer for all supported clock sources of LCD
  */
-#define SOC_LCD_CLKS {SOC_MOD_CLK_PLL_F160M, SOC_MOD_CLK_APLL, SOC_MOD_CLK_XTAL}
+#define SOC_LCD_CLKS {SOC_MOD_CLK_PLL_F160M}
 
 /**
  * @brief Type of LCD clock source
  */
 typedef enum {
     LCD_CLK_SRC_PLL160M = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the source clock */
-    LCD_CLK_SRC_APLL = SOC_MOD_CLK_APLL,         /*!< Select APLL as the source clock */
-    LCD_CLK_SRC_XTAL = SOC_MOD_CLK_XTAL,         /*!< Select XTAL as the source clock */
     LCD_CLK_SRC_DEFAULT = SOC_MOD_CLK_PLL_F160M, /*!< Select PLL_F160M as the default choice */
 } soc_periph_lcd_clk_src_t;