Browse Source

drivers: display: extend support for renesas,ra-glcdc driver

Change pinctrl-0 dts prop as optional in case DSI display is used
Add these APIs support: set_brightness, set_contrast, get_framebuffer
Add a new config to select frame buffer section

Signed-off-by: Danh Doan <danh.doan.ue@bp.renesas.com>
pull/87481/head
Danh Doan 7 months ago committed by Benjamin Cabé
parent
commit
0eef4fe150
  1. 14
      boards/renesas/ek_ra8d1/Kconfig.defconfig
  2. 10
      drivers/display/Kconfig.renesas_ra
  3. 416
      drivers/display/display_renesas_ra.c
  4. 126
      drivers/display/display_renesas_ra.h
  5. 90
      dts/bindings/display/renesas,ra-glcdc.yaml

14
boards/renesas/ek_ra8d1/Kconfig.defconfig

@ -1,4 +1,4 @@
# Copyright (c) 2024 Renesas Electronics Corporation # Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
if BOARD_EK_RA8D1 if BOARD_EK_RA8D1
@ -10,11 +10,21 @@ config NET_L2_ETHERNET
endif # NETWORKING endif # NETWORKING
if DISPLAY
if SHIELD_RTKMIPILCDB00000BE if SHIELD_RTKMIPILCDB00000BE
config MEMC config MEMC
default y default y
config RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION
default ".sdram"
depends on RENESAS_RA_GLCDC
endif # SHIELD_RTKMIPILCDB00000BE
endif # DISPLAY
if LVGL if LVGL
config LV_Z_VDB_CUSTOM_SECTION config LV_Z_VDB_CUSTOM_SECTION
@ -22,6 +32,4 @@ config LV_Z_VDB_CUSTOM_SECTION
endif # LVGL endif # LVGL
endif # SHIELD_RTKMIPILCDB00000BE
endif # BOARD_EK_RA8D1 endif # BOARD_EK_RA8D1

10
drivers/display/Kconfig.renesas_ra

@ -1,6 +1,6 @@
# Renesas RA Family # Renesas RA Family
# Copyright (c) 2024 Renesas Electronics Corporation # Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
config RENESAS_RA_GLCDC config RENESAS_RA_GLCDC
@ -23,6 +23,14 @@ config RENESAS_RA_GLCDC_FB_NUM
- 1 single frame buffer in RENESAS RA GLCDC driver. - 1 single frame buffer in RENESAS RA GLCDC driver.
- 2 double frame buffer in RENESAS RA GLCDC driver. - 2 double frame buffer in RENESAS RA GLCDC driver.
config RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION
string "RAM memory section to place frame buffer"
depends on RENESAS_RA_GLCDC_FB_NUM > 0
help
RAM memory section name to place frame buffer.
Example: to place display frame buffer in external SDRAM (.sdram section)
CONFIG_RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION=".sdram"
if LVGL if LVGL
# Force display buffers to be aligned to cache line size (64 bytes) # Force display buffers to be aligned to cache line size (64 bytes)

416
drivers/display/display_renesas_ra.c

