mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-27 20:04:21 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			70 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  */
 | |
| 
 | |
| #include "hal/lcd_hal.h"
 | |
| #include "hal/lcd_ll.h"
 | |
| #include "hal/log.h"
 | |
| 
 | |
| void lcd_hal_init(lcd_hal_context_t *hal, int id)
 | |
| {
 | |
|     hal->dev = LCD_LL_GET_HW(id);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @brief helper function, calculate the Greatest Common Divisor
 | |
|  * @note gcd(a, b) = gcd(b, a % b)
 | |
|  * @param a bigger value
 | |
|  * @param b smaller value
 | |
|  * @return result of gcd(a, b)
 | |
|  */
 | |
| __attribute__((always_inline))
 | |
| static inline uint32_t _gcd(uint32_t a, uint32_t b)
 | |
| {
 | |
|     uint32_t c = a % b;
 | |
|     while (c != 0) {
 | |
|         a = b;
 | |
|         b = c;
 | |
|         c = a % b;
 | |
|     }
 | |
|     return b;
 | |
| }
 | |
| 
 | |
| 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)
 | |
| {
 | |
|     // lcd_clk = module_clock_src / (n + b / a)
 | |
|     // pixel_clk = lcd_clk / mo
 | |
|     uint32_t mo = src_freq_hz / expect_pclk_freq_hz / LCD_LL_CLK_FRAC_DIV_N_MAX + 1;
 | |
|     if (mo == 1 && !(lcd_clk_flags & LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK)) {
 | |
|         mo = 2;
 | |
|     }
 | |
|     uint32_t n = src_freq_hz / expect_pclk_freq_hz / mo;
 | |
|     uint32_t a = 0;
 | |
|     uint32_t b = 0;
 | |
|     // delta_hz / expect_pclk_freq_hz <==> b / a
 | |
|     uint32_t delta_hz = src_freq_hz / mo - expect_pclk_freq_hz * n;
 | |
|     // fractional divider
 | |
|     if (delta_hz) {
 | |
|         uint32_t gcd = _gcd(expect_pclk_freq_hz, delta_hz);
 | |
|         a = expect_pclk_freq_hz / gcd;
 | |
|         b = delta_hz / gcd;
 | |
|         // normalize div_a and div_b
 | |
|         uint32_t d = a / LCD_LL_CLK_FRAC_DIV_AB_MAX + 1;
 | |
|         a /= d;
 | |
|         b /= d;
 | |
|     }
 | |
| 
 | |
|     HAL_EARLY_LOGD("lcd_hal", "n=%d,a=%d,b=%d,mo=%d", n, a, b, mo);
 | |
| 
 | |
|     lcd_ll_set_group_clock_coeff(hal->dev, n, a, b);
 | |
|     lcd_ll_set_pixel_clock_prescale(hal->dev, mo);
 | |
| 
 | |
|     if (delta_hz) {
 | |
|         return ((uint64_t)src_freq_hz * a) / (n * a + b) / mo;
 | |
|     } else {
 | |
|         return src_freq_hz / n / mo;
 | |
|     }
 | |
| }
 | 
