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 <phibang.nguyen@nxp.com>
This commit is contained in:
Phi Bang Nguyen 2025-04-10 19:50:23 +02:00 committed by Benjamin Cabé
commit 7a1285efe5
4 changed files with 83 additions and 11 deletions

View file

@ -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;
}

View file

@ -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++;
}
}
}

View file

@ -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);

View file

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