@ -17,7 +17,6 @@
LOG_MODULE_REGISTER(display_renesas_ra, CONFIG_DISPLAY_LOG_LEVEL); LOG_MODULE_REGISTER(display_renesas_ra, CONFIG_DISPLAY_LOG_LEVEL);
void glcdc_line_detect_isr(void);
struct display_ra_config { struct display_ra_config {
const struct pinctrl_dev_config *pincfg; const struct pinctrl_dev_config *pincfg;
const struct gpio_dt_spec backlight_gpio; const struct gpio_dt_spec backlight_gpio;
@ -25,31 +24,40 @@ struct display_ra_config {
struct clock_control_ra_subsys_cfg clock_glcdc_subsys; struct clock_control_ra_subsys_cfg clock_glcdc_subsys;
uint16_t height; uint16_t height;
uint16_t width; uint16_t width;
uint32_t display_frame_size;
enum display_pixel_format pixel_format;
void (*irq_configure)(void); void (*irq_configure)(void);
}; };
struct display_ra_data { struct display_ra_data {
glcdc_instance_ctrl_t display_ctrl; glcdc_instance_ctrl_t display_ctrl;
display_cfg_t display_fsp_cfg; display_cfg_t display_fsp_cfg;
uint8_t *p_base;
uint32_t frame_buffer_len;
const uint8_t *pend_buf; const uint8_t *pend_buf;
const uint8_t *front_buf; const uint8_t *front_buf;
uint8_t pixel_size; uint8_t pixel_size;
enum display_pixel_format current_pixel_format;
uint8_t *frame_buffer; uint8_t *frame_buffer;
struct k_sem sem; uint32_t frame_buffer_len;
struct k_sem frame_buf_sem;
}; };
extern void glcdc_line_detect_isr(void);
static void renesas_ra_glcdc_isr(const struct device *dev) static void renesas_ra_glcdc_isr(const struct device *dev)
{ {
ARG_UNUSED(dev);
glcdc_line_detect_isr();
}
static void renesas_ra_callback_adapter(display_callback_args_t *p_args)
{
const struct device *dev = p_args->p_context;
struct display_ra_data *data = dev->data; struct display_ra_data *data = dev->data;
glcdc_line_detect_isr(); if (p_args->event == DISPLAY_EVENT_LINE_DETECTION) {
if (data->front_buf != data->pend_buf) { if (data->front_buf != data->pend_buf) {
data->front_buf = data->pend_buf; data->front_buf = data->pend_buf;
k_sem_give(&data->sem); }
k_sem_give(&data->frame_buf_sem);
} }
} }
@ -58,24 +66,31 @@ static int ra_display_write(const struct device *dev, const uint16_t x, const ui
{ {
struct display_ra_data *data = dev->data; struct display_ra_data *data = dev->data;
const struct display_ra_config *config = dev->config; const struct display_ra_config *config = dev->config;
uint8_t *dst = NULL;
const uint8_t *src = buf;
const uint8_t *l_pend_buf = NULL; const uint8_t *l_pend_buf = NULL;
uint16_t row; bool vsync_wait = false;
int err; fsp_err_t err;
__ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width"); if (desc->pitch < desc->width) {
__ASSERT((desc->pitch * BYTE_PER_PIXEL * desc->height) <= desc->buf_size, LOG_ERR("Pitch is smaller than width");
"Input buffer too small"); return -EINVAL;
}
if ((desc->pitch * data->pixel_size * desc->height) > desc->buf_size) {
LOG_ERR("Input buffer too small");
return -EINVAL;
}
if (x == 0 && y == 0 && desc->height == DISPLAY_VSIZE && desc->width == DISPLAY_HSIZE && if (x == 0 && y == 0 && desc->height == config->height && desc->width == config->width) {
desc->pitch == DISPLAY_HSIZE) {
l_pend_buf = buf; l_pend_buf = buf;
} else { } else {
if (CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0) { #if CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0
LOG_ERR("Partial write requires internal frame buffer"); LOG_ERR("Partial write requires internal frame buffer");
return -ENOTSUP; return -ENOTSUP;
} #else
const uint8_t *src = buf;
uint8_t *dst = NULL;
uint16_t row;
dst = data->frame_buffer; dst = data->frame_buffer;
if (CONFIG_RENESAS_RA_GLCDC_FB_NUM == 2) { if (CONFIG_RENESAS_RA_GLCDC_FB_NUM == 2) {
@ -99,24 +114,37 @@ static int ra_display_write(const struct device *dev, const uint16_t x, const ui
dst += (config->width * data->pixel_size); dst += (config->width * data->pixel_size);
src += (desc->pitch * data->pixel_size); src += (desc->pitch * data->pixel_size);
} }
#endif /* CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0 */
} }
if (data->front_buf == l_pend_buf) { k_sem_reset(&data->frame_buf_sem);
return 0;
}
k_sem_reset(&data->sem);
if (data->front_buf != l_pend_buf) {
data->pend_buf = l_pend_buf; data->pend_buf = l_pend_buf;
err = R_GLCDC_BufferChange(&data->display_ctrl, (uint8_t *)data->pend_buf, err = R_GLCDC_BufferChange(&data->display_ctrl, (uint8_t *)data->pend_buf,
DISPLAY_FRAME_LAYER_1); DISPLAY_FRAME_LAYER_1);
if (err) { if (err != FSP_SUCCESS) {
LOG_ERR("GLCDC buffer change failed"); LOG_ERR("GLCDC buffer change failed");
return -EIO; return -EIO;
} }
k_sem_take(&data->sem, K_FOREVER); vsync_wait = true;
}
if (data->display_ctrl.state != DISPLAY_STATE_DISPLAYING) {
err = R_GLCDC_Start(&data->display_ctrl);
if (err != FSP_SUCCESS) {
LOG_ERR("GLCDC start failed");
return -EIO;
}
vsync_wait = true;
}
if (vsync_wait) {
k_sem_take(&data->frame_buf_sem, K_FOREVER);
}
return 0; return 0;
} }
@ -146,65 +174,179 @@ static int ra_display_read(const struct device *dev, const uint16_t x, const uin
static int ra_display_blanking_on(const struct device *dev) static int ra_display_blanking_on(const struct device *dev)
{ {
const struct display_ra_config *config = dev->config; const struct display_ra_config *config = dev->config;
int err; int ret = 0;
if (config->backlight_gpio.port != NULL) { if (config->backlight_gpio.port != NULL) {
err = gpio_pin_set_dt(&config->backlight_gpio, 0); ret = gpio_pin_set_dt(&config->backlight_gpio, 0);
if (err) {
LOG_ERR("Disable backlight failed! (%d)", err);
return err;
}
} else { } else {
return -ENOTSUP; ret = -ENOTSUP;
} }
return 0; return ret;
} }
static int ra_display_blanking_off(const struct device *dev) static int ra_display_blanking_off(const struct device *dev)
{ {
const struct display_ra_config *config = dev->config; const struct display_ra_config *config = dev->config;
int err; int ret = 0;
if (config->backlight_gpio.port != NULL) { if (config->backlight_gpio.port != NULL) {
err = gpio_pin_set_dt(&config->backlight_gpio, 1); ret = gpio_pin_set_dt(&config->backlight_gpio, 1);
if (err) {
LOG_ERR("Enable backlight failed! (%d)", err);
return err;
}
} else { } else {
return -ENOTSUP; ret = -ENOTSUP;
} }
return 0; return ret;
} }
static void ra_display_get_capabilities(const struct device *dev, static void ra_display_get_capabilities(const struct device *dev,
struct display_capabilities *capabilities) struct display_capabilities *capabilities)
{ {
const struct display_ra_config *config = dev->config; const struct display_ra_config *config = dev->config;
struct display_ra_data *data = dev->data;
memset(capabilities, 0, sizeof(struct display_capabilities));
capabilities->x_resolution = config->width; capabilities->x_resolution = config->width;
capabilities->y_resolution = config->height; capabilities->y_resolution = config->height;
capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
capabilities->supported_pixel_formats = capabilities->supported_pixel_formats =
PIXEL_FORMAT_RGB_888 | PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_RGB_565; PIXEL_FORMAT_RGB_888 | PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_RGB_565;
capabilities->current_pixel_format = (config->pixel_format == PIXEL_FORMAT_RGB_888) capabilities->current_pixel_format = data->current_pixel_format;
? PIXEL_FORMAT_ARGB_8888 capabilities->screen_info = 0U;
: config->pixel_format;
} }
static int ra_display_set_pixel_format(const struct device *dev, static int ra_display_set_pixel_format(const struct device *dev,
const enum display_pixel_format pixel_format) const enum display_pixel_format pixel_format)
{ {
const struct display_ra_config *config = dev->config; const struct display_ra_config *config = dev->config;
struct display_ra_data *data = dev->data;
display_runtime_cfg_t layer_cfg;
enum display_pixel_format set_pixel_format;
display_in_format_t hardware_pixel_format;
uint32_t buf_len;
fsp_err_t err;
if (pixel_format == config->pixel_format) { if (pixel_format == data->current_pixel_format) {
return 0; return 0;
} }
LOG_ERR("Pixel format changes must be set in dts at build time.");
if (data->display_ctrl.state == DISPLAY_STATE_DISPLAYING) {
LOG_ERR("Cannot change the display format while displaying");
return -EWOULDBLOCK;
}
switch (pixel_format) {
case PIXEL_FORMAT_RGB_888:
set_pixel_format = PIXEL_FORMAT_ARGB_8888;
hardware_pixel_format = DISPLAY_IN_FORMAT_32BITS_RGB888;
break;
case PIXEL_FORMAT_ARGB_8888:
set_pixel_format = PIXEL_FORMAT_ARGB_8888;
hardware_pixel_format = DISPLAY_IN_FORMAT_32BITS_ARGB8888;
break;
case PIXEL_FORMAT_RGB_565:
set_pixel_format = PIXEL_FORMAT_RGB_565;
hardware_pixel_format = DISPLAY_IN_FORMAT_16BITS_RGB565;
break;
default:
return -ENOTSUP;
}
buf_len = (config->height * config->width * DISPLAY_BITS_PER_PIXEL(set_pixel_format)) >> 3;
if (buf_len > data->frame_buffer_len) {
LOG_ERR("Frame buffer is smaller than new pixel format require");
return -ENOTSUP; return -ENOTSUP;
}
memcpy(&layer_cfg.input, &data->display_fsp_cfg.input[0], sizeof(display_input_cfg_t));
memcpy(&layer_cfg.layer, &data->display_fsp_cfg.layer[0], sizeof(display_layer_t));
layer_cfg.input.format = hardware_pixel_format;
layer_cfg.input.hstride =
ROUND_UP(layer_cfg.input.hsize * DISPLAY_BITS_PER_PIXEL(set_pixel_format),
NUM_BITS(uint64_t)) /
DISPLAY_BITS_PER_PIXEL(set_pixel_format);
err = R_GLCDC_LayerChange(&data->display_ctrl, &layer_cfg, DISPLAY_FRAME_LAYER_1);
if (err != FSP_SUCCESS) {
LOG_ERR("Failed to change the pixel format");
return -EIO;
}
data->current_pixel_format = pixel_format;
data->pixel_size = DISPLAY_BITS_PER_PIXEL(set_pixel_format) >> 3;
return 0;
}
static int ra_display_color_config(const struct device *dev,
const display_correction_t *display_color_cfg)
{
struct display_ra_data *data = dev->data;
fsp_err_t err;
int ret;
err = R_GLCDC_ColorCorrection(&data->display_ctrl, display_color_cfg);
switch (err) {
case FSP_SUCCESS:
ret = 0;
break;
case FSP_ERR_INVALID_UPDATE_TIMING:
ret = -EWOULDBLOCK;
break;
default:
ret = -EIO;
break;
}
return ret;
}
#define RENESAS_RA_GLCDC_BRIGHTNESS_MAX 1023U
static int ra_display_set_brightness(const struct device *dev, const uint8_t brightness)
{
struct display_ra_data *data = dev->data;
const uint32_t brightness_adj =
DIV_ROUND_CLOSEST(brightness * RENESAS_RA_GLCDC_BRIGHTNESS_MAX, UINT8_MAX);
display_correction_t display_color_cfg;
if (brightness_adj == 0) {
return -EINVAL;
}
memcpy(&display_color_cfg.contrast, &data->display_fsp_cfg.output.contrast,
sizeof(display_contrast_t));
display_color_cfg.brightness = (display_brightness_t){
.enable = true, .r = brightness_adj, .g = brightness_adj, .b = brightness_adj};
return ra_display_color_config(dev, &display_color_cfg);
}
static int ra_display_set_contrast(const struct device *dev, const uint8_t contrast)
{
struct display_ra_data *data = dev->data;
display_correction_t display_color_cfg;
if (contrast == 0) {
return -EINVAL;
}
memcpy(&display_color_cfg.brightness, &data->display_fsp_cfg.output.brightness,
sizeof(display_brightness_t));
display_color_cfg.contrast =
(display_contrast_t){.enable = true, .r = contrast, .g = contrast, .b = contrast};
return ra_display_color_config(dev, &display_color_cfg);
}
static void *ra_display_get_framebuffer(const struct device *dev)
{
struct display_ra_data *data = dev->data;
return (void *)data->front_buf;
} }
static DEVICE_API(display, display_api) = { static DEVICE_API(display, display_api) = {
@ -214,6 +356,9 @@ static DEVICE_API(display, display_api) = {
.set_pixel_format = ra_display_set_pixel_format, .set_pixel_format = ra_display_set_pixel_format,
.write = ra_display_write, .write = ra_display_write,
.read = ra_display_read, .read = ra_display_read,
.set_brightness = ra_display_set_brightness,
.set_contrast = ra_display_set_contrast,
.get_framebuffer = ra_display_get_framebuffer,
}; };
static int display_init(const struct device *dev) static int display_init(const struct device *dev)
@ -235,12 +380,16 @@ static int display_init(const struct device *dev)
R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT); R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
#endif #endif
if (config->pincfg != NULL) {
err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
if (err) { if (err) {
LOG_ERR("pin function initial failed"); LOG_ERR("pin function initial failed");
return err; return err;
} }
k_sem_init(&data->sem, 0, 1); }
k_sem_init(&data->frame_buf_sem, 0, 1);
err = clock_control_on(config->clock_dev, err = clock_control_on(config->clock_dev,
(clock_control_subsys_t)&config->clock_glcdc_subsys); (clock_control_subsys_t)&config->clock_glcdc_subsys);
@ -261,12 +410,6 @@ static int display_init(const struct device *dev)
return err; return err;
} }
err = R_GLCDC_Start(&data->display_ctrl);
if (err) {
LOG_ERR("GLCDC start failed");
return -EIO;
}
config->irq_configure(); config->irq_configure();
return 0; return 0;
@ -286,146 +429,83 @@ static int display_init(const struct device *dev)
#define IRQ_CONFIGURE_DEFINE(id) .irq_configure = glcdc_renesas_ra_configure_func_##id #define IRQ_CONFIGURE_DEFINE(id) .irq_configure = glcdc_renesas_ra_configure_func_##id
#define RENESAS_RA_FRAME_BUFFER_LEN(id) \ #define RENESAS_RA_FRAME_BUFFER_LEN(id) \
(BYTE_PER_PIXEL * DT_INST_PROP(id, height) * DT_INST_PROP(id, width)) (RENESAS_RA_GLCDC_PIXEL_BYTE_SIZE(id) * DT_INST_PROP(id, height) * DT_INST_PROP(id, width))
#ifdef CONFIG_RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION
#define FRAME_BUFFER_SECTION Z_GENERIC_SECTION(CONFIG_RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION)
#else
#define FRAME_BUFFER_SECTION
#endif /* CONFIG_RENESAS_RA_GLCDC_FRAME_BUFFER_SECTION */
#define RENESAS_RA_GLCDC_DEVICE_PINCTRL_INIT(n) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, pinctrl_0), (PINCTRL_DT_INST_DEFINE(n)), ())
#define RENESAS_RA_GLCDC_DEVICE_PINCTRL_GET(n) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, pinctrl_0), (PINCTRL_DT_INST_DEV_CONFIG_GET(n)), \
(NULL))
#define RENESAS_RA_DEVICE_INIT(id) \ #define RENESAS_RA_DEVICE_INIT(id) \
PINCTRL_DT_INST_DEFINE(id); \ RENESAS_RA_GLCDC_DEVICE_PINCTRL_INIT(id); \
IRQ_CONFIGURE_FUNC(id) \ IRQ_CONFIGURE_FUNC(id) \
Z_GENERIC_SECTION(".sdram") \ FRAME_BUFFER_SECTION static uint8_t __aligned(64) \
static uint8_t __aligned(64) \
fb_background##id[CONFIG_RENESAS_RA_GLCDC_FB_NUM * RENESAS_RA_FRAME_BUFFER_LEN(id)]; \ fb_background##id[CONFIG_RENESAS_RA_GLCDC_FB_NUM * RENESAS_RA_FRAME_BUFFER_LEN(id)]; \
static const glcdc_extended_cfg_t display_extend_cfg##id = { \ static const glcdc_extended_cfg_t display_extend_cfg##id = { \
.tcon_hsync = GLCDC_TCON_PIN_1, \ .tcon_hsync = RENESAS_RA_GLCDC_TCON_HSYNC_PIN(id), \
.tcon_vsync = GLCDC_TCON_PIN_0, \ .tcon_vsync = RENESAS_RA_GLCDC_TCON_VSYNC_PIN(id), \
.tcon_de = GLCDC_TCON_PIN_2, \ .tcon_de = RENESAS_RA_GLCDC_TCON_DE_PIN(id), \
.correction_proc_order = GLCDC_CORRECTION_PROC_ORDER_BRIGHTNESS_CONTRAST2GAMMA, \ .correction_proc_order = GLCDC_CORRECTION_PROC_ORDER_BRIGHTNESS_CONTRAST2GAMMA, \
.clksrc = GLCDC_CLK_SRC_INTERNAL, \ .clksrc = GLCDC_CLK_SRC_INTERNAL, \
.clock_div_ratio = GLCDC_PANEL_CLK_DIVISOR_8, \ .clock_div_ratio = RENESAS_RA_GLCDC_OUTPUT_CLOCK_DIV(id), \
.dithering_mode = GLCDC_DITHERING_MODE_TRUNCATE, \ .phy_layer = NULL}; \
.dithering_pattern_A = GLCDC_DITHERING_PATTERN_11, \
.dithering_pattern_B = GLCDC_DITHERING_PATTERN_11, \
.dithering_pattern_C = GLCDC_DITHERING_PATTERN_11, \
.dithering_pattern_D = GLCDC_DITHERING_PATTERN_11, \
.phy_layer = NULL, \
}; \
static struct display_ra_data ra_data##id = { \ static struct display_ra_data ra_data##id = { \
.frame_buffer = fb_background##id, \ .frame_buffer = fb_background##id, \
.frame_buffer_len = RENESAS_RA_FRAME_BUFFER_LEN(id), \ .frame_buffer_len = RENESAS_RA_FRAME_BUFFER_LEN(id), \
.front_buf = fb_background##id, \ .front_buf = fb_background##id, \
.pend_buf = fb_background##id, \ .pend_buf = fb_background##id, \
.pixel_size = BYTE_PER_PIXEL, \ .pixel_size = RENESAS_RA_GLCDC_PIXEL_BYTE_SIZE(id), \
.p_base = (uint8_t *)&fb_background##id, \ .current_pixel_format = RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(id), \
.display_fsp_cfg = { \ .display_fsp_cfg = { \
.input[0] = {.p_base = (uint32_t *)&fb_background##id, \ .input[0] = {.p_base = (uint32_t *)fb_background##id, \
.hsize = DISPLAY_HSIZE, \ .hsize = DISPLAY_HSIZE(id), \
.vsize = DISPLAY_VSIZE, \ .vsize = DISPLAY_VSIZE(id), \
.hstride = DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0, \ .hstride = RENESAS_RA_DISPLAY_BUFFER_HSTRIDE_BYTE(id), \
.format = \ .format = RENESAS_RA_GLCDC_IN_PIXEL_FORMAT(id), \
(INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_565) \
? DISPLAY_IN_FORMAT_16BITS_RGB565 \
: (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_888) \
? DISPLAY_IN_FORMAT_32BITS_RGB888 \
: DISPLAY_IN_FORMAT_32BITS_ARGB8888, \
.line_descending_enable = false, \
.lines_repeat_enable = false, \
.lines_repeat_times = 0}, \
.input[1] = {.p_base = NULL, \
.hsize = DISPLAY_HSIZE, \
.vsize = DISPLAY_VSIZE, \
.hstride = DISPLAY_BUFFER_STRIDE_PIXELS_INPUT1, \
.format = DISPLAY_IN_FORMAT_16BITS_RGB565, \
.line_descending_enable = false, \ .line_descending_enable = false, \
.lines_repeat_enable = false, \ .lines_repeat_enable = false, \
.lines_repeat_times = 0}, \ .lines_repeat_times = 0}, \
.layer[0] = {.coordinate = {.x = 0, .y = 0}, \ .layer[0] = {.coordinate = {.x = 0, .y = 0}, \
.bg_color = {.byte = {.a = LAYER_ALPHA, \ .bg_color = RENESAS_RA_GLCDC_BG_COLOR(id), \
.r = LAYER_RED, \
.g = LAYER_GREEN, \
.b = LAYER_BLUE}}, \
.fade_control = DISPLAY_FADE_CONTROL_NONE, \
.fade_speed = 0}, \
.layer[1] = {.coordinate = {.x = 0, .y = 0}, \
.bg_color = {.byte = {.a = LAYER_ALPHA, \
.r = LAYER_RED, \
.g = LAYER_GREEN, \
.b = LAYER_BLUE}}, \
.fade_control = DISPLAY_FADE_CONTROL_NONE, \ .fade_control = DISPLAY_FADE_CONTROL_NONE, \
.fade_speed = 0}, \ .fade_speed = 0}, \
.output = {.htiming = {.total_cyc = \ .input[1] = {.p_base = NULL}, \
DT_INST_PROP(id, width) + \ .output = {.htiming = RENESAS_RA_GLCDC_HTIMING(id), \
DT_PROP(DT_INST_CHILD(id, display_timings), \ .vtiming = RENESAS_RA_GLCDC_VTIMING(id), \
hback_porch) + \ .format = RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT(id), \
DT_PROP(DT_INST_CHILD(id, display_timings), \ .endian = RENESAS_RA_GLCDC_OUTPUT_ENDIAN(id), \
hfront_porch) + \ .color_order = RENESAS_RA_GLCDC_OUTPUT_COLOR_ODER(id), \
DT_PROP(DT_INST_CHILD(id, display_timings), \ .data_enable_polarity = \
hsync_len), \ RENESAS_RA_GLCDC_OUTPUT_DE_POLARITY(id), \
.display_cyc = DT_INST_PROP(id, width), \ .sync_edge = RENESAS_RA_GLCDC_OUTPUT_SYNC_EDGE(id), \
.back_porch = \ .bg_color = RENESAS_RA_GLCDC_BG_COLOR(id), \
DT_PROP(DT_INST_CHILD(id, display_timings), \ .brightness = {.enable = false}, \
hback_porch), \ .contrast = {.enable = false}, \
.sync_width = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hsync_len), \
.sync_polarity = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hsync_active)}, \
.vtiming = {.total_cyc = \
DT_INST_PROP(id, height) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vback_porch) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vfront_porch) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vsync_len), \
.display_cyc = DT_INST_PROP(id, height), \
.back_porch = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vback_porch), \
.sync_width = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vsync_len), \
.sync_polarity = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
vsync_active)}, \
.format = (OUTPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_565) \
? DISPLAY_OUT_FORMAT_16BITS_RGB565 \
: DISPLAY_OUT_FORMAT_24BITS_RGB888, \
.endian = DISPLAY_ENDIAN_LITTLE, \
.color_order = DISPLAY_COLOR_ORDER_RGB, \
.data_enable_polarity = DISPLAY_SIGNAL_POLARITY_HIACTIVE, \
.sync_edge = DISPLAY_SIGNAL_SYNC_EDGE_FALLING, \
.bg_color = {.byte = {.a = OUTPUT_ALPHA, \
.r = OUTPUT_RED, \
.g = OUTPUT_GREEN, \
.b = OUTPUT_BLUE}}, \
.brightness = {.enable = false, \
.r = OUTPUT_RED, \
.g = OUTPUT_GREEN, \
.b = OUTPUT_BLUE}, \
.contrast = {.enable = false, \
.r = OUTPUT_RED, \
.g = OUTPUT_GREEN, \
.b = OUTPUT_BLUE}, \
.dithering_on = false}, \ .dithering_on = false}, \
.p_callback = NULL, \ .p_callback = renesas_ra_callback_adapter, \
.p_context = NULL, \ .p_context = DEVICE_DT_INST_GET(id), \
.p_extend = (void *)(&display_extend_cfg##id), \ .p_extend = (void *)(&display_extend_cfg##id), \
.line_detect_ipl = BSP_IRQ_DISABLED, \ .line_detect_irq = DT_INST_IRQ_BY_NAME(id, line, irq), \
.underflow_1_ipl = BSP_IRQ_DISABLED, \ .line_detect_ipl = DT_INST_IRQ_BY_NAME(id, line, priority), \
.underflow_2_ipl = BSP_IRQ_DISABLED}}; \ .underflow_1_irq = BSP_IRQ_DISABLED, \
.underflow_2_irq = BSP_IRQ_DISABLED}}; \
static struct display_ra_config ra_config##id = { \ static struct display_ra_config ra_config##id = { \
IRQ_CONFIGURE_DEFINE(id), \ IRQ_CONFIGURE_DEFINE(id), \
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ .pincfg = RENESAS_RA_GLCDC_DEVICE_PINCTRL_GET(id), \
.backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \ .backlight_gpio = GPIO_DT_SPEC_INST_GET_OR(id, backlight_gpios, NULL), \
.height = DT_INST_PROP(id, height), \ .height = DT_INST_PROP(id, height), \
.width = DT_INST_PROP(id, width), \ .width = DT_INST_PROP(id, width), \
.pixel_format = DT_INST_PROP(id, input_pixel_format), \
.display_frame_size = \
(DT_INST_PROP(id, width)) * (DT_INST_PROP(id, height)) * BYTE_PER_PIXEL, \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
.clock_glcdc_subsys = {.mstp = (uint32_t)DT_INST_CLOCKS_CELL_BY_IDX(id, 0, mstp), \ .clock_glcdc_subsys = {.mstp = (uint32_t)DT_INST_CLOCKS_CELL_BY_IDX(id, 0, mstp), \
.stop_bit = DT_INST_CLOCKS_CELL_BY_IDX(id, 0, stop_bit)}, \ .stop_bit = DT_INST_CLOCKS_CELL_BY_IDX(id, 0, stop_bit)}}; \
}; \
DEVICE_DT_INST_DEFINE(id, &display_init, NULL, &ra_data##id, &ra_config##id, POST_KERNEL, \ DEVICE_DT_INST_DEFINE(id, &display_init, NULL, &ra_data##id, &ra_config##id, POST_KERNEL, \
CONFIG_DISPLAY_INIT_PRIORITY, &display_api); CONFIG_DISPLAY_INIT_PRIORITY, &display_api);

