aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/ov7670.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index 95507770f120..e7555d1f90e6 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -1131,6 +1131,67 @@ static int ov7670_s_vflip(struct v4l2_subdev *sd, int value)
1131 return ret; 1131 return ret;
1132} 1132}
1133 1133
1134/*
1135 * GAIN is split between REG_GAIN and REG_VREF[7:6]. If one believes
1136 * the data sheet, the VREF parts should be the most significant, but
1137 * experience shows otherwise. There seems to be little value in
1138 * messing with the VREF bits, so we leave them alone.
1139 */
1140static int ov7670_g_gain(struct v4l2_subdev *sd, __s32 *value)
1141{
1142 int ret;
1143 unsigned char gain;
1144
1145 ret = ov7670_read(sd, REG_GAIN, &gain);
1146 *value = gain;
1147 return ret;
1148}
1149
1150static int ov7670_s_gain(struct v4l2_subdev *sd, int value)
1151{
1152 int ret;
1153 unsigned char com8;
1154
1155 ret = ov7670_write(sd, REG_GAIN, value & 0xff);
1156 /* Have to turn off AGC as well */
1157 if (ret == 0) {
1158 ret = ov7670_read(sd, REG_COM8, &com8);
1159 ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AGC);
1160 }
1161 return ret;
1162}
1163
1164/*
1165 * Tweak autogain.
1166 */
1167static int ov7670_g_autogain(struct v4l2_subdev *sd, __s32 *value)
1168{
1169 int ret;
1170 unsigned char com8;
1171
1172 ret = ov7670_read(sd, REG_COM8, &com8);
1173 *value = (com8 & COM8_AGC) != 0;
1174 return ret;
1175}
1176
1177static int ov7670_s_autogain(struct v4l2_subdev *sd, int value)
1178{
1179 int ret;
1180 unsigned char com8;
1181
1182 ret = ov7670_read(sd, REG_COM8, &com8);
1183 if (ret == 0) {
1184 if (value)
1185 com8 |= COM8_AGC;
1186 else
1187 com8 &= ~COM8_AGC;
1188 ret = ov7670_write(sd, REG_COM8, com8);
1189 }
1190 return ret;
1191}
1192
1193
1194
1134static int ov7670_queryctrl(struct v4l2_subdev *sd, 1195static int ov7670_queryctrl(struct v4l2_subdev *sd,
1135 struct v4l2_queryctrl *qc) 1196 struct v4l2_queryctrl *qc)
1136{ 1197{
@@ -1147,6 +1208,10 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd,
1147 return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); 1208 return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128);
1148 case V4L2_CID_HUE: 1209 case V4L2_CID_HUE:
1149 return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); 1210 return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0);
1211 case V4L2_CID_GAIN:
1212 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1213 case V4L2_CID_AUTOGAIN:
1214 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1150 } 1215 }
1151 return -EINVAL; 1216 return -EINVAL;
1152} 1217}
@@ -1166,6 +1231,10 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1166 return ov7670_g_vflip(sd, &ctrl->value); 1231 return ov7670_g_vflip(sd, &ctrl->value);
1167 case V4L2_CID_HFLIP: 1232 case V4L2_CID_HFLIP:
1168 return ov7670_g_hflip(sd, &ctrl->value); 1233 return ov7670_g_hflip(sd, &ctrl->value);
1234 case V4L2_CID_GAIN:
1235 return ov7670_g_gain(sd, &ctrl->value);
1236 case V4L2_CID_AUTOGAIN:
1237 return ov7670_g_autogain(sd, &ctrl->value);
1169 } 1238 }
1170 return -EINVAL; 1239 return -EINVAL;
1171} 1240}
@@ -1185,6 +1254,10 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1185 return ov7670_s_vflip(sd, ctrl->value); 1254 return ov7670_s_vflip(sd, ctrl->value);
1186 case V4L2_CID_HFLIP: 1255 case V4L2_CID_HFLIP:
1187 return ov7670_s_hflip(sd, ctrl->value); 1256 return ov7670_s_hflip(sd, ctrl->value);
1257 case V4L2_CID_GAIN:
1258 return ov7670_s_gain(sd, ctrl->value);
1259 case V4L2_CID_AUTOGAIN:
1260 return ov7670_s_autogain(sd, ctrl->value);
1188 } 1261 }
1189 return -EINVAL; 1262 return -EINVAL;
1190} 1263}