Skip to content

video: introduction of STM32 DCMIPP driver #89407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions drivers/video/video_stm32_dcmipp.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <zephyr/drivers/video-controls.h>
#include <zephyr/dt-bindings/video/video-interfaces.h>
#include <zephyr/logging/log.h>
#include <zephyr/video/stm32_dcmipp.h>

#include "video_ctrls.h"
#include "video_device.h"
Expand All @@ -33,6 +34,26 @@
#define STM32_DCMIPP_HAS_PIXEL_PIPES
#endif

/* Weak function declaration in order to interface with external ISP handler */
void __weak stm32_dcmipp_isp_vsync_update(DCMIPP_HandleTypeDef *hdcmipp, uint32_t Pipe)
{
}

int __weak stm32_dcmipp_isp_init(DCMIPP_HandleTypeDef *hdcmipp, const struct device *source)
{
return 0;
}

int __weak stm32_dcmipp_isp_start(void)
{
return 0;
}

int __weak stm32_dcmipp_isp_stop(void)
{
return 0;
}
Comment on lines +37 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my better knowledge, could you give some more details about the external ISP handler who could override these functions ? Is it supposed to be the application, the drivers or some library ? Thanks

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The application (or a library linked together with the application) would implement those function which perform the ISP configuration via the DCMIPP HAL code. There are already available library for that purpose, such as

https://wiki.st.com/stm32mcu/wiki/ISP:ISP_middleware
https://github.com/STMicroelectronics/STM32CubeN6/tree/v1.1.0/Middlewares/ST/STM32_ISP_Library

So the Zephyr DCMIPP driver is performing all the pipeline configuration and the ISP part (aka, statistics analysis, configuration of various ISP blocks) are done via those handler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we need some thing equivalent to libcamera mechanisms in the future to support these cases generically


LOG_MODULE_REGISTER(stm32_dcmipp, CONFIG_VIDEO_LOG_LEVEL);

typedef void (*irq_config_func_t)(const struct device *dev);
Expand Down Expand Up @@ -148,6 +169,12 @@ void HAL_DCMIPP_PIPE_VsyncEventCallback(DCMIPP_HandleTypeDef *hdcmipp, uint32_t
struct stm32_dcmipp_pipe_data *pipe = dcmipp->pipe[Pipe];
int ret;

/*
* Let the external ISP handler know that a VSYNC happened a new statistics are
* thus available
*/
stm32_dcmipp_isp_vsync_update(hdcmipp, Pipe);

if (pipe->state != STM32_DCMIPP_RUNNING) {
return;
}
Expand Down Expand Up @@ -526,9 +553,64 @@ static int stm32_dcmipp_set_fmt(const struct device *dev, struct video_format *f
return ret;
}

#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
static void stm32_dcmipp_get_isp_decimation(struct stm32_dcmipp_data *dcmipp)
{
DCMIPP_DecimationConfTypeDef ispdec_cfg;
uint32_t is_enabled;

is_enabled = HAL_DCMIPP_PIPE_IsEnabledISPDecimation(&dcmipp->hdcmipp, DCMIPP_PIPE1);
if (is_enabled == 0) {
dcmipp->isp_dec_hratio = 1;
dcmipp->isp_dec_vratio = 1;
} else {
HAL_DCMIPP_PIPE_GetISPDecimationConfig(&dcmipp->hdcmipp, DCMIPP_PIPE1, &ispdec_cfg);
dcmipp->isp_dec_hratio = 1 << (ispdec_cfg.HRatio >> DCMIPP_P1DECR_HDEC_Pos);
dcmipp->isp_dec_vratio = 1 << (ispdec_cfg.VRatio >> DCMIPP_P1DECR_VDEC_Pos);
}
}
#endif

static int stm32_dcmipp_get_fmt(const struct device *dev, struct video_format *fmt)
{
struct stm32_dcmipp_pipe_data *pipe = dev->data;
#if defined(STM32_DCMIPP_HAS_PIXEL_PIPES)
struct stm32_dcmipp_data *dcmipp = pipe->dcmipp;
const struct stm32_dcmipp_config *config = dev->config;
static atomic_t isp_init_once;
int ret;

/* Initialize the external ISP handling stack */
/*
* TODO - this is not the right place to do that, however we need to know
* the source format before calling the isp_init handler hence can't
* do that within the stm32_dcmipp_init function due to unknown
* driver initialization order
*
* Would need an ops that get called when both side of an endpoint get
* initiialized
*/
if (atomic_cas(&isp_init_once, 0, 1) &&
(pipe->id == DCMIPP_PIPE1 || pipe->id == DCMIPP_PIPE2)) {
/*
* It is necessary to perform a dummy configuration here otherwise any
* ISP related configuration done by the stm32_dcmipp_isp_init will
* fail due to the HAL DCMIPP driver not being in READY state
*/
ret = stm32_dcmipp_conf_parallel(dcmipp->dev, &stm32_dcmipp_input_fmt_desc[0]);
if (ret < 0) {
LOG_ERR("Failed to perform dummy parallel configuration");
return ret;
}

ret = stm32_dcmipp_isp_init(&dcmipp->hdcmipp, config->source_dev);
if (ret < 0) {
LOG_ERR("Failed to initialize the ISP");
return ret;
}
stm32_dcmipp_get_isp_decimation(dcmipp);
}
#endif

*fmt = pipe->fmt;

Expand Down Expand Up @@ -864,6 +946,12 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
}
#endif

/* Initialize the external ISP handling stack */
ret = stm32_dcmipp_isp_init(&dcmipp->hdcmipp, config->source_dev);
if (ret < 0) {
goto out;
}

/* Enable the DCMIPP Pipeline */
if (config->bus_type == VIDEO_BUS_TYPE_PARALLEL) {
ret = HAL_DCMIPP_PIPE_Start(&dcmipp->hdcmipp, pipe->id,
Expand Down Expand Up @@ -909,6 +997,12 @@ static int stm32_dcmipp_stream_enable(const struct device *dev)
}
}

/* Start the external ISP handling */
ret = stm32_dcmipp_isp_start();
if (ret < 0) {
goto out;
}

pipe->state = STM32_DCMIPP_RUNNING;
pipe->is_streaming = true;
dcmipp->enabled_pipe++;
Expand All @@ -933,6 +1027,12 @@ static int stm32_dcmipp_stream_disable(const struct device *dev)
goto out;
}

/* Stop the external ISP handling */
ret = stm32_dcmipp_isp_stop();
if (ret < 0) {
goto out;
}

/* Disable the DCMIPP Pipeline */
if (config->bus_type == VIDEO_BUS_TYPE_PARALLEL) {
ret = HAL_DCMIPP_PIPE_Stop(&dcmipp->hdcmipp, pipe->id);
Expand Down
16 changes: 16 additions & 0 deletions include/zephyr/video/stm32_dcmipp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2025 STMicroelectronics.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef ZEPHYR_INCLUDE_VIDEO_STM32_DCMIPP_H_
#define ZEPHYR_INCLUDE_VIDEO_STM32_DCMIPP_H_

/* Prototypes of ISP external handler weak functions */
void stm32_dcmipp_isp_vsync_update(DCMIPP_HandleTypeDef *hdcmipp, uint32_t Pipe);
int stm32_dcmipp_isp_init(DCMIPP_HandleTypeDef *hdcmipp, const struct device *source);
int stm32_dcmipp_isp_start(void);
int stm32_dcmipp_isp_stop(void);

#endif /* ZEPHYR_INCLUDE_VIDEO_STM32_DCMIPP_H_ */