126
drivers/display/display_renesas_ra.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2024 Renesas Electronics Corporation * Copyright (c) 2024-2025 Renesas Electronics Corporation
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -9,42 +9,92 @@
#include <zephyr/drivers/display.h> #include <zephyr/drivers/display.h>
#define INPUT_FORMAT_PIXEL DT_INST_PROP(0, input_pixel_format) #define ROUND_UP_64BYTES(x) ROUND_UP(x, NUM_BITS(uint64_t))
#define OUTPUT_FORMAT_PIXEL DT_INST_PROP(0, output_pixel_format) #define INPUT_FORMAT_PIXEL(n) DT_INST_PROP(n, input_pixel_format)
#define OUTPUT_FORMAT_PIXEL(n) DT_INST_PROP(n, output_pixel_format)
#if (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_565)
#define BYTE_PER_PIXEL (2) #define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_1 (DISPLAY_IN_FORMAT_32BITS_RGB888)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (16) #define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_8 (DISPLAY_IN_FORMAT_32BITS_ARGB8888)
#elif (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_888) #define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_16 (DISPLAY_IN_FORMAT_16BITS_RGB565)
#define BYTE_PER_PIXEL (4)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (32) #define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_1 (DISPLAY_OUT_FORMAT_24BITS_RGB888)
#elif (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_ARGB_8888) #define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_16 (DISPLAY_OUT_FORMAT_16BITS_RGB565)
#define BYTE_PER_PIXEL (4)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (32) #define RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(n) \
#endif (DT_INST_PROP(n, input_pixel_format) == PANEL_PIXEL_FORMAT_RGB_888 \
? PANEL_PIXEL_FORMAT_ARGB_8888 \
#define DISPLAY_BITS_PER_PIXEL_INPUT1 (16) : DT_INST_PROP(n, input_pixel_format))
#define DISPLAY_HSIZE DT_INST_PROP(0, width)
#define DISPLAY_VSIZE DT_INST_PROP(0, height) #define DISPLAY_HSIZE(n) (DT_INST_PROP(n, width))
#define DISPLAY_BUFFER_STRIDE_BYTES_INPUT0 \ #define DISPLAY_VSIZE(n) (DT_INST_PROP(n, height))
(((DISPLAY_HSIZE * DISPLAY_BITS_PER_PIXEL_INPUT0 + 0x1FF) >> 9) << 6)
#define DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0 \ #define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT(n) \
((DISPLAY_BUFFER_STRIDE_BYTES_INPUT0 * 8) / DISPLAY_BITS_PER_PIXEL_INPUT0) UTIL_CAT(RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_, INPUT_FORMAT_PIXEL(n))
#define DISPLAY_BUFFER_STRIDE_BYTES_INPUT1 \
(((DISPLAY_HSIZE * DISPLAY_BITS_PER_PIXEL_INPUT1 + 0x1FF) >> 9) << 6) #define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT(n) \
#define DISPLAY_BUFFER_STRIDE_PIXELS_INPUT1 \ UTIL_CAT(RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_, OUTPUT_FORMAT_PIXEL(n))
((DISPLAY_BUFFER_STRIDE_BYTES_INPUT1 * 8) / DISPLAY_BITS_PER_PIXEL_INPUT1)
#define RENESAS_RA_GLCDC_PIXEL_BYTE_SIZE(n) \
#define LAYER_GREEN (255) (DISPLAY_BITS_PER_PIXEL(RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(n)) >> 3)
#define LAYER_RED (255)
#define LAYER_BLUE (255) #define RENESAS_RA_DISPLAY_BUFFER_HSTRIDE_BYTE(n) \
#define LAYER_ALPHA (255) (ROUND_UP_64BYTES(DISPLAY_HSIZE(n) * DISPLAY_BITS_PER_PIXEL(INPUT_FORMAT_PIXEL(n))) / \
#define OUTPUT_GREEN (0) DISPLAY_BITS_PER_PIXEL(INPUT_FORMAT_PIXEL(n)))
#define OUTPUT_RED (0)
#define OUTPUT_BLUE (0) #define RENESAS_RA_GLCDC_HTIMING(n) \
#define OUTPUT_ALPHA (255) {.total_cyc = DT_INST_PROP(n, width) + \
#define GLCDC_BRIGHTNESS_MAX (1023U) DT_PROP(DT_INST_CHILD(n, display_timings), hback_porch) + \
#define BRIGHTNESS_MAX (255U) DT_PROP(DT_INST_CHILD(n, display_timings), hfront_porch) + \
#define GLCDC_CONTRAST_MAX (255U) DT_PROP(DT_INST_CHILD(n, display_timings), hsync_len), \
.display_cyc = DT_INST_PROP(n, width), \
.back_porch = DT_PROP(DT_INST_CHILD(n, display_timings), hback_porch), \
.sync_width = DT_PROP(DT_INST_CHILD(n, display_timings), hsync_len), \
.sync_polarity = DT_PROP(DT_INST_CHILD(n, display_timings), hsync_active)}
#define RENESAS_RA_GLCDC_VTIMING(n) \
{.total_cyc = DT_INST_PROP(n, height) + \
DT_PROP(DT_INST_CHILD(n, display_timings), vback_porch) + \
DT_PROP(DT_INST_CHILD(n, display_timings), vfront_porch) + \
DT_PROP(DT_INST_CHILD(n, display_timings), vsync_len), \
.display_cyc = DT_INST_PROP(n, height), \
.back_porch = DT_PROP(DT_INST_CHILD(n, display_timings), vback_porch), \
.sync_width = DT_PROP(DT_INST_CHILD(n, display_timings), vsync_len), \
.sync_polarity = DT_PROP(DT_INST_CHILD(n, display_timings), vsync_active)}
#define RENESAS_RA_GLCDC_OUTPUT_ENDIAN(n) \
UTIL_CAT(DISPLAY_ENDIAN_, DT_INST_STRING_UPPER_TOKEN_OR(n, output_endian, LITTLE))
#define RENESAS_RA_GLCDC_OUTPUT_COLOR_ODER(n) \
UTIL_CAT(DISPLAY_COLOR_ORDER_, DT_INST_STRING_UPPER_TOKEN_OR(n, output_color_oder, RGB))
#define RENESAS_RA_GLCDC_OUTPUT_DE_POLARITY(n) \
UTIL_CAT(DISPLAY_SIGNAL_POLARITY_, \
DT_INST_STRING_UPPER_TOKEN_OR(n, output_data_signal_polarity, HIACTIVE))
#define RENESAS_RA_GLCDC_OUTPUT_SYNC_EDGE(n) \
UTIL_CAT(DISPLAY_SIGNAL_SYNC_EDGE_, \
DT_INST_STRING_UPPER_TOKEN_OR(n, output_signal_sync_edge, FALLING))
#define RENESAS_RA_GLCDC_BG_COLOR(n) \
{ \
.byte = { \
.a = DT_INST_PROP_OR(n, def_back_color_alpha, 255), \
.r = DT_INST_PROP_OR(n, def_back_color_red, 255), \
.g = DT_INST_PROP_OR(n, def_back_color_green, 255), \
.b = DT_INST_PROP_OR(n, def_back_color_blue, 255) \
} \
}
#define RENESAS_RA_GLCDC_TCON_HSYNC_PIN(n) \
UTIL_CAT(GLCDC_, DT_INST_STRING_UPPER_TOKEN_OR(n, output_pin_hsync, TCON_PIN_1))
#define RENESAS_RA_GLCDC_TCON_VSYNC_PIN(n) \
UTIL_CAT(GLCDC_, DT_INST_STRING_UPPER_TOKEN_OR(n, output_pin_vsync, TCON_PIN_0))
#define RENESAS_RA_GLCDC_TCON_DE_PIN(n) \
UTIL_CAT(GLCDC_, DT_INST_STRING_UPPER_TOKEN_OR(n, output_pin_de, TCON_PIN_2))
#define RENESAS_RA_GLCDC_OUTPUT_CLOCK_DIV(n) \
UTIL_CAT(GLCDC_PANEL_CLK_DIVISOR_, DT_INST_PROP_OR(n, output_clock_divisor, 8))
#endif /* ZEPHYR_DRIVERS_DISPLAY_RENESAS_RA_H_ */ #endif /* ZEPHYR_DRIVERS_DISPLAY_RENESAS_RA_H_ */

