diff --git a/drivers/video/gc2145.c b/drivers/video/gc2145.c index 22277679652..3b6596453ee 100644 --- a/drivers/video/gc2145.c +++ b/drivers/video/gc2145.c @@ -1110,13 +1110,15 @@ static int gc2145_get_caps(const struct device *dev, enum video_endpoint_id ep, return 0; } -static int gc2145_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int gc2145_set_ctrl(const struct device *dev, uint32_t id) { - switch (ctrl->id) { + struct gc2145_data *drv_data = dev->data; + + switch (id) { case VIDEO_CID_HFLIP: - return gc2145_set_ctrl_hmirror(dev, ctrl->val); + return gc2145_set_ctrl_hmirror(dev, drv_data->ctrls.hflip.val); case VIDEO_CID_VFLIP: - return gc2145_set_ctrl_vflip(dev, ctrl->val); + return gc2145_set_ctrl_vflip(dev, drv_data->ctrls.vflip.val); default: return -ENOTSUP; } diff --git a/drivers/video/mt9m114.c b/drivers/video/mt9m114.c index fc4435ccd3f..16d4e61bb39 100644 --- a/drivers/video/mt9m114.c +++ b/drivers/video/mt9m114.c @@ -473,20 +473,23 @@ static int mt9m114_get_caps(const struct device *dev, enum video_endpoint_id ep, return 0; } -static int mt9m114_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int mt9m114_set_ctrl(const struct device *dev, uint32_t id) { int ret = 0; + struct mt9m114_data *drv_data = dev->data; - switch (ctrl->id) { + switch (id) { case VIDEO_CID_HFLIP: - ret = mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2, - MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN, - ctrl->val ? MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN : 0); + ret = mt9m114_modify_reg( + dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2, + MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN, + drv_data->ctrls.hflip.val ? MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN : 0); break; case VIDEO_CID_VFLIP: - ret = mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2, - MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN, - ctrl->val ? MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN : 0); + ret = mt9m114_modify_reg( + dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2, + MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN, + drv_data->ctrls.vflip.val ? MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN : 0); break; default: return -ENOTSUP; diff --git a/drivers/video/ov2640.c b/drivers/video/ov2640.c index a9e50c7ab44..5da0c2d504e 100644 --- a/drivers/video/ov2640.c +++ b/drivers/video/ov2640.c @@ -895,32 +895,35 @@ static int ov2640_get_caps(const struct device *dev, return 0; } -static int ov2640_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int ov2640_set_ctrl(const struct device *dev, uint32_t id) { - switch (ctrl->id) { + struct ov2640_data *drv_data = dev->data; + struct ov2640_ctrls *ctrls = &drv_data->ctrls; + + switch (id) { case VIDEO_CID_HFLIP: - return ov2640_set_horizontal_mirror(dev, ctrl->val); + return ov2640_set_horizontal_mirror(dev, ctrls->hflip.val); case VIDEO_CID_VFLIP: - return ov2640_set_vertical_flip(dev, ctrl->val); + return ov2640_set_vertical_flip(dev, ctrls->vflip.val); case VIDEO_CID_EXPOSURE: - return ov2640_set_exposure_ctrl(dev, ctrl->val); + return ov2640_set_exposure_ctrl(dev, ctrls->ae.val); case VIDEO_CID_WHITE_BALANCE_TEMPERATURE: - return ov2640_set_white_bal(dev, ctrl->val); + return ov2640_set_white_bal(dev, ctrls->awb.val); case VIDEO_CID_GAIN: - return ov2640_set_gain_ctrl(dev, ctrl->val); + return ov2640_set_gain_ctrl(dev, ctrls->gain.val); case VIDEO_CID_BRIGHTNESS: - return ov2640_set_level(dev, ctrl->val, NUM_BRIGHTNESS_LEVELS, + return ov2640_set_level(dev, ctrls->brightness.val, NUM_BRIGHTNESS_LEVELS, ARRAY_SIZE(brightness_regs[0]), brightness_regs); case VIDEO_CID_CONTRAST: - return ov2640_set_level(dev, ctrl->val, NUM_CONTRAST_LEVELS, + return ov2640_set_level(dev, ctrls->contrast.val, NUM_CONTRAST_LEVELS, ARRAY_SIZE(contrast_regs[0]), contrast_regs); case VIDEO_CID_SATURATION: - return ov2640_set_level(dev, ctrl->val, NUM_SATURATION_LEVELS, + return ov2640_set_level(dev, ctrls->saturation.val, NUM_SATURATION_LEVELS, ARRAY_SIZE(saturation_regs[0]), saturation_regs); case VIDEO_CID_JPEG_COMPRESSION_QUALITY: - return ov2640_set_quality(dev, ctrl->val); + return ov2640_set_quality(dev, ctrls->jpeg.val); case VIDEO_CID_TEST_PATTERN: - return ov2640_set_colorbar(dev, ctrl->val); + return ov2640_set_colorbar(dev, ctrls->test_pattern.val); default: return -ENOTSUP; } diff --git a/drivers/video/ov5640.c b/drivers/video/ov5640.c index 26263643b21..71957326364 100644 --- a/drivers/video/ov5640.c +++ b/drivers/video/ov5640.c @@ -145,7 +145,11 @@ struct ov5640_mode_config { }; struct ov5640_ctrls { - struct video_ctrl gain; + /* gain auto-cluster */ + struct { + struct video_ctrl auto_gain; + struct video_ctrl gain; + }; struct video_ctrl brightness; struct video_ctrl contrast; struct video_ctrl hue; @@ -1034,24 +1038,30 @@ static int ov5640_set_ctrl_contrast(const struct device *dev, int value) return ov5640_write_reg(&cfg->i2c, SDE_CTRL6_REG, value & 0xff); } -static int ov5640_set_ctrl_gain(const struct device *dev, int value) +static int ov5640_set_ctrl_gain(const struct device *dev) { const struct ov5640_config *cfg = dev->config; + struct ov5640_data *drv_data = dev->data; + struct ov5640_ctrls *ctrls = &drv_data->ctrls; - if (value) { - int ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_MANUAL, BIT(1), BIT(0)); + int ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_MANUAL, BIT(1), + ctrls->auto_gain.val ? 0 : BIT(1)); + if (ret) { + return ret; + } + + if (!ctrls->auto_gain.val) { + ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_REAL_GAIN, 0x03, + (ctrls->gain.val >> 8) & 0x03); if (ret) { return ret; } - struct ov5640_reg gain_params[] = {{AEC_PK_REAL_GAIN, value >> 8}, - {AEC_PK_REAL_GAIN + 1, value & 0xff}}; - - return ov5640_write_multi_regs(&cfg->i2c, gain_params, ARRAY_SIZE(gain_params)); - } else { - return ov5640_write_reg(&cfg->i2c, AEC_PK_MANUAL, 0); + ret = ov5640_write_reg(&cfg->i2c, AEC_PK_REAL_GAIN + 1, ctrls->gain.val & 0xff); } + + return ret; } static int ov5640_set_ctrl_hflip(const struct device *dev, int value) @@ -1096,32 +1106,68 @@ static int ov5640_set_ctrl_power_line_freq(const struct device *dev, int value) return ov5640_modify_reg(&cfg->i2c, HZ5060_CTRL01_REG, BIT(7), BIT(7)); } -static int ov5640_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int ov5640_set_ctrl(const struct device *dev, uint32_t id) { - switch (ctrl->id) { + struct ov5640_data *drv_data = dev->data; + struct ov5640_ctrls *ctrls = &drv_data->ctrls; + + switch (id) { case VIDEO_CID_TEST_PATTERN: - return ov5640_set_ctrl_test_pattern(dev, ctrl->val); + return ov5640_set_ctrl_test_pattern(dev, ctrls->test_pattern.val); case VIDEO_CID_HUE: - return ov5640_set_ctrl_hue(dev, ctrl->val); + return ov5640_set_ctrl_hue(dev, ctrls->hue.val); case VIDEO_CID_SATURATION: - return ov5640_set_ctrl_saturation(dev, ctrl->val); + return ov5640_set_ctrl_saturation(dev, ctrls->saturation.val); case VIDEO_CID_BRIGHTNESS: - return ov5640_set_ctrl_brightness(dev, ctrl->val); + return ov5640_set_ctrl_brightness(dev, ctrls->brightness.val); case VIDEO_CID_CONTRAST: - return ov5640_set_ctrl_contrast(dev, ctrl->val); - case VIDEO_CID_GAIN: - return ov5640_set_ctrl_gain(dev, ctrl->val); + return ov5640_set_ctrl_contrast(dev, ctrls->contrast.val); + case VIDEO_CID_AUTOGAIN: + return ov5640_set_ctrl_gain(dev); case VIDEO_CID_HFLIP: - return ov5640_set_ctrl_hflip(dev, ctrl->val); + return ov5640_set_ctrl_hflip(dev, ctrls->hflip.val); case VIDEO_CID_VFLIP: - return ov5640_set_ctrl_vflip(dev, ctrl->val); + return ov5640_set_ctrl_vflip(dev, ctrls->vflip.val); case VIDEO_CID_POWER_LINE_FREQUENCY: - return ov5640_set_ctrl_power_line_freq(dev, ctrl->val); + return ov5640_set_ctrl_power_line_freq(dev, ctrls->light_freq.val); default: return -ENOTSUP; } } +static int ov5640_get_gain(const struct device *dev) +{ + int ret; + uint16_t gain; + const struct ov5640_config *cfg = dev->config; + + ret = ov5640_read_reg(&cfg->i2c, AEC_PK_REAL_GAIN, &gain, sizeof(gain)); + if (ret) { + return ret; + } + + return gain & 0x3ff; +} + +static int ov5640_get_volatile_ctrl(const struct device *dev, uint32_t id) +{ + int val; + struct ov5640_data *drv_data = dev->data; + struct ov5640_ctrls *ctrls = &drv_data->ctrls; + + switch (id) { + case VIDEO_CID_AUTOGAIN: + val = ov5640_get_gain(dev); + if (val < 0) { + return val; + } + ctrls->gain.val = val; + break; + } + + return 0; +} + static int ov5640_get_frmival(const struct device *dev, enum video_endpoint_id ep, struct video_frmival *frmival) { @@ -1171,6 +1217,7 @@ static DEVICE_API(video, ov5640_driver_api) = { .get_caps = ov5640_get_caps, .set_stream = ov5640_set_stream, .set_ctrl = ov5640_set_ctrl, + .get_volatile_ctrl = ov5640_get_volatile_ctrl, .set_frmival = ov5640_set_frmival, .get_frmival = ov5640_get_frmival, .enum_frmival = ov5640_enum_frmival, @@ -1182,13 +1229,21 @@ static int ov5640_init_controls(const struct device *dev) struct ov5640_data *drv_data = dev->data; struct ov5640_ctrls *ctrls = &drv_data->ctrls; + ret = video_init_ctrl(&ctrls->auto_gain, dev, VIDEO_CID_AUTOGAIN, + (struct video_ctrl_range){.min = 0, .max = 1, .step = 1, .def = 1}); + if (ret) { + return ret; + } + ret = video_init_ctrl( - &ctrls->gain, dev, VIDEO_CID_GAIN, + &ctrls->gain, dev, VIDEO_CID_ANALOGUE_GAIN, (struct video_ctrl_range){.min = 0, .max = 1023, .step = 1, .def = 0}); if (ret) { return ret; } + video_auto_cluster_ctrl(&ctrls->auto_gain, 2, true); + ret = video_init_ctrl( &ctrls->brightness, dev, VIDEO_CID_BRIGHTNESS, (struct video_ctrl_range){.min = -15, .max = 15, .step = 1, .def = 0}); diff --git a/drivers/video/ov7670.c b/drivers/video/ov7670.c index 192a63a7908..17fce01cd5a 100644 --- a/drivers/video/ov7670.c +++ b/drivers/video/ov7670.c @@ -581,17 +581,19 @@ static int ov7670_set_stream(const struct device *dev, bool enable) return 0; } -static int ov7670_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int ov7670_set_ctrl(const struct device *dev, uint32_t id) { const struct ov7670_config *config = dev->config; + struct ov7670_data *drv_data = dev->data; + struct ov7670_ctrls *ctrls = &drv_data->ctrls; - switch (ctrl->id) { + switch (id) { case VIDEO_CID_HFLIP: - return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, - OV7670_MVFP_HFLIP, ctrl->val ? OV7670_MVFP_HFLIP : 0); + return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, OV7670_MVFP_HFLIP, + ctrls->hflip.val ? OV7670_MVFP_HFLIP : 0); case VIDEO_CID_VFLIP: - return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, - OV7670_MVFP_VFLIP, ctrl->val ? OV7670_MVFP_VFLIP : 0); + return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, OV7670_MVFP_VFLIP, + ctrls->vflip.val ? OV7670_MVFP_VFLIP : 0); default: return -ENOTSUP; } diff --git a/drivers/video/video_ctrls.c b/drivers/video/video_ctrls.c index 0dc99820ba5..ffc84fc9414 100644 --- a/drivers/video/video_ctrls.c +++ b/drivers/video/video_ctrls.c @@ -94,6 +94,10 @@ int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t return ret; } + ctrl->cluster_sz = 0; + ctrl->cluster = NULL; + ctrl->is_auto = false; + ctrl->has_volatiles = false; ctrl->vdev = vdev; ctrl->id = id; ctrl->type = type; @@ -119,6 +123,50 @@ int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t 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) +{ + return master->type == VIDEO_CTRL_TYPE_INTEGER64 ? master->val64 == 0 : master->val == 0; +} + +void video_cluster_ctrl(struct video_ctrl *ctrls, uint8_t sz) +{ + bool has_volatiles = false; + + __ASSERT(!sz && !ctrls, "The 1st control, i.e. the master, must not be NULL"); + + for (uint8_t i = 0; i < sz; i++) { + ctrls[i].cluster_sz = sz; + ctrls[i].cluster = ctrls; + if (ctrls[i].flags & VIDEO_CTRL_FLAG_VOLATILE) { + has_volatiles = true; + } + } + + ctrls->has_volatiles = has_volatiles; +} + +void video_auto_cluster_ctrl(struct video_ctrl *ctrls, uint8_t sz, bool set_volatile) +{ + video_cluster_ctrl(ctrls, sz); + + __ASSERT(sz > 1, "Control auto cluster size must be > 1"); + __ASSERT(!(set_volatile && !DEVICE_API_GET(video, ctrls->vdev->dev)->get_volatile_ctrl), + "Volatile is set but no ops"); + + ctrls->is_auto = true; + ctrls->has_volatiles = set_volatile; + ctrls->flags |= VIDEO_CTRL_FLAG_UPDATE; + + /* If the cluster is in automatic mode, mark all manual controls inactive and volatile */ + for (uint8_t i = 1; i < sz; i++) { + if (!is_cluster_manual(ctrls)) { + ctrls[i].flags |= VIDEO_CTRL_FLAG_INACTIVE | + (set_volatile ? VIDEO_CTRL_FLAG_VOLATILE : 0); + } + } +} + static int video_find_ctrl(const struct device *dev, uint32_t id, struct video_ctrl **ctrl) { struct video_device *vdev = video_find_vdev(dev); @@ -157,11 +205,15 @@ int video_get_ctrl(const struct device *dev, struct video_control *control) } /* Call driver's get_volatile_ctrl */ - return DEVICE_API_GET(video, ctrl->vdev->dev) - ->get_volatile_ctrl(ctrl->vdev->dev, control); + ret = DEVICE_API_GET(video, ctrl->vdev->dev) + ->get_volatile_ctrl(ctrl->vdev->dev, + ctrl->cluster ? ctrl->cluster->id : ctrl->id); + if (ret) { + return ret; + } } - /* Read control value in cache memory */ + /* Give the control's current value to user */ if (ctrl->type == VIDEO_CTRL_TYPE_INTEGER64) { control->val64 = ctrl->val64; } else { @@ -174,8 +226,10 @@ int video_get_ctrl(const struct device *dev, struct video_control *control) int video_set_ctrl(const struct device *dev, struct video_control *control) { struct video_ctrl *ctrl = NULL; - int ret = video_find_ctrl(dev, control->id, &ctrl); + uint8_t i = 0; + int32_t val = 0; + int64_t val64 = 0; if (ret) { return ret; @@ -186,6 +240,11 @@ int video_set_ctrl(const struct device *dev, struct video_control *control) return -EACCES; } + if (ctrl->flags & VIDEO_CTRL_FLAG_INACTIVE) { + LOG_ERR("Control id 0x%x is inactive\n", control->id); + return -EACCES; + } + if (ctrl->type == VIDEO_CTRL_TYPE_INTEGER64 ? !IN_RANGE(control->val64, ctrl->range.min64, ctrl->range.max64) : !IN_RANGE(control->val, ctrl->range.min, ctrl->range.max)) { @@ -193,25 +252,81 @@ int video_set_ctrl(const struct device *dev, struct video_control *control) return -EINVAL; } - if (DEVICE_API_GET(video, ctrl->vdev->dev)->set_ctrl == NULL) { - goto update; + /* No new value */ + if (ctrl->type == VIDEO_CTRL_TYPE_INTEGER64 ? ctrl->val64 == control->val64 + : ctrl->val == control->val) { + return 0; } - /* Call driver's set_ctrl */ - ret = DEVICE_API_GET(video, ctrl->vdev->dev)->set_ctrl(ctrl->vdev->dev, control); - if (ret) { - return ret; - } - -update: - /* Only update the ctrl in memory once everything is OK */ + /* Backup the control's value then set it to the new value */ if (ctrl->type == VIDEO_CTRL_TYPE_INTEGER64) { + val64 = ctrl->val64; ctrl->val64 = control->val64; } else { + val = ctrl->val; ctrl->val = control->val; } + /* + * For auto-clusters having volatiles, before switching to manual mode, get the current + * volatile values since those will become the initial manual values after this switch. + */ + if (ctrl == ctrl->cluster && ctrl->is_auto && ctrl->has_volatiles && + is_cluster_manual(ctrl)) { + + if (DEVICE_API_GET(video, ctrl->vdev->dev)->get_volatile_ctrl == NULL) { + ret = -ENOSYS; + goto restore; + } + + ret = DEVICE_API_GET(video, ctrl->vdev->dev) + ->get_volatile_ctrl(ctrl->vdev->dev, ctrl->id); + if (ret) { + goto restore; + } + } + + /* Call driver's set_ctrl */ + if (DEVICE_API_GET(video, ctrl->vdev->dev)->set_ctrl) { + ret = DEVICE_API_GET(video, ctrl->vdev->dev) + ->set_ctrl(ctrl->vdev->dev, ctrl->cluster ? ctrl->cluster->id : ctrl->id); + if (ret) { + goto restore; + } + } + + /* Update the manual controls' flags of the cluster */ + if (ctrl->cluster && ctrl->cluster->is_auto) { + for (i = 1; i < ctrl->cluster_sz; i++) { + if (!is_cluster_manual(ctrl->cluster)) { + /* Automatic mode: set the inactive and volatile flags of the manual + * controls + */ + ctrl->cluster[i].flags |= + VIDEO_CTRL_FLAG_INACTIVE | + (ctrl->cluster->has_volatiles ? VIDEO_CTRL_FLAG_VOLATILE + : 0); + } else { + /* Manual mode: clear the inactive and volatile flags of the manual + * controls + */ + ctrl->cluster[i].flags &= + ~(VIDEO_CTRL_FLAG_INACTIVE | VIDEO_CTRL_FLAG_VOLATILE); + } + } + } + return 0; + +restore: + /* Restore the old control's value */ + if (ctrl->type == VIDEO_CTRL_TYPE_INTEGER64) { + ctrl->val64 = val64; + } else { + ctrl->val = val; + } + + return ret; } static inline const char *video_get_ctrl_name(uint32_t id) @@ -228,8 +343,12 @@ static inline const char *video_get_ctrl_name(uint32_t id) return "Hue"; case VIDEO_CID_EXPOSURE: return "Exposure"; + case VIDEO_CID_AUTOGAIN: + return "Gain, Automatic"; case VIDEO_CID_GAIN: return "Gain"; + case VIDEO_CID_ANALOGUE_GAIN: + return "Analogue Gain"; case VIDEO_CID_HFLIP: return "Horizontal Flip"; case VIDEO_CID_VFLIP: diff --git a/drivers/video/video_ctrls.h b/drivers/video/video_ctrls.h index 4d0262ea849..b154ad3431a 100644 --- a/drivers/video/video_ctrls.h +++ b/drivers/video/video_ctrls.h @@ -39,6 +39,12 @@ struct video_device; * @see video_control for the struct used in public API */ struct video_ctrl { + /* Fields should not touched by drivers, used only for the 1st control of a cluster */ + struct video_ctrl *cluster; + uint8_t cluster_sz; + bool is_auto; + bool has_volatiles; + const struct video_device *vdev; uint32_t id; enum video_ctrl_type type; @@ -54,4 +60,8 @@ struct video_ctrl { int video_init_ctrl(struct video_ctrl *ctrl, const struct device *dev, uint32_t id, struct video_ctrl_range range); +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); + #endif /* ZEPHYR_INCLUDE_DRIVERS_VIDEO_VIDEO_CTRLS_H_ */ diff --git a/drivers/video/video_emul_imager.c b/drivers/video/video_emul_imager.c index d9f65939070..8dffbba11f6 100644 --- a/drivers/video/video_emul_imager.c +++ b/drivers/video/video_emul_imager.c @@ -193,9 +193,11 @@ static int emul_imager_write_multi(const struct device *const dev, return 0; } -static int emul_imager_set_ctrl(const struct device *dev, struct video_control *ctrl) +static int emul_imager_set_ctrl(const struct device *dev, uint32_t id) { - return emul_imager_write_reg(dev, EMUL_IMAGER_REG_CUSTOM, ctrl->val); + struct emul_imager_data *data = dev->data; + + return emul_imager_write_reg(dev, EMUL_IMAGER_REG_CUSTOM, data->ctrls.custom.val); } /* Customize this function according to your "struct emul_imager_mode". */ diff --git a/include/zephyr/drivers/video-controls.h b/include/zephyr/drivers/video-controls.h index e1b11a4b49f..73937ba1958 100644 --- a/include/zephyr/drivers/video-controls.h +++ b/include/zephyr/drivers/video-controls.h @@ -57,7 +57,13 @@ extern "C" { /** Amount of time an image sensor is exposed to light, affecting the brightness */ #define VIDEO_CID_EXPOSURE (VIDEO_CID_BASE + 17) -/** Amount of amplification performed to each pixel electrical signal, affecting the brightness */ +/** Automatic gain control */ +#define VIDEO_CID_AUTOGAIN (VIDEO_CID_BASE + 18) + +/** Gain control. Most devices control only digital gain with this control. + * Devices that recognise the difference between digital and analogue gain use + * VIDEO_CID_DIGITAL_GAIN and VIDEO_CID_ANALOGUE_GAIN. + */ #define VIDEO_CID_GAIN (VIDEO_CID_BASE + 19) /** Flip the image horizontally: the left side becomes the right side */ @@ -137,6 +143,9 @@ enum video_power_line_frequency { */ #define VIDEO_CID_IMAGE_SOURCE_CLASS_BASE 0x009e0900 +/** Analogue gain control. */ +#define VIDEO_CID_ANALOGUE_GAIN (VIDEO_CID_IMAGE_SOURCE_CLASS_BASE + 3) + /** * @} */ diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index 184492d1952..c0b814932f7 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -321,9 +321,10 @@ typedef int (*video_api_set_stream_t)(const struct device *dev, bool enable); * @typedef video_api_ctrl_t * @brief Set/Get a video control value. * - * See video_set_ctrl() or video_get_ctrl() for argument descriptions. + * @param dev Pointer to the device structure. + * @param cid Id of the control to set/get its value. */ -typedef int (*video_api_ctrl_t)(const struct device *dev, struct video_control *ctrl); +typedef int (*video_api_ctrl_t)(const struct device *dev, uint32_t cid); /** * @typedef video_api_get_caps_t