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

10
drivers/display/Kconfig.renesas_ra

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
# Renesas RA Family
# Copyright (c) 2024 Renesas Electronics Corporation
# Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0
config RENESAS_RA_GLCDC
@ -23,6 +23,14 @@ config RENESAS_RA_GLCDC_FB_NUM @@ -23,6 +23,14 @@ config RENESAS_RA_GLCDC_FB_NUM
- 1 single 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
# Force display buffers to be aligned to cache line size (64 bytes)

442
drivers/display/display_renesas_ra.c

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
LOG_MODULE_REGISTER(display_renesas_ra, CONFIG_DISPLAY_LOG_LEVEL);
void glcdc_line_detect_isr(void);
struct display_ra_config {
const struct pinctrl_dev_config *pincfg;
const struct gpio_dt_spec backlight_gpio;
@ -25,31 +24,40 @@ struct display_ra_config { @@ -25,31 +24,40 @@ struct display_ra_config {
struct clock_control_ra_subsys_cfg clock_glcdc_subsys;
uint16_t height;
uint16_t width;
uint32_t display_frame_size;
enum display_pixel_format pixel_format;
void (*irq_configure)(void);
};
struct display_ra_data {
glcdc_instance_ctrl_t display_ctrl;
display_cfg_t display_fsp_cfg;
uint8_t *p_base;
uint32_t frame_buffer_len;
const uint8_t *pend_buf;
const uint8_t *front_buf;
uint8_t pixel_size;
enum display_pixel_format current_pixel_format;
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)
{
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;
glcdc_line_detect_isr();
if (data->front_buf != data->pend_buf) {
data->front_buf = data->pend_buf;
k_sem_give(&data->sem);
if (p_args->event == DISPLAY_EVENT_LINE_DETECTION) {
if (data->front_buf != data->pend_buf) {
data->front_buf = data->pend_buf;
}
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 @@ -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;
const struct display_ra_config *config = dev->config;
uint8_t *dst = NULL;
const uint8_t *src = buf;
const uint8_t *l_pend_buf = NULL;
uint16_t row;
int err;
bool vsync_wait = false;
fsp_err_t err;
__ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width");
__ASSERT((desc->pitch * BYTE_PER_PIXEL * desc->height) <= desc->buf_size,
"Input buffer too small");
if (desc->pitch < desc->width) {
LOG_ERR("Pitch is smaller than width");
return -EINVAL;
}
if (x == 0 && y == 0 && desc->height == DISPLAY_VSIZE && desc->width == DISPLAY_HSIZE &&
desc->pitch == DISPLAY_HSIZE) {
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 == config->height && desc->width == config->width) {
l_pend_buf = buf;
} else {
if (CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0) {
LOG_ERR("Partial write requires internal frame buffer");
return -ENOTSUP;
}
#if CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0
LOG_ERR("Partial write requires internal frame buffer");
return -ENOTSUP;
#else
const uint8_t *src = buf;
uint8_t *dst = NULL;
uint16_t row;
dst = data->frame_buffer;
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 @@ -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);
src += (desc->pitch * data->pixel_size);
}
#endif /* CONFIG_RENESAS_RA_GLCDC_FB_NUM == 0 */
}
if (data->front_buf == l_pend_buf) {
return 0;
}
k_sem_reset(&data->frame_buf_sem);
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,
DISPLAY_FRAME_LAYER_1);
if (err != FSP_SUCCESS) {
LOG_ERR("GLCDC buffer change failed");
return -EIO;
}
err = R_GLCDC_BufferChange(&data->display_ctrl, (uint8_t *)data->pend_buf,
DISPLAY_FRAME_LAYER_1);
if (err) {
LOG_ERR("GLCDC buffer change failed");
return -EIO;
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;
}
k_sem_take(&data->sem, K_FOREVER);
if (vsync_wait) {
k_sem_take(&data->frame_buf_sem, K_FOREVER);
}
return 0;
}
@ -146,65 +174,179 @@ static int ra_display_read(const struct device *dev, const uint16_t x, const uin @@ -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)
{
const struct display_ra_config *config = dev->config;
int err;
int ret = 0;
if (config->backlight_gpio.port != NULL) {
err = gpio_pin_set_dt(&config->backlight_gpio, 0);
if (err) {
LOG_ERR("Disable backlight failed! (%d)", err);
return err;
}
ret = gpio_pin_set_dt(&config->backlight_gpio, 0);
} else {
return -ENOTSUP;
ret = -ENOTSUP;
}
return 0;
return ret;
}
static int ra_display_blanking_off(const struct device *dev)
{
const struct display_ra_config *config = dev->config;
int err;
int ret = 0;
if (config->backlight_gpio.port != NULL) {
err = gpio_pin_set_dt(&config->backlight_gpio, 1);
if (err) {
LOG_ERR("Enable backlight failed! (%d)", err);
return err;
}
ret = gpio_pin_set_dt(&config->backlight_gpio, 1);
} else {
return -ENOTSUP;
ret = -ENOTSUP;
}
return 0;
return ret;
}
static void ra_display_get_capabilities(const struct device *dev,
struct display_capabilities *capabilities)
{
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->y_resolution = config->height;
capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
capabilities->supported_pixel_formats =
PIXEL_FORMAT_RGB_888 | PIXEL_FORMAT_ARGB_8888 | PIXEL_FORMAT_RGB_565;
capabilities->current_pixel_format = (config->pixel_format == PIXEL_FORMAT_RGB_888)
? PIXEL_FORMAT_ARGB_8888
: config->pixel_format;
capabilities->current_pixel_format = data->current_pixel_format;
capabilities->screen_info = 0U;
}
static int ra_display_set_pixel_format(const struct device *dev,
const enum display_pixel_format pixel_format)
{
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;
}
LOG_ERR("Pixel format changes must be set in dts at build time.");
return -ENOTSUP;
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;
}
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) = {
@ -214,6 +356,9 @@ static DEVICE_API(display, display_api) = { @@ -214,6 +356,9 @@ static DEVICE_API(display, display_api) = {
.set_pixel_format = ra_display_set_pixel_format,
.write = ra_display_write,
.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)
@ -235,12 +380,16 @@ 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);
#endif
err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
if (err) {
LOG_ERR("pin function initial failed");
return err;
if (config->pincfg != NULL) {
err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
if (err) {
LOG_ERR("pin function initial failed");
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,
(clock_control_subsys_t)&config->clock_glcdc_subsys);
@ -261,12 +410,6 @@ static int display_init(const struct device *dev) @@ -261,12 +410,6 @@ static int display_init(const struct device *dev)
return err;
}
err = R_GLCDC_Start(&data->display_ctrl);
if (err) {
LOG_ERR("GLCDC start failed");
return -EIO;
}
config->irq_configure();
return 0;
@ -286,146 +429,83 @@ static int display_init(const struct device *dev) @@ -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 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) \
PINCTRL_DT_INST_DEFINE(id); \
RENESAS_RA_GLCDC_DEVICE_PINCTRL_INIT(id); \
IRQ_CONFIGURE_FUNC(id) \
Z_GENERIC_SECTION(".sdram") \
static uint8_t __aligned(64) \
FRAME_BUFFER_SECTION static uint8_t __aligned(64) \
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 = { \
.tcon_hsync = GLCDC_TCON_PIN_1, \
.tcon_vsync = GLCDC_TCON_PIN_0, \
.tcon_de = GLCDC_TCON_PIN_2, \
.tcon_hsync = RENESAS_RA_GLCDC_TCON_HSYNC_PIN(id), \
.tcon_vsync = RENESAS_RA_GLCDC_TCON_VSYNC_PIN(id), \
.tcon_de = RENESAS_RA_GLCDC_TCON_DE_PIN(id), \
.correction_proc_order = GLCDC_CORRECTION_PROC_ORDER_BRIGHTNESS_CONTRAST2GAMMA, \
.clksrc = GLCDC_CLK_SRC_INTERNAL, \
.clock_div_ratio = GLCDC_PANEL_CLK_DIVISOR_8, \
.dithering_mode = GLCDC_DITHERING_MODE_TRUNCATE, \
.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, \
}; \
.clock_div_ratio = RENESAS_RA_GLCDC_OUTPUT_CLOCK_DIV(id), \
.phy_layer = NULL}; \
static struct display_ra_data ra_data##id = { \
.frame_buffer = fb_background##id, \
.frame_buffer_len = RENESAS_RA_FRAME_BUFFER_LEN(id), \
.front_buf = fb_background##id, \
.pend_buf = fb_background##id, \
.pixel_size = BYTE_PER_PIXEL, \
.p_base = (uint8_t *)&fb_background##id, \
.pixel_size = RENESAS_RA_GLCDC_PIXEL_BYTE_SIZE(id), \
.current_pixel_format = RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(id), \
.display_fsp_cfg = { \
.input[0] = {.p_base = (uint32_t *)&fb_background##id, \
.hsize = DISPLAY_HSIZE, \
.vsize = DISPLAY_VSIZE, \
.hstride = DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0, \
.format = \
(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, \
.input[0] = {.p_base = (uint32_t *)fb_background##id, \
.hsize = DISPLAY_HSIZE(id), \
.vsize = DISPLAY_VSIZE(id), \
.hstride = RENESAS_RA_DISPLAY_BUFFER_HSTRIDE_BYTE(id), \
.format = RENESAS_RA_GLCDC_IN_PIXEL_FORMAT(id), \
.line_descending_enable = false, \
.lines_repeat_enable = false, \
.lines_repeat_times = 0}, \
.layer[0] = {.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_speed = 0}, \
.layer[1] = {.coordinate = {.x = 0, .y = 0}, \
.bg_color = {.byte = {.a = LAYER_ALPHA, \
.r = LAYER_RED, \
.g = LAYER_GREEN, \
.b = LAYER_BLUE}}, \
.bg_color = RENESAS_RA_GLCDC_BG_COLOR(id), \
.fade_control = DISPLAY_FADE_CONTROL_NONE, \
.fade_speed = 0}, \
.output = {.htiming = {.total_cyc = \
DT_INST_PROP(id, width) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hback_porch) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hfront_porch) + \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hsync_len), \
.display_cyc = DT_INST_PROP(id, width), \
.back_porch = \
DT_PROP(DT_INST_CHILD(id, display_timings), \
hback_porch), \
.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}, \
.input[1] = {.p_base = NULL}, \
.output = {.htiming = RENESAS_RA_GLCDC_HTIMING(id), \
.vtiming = RENESAS_RA_GLCDC_VTIMING(id), \
.format = RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT(id), \
.endian = RENESAS_RA_GLCDC_OUTPUT_ENDIAN(id), \
.color_order = RENESAS_RA_GLCDC_OUTPUT_COLOR_ODER(id), \
.data_enable_polarity = \
RENESAS_RA_GLCDC_OUTPUT_DE_POLARITY(id), \
.sync_edge = RENESAS_RA_GLCDC_OUTPUT_SYNC_EDGE(id), \
.bg_color = RENESAS_RA_GLCDC_BG_COLOR(id), \
.brightness = {.enable = false}, \
.contrast = {.enable = false}, \
.dithering_on = false}, \
.p_callback = NULL, \
.p_context = NULL, \
.p_callback = renesas_ra_callback_adapter, \
.p_context = DEVICE_DT_INST_GET(id), \
.p_extend = (void *)(&display_extend_cfg##id), \
.line_detect_ipl = BSP_IRQ_DISABLED, \
.underflow_1_ipl = BSP_IRQ_DISABLED, \
.underflow_2_ipl = BSP_IRQ_DISABLED}}; \
.line_detect_irq = DT_INST_IRQ_BY_NAME(id, line, irq), \
.line_detect_ipl = DT_INST_IRQ_BY_NAME(id, line, priority), \
.underflow_1_irq = BSP_IRQ_DISABLED, \
.underflow_2_irq = BSP_IRQ_DISABLED}}; \
static struct display_ra_config ra_config##id = { \
IRQ_CONFIGURE_DEFINE(id), \
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
.backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \
.pincfg = RENESAS_RA_GLCDC_DEVICE_PINCTRL_GET(id), \
.backlight_gpio = GPIO_DT_SPEC_INST_GET_OR(id, backlight_gpios, NULL), \
.height = DT_INST_PROP(id, height), \
.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_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, \
CONFIG_DISPLAY_INIT_PRIORITY, &display_api);