90
dts/bindings/display/renesas,ra-glcdc.yaml

@ -1,4 +1,4 @@
# Copyright (c) 2024 Renesas Electronics Corporation # Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
description: Renesas Graphic LCD controller description: Renesas Graphic LCD controller
@ -15,10 +15,9 @@ properties:
required: true required: true
pinctrl-0: pinctrl-0:
required: true description: |
Provide a pin configuration for using parallel pixel output. In combination with DSI HOST
pinctrl-names: the pin configuration is not necessary due to dedicated (MIPI D-PHY) pins.
required: true
interrupts: interrupts:
required: true required: true
@ -30,11 +29,74 @@ properties:
backlight-gpios: backlight-gpios:
type: phandle-array type: phandle-array
required: true
description: | description: |
The BLn pin is asserted to control the backlight of the panel. The BLn pin is asserted to control the backlight of the panel.
The sensor receives this as an active-high signal. The sensor receives this as an active-high signal.
output-pin-hsync:
type: string
enum:
- "TCON_PIN_NONE"
- "TCON_PIN_0"
- "TCON_PIN_1"
- "TCON_PIN_2"
- "TCON_PIN_3"
description: Select the Parallel LCD HSYNC pin. Please do not select if using DSI Display.
output-pin-vsync:
type: string
enum:
- "TCON_PIN_NONE"
- "TCON_PIN_0"
- "TCON_PIN_1"
- "TCON_PIN_2"
- "TCON_PIN_3"
description: Select the Parallel LCD VSYNC pin. Please do not select if using DSI Display.
output-pin-de:
type: string
enum:
- "TCON_PIN_NONE"
- "TCON_PIN_0"
- "TCON_PIN_1"
- "TCON_PIN_2"
- "TCON_PIN_3"
description: Select the Parallel LCD DE pin. Please do not select if using DSI Display.
output-clock-divisor:
type: int
enum: [1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 16, 24, 32]
description: |
Select the GLCDC clock frequency division ratio to output for panel.
output-endian:
type: string
enum:
- "LITTLE"
- "BIG"
description: Select the output data bit order. Default is little endian.
output-color-oder:
type: string
enum:
- "RGB"
- "GBR"
description: Select the output color order in pixel. Default is RGB.
output-data-signal-polarity:
type: string
enum:
- "LOACTIVE"
- "HIACTIVE"
description: Select the output data enable signal polarity. Default is high active.
output-signal-sync-edge:
type: string
enum:
- "FALLING"
- "RISING"
description: Select the output signal synchronization edge. Default is falling edge.
input-pixel-format: input-pixel-format:
type: int type: int
required: true required: true
@ -46,3 +108,19 @@ properties:
required: true required: true
description: | description: |
Initial output Pixel format for Graphic LCD controller. Initial output Pixel format for Graphic LCD controller.
def-back-color-alpha:
type: int
description: Default display background color - alpha
def-back-color-red:
type: int
description: Default display background color - red
def-back-color-green:
type: int
description: Default display background color - green
def-back-color-blue:
type: int
description: Default display background color - blue

Loading…
Cancel
Save