aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov7670.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ov7670.c')
-rw-r--r--drivers/media/video/ov7670.c286
1 files changed, 251 insertions, 35 deletions
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c
index aaa50f9b8e78..91c886ab15c6 100644
--- a/drivers/media/video/ov7670.c
+++ b/drivers/media/video/ov7670.c
@@ -198,6 +198,7 @@ struct ov7670_info {
198 struct ov7670_format_struct *fmt; /* Current format */ 198 struct ov7670_format_struct *fmt; /* Current format */
199 unsigned char sat; /* Saturation value */ 199 unsigned char sat; /* Saturation value */
200 int hue; /* Hue value */ 200 int hue; /* Hue value */
201 u8 clkrc; /* Clock divider value */
201}; 202};
202 203
203static inline struct ov7670_info *to_state(struct v4l2_subdev *sd) 204static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
@@ -351,7 +352,7 @@ static struct regval_list ov7670_default_regs[] = {
351static struct regval_list ov7670_fmt_yuv422[] = { 352static struct regval_list ov7670_fmt_yuv422[] = {
352 { REG_COM7, 0x0 }, /* Selects YUV mode */ 353 { REG_COM7, 0x0 }, /* Selects YUV mode */
353 { REG_RGB444, 0 }, /* No RGB444 please */ 354 { REG_RGB444, 0 }, /* No RGB444 please */
354 { REG_COM1, 0 }, 355 { REG_COM1, 0 }, /* CCIR601 */
355 { REG_COM15, COM15_R00FF }, 356 { REG_COM15, COM15_R00FF },
356 { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */ 357 { REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
357 { 0x4f, 0x80 }, /* "matrix coefficient 1" */ 358 { 0x4f, 0x80 }, /* "matrix coefficient 1" */
@@ -367,7 +368,7 @@ static struct regval_list ov7670_fmt_yuv422[] = {
367static struct regval_list ov7670_fmt_rgb565[] = { 368static struct regval_list ov7670_fmt_rgb565[] = {
368 { REG_COM7, COM7_RGB }, /* Selects RGB mode */ 369 { REG_COM7, COM7_RGB }, /* Selects RGB mode */
369 { REG_RGB444, 0 }, /* No RGB444 please */ 370 { REG_RGB444, 0 }, /* No RGB444 please */
370 { REG_COM1, 0x0 }, 371 { REG_COM1, 0x0 }, /* CCIR601 */
371 { REG_COM15, COM15_RGB565 }, 372 { REG_COM15, COM15_RGB565 },
372 { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ 373 { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */
373 { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ 374 { 0x4f, 0xb3 }, /* "matrix coefficient 1" */
@@ -383,7 +384,7 @@ static struct regval_list ov7670_fmt_rgb565[] = {
383static struct regval_list ov7670_fmt_rgb444[] = { 384static struct regval_list ov7670_fmt_rgb444[] = {
384 { REG_COM7, COM7_RGB }, /* Selects RGB mode */ 385 { REG_COM7, COM7_RGB }, /* Selects RGB mode */
385 { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */ 386 { REG_RGB444, R444_ENABLE }, /* Enable xxxxrrrr ggggbbbb */
386 { REG_COM1, 0x40 }, /* Magic reserved bit */ 387 { REG_COM1, 0x0 }, /* CCIR601 */
387 { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */ 388 { REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */
388 { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ 389 { REG_COM9, 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */
389 { 0x4f, 0xb3 }, /* "matrix coefficient 1" */ 390 { 0x4f, 0xb3 }, /* "matrix coefficient 1" */
@@ -408,8 +409,13 @@ static struct regval_list ov7670_fmt_raw[] = {
408 409
409/* 410/*
410 * Low-level register I/O. 411 * Low-level register I/O.
412 *
413 * Note that there are two versions of these. On the XO 1, the
414 * i2c controller only does SMBUS, so that's what we use. The
415 * ov7670 is not really an SMBUS device, though, so the communication
416 * is not always entirely reliable.
411 */ 417 */
412 418#ifdef CONFIG_OLPC_XO_1
413static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg, 419static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
414 unsigned char *value) 420 unsigned char *value)
415{ 421{
@@ -432,9 +438,67 @@ static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
432 int ret = i2c_smbus_write_byte_data(client, reg, value); 438 int ret = i2c_smbus_write_byte_data(client, reg, value);
433 439
434 if (reg == REG_COM7 && (value & COM7_RESET)) 440 if (reg == REG_COM7 && (value & COM7_RESET))
435 msleep(2); /* Wait for reset to run */ 441 msleep(5); /* Wait for reset to run */
442 return ret;
443}
444
445#else /* ! CONFIG_OLPC_XO_1 */
446/*
447 * On most platforms, we'd rather do straight i2c I/O.
448 */
449static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
450 unsigned char *value)
451{
452 struct i2c_client *client = v4l2_get_subdevdata(sd);
453 u8 data = reg;
454 struct i2c_msg msg;
455 int ret;
456
457 /*
458 * Send out the register address...
459 */
460 msg.addr = client->addr;
461 msg.flags = 0;
462 msg.len = 1;
463 msg.buf = &data;
464 ret = i2c_transfer(client->adapter, &msg, 1);
465 if (ret < 0) {
466 printk(KERN_ERR "Error %d on register write\n", ret);
467 return ret;
468 }
469 /*
470 * ...then read back the result.
471 */
472 msg.flags = I2C_M_RD;
473 ret = i2c_transfer(client->adapter, &msg, 1);
474 if (ret >= 0) {
475 *value = data;
476 ret = 0;
477 }
478 return ret;
479}
480
481
482static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
483 unsigned char value)
484{
485 struct i2c_client *client = v4l2_get_subdevdata(sd);
486 struct i2c_msg msg;
487 unsigned char data[2] = { reg, value };
488 int ret;
489
490 msg.addr = client->addr;
491 msg.flags = 0;
492 msg.len = 2;
493 msg.buf = data;
494 ret = i2c_transfer(client->adapter, &msg, 1);
495 if (ret > 0)
496 ret = 0;
497 if (reg == REG_COM7 && (value & COM7_RESET))
498 msleep(5); /* Wait for reset to run */
436 return ret; 499 return ret;
437} 500}
501#endif /* CONFIG_OLPC_XO_1 */
438 502
439 503
440/* 504/*
@@ -744,22 +808,12 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
744 struct ov7670_format_struct *ovfmt; 808 struct ov7670_format_struct *ovfmt;
745 struct ov7670_win_size *wsize; 809 struct ov7670_win_size *wsize;
746 struct ov7670_info *info = to_state(sd); 810 struct ov7670_info *info = to_state(sd);
747 unsigned char com7, clkrc = 0; 811 unsigned char com7;
748 812
749 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize); 813 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
750 if (ret) 814 if (ret)
751 return ret; 815 return ret;
752 /* 816 /*
753 * HACK: if we're running rgb565 we need to grab then rewrite
754 * CLKRC. If we're *not*, however, then rewriting clkrc hoses
755 * the colors.
756 */
757 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565) {
758 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
759 if (ret)
760 return ret;
761 }
762 /*
763 * COM7 is a pain in the ass, it doesn't like to be read then 817 * COM7 is a pain in the ass, it doesn't like to be read then
764 * quickly written afterward. But we have everything we need 818 * quickly written afterward. But we have everything we need
765 * to set it absolutely here, as long as the format-specific 819 * to set it absolutely here, as long as the format-specific
@@ -779,8 +833,18 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
779 ret = ov7670_write_array(sd, wsize->regs); 833 ret = ov7670_write_array(sd, wsize->regs);
780 info->fmt = ovfmt; 834 info->fmt = ovfmt;
781 835
782 if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB565 && ret == 0) 836 /*
783 ret = ov7670_write(sd, REG_CLKRC, clkrc); 837 * If we're running RGB565, we must rewrite clkrc after setting
838 * the other parameters or the image looks poor. If we're *not*
839 * doing RGB565, we must not rewrite clkrc or the image looks
840 * *really* poor.
841 *
842 * (Update) Now that we retain clkrc state, we should be able
843 * to write it unconditionally, and that will make the frame
844 * rate persistent too.
845 */
846 if (ret == 0)
847 ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
784 return ret; 848 return ret;
785} 849}
786 850
@@ -791,20 +855,17 @@ static int ov7670_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
791static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms) 855static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
792{ 856{
793 struct v4l2_captureparm *cp = &parms->parm.capture; 857 struct v4l2_captureparm *cp = &parms->parm.capture;
794 unsigned char clkrc; 858 struct ov7670_info *info = to_state(sd);
795 int ret;
796 859
797 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 860 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
798 return -EINVAL; 861 return -EINVAL;
799 ret = ov7670_read(sd, REG_CLKRC, &clkrc); 862
800 if (ret < 0)
801 return ret;
802 memset(cp, 0, sizeof(struct v4l2_captureparm)); 863 memset(cp, 0, sizeof(struct v4l2_captureparm));
803 cp->capability = V4L2_CAP_TIMEPERFRAME; 864 cp->capability = V4L2_CAP_TIMEPERFRAME;
804 cp->timeperframe.numerator = 1; 865 cp->timeperframe.numerator = 1;
805 cp->timeperframe.denominator = OV7670_FRAME_RATE; 866 cp->timeperframe.denominator = OV7670_FRAME_RATE;
806 if ((clkrc & CLK_EXT) == 0 && (clkrc & CLK_SCALE) > 1) 867 if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1)
807 cp->timeperframe.denominator /= (clkrc & CLK_SCALE); 868 cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE);
808 return 0; 869 return 0;
809} 870}
810 871
@@ -812,19 +873,14 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
812{ 873{
813 struct v4l2_captureparm *cp = &parms->parm.capture; 874 struct v4l2_captureparm *cp = &parms->parm.capture;
814 struct v4l2_fract *tpf = &cp->timeperframe; 875 struct v4l2_fract *tpf = &cp->timeperframe;
815 unsigned char clkrc; 876 struct ov7670_info *info = to_state(sd);
816 int ret, div; 877 int div;
817 878
818 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 879 if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
819 return -EINVAL; 880 return -EINVAL;
820 if (cp->extendedmode != 0) 881 if (cp->extendedmode != 0)
821 return -EINVAL; 882 return -EINVAL;
822 /* 883
823 * CLKRC has a reserved bit, so let's preserve it.
824 */
825 ret = ov7670_read(sd, REG_CLKRC, &clkrc);
826 if (ret < 0)
827 return ret;
828 if (tpf->numerator == 0 || tpf->denominator == 0) 884 if (tpf->numerator == 0 || tpf->denominator == 0)
829 div = 1; /* Reset to full rate */ 885 div = 1; /* Reset to full rate */
830 else 886 else
@@ -833,10 +889,10 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
833 div = 1; 889 div = 1;
834 else if (div > CLK_SCALE) 890 else if (div > CLK_SCALE)
835 div = CLK_SCALE; 891 div = CLK_SCALE;
836 clkrc = (clkrc & 0x80) | div; 892 info->clkrc = (info->clkrc & 0x80) | div;
837 tpf->numerator = 1; 893 tpf->numerator = 1;
838 tpf->denominator = OV7670_FRAME_RATE/div; 894 tpf->denominator = OV7670_FRAME_RATE/div;
839 return ov7670_write(sd, REG_CLKRC, clkrc); 895 return ov7670_write(sd, REG_CLKRC, info->clkrc);
840} 896}
841 897
842 898
@@ -1115,6 +1171,140 @@ static int ov7670_s_vflip(struct v4l2_subdev *sd, int value)
1115 return ret; 1171 return ret;
1116} 1172}
1117 1173
1174/*
1175 * GAIN is split between REG_GAIN and REG_VREF[7:6]. If one believes
1176 * the data sheet, the VREF parts should be the most significant, but
1177 * experience shows otherwise. There seems to be little value in
1178 * messing with the VREF bits, so we leave them alone.
1179 */
1180static int ov7670_g_gain(struct v4l2_subdev *sd, __s32 *value)
1181{
1182 int ret;
1183 unsigned char gain;
1184
1185 ret = ov7670_read(sd, REG_GAIN, &gain);
1186 *value = gain;
1187 return ret;
1188}
1189
1190static int ov7670_s_gain(struct v4l2_subdev *sd, int value)
1191{
1192 int ret;
1193 unsigned char com8;
1194
1195 ret = ov7670_write(sd, REG_GAIN, value & 0xff);
1196 /* Have to turn off AGC as well */
1197 if (ret == 0) {
1198 ret = ov7670_read(sd, REG_COM8, &com8);
1199 ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AGC);
1200 }
1201 return ret;
1202}
1203
1204/*
1205 * Tweak autogain.
1206 */
1207static int ov7670_g_autogain(struct v4l2_subdev *sd, __s32 *value)
1208{
1209 int ret;
1210 unsigned char com8;
1211
1212 ret = ov7670_read(sd, REG_COM8, &com8);
1213 *value = (com8 & COM8_AGC) != 0;
1214 return ret;
1215}
1216
1217static int ov7670_s_autogain(struct v4l2_subdev *sd, int value)
1218{
1219 int ret;
1220 unsigned char com8;
1221
1222 ret = ov7670_read(sd, REG_COM8, &com8);
1223 if (ret == 0) {
1224 if (value)
1225 com8 |= COM8_AGC;
1226 else
1227 com8 &= ~COM8_AGC;
1228 ret = ov7670_write(sd, REG_COM8, com8);
1229 }
1230 return ret;
1231}
1232
1233/*
1234 * Exposure is spread all over the place: top 6 bits in AECHH, middle
1235 * 8 in AECH, and two stashed in COM1 just for the hell of it.
1236 */
1237static int ov7670_g_exp(struct v4l2_subdev *sd, __s32 *value)
1238{
1239 int ret;
1240 unsigned char com1, aech, aechh;
1241
1242 ret = ov7670_read(sd, REG_COM1, &com1) +
1243 ov7670_read(sd, REG_AECH, &aech) +
1244 ov7670_read(sd, REG_AECHH, &aechh);
1245 *value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03);
1246 return ret;
1247}
1248
1249static int ov7670_s_exp(struct v4l2_subdev *sd, int value)
1250{
1251 int ret;
1252 unsigned char com1, com8, aech, aechh;
1253
1254 ret = ov7670_read(sd, REG_COM1, &com1) +
1255 ov7670_read(sd, REG_COM8, &com8);
1256 ov7670_read(sd, REG_AECHH, &aechh);
1257 if (ret)
1258 return ret;
1259
1260 com1 = (com1 & 0xfc) | (value & 0x03);
1261 aech = (value >> 2) & 0xff;
1262 aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f);
1263 ret = ov7670_write(sd, REG_COM1, com1) +
1264 ov7670_write(sd, REG_AECH, aech) +
1265 ov7670_write(sd, REG_AECHH, aechh);
1266 /* Have to turn off AEC as well */
1267 if (ret == 0)
1268 ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AEC);
1269 return ret;
1270}
1271
1272/*
1273 * Tweak autoexposure.
1274 */
1275static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value)
1276{
1277 int ret;
1278 unsigned char com8;
1279 enum v4l2_exposure_auto_type *atype = (enum v4l2_exposure_auto_type *) value;
1280
1281 ret = ov7670_read(sd, REG_COM8, &com8);
1282 if (com8 & COM8_AEC)
1283 *atype = V4L2_EXPOSURE_AUTO;
1284 else
1285 *atype = V4L2_EXPOSURE_MANUAL;
1286 return ret;
1287}
1288
1289static int ov7670_s_autoexp(struct v4l2_subdev *sd,
1290 enum v4l2_exposure_auto_type value)
1291{
1292 int ret;
1293 unsigned char com8;
1294
1295 ret = ov7670_read(sd, REG_COM8, &com8);
1296 if (ret == 0) {
1297 if (value == V4L2_EXPOSURE_AUTO)
1298 com8 |= COM8_AEC;
1299 else
1300 com8 &= ~COM8_AEC;
1301 ret = ov7670_write(sd, REG_COM8, com8);
1302 }
1303 return ret;
1304}
1305
1306
1307
1118static int ov7670_queryctrl(struct v4l2_subdev *sd, 1308static int ov7670_queryctrl(struct v4l2_subdev *sd,
1119 struct v4l2_queryctrl *qc) 1309 struct v4l2_queryctrl *qc)
1120{ 1310{
@@ -1131,6 +1321,14 @@ static int ov7670_queryctrl(struct v4l2_subdev *sd,
1131 return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128); 1321 return v4l2_ctrl_query_fill(qc, 0, 256, 1, 128);
1132 case V4L2_CID_HUE: 1322 case V4L2_CID_HUE:
1133 return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0); 1323 return v4l2_ctrl_query_fill(qc, -180, 180, 5, 0);
1324 case V4L2_CID_GAIN:
1325 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
1326 case V4L2_CID_AUTOGAIN:
1327 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1328 case V4L2_CID_EXPOSURE:
1329 return v4l2_ctrl_query_fill(qc, 0, 65535, 1, 500);
1330 case V4L2_CID_EXPOSURE_AUTO:
1331 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
1134 } 1332 }
1135 return -EINVAL; 1333 return -EINVAL;
1136} 1334}
@@ -1150,6 +1348,14 @@ static int ov7670_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1150 return ov7670_g_vflip(sd, &ctrl->value); 1348 return ov7670_g_vflip(sd, &ctrl->value);
1151 case V4L2_CID_HFLIP: 1349 case V4L2_CID_HFLIP:
1152 return ov7670_g_hflip(sd, &ctrl->value); 1350 return ov7670_g_hflip(sd, &ctrl->value);
1351 case V4L2_CID_GAIN:
1352 return ov7670_g_gain(sd, &ctrl->value);
1353 case V4L2_CID_AUTOGAIN:
1354 return ov7670_g_autogain(sd, &ctrl->value);
1355 case V4L2_CID_EXPOSURE:
1356 return ov7670_g_exp(sd, &ctrl->value);
1357 case V4L2_CID_EXPOSURE_AUTO:
1358 return ov7670_g_autoexp(sd, &ctrl->value);
1153 } 1359 }
1154 return -EINVAL; 1360 return -EINVAL;
1155} 1361}
@@ -1169,6 +1375,15 @@ static int ov7670_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
1169 return ov7670_s_vflip(sd, ctrl->value); 1375 return ov7670_s_vflip(sd, ctrl->value);
1170 case V4L2_CID_HFLIP: 1376 case V4L2_CID_HFLIP:
1171 return ov7670_s_hflip(sd, ctrl->value); 1377 return ov7670_s_hflip(sd, ctrl->value);
1378 case V4L2_CID_GAIN:
1379 return ov7670_s_gain(sd, ctrl->value);
1380 case V4L2_CID_AUTOGAIN:
1381 return ov7670_s_autogain(sd, ctrl->value);
1382 case V4L2_CID_EXPOSURE:
1383 return ov7670_s_exp(sd, ctrl->value);
1384 case V4L2_CID_EXPOSURE_AUTO:
1385 return ov7670_s_autoexp(sd,
1386 (enum v4l2_exposure_auto_type) ctrl->value);
1172 } 1387 }
1173 return -EINVAL; 1388 return -EINVAL;
1174} 1389}
@@ -1268,6 +1483,7 @@ static int ov7670_probe(struct i2c_client *client,
1268 1483
1269 info->fmt = &ov7670_formats[0]; 1484 info->fmt = &ov7670_formats[0];
1270 info->sat = 128; /* Review this */ 1485 info->sat = 128; /* Review this */
1486 info->clkrc = 1; /* 30fps */
1271 1487
1272 return 0; 1488 return 0;
1273} 1489}