aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
authorJonathan Corbet <corbet@lwn.net>2010-03-05 14:48:39 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-17 23:51:22 -0400
commit364e93372fb21ef5de18d0122c78789f065ddbf5 (patch)
treebfea3132d78b976ccae551f603f0d1c7845e5862 /drivers/media/video/ov7670.c
parent81898671247a6cfa6bfd6a32faee18b3999b6610 (diff)
V4L/DVB: ov7670: wire up controls for exposure and autoexposure
Signed-off-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r--drivers/media/video/ov7670.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index e7555d1f90e6..90c44598dd51 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -1190,6 +1190,79 @@ static int ov7670_s_autogain(struct v4l2_subdev *sd, int value)
1190 return ret; 1190 return ret;
1191} 1191}
1192 1192
1193/*
1194 * Exposure is spread all over the place: top 6 bits in AECHH, middle
1195 * 8 in AECH, and two stashed in COM1 just for the hell of it.
1196 */
1197static int ov7670_g_exp(struct v4l2_subdev *sd, __s32 *value)
1198{
1199 int ret;
1200 unsigned char com1, aech, aechh;
1201
1202 ret = ov7670_read(sd, REG_COM1, &com1) +
1203 ov7670_read(sd, REG_AECH, &aech) +
1204 ov7670_read(sd, REG_AECHH, &aechh);
1205 *value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03);
1206 return ret;
1207}
1208
1209static int ov7670_s_exp(struct v4l2_subdev *sd, int value)
1210{
1211 int ret;
1212 unsigned char com1, com8, aech, aechh;
1213
1214 ret = ov7670_read(sd, REG_COM1, &com1) +
1215 ov7670_read(sd, REG_COM8, &com8);
1216 ov7670_read(sd, REG_AECHH, &aechh);
1217 if (ret)
1218 return ret;
1219
1220 com1 = (com1 & 0xfc) | (value & 0x03);
1221 aech = (value >> 2) & 0xff;
1222 aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f);
1223 ret = ov7670_write(sd, REG_COM1, com1) +
1224 ov7670_write(sd, REG_AECH, aech) +
1225 ov7670_write(sd, REG_AECHH, aechh);
1226 /* Have to turn off AEC as well */
1227 if (ret == 0)
1228 ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AEC);
1229 return ret;
1230}
1231
1232/*
1233 * Tweak autoexposure.
1234 */
1235static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value)
1236{
1237 int ret;
1238 unsigned char com8;
1239 enum v4l2_exposure_auto_type *atype = (enum v4l2_exposure_auto_type *) value;
1240
1241 ret = ov7670_read(sd, REG_COM8, &com8);
1242 if (com8 & COM8_AEC)
1243 *value = V4L2_EXPOSURE_AUTO;
1244 else
1245 *value = V4L2_EXPOSURE_MANUAL;
1246 return ret;
1247}
1248
1249static int ov7670_s_autoexp(struct v4l2_subdev *sd,
1250 enum v4l2_exposure_auto_type value)
1251{
1252 int ret;
1253 unsigned char com8;
1254
1255 ret = ov7670_read(sd, REG_COM8, &com8);
1256 if (ret == 0) {
1257 if (value == V4L2_EXPOSURE_AUTO)
1258 com8 |= COM8_AEC;
1259 else
1260 com8 &= ~COM8_AEC;
1261 ret = ov7670_write(sd, REG_COM8, com8);
1262 }
1263 return ret;
1264}
1265
1193 1266
1194 1267
1195static int ov7670_queryctrl(struct v4l2_subdev *sd, 1268static int ov7670_queryctrl(struct v4l2_subdev *sd,
@@ -1212,6 +1285,10 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd,
1212 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); 1285 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1213 case V4L2_CID_AUTOGAIN: 1286 case V4L2_CID_AUTOGAIN:
1214 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1); 1287 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1288 case V4L2_CID_EXPOSURE:
1289 return v4l2_ctrl_query_fill(qc, 0, 65535, 1, 500);
1290 case V4L2_CID_EXPOSURE_AUTO:
1291 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1215 } 1292 }
1216 return -EINVAL; 1293 return -EINVAL;
1217} 1294}
@@ -1235,6 +1312,10 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1235 return ov7670_g_gain(sd, &ctrl->value); 1312 return ov7670_g_gain(sd, &ctrl->value);
1236 case V4L2_CID_AUTOGAIN: 1313 case V4L2_CID_AUTOGAIN:
1237 return ov7670_g_autogain(sd, &ctrl->value); 1314 return ov7670_g_autogain(sd, &ctrl->value);
1315 case V4L2_CID_EXPOSURE:
1316 return ov7670_g_exp(sd, &ctrl->value);
1317 case V4L2_CID_EXPOSURE_AUTO:
1318 return ov7670_g_autoexp(sd, &ctrl->value);
1238 } 1319 }
1239 return -EINVAL; 1320 return -EINVAL;
1240} 1321}
@@ -1258,6 +1339,11 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1258 return ov7670_s_gain(sd, ctrl->value); 1339 return ov7670_s_gain(sd, ctrl->value);
1259 case V4L2_CID_AUTOGAIN: 1340 case V4L2_CID_AUTOGAIN:
1260 return ov7670_s_autogain(sd, ctrl->value); 1341 return ov7670_s_autogain(sd, ctrl->value);
1342 case V4L2_CID_EXPOSURE:
1343 return ov7670_s_exp(sd, ctrl->value);
1344 case V4L2_CID_EXPOSURE_AUTO:
1345 return ov7670_s_autoexp(sd,
1346 (enum v4l2_exposure_auto_type) ctrl->value);
1261 } 1347 }
1262 return -EINVAL; 1348 return -EINVAL;
1263} 1349}