From 7a1285efe598b5280b10f47e5eb419fda16a55ef Mon Sep 17 00:00:00 2001 From: Phi Bang Nguyen Date: Thu, 10 Apr 2025 19:50:23 +0200 Subject: [PATCH] drivers: video: Add support for controls of menu types Add support for controls of menu types, standard menu and drivers' defined menu. Rework the ov5640's test pattern and power line frequency controls using this new support. Signed-off-by: Phi Bang Nguyen --- drivers/video/ov5640.c | 23 +++++----- drivers/video/video_ctrls.c | 56 ++++++++++++++++++++++++- drivers/video/video_ctrls.h | 4 ++ include/zephyr/drivers/video-controls.h | 11 +++++ 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/drivers/video/ov5640.c b/drivers/video/ov5640.c index 71957326364..c70908a2434 100644 --- a/drivers/video/ov5640.c +++ b/drivers/video/ov5640.c @@ -956,6 +956,15 @@ static const uint8_t test_pattern_val[] = { TEST_PATTERN_ENABLE | TEST_PATTERN_SQUARE | TEST_PATTERN_ROLLING, }; +static const char *const test_pattern_menu[] = { + "Disabled", + "Color bars", + "Color bars with rolling bar", + "Color squares", + "Color squares with rolling bar", + NULL +}; + static int ov5640_set_ctrl_test_pattern(const struct device *dev, int value) { const struct ov5640_config *cfg = dev->config; @@ -1282,20 +1291,14 @@ static int ov5640_init_controls(const struct device *dev) return ret; } - ret = video_init_ctrl( - &ctrls->light_freq, dev, VIDEO_CID_POWER_LINE_FREQUENCY, - (struct video_ctrl_range){.min = VIDEO_CID_POWER_LINE_FREQUENCY_DISABLED, - .max = VIDEO_CID_POWER_LINE_FREQUENCY_AUTO, - .step = 1, - .def = VIDEO_CID_POWER_LINE_FREQUENCY_50HZ}); + ret = video_init_menu_ctrl(&ctrls->light_freq, dev, VIDEO_CID_POWER_LINE_FREQUENCY, + VIDEO_CID_POWER_LINE_FREQUENCY_50HZ, NULL); if (ret) { return ret; } - ret = video_init_ctrl( - &ctrls->test_pattern, dev, VIDEO_CID_TEST_PATTERN, - (struct video_ctrl_range){ - .min = 0, .max = ARRAY_SIZE(test_pattern_val) - 1, .step = 1, .def = 0}); + ret = video_init_menu_ctrl(&ctrls->test_pattern, dev, VIDEO_CID_TEST_PATTERN, 0, + test_pattern_menu); if (ret) { return ret; } diff --git a/drivers/video/video_ctrls.c b/drivers/video/video_ctrls.c index ffc84fc9414..25906f13c31 100644 --- a/drivers/video/video_ctrls.c +++ b/drivers/video/video_ctrls.c @@ -15,6 +15,24 @@ LOG_MODULE_REGISTER(video_ctrls, CONFIG_VIDEO_LOG_LEVEL); +static inline const char *const *video_get_std_menu_ctrl(uint32_t id) +{ + static const char *const camera_power_line_frequency[] = {"Disabled", "50 Hz", "60 Hz", + "Auto", NULL}; + static const char *const camera_exposure_auto[] = {"Auto Mode", "Manual Mode", + "Shutter Priority Mode", + "Aperture Priority Mode", NULL}; + + switch (id) { + case VIDEO_CID_POWER_LINE_FREQUENCY: + return camera_power_line_frequency; + case VIDEO_CID_EXPOSURE_AUTO: + return camera_exposure_auto; + default: + return NULL; + } +} + static inline int check_range(enum video_ctrl_type type, struct video_ctrl_range range) { switch (type) { @@ -98,6 +116,7 @@ int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t ctrl->cluster = NULL; ctrl->is_auto = false; ctrl->has_volatiles = false; + ctrl->menu = NULL; ctrl->vdev = vdev; ctrl->id = id; ctrl->type = type; @@ -123,6 +142,34 @@ int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t return 0; } +int video_init_menu_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t id, + uint8_t def, const char *const menu[]) +{ + int ret; + uint8_t sz = 0; + const char *const *_menu = menu ? menu : video_get_std_menu_ctrl(id); + + if (!_menu) { + return -EINVAL; + } + + while (_menu[sz]) { + sz++; + } + + ret = video_init_ctrl( + ctrl, dev, id, + (struct video_ctrl_range){.min = 0, .max = sz - 1, .step = 1, .def = def}); + + if (ret) { + return ret; + } + + ctrl->menu = _menu; + + return 0; +} + /* By definition, the cluster is in manual mode if the master control value is 0 */ static inline bool is_cluster_manual(const struct video_ctrl *master) { @@ -404,7 +451,7 @@ fill_query: cq->type = ctrl->type; cq->flags = ctrl->flags; cq->range = ctrl->range; - + cq->menu = ctrl->menu; cq->name = video_get_ctrl_name(cq->id); return 0; @@ -457,4 +504,11 @@ void video_print_ctrl(const struct device *const dev, const struct video_ctrl_qu cq->name, cq->id, typebuf, cq->flags, cq->range.min, cq->range.max, cq->range.step, cq->range.def, vc.val); } + + if (cq->menu) { + while (cq->menu[i]) { + LOG_INF("%*s %u: %s", 32, "", i, cq->menu[i]); + i++; + } + } } diff --git a/drivers/video/video_ctrls.h b/drivers/video/video_ctrls.h index b154ad3431a..07c6c5575f3 100644 --- a/drivers/video/video_ctrls.h +++ b/drivers/video/video_ctrls.h @@ -54,12 +54,16 @@ struct video_ctrl { int32_t val; int64_t val64; }; + const char *const *menu; sys_dnode_t node; }; int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t id, struct video_ctrl_range range); +int video_init_menu_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t id, + uint8_t def, const char *const menu[]); + void video_cluster_ctrl(struct video_ctrl *ctrls, uint8_t sz); void video_auto_cluster_ctrl(struct video_ctrl *ctrls, uint8_t sz, bool set_volatile); diff --git a/include/zephyr/drivers/video-controls.h b/include/zephyr/drivers/video-controls.h index 73937ba1958..4304316c181 100644 --- a/include/zephyr/drivers/video-controls.h +++ b/include/zephyr/drivers/video-controls.h @@ -107,6 +107,15 @@ enum video_power_line_frequency { */ #define VIDEO_CID_CAMERA_CLASS_BASE 0x009a0900 +/** Adjustments of exposure time and/or iris aperture. */ +#define VIDEO_CID_EXPOSURE_AUTO (VIDEO_CID_CAMERA_CLASS_BASE + 1) +enum video_exposure_auto_type { + VIDEO_EXPOSURE_AUTO = 0, + VIDEO_EXPOSURE_MANUAL = 1, + VIDEO_EXPOSURE_SHUTTER_PRIORITY = 2, + VIDEO_EXPOSURE_APERTURE_PRIORITY = 3 +}; + /** Amount of optical zoom applied through to the camera optics */ #define VIDEO_CID_ZOOM_ABSOLUTE (VIDEO_CID_CAMERA_CLASS_BASE + 13) @@ -256,6 +265,8 @@ struct video_ctrl_query { uint32_t flags; /** control range */ struct video_ctrl_range range; + /** menu if control is of menu type */ + const char *const *menu; }; /**