mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 00:21:44 +01:00 
			
		
		
		
	refactor(hal): use hal utils to calculate clock division
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
@@ -7,31 +7,13 @@
 | 
			
		||||
#include "hal/lcd_hal.h"
 | 
			
		||||
#include "hal/lcd_ll.h"
 | 
			
		||||
#include "hal/log.h"
 | 
			
		||||
#include "hal/hal_utils.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)
 | 
			
		||||
@@ -40,30 +22,19 @@ uint32_t lcd_hal_cal_pclk_freq(lcd_hal_context_t *hal, uint32_t src_freq_hz, uin
 | 
			
		||||
    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_utils_clk_info_t lcd_clk_info = {
 | 
			
		||||
        .src_freq_hz = src_freq_hz,
 | 
			
		||||
        .exp_freq_hz = expect_pclk_freq_hz * mo,
 | 
			
		||||
        .max_integ = LCD_LL_CLK_FRAC_DIV_N_MAX,
 | 
			
		||||
        .min_integ = 2,
 | 
			
		||||
        .max_fract = LCD_LL_CLK_FRAC_DIV_AB_MAX,
 | 
			
		||||
    };
 | 
			
		||||
    hal_utils_clk_div_t lcd_clk_div = {};
 | 
			
		||||
    uint32_t real_freq = hal_utils_calc_clk_div_frac_fast(&lcd_clk_info, &lcd_clk_div);
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    HAL_EARLY_LOGD("lcd_hal", "n=%"PRIu32",a=%"PRIu32",b=%"PRIu32",mo=%"PRIu32"", n, a, b, mo);
 | 
			
		||||
 | 
			
		||||
    lcd_ll_set_group_clock_coeff(hal->dev, n, a, b);
 | 
			
		||||
    lcd_ll_set_group_clock_coeff(hal->dev, lcd_clk_div.integer, lcd_clk_div.denominator, lcd_clk_div.numerator);
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
    return real_freq / mo;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user