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; }; /**