@@ -145,7 +145,11 @@ struct ov5640_mode_config {
145145};
146146
147147struct 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
10571067static 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+
11251171static 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 });
0 commit comments