From dfbc9b763ec90eddbe0210d41fe5caf64bb4cacf Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 11:20:19 +0700 Subject: [PATCH 1/7] manifest: Update hal_renesas to support CEU on RA SoCs Update hal_renesas to support CEU on RA SoCs Signed-off-by: Duy Vo Signed-off-by: Khanh Nguyen --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index e079b568d77b..7f0d2b08b58e 100644 --- a/west.yml +++ b/west.yml @@ -226,7 +226,7 @@ manifest: - hal - name: hal_renesas path: modules/hal/renesas - revision: 0769fe1520f6c14e6301188588da758a609f181d + revision: pull/113/head groups: - hal - name: hal_rpi_pico From e2a7cb97f6dd1f642ed35432ef73f555c7524732 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 11:26:51 +0700 Subject: [PATCH 2/7] drivers: video: add support for Renesas RA CEU driver Add support for the Renesas RA Capture Engine Unit (CEU), including driver source files, Kconfig options, and DTS bindings. - Add initial implementation of the RA CEU driver - Add dedicated Kconfig and CMake integration - Provide Devicetree bindings for the RA CEU - Update module Kconfig to include the new driver This enables image capture functionality using the CEU peripheral on Renesas RA series MCUs. Signed-off-by: Duy Vo Signed-off-by: Khanh Nguyen --- drivers/video/CMakeLists.txt | 1 + drivers/video/Kconfig | 2 + drivers/video/Kconfig.renesas_ra_ceu | 19 + drivers/video/video_renesas_ra_ceu.c | 460 +++++++++++++++++++++++++ dts/bindings/video/renesas,ra-ceu.yaml | 83 +++++ modules/Kconfig.renesas | 5 + 6 files changed, 570 insertions(+) create mode 100644 drivers/video/Kconfig.renesas_ra_ceu create mode 100644 drivers/video/video_renesas_ra_ceu.c create mode 100644 dts/bindings/video/renesas,ra-ceu.yaml diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 083df586b003..7c0a269a00de 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -25,5 +25,6 @@ zephyr_library_sources_ifdef(CONFIG_VIDEO_EMUL_RX video_emul_rx.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_IMX335 imx335.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_ST_MIPID02 video_st_mipid02.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_DCMIPP video_stm32_dcmipp.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_RENESAS_RA_CEU video_renesas_ra_ceu.c) zephyr_linker_sources(DATA_SECTIONS video.ld) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 924e2156273c..7b1f57a83c48 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -96,4 +96,6 @@ source "drivers/video/Kconfig.st_mipid02" source "drivers/video/Kconfig.stm32_dcmipp" +source "drivers/video/Kconfig.renesas_ra_ceu" + endif # VIDEO diff --git a/drivers/video/Kconfig.renesas_ra_ceu b/drivers/video/Kconfig.renesas_ra_ceu new file mode 100644 index 000000000000..dbdd04572b46 --- /dev/null +++ b/drivers/video/Kconfig.renesas_ra_ceu @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_RENESAS_RA_CEU + bool + default y + depends on DT_HAS_RENESAS_RA_CEU_ENABLED + select PINCTRL + select PWM + select USE_RA_FSP_CEU + help + Enable driver for Renesas RA CEU. + +config VIDEO_RENESAS_BUFFER_SDRAM + bool "Allocate the video buffer into SDRAM" + depends on VIDEO_RENESAS_RA_CEU + select MEMC + help + Allocate the video buffer into SDRAM diff --git a/drivers/video/video_renesas_ra_ceu.c b/drivers/video/video_renesas_ra_ceu.c new file mode 100644 index 000000000000..d9f09f580209 --- /dev/null +++ b/drivers/video/video_renesas_ra_ceu.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2025 Renesas Electronics Co. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ra_ceu + +#include +#include +#include +#include +#include +#include +#include + +#include "video_device.h" +#include "r_ceu.h" + +LOG_MODULE_REGISTER(renesas_ra_video_ceu, CONFIG_VIDEO_LOG_LEVEL); + +/* + * Hardware alignment constraints: + * - Width must be a multiple of 8 pixels. + * - Height must be a multiple of 4 lines. + */ +#define CEU_WIDTH_ALIGN 8U +#define CEU_HEIGHT_ALIGN 4U + +/* + * Default capture configuration: + * - Resolution: 128x96 + * - Bytes per pixel: 2 + */ +#define CEU_DEFAULT_WIDTH 128U +#define CEU_DEFAULT_HEIGHT 96U +#define CEU_DEFAULT_START_X 0U +#define CEU_DEFAULT_START_Y 0U +#define CEU_DEFAULT_BYTES_PER_PIXEL 2U + +struct video_renesas_ra_ceu_config { + void (*irq_config_func)(const struct device *dev); + const struct device *clock_dev; + const struct device *cam_xclk_dev; + const struct device *source_dev; + const struct pinctrl_dev_config *pincfg; + const struct clock_control_ra_subsys_cfg clock_subsys; +}; + +struct video_renesas_ra_ceu_data { + struct video_renesas_ra_ceu_config *config; + struct st_ceu_instance_ctrl *fsp_ctrl; + struct st_capture_cfg *fsp_cfg; + struct st_ceu_extended_cfg *fsp_extend_cfg; + struct video_buffer *vbuf; + struct video_format fmt; + struct k_fifo fifo_in; + struct k_fifo fifo_out; + bool is_streaming; +#ifdef CONFIG_POLL + struct k_poll_signal *signal_out; +#endif +}; + +extern void ceu_isr(void); + +static void video_renesas_ra_ceu_callback(capture_callback_args_t *p_args) +{ + const struct device *dev = p_args->p_context; + struct video_renesas_ra_ceu_data *data = dev->data; + fsp_err_t err; + + if (p_args->event & CEU_EVENT_FRAME_END) { + if (data->vbuf) { + data->vbuf->timestamp = k_uptime_get_32(); + k_fifo_put(&data->fifo_out, data->vbuf); + data->vbuf = NULL; + } + + data->vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT); + if (data->vbuf == NULL) { + return; + } + + err = R_CEU_CaptureStart(&data->fsp_ctrl, data->vbuf->buffer); + if (err != FSP_SUCCESS) { + return; + } + } +} + +static int video_renesas_ra_ceu_get_format(const struct device *dev, struct video_format *fmt) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + int ret; + + ret = video_get_format(config->source_dev, fmt); + if (ret < 0) { + LOG_DBG("Failed to get video format from source device"); + return ret; + } + + fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE; + + return 0; +} + +static int video_renesas_ra_ceu_set_format(const struct device *dev, struct video_format *fmt) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + fsp_err_t err; + int ret; + + fmt->pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE; + + ret = video_set_format(data->config->source_dev, fmt); + if (ret < 0) { + LOG_DBG("Failed to set format on source device"); + return ret; + } + + if (fmt->width % CEU_WIDTH_ALIGN) { + LOG_DBG("Width %d not a multiple of %d", fmt->width, CEU_WIDTH_ALIGN); + return -ENOTSUP; + } + if (fmt->height % CEU_HEIGHT_ALIGN) { + LOG_DBG("Height %d not a multiple of %d", fmt->height, CEU_HEIGHT_ALIGN); + return -ENOTSUP; + } + + if (data->fsp_ctrl->open) { + R_CEU_Close(data->fsp_ctrl); + } + + data->fsp_cfg->x_capture_pixels = fmt->width; + data->fsp_cfg->y_capture_pixels = fmt->height; + data->fsp_cfg->bytes_per_pixel = video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE; + + err = R_CEU_Open(data->fsp_ctrl, data->fsp_cfg); + if (err != FSP_SUCCESS) { + LOG_DBG("Failed to open CEU"); + return -EIO; + } + + memcpy(&data->fmt, fmt, sizeof(struct video_format)); + + return 0; +} + +static int video_renesas_ra_ceu_get_caps(const struct device *dev, struct video_caps *caps) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + + caps->min_line_count = caps->max_line_count = LINE_COUNT_HEIGHT; + + return video_get_caps(config->source_dev, caps); +} + +static int video_renesas_ra_ceu_set_stream(const struct device *dev, bool enable, + enum video_buf_type type) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + struct video_renesas_ra_ceu_data *data = dev->data; + fsp_err_t err; + + if (!enable) { + if (video_stream_stop(config->source_dev, type)) { + LOG_DBG("Failed to stop source device stream"); + return -EIO; + } + + data->is_streaming = false; + R_CEU->CAPSR = R_CEU_CAPSR_CPKIL_Msk; + } + + if (data->is_streaming) { + return -EBUSY; + } + + data->vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT); + if (data->vbuf == NULL) { + LOG_DBG("No enqueued video buffers available to start streaming"); + return -EAGAIN; + } + + err = R_CEU_CaptureStart(&data->fsp_ctrl, data->vbuf->buffer); + if (err != FSP_SUCCESS) { + LOG_DBG("Failed to start CEU capture"); + return -EIO; + } + + if (video_stream_start(config->source_dev, type)) { + LOG_DBG("Failed to start source device stream"); + return -EIO; + } + + data->is_streaming = true; + + return 0; +} + +static int video_renesas_ra_ceu_enqueue(const struct device *dev, struct video_buffer *vbuf) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + const uint32_t buffer_size = data->fmt.pitch * data->fmt.height; + + if (buffer_size > vbuf->size) { + LOG_DBG("Enqueue buffer too small"); + return -EINVAL; + } + + vbuf->bytesused = buffer_size; + vbuf->line_offset = 0; + + k_fifo_put(&data->fifo_in, vbuf); + + return 0; +} + +static int video_renesas_ra_ceu_dequeue(const struct device *dev, struct video_buffer **buf, + k_timeout_t timeout) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + + *buf = k_fifo_get(&data->fifo_out, timeout); + if (*buf == NULL) { + LOG_DBG("Dequeue timeout or no completed buffer available"); + return -EAGAIN; + } + + return 0; +} + +static int video_renesas_ra_ceu_get_frmival(const struct device *dev, struct video_frmival *frmival) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + + return video_get_frmival(config->source_dev, frmival); +} + +static int video_renesas_ra_ceu_set_frmival(const struct device *dev, struct video_frmival *frmival) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + + return video_set_frmival(config->source_dev, frmival); +} + +static int video_renesas_ra_ceu_enum_frmival(const struct device *dev, + struct video_frmival_enum *fie) +{ + const struct video_renesas_ra_ceu_config *config = dev->config; + + return video_enum_frmival(config->source_dev, fie); +} + +static int video_renesas_ra_ceu_flush(const struct device *dev, bool cancel) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + struct video_buffer *vbuf = NULL; + enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT; + + if (cancel) { + if (data->is_streaming) { + video_renesas_ra_ceu_set_stream(dev, false, type); + } + if (data->vbuf) { + k_fifo_put(&data->fifo_out, data->vbuf); + data->vbuf = NULL; + } + while ((vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT)) != NULL) { + k_fifo_put(&data->fifo_out, vbuf); +#ifdef CONFIG_POLL + if (data->signal_out) { + k_poll_signal_raise(data->signal_out, VIDEO_BUF_ABORTED); + } +#endif + } + } else { + while (!k_fifo_is_empty(&data->fifo_in)) { + k_sleep(K_MSEC(1)); + } + } + + return 0; +} + +#ifdef CONFIG_POLL +int video_renesas_ra_ceu_set_signal(const struct device *dev, struct k_poll_signal *sig) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + + data->signal_out = sig; + return 0; +} +#endif + +static int video_renesas_ra_ceu_init(const struct device *dev) +{ + struct video_renesas_ra_ceu_data *data = dev->data; + fsp_err_t err; + int ret; + + ret = pinctrl_apply_state(data->config->pincfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_DBG("Failed to configure pinctrl"); + return ret; + } + + if (!device_is_ready(data->config->clock_dev)) { + LOG_DBG("Clock control device not ready"); + return -ENODEV; + } + + ret = clock_control_on(data->config->clock_dev, + (clock_control_subsys_t)&data->config->clock_subsys); + if (ret < 0) { + LOG_DBG("Failed to enable clock control"); + return ret; + } + + data->config->irq_config_func(dev); + k_fifo_init(&data->fifo_in); + k_fifo_init(&data->fifo_out); + + err = R_CEU_Open(data->fsp_ctrl, data->fsp_cfg); + if (err != FSP_SUCCESS) { + LOG_DBG("Failed to open CEU hardware"); + return -EIO; + } + + return 0; +} + +static DEVICE_API(video, video_renesas_ra_ceu_driver_api) = { + .get_format = video_renesas_ra_ceu_get_format, + .set_format = video_renesas_ra_ceu_set_format, + .get_caps = video_renesas_ra_ceu_get_caps, + .set_stream = video_renesas_ra_ceu_set_stream, + .enqueue = video_renesas_ra_ceu_enqueue, + .dequeue = video_renesas_ra_ceu_dequeue, + .enum_frmival = video_renesas_ra_ceu_enum_frmival, + .set_frmival = video_renesas_ra_ceu_set_frmival, + .get_frmival = video_renesas_ra_ceu_get_frmival, + .flush = video_renesas_ra_ceu_flush, +#ifdef CONFIG_POLL + .set_signal = video_renesas_ra_ceu_set_signal, +#endif +}; + +#define EVENT_CEU_INT(inst) BSP_PRV_IELS_ENUM(CONCAT(EVENT_CEU, _CEUI)) + +#define EP_INST_NODE(inst) DT_INST_ENDPOINT_BY_ID(inst, 0, 0) + +#define EP_INST_PROP_SEL(inst, prop, match_val, val_if_true, val_if_false) \ + (DT_PROP(EP_INST_NODE(inst), prop) == (match_val) ? (val_if_true) : (val_if_false)) + +#define SOURCE_DEV(inst) DEVICE_DT_GET(DT_NODE_REMOTE_DEVICE(EP_INST_NODE(inst))) + +#define VIDEO_RENESAS_RA_CEU_INIT(inst) \ + static void video_renesas_ra_ceu_irq_config_func##inst(const struct device *dev) \ + { \ + R_ICU->IELSR[DT_INST_IRQ_BY_NAME(inst, ceui, irq)] = EVENT_CEU_INT(inst); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, ceui, irq), \ + DT_INST_IRQ_BY_NAME(inst, ceui, priority), ceu_isr, NULL, 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, ceui, irq)); \ + } \ + \ + static int video_renesas_ra_ceu_cam_clock_init##inst(void) \ + { \ + const struct device *dev = DEVICE_DT_INST_GET(inst); \ + const struct video_renesas_ra_ceu_config *config = dev->config; \ + int ret; \ + \ + if (!device_is_ready(config->cam_xclk_dev)) { \ + LOG_DBG("Camera clock control device not ready"); \ + return -ENODEV; \ + } \ + \ + ret = clock_control_on(config->cam_xclk_dev, (clock_control_subsys_t)0); \ + if (ret < 0) { \ + LOG_DBG("Failed to enable camera clock control"); \ + return ret; \ + } \ + return 0; \ + } \ + \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + static struct video_renesas_ra_ceu_config video_renesas_ra_ceu_config##inst = { \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(inst, pclk)), \ + .cam_xclk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(inst, cam_xclk)), \ + .source_dev = SOURCE_DEV(inst), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .clock_subsys = \ + { \ + .mstp = DT_INST_CLOCKS_CELL_BY_NAME(inst, pclk, mstp), \ + .stop_bit = DT_INST_CLOCKS_CELL_BY_NAME(inst, pclk, stop_bit), \ + }, \ + .irq_config_func = video_renesas_ra_ceu_irq_config_func##inst, \ + }; \ + \ + static struct st_ceu_instance_ctrl video_renesas_ra_ceu_fsp_ctrl##inst = { \ + .p_context = DEVICE_DT_INST_GET(inst), \ + .p_callback_memory = NULL, \ + }; \ + \ + static struct st_ceu_extended_cfg video_renesas_ra_ceu_fsp_extend_cfg##inst = { \ + .capture_format = CEU_CAPTURE_FORMAT_DATA_SYNCHRONOUS, \ + .data_bus_width = EP_INST_PROP_SEL(inst, bus_width, 8, 0, 1), \ + .edge_info = \ + { \ + .dsel = EP_INST_PROP_SEL(inst, pclk_sample, 1, 0, 1), \ + .hdsel = EP_INST_PROP_SEL(inst, hsync_sample, 1, 0, 1), \ + .vdsel = EP_INST_PROP_SEL(inst, vsync_sample, 1, 0, 1), \ + }, \ + .hsync_polarity = EP_INST_PROP_SEL(inst, hsync_active, 1, 0, 1), \ + .vsync_polarity = EP_INST_PROP_SEL(inst, vsync_active, 1, 0, 1), \ + .byte_swapping = \ + { \ + .swap_8bit_units = DT_INST_PROP(inst, swap_8bits), \ + .swap_16bit_units = DT_INST_PROP(inst, swap_16bits), \ + .swap_32bit_units = DT_INST_PROP(inst, swap_32bits), \ + }, \ + .burst_mode = DT_INST_ENUM_IDX(inst, burst_transfer), \ + .ceu_ipl = DT_INST_IRQ_BY_NAME(inst, ceui, priority), \ + .ceu_irq = DT_INST_IRQ_BY_NAME(inst, ceui, irq), \ + .interrupts_enabled = R_CEU_CEIER_CPEIE_Msk | R_CEU_CEIER_VDIE_Msk | \ + R_CEU_CEIER_CDTOFIE_Msk | R_CEU_CEIER_VBPIE_Msk | \ + R_CEU_CEIER_NHDIE_Msk | R_CEU_CEIER_NVDIE_Msk, \ + }; \ + \ + static struct st_capture_cfg video_renesas_ra_ceu_fsp_cfg##inst = { \ + .x_capture_pixels = CEU_DEFAULT_WIDTH, \ + .y_capture_pixels = CEU_DEFAULT_HEIGHT, \ + .x_capture_start_pixel = CEU_DEFAULT_START_X, \ + .y_capture_start_pixel = CEU_DEFAULT_START_Y, \ + .bytes_per_pixel = CEU_DEFAULT_BYTES_PER_PIXEL, \ + .p_extend = &video_renesas_ra_ceu_fsp_extend_cfg##inst, \ + .p_callback = video_renesas_ra_ceu_callback, \ + .p_context = DEVICE_DT_INST_GET(inst), \ + }; \ + \ + static struct video_renesas_ra_ceu_data video_renesas_ra_ceu_data##inst = { \ + .config = &video_renesas_ra_ceu_config##inst, \ + .fsp_ctrl = &video_renesas_ra_ceu_fsp_ctrl##inst, \ + .fsp_cfg = &video_renesas_ra_ceu_fsp_cfg##inst, \ + .fsp_extend_cfg = &video_renesas_ra_ceu_fsp_extend_cfg##inst, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &video_renesas_ra_ceu_init, NULL, \ + &video_renesas_ra_ceu_data##inst, \ + &video_renesas_ra_ceu_config##inst, POST_KERNEL, \ + CONFIG_VIDEO_INIT_PRIORITY, &video_renesas_ra_ceu_driver_api); \ + \ + VIDEO_DEVICE_DEFINE(renesas_ra_ceu##inst, DEVICE_DT_INST_GET(inst), SOURCE_DEV(inst)); \ + \ + SYS_INIT(video_renesas_ra_ceu_cam_clock_init##inst, POST_KERNEL, \ + CONFIG_CLOCK_CONTROL_PWM_INIT_PRIORITY); + +DT_INST_FOREACH_STATUS_OKAY(VIDEO_RENESAS_RA_CEU_INIT) diff --git a/dts/bindings/video/renesas,ra-ceu.yaml b/dts/bindings/video/renesas,ra-ceu.yaml new file mode 100644 index 000000000000..f31cfb53b6c6 --- /dev/null +++ b/dts/bindings/video/renesas,ra-ceu.yaml @@ -0,0 +1,83 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RA Capture Engine Unit Driver (ceu) + +compatible: "renesas,ra-ceu" + +include: [base.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + clock-names: + required: true + enum: + - "pclk" + - "cam-xclk" + + swap-8bits: + type: boolean + description: Bytes may be swapped in 8-bit units + + swap-16bits: + type: boolean + description: Bytes may be swapped in 16-bit units + + swap-32bits: + type: boolean + description: Bytes may be swapped in 32-bit units + + burst-transfer: + required: true + type: int + enum: + - 32 # Transfers data to the bus in 32-byte units + - 64 # Transfers data to the bus in 64-byte units + - 128 # Transfers data to the bus in 128-byte units + - 256 # Transfers data to the bus in 256-byte units + description: | + Specifies the data transfer unit size to the bus bridge module. + +child-binding: + child-binding: + include: video-interfaces.yaml + + properties: + hsync-active: + required: true + + vsync-active: + required: true + + pclk-sample: + required: true + + vsync-sample: + required: true + type: int + enum: + - 0 # Falling edge + - 1 # Rising edge + description: | + Sample on the falling or rising edge of the vsync signal. + + hsync-sample: + required: true + type: int + enum: + - 0 # Falling edge + - 1 # Rising edge + description: | + Sample on the falling or rising edge of the hsync signal. + + bus-width: + required: true + type: int + enum: + - 8 # Use 8 data lines for the parallel interface + - 16 # Use 16 data lines for the parallel interface diff --git a/modules/Kconfig.renesas b/modules/Kconfig.renesas index e6e833dff548..9bea115853da 100644 --- a/modules/Kconfig.renesas +++ b/modules/Kconfig.renesas @@ -191,6 +191,11 @@ config USE_RA_FSP_ELC help Enable RA FSP ELC driver +config USE_RA_FSP_CEU + bool + help + Enable RA FSP CEU driver + endif # HAS_RENESAS_RA_FSP if HAS_RENESAS_RZ_FSP From 799fccf79a3b8eac5ac5b9a030a42d6484c771d2 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 11:55:18 +0700 Subject: [PATCH 3/7] include: dt-bindings: renesas: Add RA CEU pin definitions Add pin definitions required by the RA Capture Engine Unit Signed-off-by: Duy Vo Signed-off-by: Khanh Nguyen --- include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h index 1f626c37abbf..34ccdce85475 100644 --- a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-ra.h @@ -47,6 +47,7 @@ #define RA_PSEL_ETH_RMII 0x17 #define RA_PSEL_GLCDC 0x19 #define RA_PSEL_OSPI 0x1c +#define RA_PSEL_CEU 0xf #define RA_PSEL_POS 8 #define RA_PSEL_MASK 0x1f From fca0cf860853c5939bed2b20603807f8d8de2a7d Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 11:59:45 +0700 Subject: [PATCH 4/7] dts: arm: renesas: Add CEU nodes for RA8D1 and RA8M1 SoCs Add CEU to r7fa8d1xh.dtsi and r7fa8m1xh.dtsi Signed-off-by: Khanh Nguyen --- dts/arm/renesas/ra/ra8/r7fa8d1xh.dtsi | 7 +++++++ dts/arm/renesas/ra/ra8/r7fa8m1xh.dtsi | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/dts/arm/renesas/ra/ra8/r7fa8d1xh.dtsi b/dts/arm/renesas/ra/ra8/r7fa8d1xh.dtsi index e1abfa502484..fabef6762b00 100644 --- a/dts/arm/renesas/ra/ra8/r7fa8d1xh.dtsi +++ b/dts/arm/renesas/ra/ra8/r7fa8d1xh.dtsi @@ -295,6 +295,13 @@ status = "disabled"; }; }; + + ceu: ceu@40348000 { + compatible = "renesas,ra-ceu"; + reg = <0x40348000 0x8000>; + clocks = <&pclka MSTPC 16>; + status = "disabled"; + }; }; usbhs_phy: usbhs-phy { diff --git a/dts/arm/renesas/ra/ra8/r7fa8m1xh.dtsi b/dts/arm/renesas/ra/ra8/r7fa8m1xh.dtsi index 60fbd8c287ef..43c454f3b1d7 100644 --- a/dts/arm/renesas/ra/ra8/r7fa8m1xh.dtsi +++ b/dts/arm/renesas/ra/ra8/r7fa8m1xh.dtsi @@ -259,6 +259,13 @@ status = "disabled"; }; }; + + ceu: ceu@40348000 { + compatible = "renesas,ra-ceu"; + reg = <0x40348000 0x8000>; + clocks = <&pclka MSTPC 16>; + status = "disabled"; + }; }; usbhs_phy: usbhs-phy { From fb39bb85c09145d7120e3ca39ec39c52bde807a7 Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 13:03:37 +0700 Subject: [PATCH 5/7] boards: renesas: Enable CEU video capture support on EK-RA8D1 - Add CEU pin configuration to ek_ra8d1-pinctrl.dtsi - Enable CEU node and Arducam 20-pin connector in ek_ra8d1.dts - Configure PWM3 as external XCLK via pwm-clock node - Update board YAML to declare video support Signed-off-by: Duy Vo Signed-off-by: Khanh Nguyen --- boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi | 35 ++++++++++++++ boards/renesas/ek_ra8d1/ek_ra8d1.dts | 46 +++++++++++++++++++ boards/renesas/ek_ra8d1/ek_ra8d1.yaml | 1 + 3 files changed, 82 insertions(+) diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi index af7c788374be..43ea0e5968ae 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi +++ b/boards/renesas/ek_ra8d1/ek_ra8d1-pinctrl.dtsi @@ -10,6 +10,7 @@ psels = ; drive-strength = "medium"; }; + group2 { /* rx */ psels = ; @@ -35,11 +36,26 @@ }; }; + pwm3_default: pwm3_default { + group1 { + /* GTIOC3A */ + psels = ; + drive-strength = "medium"; + }; + + group2 { + /* GTIOC3B */ + psels = ; + drive-strength = "medium"; + }; + }; + pwm7_default: pwm7_default { group1 { /* GTIOC7A */ psels = ; }; + group2 { /* GTIOC7B */ psels = ; @@ -208,6 +224,7 @@ ; /* SDWP */ drive-strength = "high"; }; + group2 { psels = ; /* SDCLK */ drive-strength = "highspeed-high"; @@ -289,4 +306,22 @@ drive-strength = "high"; }; }; + + ceu_default: ceu_default { + group1 { + /* CEU */ + psels = , /* VIO_D0 */ + , /* VIO_D1 */ + , /* VIO_D2 */ + , /* VIO_D3 */ + , /* VIO_D4 */ + , /* VIO_D5 */ + , /* VIO_D6 */ + , /* VIO_D7 */ + , /* VIO_CLK */ + , /* VIO_HD */ + ; /* VIO_VD */ + drive-strength = "high"; + }; + }; }; diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1.dts b/boards/renesas/ek_ra8d1/ek_ra8d1.dts index 25fde67752f6..effb79de7914 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1.dts +++ b/boards/renesas/ek_ra8d1/ek_ra8d1.dts @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "ek_ra8d1-pinctrl.dtsi" / { @@ -78,6 +80,15 @@ <18 0 &ioporta 1 0>; /* DISP_RST */ }; + dvp_20pin_connector: dvp-20pin-connector { + compatible = "arducam,dvp-20pin-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0x0 0x3f>; + gpio-map = , + ; + }; + aliases { led0 = &led1; sw0 = &button0; @@ -178,6 +189,10 @@ status = "okay"; }; +&ioport7 { + status = "okay"; +}; + &ioporta { status = "okay"; }; @@ -226,6 +241,22 @@ }; }; +&pwm3 { + pinctrl-0 = <&pwm3_default>; + pinctrl-names = "default"; + interrupts = <51 12>, <52 12>; + interrupt-names = "gtioca", "overflow"; + status = "okay"; + + cam_clock: pwmclock { + compatible = "pwm-clock"; + #clock-cells = <1>; + clock-frequency = <24000000>; + pwms = <&pwm3 0 PWM_KHZ(24000) PWM_POLARITY_NORMAL>; + status = "okay"; + }; +}; + &pwm7 { pinctrl-0 = <&pwm7_default>; interrupts = <40 1>, <41 1>; @@ -329,6 +360,17 @@ }; }; +&ceu { + pinctrl-0 = <&ceu_default>; + pinctrl-names = "default"; + interrupts = <53 12>; + interrupt-names = "ceui"; + clocks = <&pclka MSTPC 16>, <&cam_clock 0>; + clock-names = "pclk", "cam-xclk"; + burst-transfer = <256>; + status = "okay"; +}; + zephyr_lcdif: &lcdif {}; zephyr_mipi_dsi: &mipi_dsi {}; @@ -337,6 +379,10 @@ renesas_mipi_i2c: &iic1 {}; pmod_sd_shield: &sdhc1 {}; +dvp_20pin_i2c: &iic1 {}; + +dvp_20pin_interface: &ceu {}; + &usbfs { pinctrl-0 = <&usbfs_default>; pinctrl-names = "default"; diff --git a/boards/renesas/ek_ra8d1/ek_ra8d1.yaml b/boards/renesas/ek_ra8d1/ek_ra8d1.yaml index c4348dcc7f50..2264a858dfef 100644 --- a/boards/renesas/ek_ra8d1/ek_ra8d1.yaml +++ b/boards/renesas/ek_ra8d1/ek_ra8d1.yaml @@ -14,4 +14,5 @@ supported: - usbd - display - counter + - video vendor: renesas From fd2a0d2a33410d76255b9d2c36f2fb28106f1c0c Mon Sep 17 00:00:00 2001 From: Khanh Nguyen Date: Fri, 20 Jun 2025 15:15:59 +0700 Subject: [PATCH 6/7] samples: video: Add CEU support for Renesas RA boards Add EK-RA8D1 board support for the capture_to_lvgl sample - Add board-specific configuration in ek_ra8d1.conf - Add Devicetree overlay enabling CEU and display path Signed-off-by: Duy Vo Signed-off-by: Khanh Nguyen --- .../capture_to_lvgl/boards/ek_ra8d1.conf | 1 + .../capture_to_lvgl/boards/ek_ra8d1.overlay | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.conf create mode 100644 samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.overlay diff --git a/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.conf b/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.conf new file mode 100644 index 000000000000..cfb4819a8e77 --- /dev/null +++ b/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.conf @@ -0,0 +1 @@ +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=160000 diff --git a/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.overlay b/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.overlay new file mode 100644 index 000000000000..485837e4111f --- /dev/null +++ b/samples/drivers/video/capture_to_lvgl/boards/ek_ra8d1.overlay @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dvp_20pin_connector { + status = "okay"; +}; + +&dvp_20pin_i2c { + status = "okay"; + clock-frequency = ; +}; + +&dvp_20pin_interface { + status = "okay"; + swap-8bits; + swap-16bits; + swap-32bits; + + port { + dvp_20pin_ep_in: endpoint { + bus-width = <8>; + hsync-active = <1>; + vsync-active = <1>; + pclk-sample = <1>; + hsync-sample = <0>; + vsync-sample = <0>; + }; + }; +}; + +&renesas_mipi_i2c { + gt911_rtkmipilcdb00000be: gt911-rtkmipilcdb00000be@5d { + status = "disabled"; + }; +}; + +&zephyr_lcdif { + input-pixel-format = ; +}; From 92a4b3bc6b427171576be1599c2ff3a5525dc754 Mon Sep 17 00:00:00 2001 From: Thao Luong Date: Wed, 25 Jun 2025 11:26:17 +0700 Subject: [PATCH 7/7] boards: renesas: ek_ra8d1: Update document for using Camera Add SW1 configuration for using Camera Exapansion Port (J59) Signed-off-by: Thao Luong --- boards/renesas/ek_ra8d1/doc/index.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/boards/renesas/ek_ra8d1/doc/index.rst b/boards/renesas/ek_ra8d1/doc/index.rst index 027f08a261d1..43fe0dd4e264 100644 --- a/boards/renesas/ek_ra8d1/doc/index.rst +++ b/boards/renesas/ek_ra8d1/doc/index.rst @@ -111,6 +111,14 @@ Supported Features | OFF | OFF | OFF | OFF | OFF | ON | ON | OFF | +-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ + - For using the Camera Expansion Port (J59) with the Camera, please set switch SW1 as following configuration: + + +-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ + | SW1-1 PMOD1 | SW1-2 TRACE | SW1-3 CAMERA | SW1-4 ETHA | SW1-5 ETHB | SW1-6 GLCD | SW1-7 SDRAM | SW1-8 I3C | + +-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ + | OFF | OFF | ON | OFF | OFF | OFF | ON | OFF | + +-------------+-------------+--------------+------------+------------+------------+-------------+-----------+ + .. warning:: Do not enable SW1-4 and SW1-5 together