2021-09-27 03:32:29 +00:00
|
|
|
/*
|
2022-05-30 08:09:40 +00:00
|
|
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
2021-09-27 03:32:29 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2021-02-26 05:58:04 +00:00
|
|
|
|
|
|
|
#include "hal/lcd_hal.h"
|
|
|
|
#include "hal/lcd_ll.h"
|
2022-05-30 08:09:40 +00:00
|
|
|
#include "hal/log.h"
|
2021-02-26 05:58:04 +00:00
|
|
|
|
|
|
|
void lcd_hal_init(lcd_hal_context_t *hal, int id)
|
|
|
|
{
|
|
|
|
hal->dev = LCD_LL_GET_HW(id);
|
|
|
|
}
|
2022-05-30 08:09:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
*/
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
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 - expect_pclk_freq_hz * mo * 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_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;
|
|
|
|
}
|
|
|
|
}
|