Skip to content

Commit f806890

Browse files
committed
drivers: video: Add support for composite controls
For controls that are dependent from others, we need to "cluster" them. Whenever one or more controls of the same cluster are set or gotten, only the callback of the 1st control of the cluster, i.e. the master control, is called. The master control is the one that represents the whole cluster. A common type of control cluster is "auto"-cluster, e.g. auto_gain/gain, auto_exposure/exposure, auto_white_balance/red_balance/blue_balance, etc. If the cluster is in automatic mode, then the manual controls are marked inactive and volatile which are read via get_volatile_ctrl(). If the cluster is put in manual mode, then the manual controls should become active again and the volatile flag is cleared. Re-implement the ov5640's autogain/analogue_gain controls with the new auto cluster mechanism so that it work correctly and fully. Signed-off-by: Phi Bang Nguyen <phibang.nguyen@nxp.com>
1 parent e00e6fd commit f806890

File tree

11 files changed

+278
-69
lines changed

11 files changed

+278
-69
lines changed

drivers/video/gc2145.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,13 +1110,15 @@ static int gc2145_get_caps(const struct device *dev, enum video_endpoint_id ep,
11101110
return 0;
11111111
}
11121112

1113-
static int gc2145_set_ctrl(const struct device *dev, struct video_control *ctrl)
1113+
static int gc2145_set_ctrl(const struct device *dev, uint32_t id)
11141114
{
1115-
switch (ctrl->id) {
1115+
struct gc2145_data *drv_data = dev->data;
1116+
1117+
switch (id) {
11161118
case VIDEO_CID_HFLIP:
1117-
return gc2145_set_ctrl_hmirror(dev, ctrl->val);
1119+
return gc2145_set_ctrl_hmirror(dev, drv_data->ctrls.hflip.val);
11181120
case VIDEO_CID_VFLIP:
1119-
return gc2145_set_ctrl_vflip(dev, ctrl->val);
1121+
return gc2145_set_ctrl_vflip(dev, drv_data->ctrls.vflip.val);
11201122
default:
11211123
return -ENOTSUP;
11221124
}

drivers/video/mt9m114.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -473,20 +473,23 @@ static int mt9m114_get_caps(const struct device *dev, enum video_endpoint_id ep,
473473
return 0;
474474
}
475475

476-
static int mt9m114_set_ctrl(const struct device *dev, struct video_control *ctrl)
476+
static int mt9m114_set_ctrl(const struct device *dev, uint32_t id)
477477
{
478478
int ret = 0;
479+
struct mt9m114_data *drv_data = dev->data;
479480

480-
switch (ctrl->id) {
481+
switch (id) {
481482
case VIDEO_CID_HFLIP:
482-
ret = mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2,
483-
MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN,
484-
ctrl->val ? MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN : 0);
483+
ret = mt9m114_modify_reg(
484+
dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2,
485+
MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN,
486+
drv_data->ctrls.hflip.val ? MT9M114_CAM_SENSOR_CTRL_HORZ_FLIP_EN : 0);
485487
break;
486488
case VIDEO_CID_VFLIP:
487-
ret = mt9m114_modify_reg(dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2,
488-
MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN,
489-
ctrl->val ? MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN : 0);
489+
ret = mt9m114_modify_reg(
490+
dev, MT9M114_CAM_SENSOR_CTRL_READ_MODE, 2,
491+
MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN,
492+
drv_data->ctrls.vflip.val ? MT9M114_CAM_SENSOR_CTRL_VERT_FLIP_EN : 0);
490493
break;
491494
default:
492495
return -ENOTSUP;

drivers/video/ov2640.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -895,32 +895,35 @@ static int ov2640_get_caps(const struct device *dev,
895895
return 0;
896896
}
897897

898-
static int ov2640_set_ctrl(const struct device *dev, struct video_control *ctrl)
898+
static int ov2640_set_ctrl(const struct device *dev, uint32_t id)
899899
{
900-
switch (ctrl->id) {
900+
struct ov2640_data *drv_data = dev->data;
901+
struct ov2640_ctrls *ctrls = &drv_data->ctrls;
902+
903+
switch (id) {
901904
case VIDEO_CID_HFLIP:
902-
return ov2640_set_horizontal_mirror(dev, ctrl->val);
905+
return ov2640_set_horizontal_mirror(dev, ctrls->hflip.val);
903906
case VIDEO_CID_VFLIP:
904-
return ov2640_set_vertical_flip(dev, ctrl->val);
907+
return ov2640_set_vertical_flip(dev, ctrls->vflip.val);
905908
case VIDEO_CID_EXPOSURE:
906-
return ov2640_set_exposure_ctrl(dev, ctrl->val);
909+
return ov2640_set_exposure_ctrl(dev, ctrls->ae.val);
907910
case VIDEO_CID_WHITE_BALANCE_TEMPERATURE:
908-
return ov2640_set_white_bal(dev, ctrl->val);
911+
return ov2640_set_white_bal(dev, ctrls->awb.val);
909912
case VIDEO_CID_GAIN:
910-
return ov2640_set_gain_ctrl(dev, ctrl->val);
913+
return ov2640_set_gain_ctrl(dev, ctrls->gain.val);
911914
case VIDEO_CID_BRIGHTNESS:
912-
return ov2640_set_level(dev, ctrl->val, NUM_BRIGHTNESS_LEVELS,
915+
return ov2640_set_level(dev, ctrls->brightness.val, NUM_BRIGHTNESS_LEVELS,
913916
ARRAY_SIZE(brightness_regs[0]), brightness_regs);
914917
case VIDEO_CID_CONTRAST:
915-
return ov2640_set_level(dev, ctrl->val, NUM_CONTRAST_LEVELS,
918+
return ov2640_set_level(dev, ctrls->contrast.val, NUM_CONTRAST_LEVELS,
916919
ARRAY_SIZE(contrast_regs[0]), contrast_regs);
917920
case VIDEO_CID_SATURATION:
918-
return ov2640_set_level(dev, ctrl->val, NUM_SATURATION_LEVELS,
921+
return ov2640_set_level(dev, ctrls->saturation.val, NUM_SATURATION_LEVELS,
919922
ARRAY_SIZE(saturation_regs[0]), saturation_regs);
920923
case VIDEO_CID_JPEG_COMPRESSION_QUALITY:
921-
return ov2640_set_quality(dev, ctrl->val);
924+
return ov2640_set_quality(dev, ctrls->jpeg.val);
922925
case VIDEO_CID_TEST_PATTERN:
923-
return ov2640_set_colorbar(dev, ctrl->val);
926+
return ov2640_set_colorbar(dev, ctrls->test_pattern.val);
924927
default:
925928
return -ENOTSUP;
926929
}

drivers/video/ov5640.c

Lines changed: 78 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ struct ov5640_mode_config {
145145
};
146146

147147
struct ov5640_ctrls {
148-
struct video_ctrl gain;
148+
/* gain auto-cluster */
149+
struct {
150+
struct video_ctrl auto_gain;
151+
struct video_ctrl gain;
152+
};
149153
struct video_ctrl brightness;
150154
struct video_ctrl contrast;
151155
struct video_ctrl hue;
@@ -1034,24 +1038,30 @@ static int ov5640_set_ctrl_contrast(const struct device *dev, int value)
10341038
return ov5640_write_reg(&cfg->i2c, SDE_CTRL6_REG, value & 0xff);
10351039
}
10361040

1037-
static int ov5640_set_ctrl_gain(const struct device *dev, int value)
1041+
static int ov5640_set_ctrl_gain(const struct device *dev)
10381042
{
10391043
const struct ov5640_config *cfg = dev->config;
1044+
struct ov5640_data *drv_data = dev->data;
1045+
struct ov5640_ctrls *ctrls = &drv_data->ctrls;
10401046

1041-
if (value) {
1042-
int ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_MANUAL, BIT(1), BIT(0));
1047+
int ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_MANUAL, BIT(1),
1048+
ctrls->auto_gain.val ? 0 : BIT(1));
1049+
1050+
if (ret) {
1051+
return ret;
1052+
}
10431053

1054+
if (!ctrls->auto_gain.val) {
1055+
ret = ov5640_modify_reg(&cfg->i2c, AEC_PK_REAL_GAIN, 0x03,
1056+
(ctrls->gain.val >> 8) & 0x03);
10441057
if (ret) {
10451058
return ret;
10461059
}
10471060

1048-
struct ov5640_reg gain_params[] = {{AEC_PK_REAL_GAIN, value >> 8},
1049-
{AEC_PK_REAL_GAIN + 1, value & 0xff}};
1050-
1051-
return ov5640_write_multi_regs(&cfg->i2c, gain_params, ARRAY_SIZE(gain_params));
1052-
} else {
1053-
return ov5640_write_reg(&cfg->i2c, AEC_PK_MANUAL, 0);
1061+
ret = ov5640_write_reg(&cfg->i2c, AEC_PK_REAL_GAIN + 1, ctrls->gain.val & 0xff);
10541062
}
1063+
1064+
return ret;
10551065
}
10561066

10571067
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)
10961106
return ov5640_modify_reg(&cfg->i2c, HZ5060_CTRL01_REG, BIT(7), BIT(7));
10971107
}
10981108

1099-
static int ov5640_set_ctrl(const struct device *dev, struct video_control *ctrl)
1109+
static int ov5640_set_ctrl(const struct device *dev, uint32_t id)
11001110
{
1101-
switch (ctrl->id) {
1111+
struct ov5640_data *drv_data = dev->data;
1112+
struct ov5640_ctrls *ctrls = &drv_data->ctrls;
1113+
1114+
switch (id) {
11021115
case VIDEO_CID_TEST_PATTERN:
1103-
return ov5640_set_ctrl_test_pattern(dev, ctrl->val);
1116+
return ov5640_set_ctrl_test_pattern(dev, ctrls->test_pattern.val);
11041117
case VIDEO_CID_HUE:
1105-
return ov5640_set_ctrl_hue(dev, ctrl->val);
1118+
return ov5640_set_ctrl_hue(dev, ctrls->hue.val);
11061119
case VIDEO_CID_SATURATION:
1107-
return ov5640_set_ctrl_saturation(dev, ctrl->val);
1120+
return ov5640_set_ctrl_saturation(dev, ctrls->saturation.val);
11081121
case VIDEO_CID_BRIGHTNESS:
1109-
return ov5640_set_ctrl_brightness(dev, ctrl->val);
1122+
return ov5640_set_ctrl_brightness(dev, ctrls->brightness.val);
11101123
case VIDEO_CID_CONTRAST:
1111-
return ov5640_set_ctrl_contrast(dev, ctrl->val);
1112-
case VIDEO_CID_GAIN:
1113-
return ov5640_set_ctrl_gain(dev, ctrl->val);
1124+
return ov5640_set_ctrl_contrast(dev, ctrls->contrast.val);
1125+
case VIDEO_CID_AUTOGAIN:
1126+
return ov5640_set_ctrl_gain(dev);
11141127
case VIDEO_CID_HFLIP:
1115-
return ov5640_set_ctrl_hflip(dev, ctrl->val);
1128+
return ov5640_set_ctrl_hflip(dev, ctrls->hflip.val);
11161129
case VIDEO_CID_VFLIP:
1117-
return ov5640_set_ctrl_vflip(dev, ctrl->val);
1130+
return ov5640_set_ctrl_vflip(dev, ctrls->vflip.val);
11181131
case VIDEO_CID_POWER_LINE_FREQUENCY:
1119-
return ov5640_set_ctrl_power_line_freq(dev, ctrl->val);
1132+
return ov5640_set_ctrl_power_line_freq(dev, ctrls->light_freq.val);
11201133
default:
11211134
return -ENOTSUP;
11221135
}
11231136
}
11241137

1138+
static int ov5640_get_gain(const struct device *dev)
1139+
{
1140+
int ret;
1141+
uint16_t gain;
1142+
const struct ov5640_config *cfg = dev->config;
1143+
1144+
ret = ov5640_read_reg(&cfg->i2c, AEC_PK_REAL_GAIN, &gain, sizeof(gain));
1145+
if (ret) {
1146+
return ret;
1147+
}
1148+
1149+
return gain & 0x3ff;
1150+
}
1151+
1152+
static int ov5640_get_volatile_ctrl(const struct device *dev, uint32_t id)
1153+
{
1154+
int val;
1155+
struct ov5640_data *drv_data = dev->data;
1156+
struct ov5640_ctrls *ctrls = &drv_data->ctrls;
1157+
1158+
switch (id) {
1159+
case VIDEO_CID_AUTOGAIN:
1160+
val = ov5640_get_gain(dev);
1161+
if (val < 0) {
1162+
return val;
1163+
}
1164+
ctrls->gain.val = val;
1165+
break;
1166+
}
1167+
1168+
return 0;
1169+
}
1170+
11251171
static int ov5640_get_frmival(const struct device *dev, enum video_endpoint_id ep,
11261172
struct video_frmival *frmival)
11271173
{
@@ -1171,6 +1217,7 @@ static DEVICE_API(video, ov5640_driver_api) = {
11711217
.get_caps = ov5640_get_caps,
11721218
.set_stream = ov5640_set_stream,
11731219
.set_ctrl = ov5640_set_ctrl,
1220+
.get_volatile_ctrl = ov5640_get_volatile_ctrl,
11741221
.set_frmival = ov5640_set_frmival,
11751222
.get_frmival = ov5640_get_frmival,
11761223
.enum_frmival = ov5640_enum_frmival,
@@ -1182,13 +1229,21 @@ static int ov5640_init_controls(const struct device *dev)
11821229
struct ov5640_data *drv_data = dev->data;
11831230
struct ov5640_ctrls *ctrls = &drv_data->ctrls;
11841231

1232+
ret = video_init_ctrl(&ctrls->auto_gain, dev, VIDEO_CID_AUTOGAIN,
1233+
(struct video_ctrl_range){.min = 0, .max = 1, .step = 1, .def = 1});
1234+
if (ret) {
1235+
return ret;
1236+
}
1237+
11851238
ret = video_init_ctrl(
1186-
&ctrls->gain, dev, VIDEO_CID_GAIN,
1239+
&ctrls->gain, dev, VIDEO_CID_ANALOGUE_GAIN,
11871240
(struct video_ctrl_range){.min = 0, .max = 1023, .step = 1, .def = 0});
11881241
if (ret) {
11891242
return ret;
11901243
}
11911244

1245+
video_auto_cluster_ctrl(&ctrls->auto_gain, 2, true);
1246+
11921247
ret = video_init_ctrl(
11931248
&ctrls->brightness, dev, VIDEO_CID_BRIGHTNESS,
11941249
(struct video_ctrl_range){.min = -15, .max = 15, .step = 1, .def = 0});

drivers/video/ov7670.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -581,17 +581,19 @@ static int ov7670_set_stream(const struct device *dev, bool enable)
581581
return 0;
582582
}
583583

584-
static int ov7670_set_ctrl(const struct device *dev, struct video_control *ctrl)
584+
static int ov7670_set_ctrl(const struct device *dev, uint32_t id)
585585
{
586586
const struct ov7670_config *config = dev->config;
587+
struct ov7670_data *drv_data = dev->data;
588+
struct ov7670_ctrls *ctrls = &drv_data->ctrls;
587589

588-
switch (ctrl->id) {
590+
switch (id) {
589591
case VIDEO_CID_HFLIP:
590-
return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP,
591-
OV7670_MVFP_HFLIP, ctrl->val ? OV7670_MVFP_HFLIP : 0);
592+
return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, OV7670_MVFP_HFLIP,
593+
ctrls->hflip.val ? OV7670_MVFP_HFLIP : 0);
592594
case VIDEO_CID_VFLIP:
593-
return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP,
594-
OV7670_MVFP_VFLIP, ctrl->val ? OV7670_MVFP_VFLIP : 0);
595+
return i2c_reg_update_byte_dt(&config->bus, OV7670_MVFP, OV7670_MVFP_VFLIP,
596+
ctrls->vflip.val ? OV7670_MVFP_VFLIP : 0);
595597
default:
596598
return -ENOTSUP;
597599
}

0 commit comments

Comments
 (0)