From 741d35d528781d8ee1df7f053275fbcb98278be0 Mon Sep 17 00:00:00 2001 From: morris Date: Sat, 6 Aug 2022 12:44:52 +0800 Subject: [PATCH] rgb_lcd: added yuv converter LL driver --- components/hal/esp32s3/include/hal/lcd_ll.h | 91 +++++++++++++++++++ components/hal/include/hal/lcd_types.h | 33 +++++++ components/soc/esp32s3/include/soc/soc_caps.h | 1 + 3 files changed, 125 insertions(+) diff --git a/components/hal/esp32s3/include/hal/lcd_ll.h b/components/hal/esp32s3/include/hal/lcd_ll.h index 98fc0a2fe2..fc5d5a6baa 100644 --- a/components/hal/esp32s3/include/hal/lcd_ll.h +++ b/components/hal/esp32s3/include/hal/lcd_ll.h @@ -5,6 +5,7 @@ */ #pragma once +#include /* For NULL declaration */ #include #include #include "hal/misc.h" @@ -27,6 +28,10 @@ extern "C" { #define LCD_LL_CLK_FRAC_DIV_AB_MAX 64 // LCD_CLK = LCD_CLK_S / (N + b/a), the a/b register is 6 bit-width #define LCD_LL_PCLK_DIV_MAX 64 // LCD_PCLK = LCD_CLK / MO, the MO register is 6 bit-width +#define LCD_LL_COLOR_RANGE_TO_REG(range) (uint8_t[]){0,1}[(range)] +#define LCD_LL_CONV_STD_TO_REG(std) (uint8_t[]){0,1}[(std)] +#define LCD_LL_YUV_SAMPLE_TO_REG(sample) (uint8_t[]){0,1,2}[(sample)] + static inline void lcd_ll_enable_clock(lcd_cam_dev_t *dev, bool en) { dev->lcd_clock.clk_en = en; @@ -119,6 +124,92 @@ static inline void lcd_ll_enable_rgb_yuv_convert(lcd_cam_dev_t *dev, bool en) dev->lcd_rgb_yuv.lcd_conv_bypass = en; } +/** + * @brief Set convert data line width + * + * @param dev LCD register base address + * @param width data line width (8 or 16) + */ +static inline void lcd_ll_set_convert_data_width(lcd_cam_dev_t *dev, uint32_t width) +{ + HAL_ASSERT(width == 8 || width == 16); + dev->lcd_rgb_yuv.lcd_conv_mode_8bits_on = (width == 8) ? 1 : 0; +} + +/** + * @brief Set the color range of input data + * + * @param dev LCD register base address + * @param range Color range + */ +static inline void lcd_ll_set_input_color_range(lcd_cam_dev_t *dev, lcd_color_range_t range) +{ + dev->lcd_rgb_yuv.lcd_conv_data_in_mode = LCD_LL_COLOR_RANGE_TO_REG(range); +} + +/** + * @brief Set the color range of output data + * + * @param dev LCD register base address + * @param range Color range + */ +static inline void lcd_ll_set_output_color_range(lcd_cam_dev_t *dev, lcd_color_range_t range) +{ + dev->lcd_rgb_yuv.lcd_conv_data_out_mode = LCD_LL_COLOR_RANGE_TO_REG(range); +} + +/** + * @brief Set YUV conversion standard + * + * @param dev LCD register base address + * @param std YUV conversion standard + */ +static inline void lcd_ll_set_yuv_convert_std(lcd_cam_dev_t *dev, lcd_yuv_conv_std_t std) +{ + dev->lcd_rgb_yuv.lcd_conv_protocol_mode = LCD_LL_CONV_STD_TO_REG(std); +} + +/** + * @brief Set the converter mode: RGB565 to YUV + * + * @param dev LCD register base address + * @param yuv_sample YUV sample mode + */ +static inline void lcd_ll_set_convert_mode_rgb_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample) +{ + dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1; + dev->lcd_rgb_yuv.lcd_conv_yuv_mode = LCD_LL_YUV_SAMPLE_TO_REG(yuv_sample); + dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3; +} + +/** + * @brief Set the converter mode: YUV to RGB565 + * + * @param dev LCD register base address + * @param yuv_sample YUV sample mode + */ +static inline void lcd_ll_set_convert_mode_yuv_to_rgb(lcd_cam_dev_t *dev, lcd_yuv_sample_t yuv_sample) +{ + dev->lcd_rgb_yuv.lcd_conv_trans_mode = 0; + dev->lcd_rgb_yuv.lcd_conv_yuv_mode = LCD_LL_YUV_SAMPLE_TO_REG(yuv_sample); + dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = 3; +} + +/** + * @brief Set the converter mode: YUV to YUV + * + * @param dev LCD register base address + * @param src_sample Source YUV sample mode + * @param dst_sample Destination YUV sample mode + */ +static inline void lcd_ll_set_convert_mode_yuv_to_yuv(lcd_cam_dev_t *dev, lcd_yuv_sample_t src_sample, lcd_yuv_sample_t dst_sample) +{ + HAL_ASSERT(src_sample != dst_sample); + dev->lcd_rgb_yuv.lcd_conv_trans_mode = 1; + dev->lcd_rgb_yuv.lcd_conv_yuv_mode = LCD_LL_YUV_SAMPLE_TO_REG(src_sample); + dev->lcd_rgb_yuv.lcd_conv_yuv2yuv_mode = LCD_LL_YUV_SAMPLE_TO_REG(dst_sample); +} + __attribute__((always_inline)) static inline void lcd_ll_set_phase_cycles(lcd_cam_dev_t *dev, uint32_t cmd_cycles, uint32_t dummy_cycles, uint32_t data_cycles) { diff --git a/components/hal/include/hal/lcd_types.h b/components/hal/include/hal/lcd_types.h index 13810a79ac..af11ef64a8 100644 --- a/components/hal/include/hal/lcd_types.h +++ b/components/hal/include/hal/lcd_types.h @@ -34,6 +34,39 @@ typedef enum { LCD_CLK_SRC_XTAL, /*!< Select XTAL as the source clock */ } lcd_clock_source_t; +/** + * @brief LCD color space + */ +typedef enum { + LCD_COLOR_SPACE_RGB, /*!< Color space: RGB */ + LCD_COLOR_SPACE_YUV, /*!< Color space: YUV */ +} lcd_color_space_t; + +/** + * @brief LCD color range + */ +typedef enum { + LCD_COLOR_RANGE_LIMIT, /*!< Limited color range */ + LCD_COLOR_RANGE_FULL, /*!< Full color range */ +} lcd_color_range_t; + +/** + * @brief YUV sampling method + */ +typedef enum { + LCD_YUV_SAMPLE_422, /*!< YUV 4:2:2 sampling */ + LCD_YUV_SAMPLE_420, /*!< YUV 4:2:0 sampling */ + LCD_YUV_SAMPLE_411, /*!< YUV 4:1:1 sampling */ +} lcd_yuv_sample_t; + +/** + * @brief The standard used for conversion between RGB and YUV + */ +typedef enum { + LCD_YUV_CONV_STD_BT601, /*!< YUV<->RGB conversion standard: BT.601 */ + LCD_YUV_CONV_STD_BT709, /*!< YUV<->RGB conversion standard: BT.709 */ +} lcd_yuv_conv_std_t; + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 75d4b6f677..9028c37ac6 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -181,6 +181,7 @@ #define SOC_LCD_RGB_PANELS (1) /*!< Support one RGB LCD panel */ #define SOC_LCD_I80_BUS_WIDTH (16) /*!< Intel 8080 bus width */ #define SOC_LCD_RGB_DATA_WIDTH (16) /*!< Number of LCD data lines */ +#define SOC_LCD_SUPPORT_RGB_YUV_CONV (1) /*!< Support color format conversion between RGB and YUV */ /*-------------------------- RTC CAPS --------------------------------------*/ #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128)