126
drivers/display/display_renesas_ra.h

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Renesas Electronics Corporation
* Copyright (c) 2024-2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -9,42 +9,92 @@ @@ -9,42 +9,92 @@
#include <zephyr/drivers/display.h>
#define INPUT_FORMAT_PIXEL DT_INST_PROP(0, input_pixel_format)
#define OUTPUT_FORMAT_PIXEL DT_INST_PROP(0, output_pixel_format)
#if (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_565)
#define BYTE_PER_PIXEL (2)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (16)
#elif (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_RGB_888)
#define BYTE_PER_PIXEL (4)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (32)
#elif (INPUT_FORMAT_PIXEL == PANEL_PIXEL_FORMAT_ARGB_8888)
#define BYTE_PER_PIXEL (4)
#define DISPLAY_BITS_PER_PIXEL_INPUT0 (32)
#endif
#define DISPLAY_BITS_PER_PIXEL_INPUT1 (16)
#define DISPLAY_HSIZE DT_INST_PROP(0, width)
#define DISPLAY_VSIZE DT_INST_PROP(0, height)
#define DISPLAY_BUFFER_STRIDE_BYTES_INPUT0 \
(((DISPLAY_HSIZE * DISPLAY_BITS_PER_PIXEL_INPUT0 + 0x1FF) >> 9) << 6)
#define DISPLAY_BUFFER_STRIDE_PIXELS_INPUT0 \
((DISPLAY_BUFFER_STRIDE_BYTES_INPUT0 * 8) / DISPLAY_BITS_PER_PIXEL_INPUT0)
#define DISPLAY_BUFFER_STRIDE_BYTES_INPUT1 \
(((DISPLAY_HSIZE * DISPLAY_BITS_PER_PIXEL_INPUT1 + 0x1FF) >> 9) << 6)
#define DISPLAY_BUFFER_STRIDE_PIXELS_INPUT1 \
((DISPLAY_BUFFER_STRIDE_BYTES_INPUT1 * 8) / DISPLAY_BITS_PER_PIXEL_INPUT1)
#define LAYER_GREEN (255)
#define LAYER_RED (255)
#define LAYER_BLUE (255)
#define LAYER_ALPHA (255)
#define OUTPUT_GREEN (0)
#define OUTPUT_RED (0)
#define OUTPUT_BLUE (0)
#define OUTPUT_ALPHA (255)
#define GLCDC_BRIGHTNESS_MAX (1023U)
#define BRIGHTNESS_MAX (255U)
#define GLCDC_CONTRAST_MAX (255U)
#define ROUND_UP_64BYTES(x) ROUND_UP(x, NUM_BITS(uint64_t))
#define INPUT_FORMAT_PIXEL(n) DT_INST_PROP(n, input_pixel_format)
#define OUTPUT_FORMAT_PIXEL(n) DT_INST_PROP(n, output_pixel_format)
#define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_1 (DISPLAY_IN_FORMAT_32BITS_RGB888)
#define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_8 (DISPLAY_IN_FORMAT_32BITS_ARGB8888)
#define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_16 (DISPLAY_IN_FORMAT_16BITS_RGB565)
#define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_1 (DISPLAY_OUT_FORMAT_24BITS_RGB888)
#define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_16 (DISPLAY_OUT_FORMAT_16BITS_RGB565)
#define RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(n) \
(DT_INST_PROP(n, input_pixel_format) == PANEL_PIXEL_FORMAT_RGB_888 \
? PANEL_PIXEL_FORMAT_ARGB_8888 \
: DT_INST_PROP(n, input_pixel_format))
#define DISPLAY_HSIZE(n) (DT_INST_PROP(n, width))
#define DISPLAY_VSIZE(n) (DT_INST_PROP(n, height))
#define RENESAS_RA_GLCDC_IN_PIXEL_FORMAT(n) \
UTIL_CAT(RENESAS_RA_GLCDC_IN_PIXEL_FORMAT_, INPUT_FORMAT_PIXEL(n))
#define RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT(n) \
UTIL_CAT(RENESAS_RA_GLCDC_OUT_PIXEL_FORMAT_, OUTPUT_FORMAT_PIXEL(n))
#define RENESAS_RA_GLCDC_PIXEL_BYTE_SIZE(n) \
(DISPLAY_BITS_PER_PIXEL(RENESAS_RA_DISPLAY_GET_PIXEL_FORMAT(n)) >> 3)
#define RENESAS_RA_DISPLAY_BUFFER_HSTRIDE_BYTE(n) \
(ROUND_UP_64BYTES(DISPLAY_HSIZE(n) * DISPLAY_BITS_PER_PIXEL(INPUT_FORMAT_PIXEL(n))) / \
DISPLAY_BITS_PER_PIXEL(INPUT_FORMAT_PIXEL(n)))
#define RENESAS_RA_GLCDC_HTIMING(n) \
{.total_cyc = DT_INST_PROP(n, width) + \
DT_PROP(DT_INST_CHILD(n, display_timings), hback_porch) + \
DT_PROP(DT_INST_CHILD(n, display_timings), hfront_porch) + \
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_ */

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
# Copyright (c) 2024 Renesas Electronics Corporation
# Copyright (c) 2024-2025 Renesas Electronics Corporation
# SPDX-License-Identifier: Apache-2.0
description: Renesas Graphic LCD controller
@ -15,10 +15,9 @@ properties: @@ -15,10 +15,9 @@ properties:
required: true
pinctrl-0:
required: true
pinctrl-names:
required: true
description: |
Provide a pin configuration for using parallel pixel output. In combination with DSI HOST
the pin configuration is not necessary due to dedicated (MIPI D-PHY) pins.
interrupts:
required: true
@ -30,11 +29,74 @@ properties: @@ -30,11 +29,74 @@ properties:
backlight-gpios:
type: phandle-array
required: true
description: |
The BLn pin is asserted to control the backlight of the panel.
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:
type: int
required: true
@ -46,3 +108,19 @@ properties: @@ -46,3 +108,19 @@ properties:
required: true
description: |
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