14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/i2c.h>
18 #include <linux/videodev2.h>
37 #define VGA_HEIGHT 480
38 #define QVGA_WIDTH 320
39 #define QVGA_HEIGHT 240
41 #define CIF_HEIGHT 288
42 #define QCIF_WIDTH 176
43 #define QCIF_HEIGHT 144
48 #define OV7670_I2C_ADDR 0x42
56 #define COM1_CCIR656 0x40
58 #define REG_GbAVE 0x06
59 #define REG_AECHH 0x07
62 #define COM2_SSLEEP 0x10
66 #define COM3_SWAP 0x40
67 #define COM3_SCALEEN 0x08
68 #define COM3_DCWEN 0x04
73 #define REG_CLKRC 0x11
75 #define CLK_SCALE 0x3f
77 #define COM7_RESET 0x80
78 #define COM7_FMT_MASK 0x38
79 #define COM7_FMT_VGA 0x00
80 #define COM7_FMT_CIF 0x20
81 #define COM7_FMT_QVGA 0x10
82 #define COM7_FMT_QCIF 0x08
85 #define COM7_BAYER 0x01
86 #define COM7_PBAYER 0x05
88 #define COM8_FASTAEC 0x80
89 #define COM8_AECSTEP 0x40
90 #define COM8_BFILT 0x20
95 #define REG_COM10 0x15
96 #define COM10_HSYNC 0x40
97 #define COM10_PCLK_HB 0x20
98 #define COM10_HREF_REV 0x08
99 #define COM10_VS_LEAD 0x04
100 #define COM10_VS_NEG 0x02
101 #define COM10_HS_NEG 0x01
102 #define REG_HSTART 0x17
103 #define REG_HSTOP 0x18
104 #define REG_VSTART 0x19
105 #define REG_VSTOP 0x1a
106 #define REG_PSHFT 0x1b
107 #define REG_MIDH 0x1c
108 #define REG_MIDL 0x1d
109 #define REG_MVFP 0x1e
110 #define MVFP_MIRROR 0x20
111 #define MVFP_FLIP 0x10
116 #define REG_HSYST 0x30
117 #define REG_HSYEN 0x31
118 #define REG_HREF 0x32
119 #define REG_TSLB 0x3a
120 #define TSLB_YLAST 0x04
121 #define REG_COM11 0x3b
122 #define COM11_NIGHT 0x80
123 #define COM11_NMFR 0x60
124 #define COM11_HZAUTO 0x10
125 #define COM11_50HZ 0x08
126 #define COM11_EXP 0x02
127 #define REG_COM12 0x3c
128 #define COM12_HREF 0x80
129 #define REG_COM13 0x3d
130 #define COM13_GAMMA 0x80
131 #define COM13_UVSAT 0x40
132 #define COM13_UVSWAP 0x01
133 #define REG_COM14 0x3e
134 #define COM14_DCWEN 0x10
135 #define REG_EDGE 0x3f
136 #define REG_COM15 0x40
137 #define COM15_R10F0 0x00
138 #define COM15_R01FE 0x80
139 #define COM15_R00FF 0xc0
140 #define COM15_RGB565 0x10
141 #define COM15_RGB555 0x30
142 #define REG_COM16 0x41
143 #define COM16_AWBGAIN 0x08
144 #define REG_COM17 0x42
145 #define COM17_AECWIN 0xc0
146 #define COM17_CBAR 0x08
157 #define REG_CMATRIX_BASE 0x4f
158 #define CMATRIX_LEN 6
159 #define REG_CMATRIX_SIGN 0x58
162 #define REG_BRIGHT 0x55
163 #define REG_CONTRAS 0x56
165 #define REG_GFIX 0x69
167 #define REG_REG76 0x76
168 #define R76_BLKPCOR 0x80
169 #define R76_WHTPCOR 0x40
171 #define REG_RGB444 0x8c
172 #define R444_ENABLE 0x02
173 #define R444_RGBX 0x01
175 #define REG_HAECC1 0x9f
176 #define REG_HAECC2 0xa0
178 #define REG_BD50MAX 0xa5
179 #define REG_HAECC3 0xa6
180 #define REG_HAECC4 0xa7
181 #define REG_HAECC5 0xa8
182 #define REG_HAECC6 0xa9
183 #define REG_HAECC7 0xaa
184 #define REG_BD60MAX 0xab
190 struct ov7670_format_struct;
193 struct ov7670_format_struct *
fmt;
223 static struct regval_list ov7670_default_regs[] = {
243 { 0x70, 0x3a }, { 0x71, 0x35 },
244 { 0x72, 0x11 }, { 0x73, 0xf0 },
248 { 0x7a, 0x20 }, { 0x7b, 0x10 },
249 { 0x7c, 0x1e }, { 0x7d, 0x35 },
250 { 0x7e, 0x5a }, { 0x7f, 0x69 },
251 { 0x80, 0x76 }, { 0x81, 0x80 },
252 { 0x82, 0x88 }, { 0x83, 0x8f },
253 { 0x84, 0x96 }, { 0x85, 0xa3 },
254 { 0x86, 0xaf }, { 0x87, 0xc4 },
255 { 0x88, 0xd7 }, { 0x89, 0xe8 },
275 { 0x21, 0x02 }, { 0x22, 0x91 },
276 { 0x29, 0x07 }, { 0x33, 0x0b },
277 { 0x35, 0x0b }, { 0x37, 0x1d },
278 { 0x38, 0x71 }, { 0x39, 0x2a },
281 { 0x6b, 0x4a }, { 0x74, 0x10 },
282 { 0x8d, 0x4f }, { 0x8e, 0 },
283 { 0x8f, 0 }, { 0x90, 0 },
284 { 0x91, 0 }, { 0x96, 0 },
285 { 0x9a, 0 }, { 0xb0, 0x84 },
286 { 0xb1, 0x0c }, { 0xb2, 0x0e },
287 { 0xb3, 0x82 }, { 0xb8, 0x0a },
290 { 0x43, 0x0a }, { 0x44, 0xf0 },
291 { 0x45, 0x34 }, { 0x46, 0x58 },
292 { 0x47, 0x28 }, { 0x48, 0x3a },
293 { 0x59, 0x88 }, { 0x5a, 0x88 },
294 { 0x5b, 0x44 }, { 0x5c, 0x67 },
295 { 0x5d, 0x49 }, { 0x5e, 0x0e },
296 { 0x6c, 0x0a }, { 0x6d, 0x55 },
297 { 0x6e, 0x11 }, { 0x6f, 0x9f },
303 { 0x4f, 0x80 }, { 0x50, 0x80 },
304 { 0x51, 0 }, { 0x52, 0x22 },
305 { 0x53, 0x5e }, { 0x54, 0x80 },
309 { 0x75, 0x05 }, { 0x76, 0xe1 },
310 { 0x4c, 0 }, { 0x77, 0x01 },
316 { 0xa4, 0x88 }, { 0x96, 0 },
317 { 0x97, 0x30 }, { 0x98, 0x20 },
318 { 0x99, 0x30 }, { 0x9a, 0x84 },
319 { 0x9b, 0x29 }, { 0x9c, 0x03 },
320 { 0x9d, 0x4c }, { 0x9e, 0x3f },
324 { 0x79, 0x01 }, { 0xc8, 0xf0 },
325 { 0x79, 0x0f }, { 0xc8, 0x00 },
326 { 0x79, 0x10 }, { 0xc8, 0x7e },
327 { 0x79, 0x0a }, { 0xc8, 0x80 },
328 { 0x79, 0x0b }, { 0xc8, 0x01 },
329 { 0x79, 0x0c }, { 0xc8, 0x0f },
330 { 0x79, 0x0d }, { 0xc8, 0x20 },
331 { 0x79, 0x09 }, { 0xc8, 0x80 },
332 { 0x79, 0x02 }, { 0xc8, 0xc0 },
333 { 0x79, 0x03 }, { 0xc8, 0x40 },
334 { 0x79, 0x05 }, { 0xc8, 0x30 },
418 unsigned char *
value)
425 *value = (
unsigned char)ret;
432 static int ov7670_write_smbus(
struct v4l2_subdev *sd,
unsigned char reg,
435 struct i2c_client *client = v4l2_get_subdevdata(sd);
446 static int ov7670_read_i2c(
struct v4l2_subdev *sd,
unsigned char reg,
447 unsigned char *value)
449 struct i2c_client *client = v4l2_get_subdevdata(sd);
479 static int ov7670_write_i2c(
struct v4l2_subdev *sd,
unsigned char reg,
482 struct i2c_client *client = v4l2_get_subdevdata(sd);
484 unsigned char data[2] = {
reg, value };
499 static int ov7670_read(
struct v4l2_subdev *sd,
unsigned char reg,
500 unsigned char *value)
504 return ov7670_read_smbus(sd, reg, value);
506 return ov7670_read_i2c(sd, reg, value);
509 static int ov7670_write(
struct v4l2_subdev *sd,
unsigned char reg,
514 return ov7670_write_smbus(sd, reg, value);
516 return ov7670_write_i2c(sd, reg, value);
547 return ov7670_write_array(sd, ov7670_default_regs);
557 ret = ov7670_init(sd, 0);
560 ret = ov7670_read(sd,
REG_MIDH, &v);
565 ret = ov7670_read(sd,
REG_MIDL, &v);
573 ret = ov7670_read(sd,
REG_PID, &v);
578 ret = ov7670_read(sd,
REG_VER, &v);
592 static struct ov7670_format_struct {
597 } ov7670_formats[] = {
601 .regs = ov7670_fmt_yuv422,
602 .cmatrix = { 128, -128, 0, -34, -94, 128 },
607 .regs = ov7670_fmt_rgb444,
608 .cmatrix = { 179, -179, 0, -61, -176, 228 },
613 .regs = ov7670_fmt_rgb565,
614 .cmatrix = { 179, -179, 0, -61, -176, 228 },
619 .regs = ov7670_fmt_raw,
620 .cmatrix = { 0, 0, 0, 0, 0, 0 },
623 #define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats)
655 static struct ov7670_win_size {
658 unsigned char com7_bit;
665 } ov7670_win_sizes[] = {
708 .regs = ov7670_qcif_regs,
712 #define N_WIN_SIZES (ARRAY_SIZE(ov7670_win_sizes))
718 static int ov7670_set_hw(
struct v4l2_subdev *sd,
int hstart,
int hstop,
728 ret = ov7670_write(sd,
REG_HSTART, (hstart >> 3) & 0xff);
729 ret += ov7670_write(sd,
REG_HSTOP, (hstop >> 3) & 0xff);
730 ret += ov7670_read(sd,
REG_HREF, &v);
731 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x7);
733 ret += ov7670_write(sd,
REG_HREF, v);
737 ret += ov7670_write(sd,
REG_VSTART, (vstart >> 2) & 0xff);
738 ret += ov7670_write(sd,
REG_VSTOP, (vstop >> 2) & 0xff);
739 ret += ov7670_read(sd,
REG_VREF, &v);
740 v = (v & 0xf0) | ((vstop & 0x3) << 2) | (vstart & 0x3);
742 ret += ov7670_write(sd,
REG_VREF, v);
753 *code = ov7670_formats[
index].mbus_code;
757 static int ov7670_try_fmt_internal(
struct v4l2_subdev *sd,
758 struct v4l2_mbus_framefmt *
fmt,
759 struct ov7670_format_struct **ret_fmt,
760 struct ov7670_win_size **ret_wsize)
763 struct ov7670_win_size *wsize;
766 if (ov7670_formats[index].mbus_code == fmt->code)
768 if (index >= N_OV7670_FMTS) {
771 fmt->code = ov7670_formats[0].mbus_code;
774 *ret_fmt = ov7670_formats +
index;
783 for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes +
N_WIN_SIZES;
785 if (fmt->width >= wsize->width && fmt->height >= wsize->height)
787 if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
789 if (ret_wsize !=
NULL)
794 fmt->width = wsize->width;
795 fmt->height = wsize->height;
796 fmt->colorspace = ov7670_formats[
index].colorspace;
800 static int ov7670_try_mbus_fmt(
struct v4l2_subdev *sd,
801 struct v4l2_mbus_framefmt *fmt)
803 return ov7670_try_fmt_internal(sd, fmt,
NULL,
NULL);
809 static int ov7670_s_mbus_fmt(
struct v4l2_subdev *sd,
810 struct v4l2_mbus_framefmt *fmt)
812 struct ov7670_format_struct *ovfmt;
813 struct ov7670_win_size *wsize;
818 ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
828 com7 = ovfmt->regs[0].value;
829 com7 |= wsize->com7_bit;
834 ov7670_write_array(sd, ovfmt->regs + 1);
835 ov7670_set_hw(sd, wsize->hstart, wsize->hstop, wsize->vstart,
839 ret = ov7670_write_array(sd, wsize->regs);
911 static int ov7670_frame_rates[] = { 30, 15, 10, 5, 1 };
913 static int ov7670_enum_frameintervals(
struct v4l2_subdev *sd,
920 interval->
discrete.denominator = ov7670_frame_rates[interval->
index];
927 static int ov7670_enum_framesizes(
struct v4l2_subdev *sd,
940 struct ov7670_win_size *
win = &ov7670_win_sizes[
index];
945 if (index == ++num_valid) {
948 fsize->
discrete.height = win->height;
960 static int ov7670_store_cmatrix(
struct v4l2_subdev *sd,
964 unsigned char signbits = 0;
977 signbits |= (1 <<
i);
978 if (matrix[i] < -255)
981 raw = (-1 * matrix[
i]) & 0xff;
987 raw = matrix[
i] & 0xff;
1006 static const int ov7670_sin_table[] = {
1007 0, 87, 173, 258, 342, 422,
1008 499, 573, 642, 707, 766, 819,
1009 866, 906, 939, 965, 984, 996,
1013 static int ov7670_sine(
int theta)
1023 sine = ov7670_sin_table[theta/
SIN_STEP];
1026 sine = 1000 - ov7670_sin_table[theta/
SIN_STEP];
1031 static int ov7670_cosine(
int theta)
1036 else if (theta < -180)
1038 return ov7670_sine(theta);
1044 static void ov7670_calc_cmatrix(
struct ov7670_info *info,
1045 int matrix[CMATRIX_LEN])
1052 matrix[i] = (info->
fmt->cmatrix[i]*info->
sat) >> 7;
1056 if (info->
hue != 0) {
1059 memcpy(tmpmatrix, matrix, CMATRIX_LEN*
sizeof(
int));
1060 sinth = ov7670_sine(info->
hue);
1061 costh = ov7670_cosine(info->
hue);
1063 matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000;
1064 matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000;
1065 matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000;
1066 matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000;
1067 matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000;
1068 matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000;
1074 static int ov7670_s_sat(
struct v4l2_subdev *sd,
int value)
1081 ov7670_calc_cmatrix(info, matrix);
1082 ret = ov7670_store_cmatrix(sd, matrix);
1094 static int ov7670_s_hue(
struct v4l2_subdev *sd,
int value)
1100 if (value < -180 || value > 180)
1103 ov7670_calc_cmatrix(info, matrix);
1104 ret = ov7670_store_cmatrix(sd, matrix);
1121 static unsigned char ov7670_sm_to_abs(
unsigned char v)
1123 if ((v & 0x80) == 0)
1125 return 128 - (v & 0x7f);
1129 static unsigned char ov7670_abs_to_sm(
unsigned char v)
1133 return (128 - v) | 0x80;
1136 static int ov7670_s_brightness(
struct v4l2_subdev *sd,
int value)
1138 unsigned char com8 = 0,
v;
1144 v = ov7670_abs_to_sm(value);
1151 unsigned char v = 0;
1154 *value = ov7670_sm_to_abs(v);
1158 static int ov7670_s_contrast(
struct v4l2_subdev *sd,
int value)
1160 return ov7670_write(sd,
REG_CONTRAS, (
unsigned char) value);
1165 unsigned char v = 0;
1175 unsigned char v = 0;
1177 ret = ov7670_read(sd,
REG_MVFP, &v);
1183 static int ov7670_s_hflip(
struct v4l2_subdev *sd,
int value)
1185 unsigned char v = 0;
1188 ret = ov7670_read(sd,
REG_MVFP, &v);
1194 ret += ov7670_write(sd,
REG_MVFP, v);
1203 unsigned char v = 0;
1205 ret = ov7670_read(sd,
REG_MVFP, &v);
1211 static int ov7670_s_vflip(
struct v4l2_subdev *sd,
int value)
1213 unsigned char v = 0;
1216 ret = ov7670_read(sd,
REG_MVFP, &v);
1222 ret += ov7670_write(sd,
REG_MVFP, v);
1237 ret = ov7670_read(sd,
REG_GAIN, &gain);
1242 static int ov7670_s_gain(
struct v4l2_subdev *sd,
int value)
1247 ret = ov7670_write(sd,
REG_GAIN, value & 0xff);
1250 ret = ov7670_read(sd,
REG_COM8, &com8);
1264 ret = ov7670_read(sd,
REG_COM8, &com8);
1269 static int ov7670_s_autogain(
struct v4l2_subdev *sd,
int value)
1274 ret = ov7670_read(sd,
REG_COM8, &com8);
1280 ret = ov7670_write(sd,
REG_COM8, com8);
1292 unsigned char com1, aech, aechh;
1294 ret = ov7670_read(sd,
REG_COM1, &com1) +
1297 *value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03);
1301 static int ov7670_s_exp(
struct v4l2_subdev *sd,
int value)
1304 unsigned char com1, com8, aech, aechh;
1306 ret = ov7670_read(sd,
REG_COM1, &com1) +
1312 com1 = (com1 & 0xfc) | (value & 0x03);
1313 aech = (value >> 2) & 0xff;
1314 aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f);
1315 ret = ov7670_write(sd,
REG_COM1, com1) +
1333 ret = ov7670_read(sd,
REG_COM8, &com8);
1341 static int ov7670_s_autoexp(
struct v4l2_subdev *sd,
1347 ret = ov7670_read(sd,
REG_COM8, &com8);
1353 ret = ov7670_write(sd,
REG_COM8, com8);
1360 static int ov7670_queryctrl(
struct v4l2_subdev *sd,
1392 return ov7670_g_brightness(sd, &ctrl->
value);
1394 return ov7670_g_contrast(sd, &ctrl->
value);
1396 return ov7670_g_sat(sd, &ctrl->
value);
1398 return ov7670_g_hue(sd, &ctrl->
value);
1400 return ov7670_g_vflip(sd, &ctrl->
value);
1402 return ov7670_g_hflip(sd, &ctrl->
value);
1404 return ov7670_g_gain(sd, &ctrl->
value);
1406 return ov7670_g_autogain(sd, &ctrl->
value);
1408 return ov7670_g_exp(sd, &ctrl->
value);
1410 return ov7670_g_autoexp(sd, &ctrl->
value);
1419 return ov7670_s_brightness(sd, ctrl->
value);
1421 return ov7670_s_contrast(sd, ctrl->
value);
1423 return ov7670_s_sat(sd, ctrl->
value);
1425 return ov7670_s_hue(sd, ctrl->
value);
1427 return ov7670_s_vflip(sd, ctrl->
value);
1429 return ov7670_s_hflip(sd, ctrl->
value);
1431 return ov7670_s_gain(sd, ctrl->
value);
1433 return ov7670_s_autogain(sd, ctrl->
value);
1435 return ov7670_s_exp(sd, ctrl->
value);
1437 return ov7670_s_autoexp(sd,
1443 static int ov7670_g_chip_ident(
struct v4l2_subdev *sd,
1446 struct i2c_client *client = v4l2_get_subdevdata(sd);
1451 #ifdef CONFIG_VIDEO_ADV_DEBUG
1454 struct i2c_client *client = v4l2_get_subdevdata(sd);
1455 unsigned char val = 0;
1462 ret = ov7670_read(sd, reg->
reg & 0xff, &val);
1470 struct i2c_client *client = v4l2_get_subdevdata(sd);
1476 ov7670_write(sd, reg->
reg & 0xff, reg->
val & 0xff);
1484 .g_chip_ident = ov7670_g_chip_ident,
1485 .g_ctrl = ov7670_g_ctrl,
1486 .s_ctrl = ov7670_s_ctrl,
1487 .queryctrl = ov7670_queryctrl,
1488 .reset = ov7670_reset,
1489 .init = ov7670_init,
1490 #ifdef CONFIG_VIDEO_ADV_DEBUG
1491 .g_register = ov7670_g_register,
1492 .s_register = ov7670_s_register,
1497 .enum_mbus_fmt = ov7670_enum_mbus_fmt,
1498 .try_mbus_fmt = ov7670_try_mbus_fmt,
1499 .s_mbus_fmt = ov7670_s_mbus_fmt,
1500 .s_parm = ov7670_s_parm,
1501 .g_parm = ov7670_g_parm,
1502 .enum_frameintervals = ov7670_enum_frameintervals,
1503 .enum_framesizes = ov7670_enum_framesizes,
1507 .core = &ov7670_core_ops,
1508 .video = &ov7670_video_ops,
1513 static int ov7670_probe(
struct i2c_client *client,
1527 if (client->
dev.platform_data) {
1543 ret = ov7670_detect(sd);
1546 "chip found @ 0x%x (%s) is not an ov7670 chip.\n",
1551 v4l_info(client,
"chip found @ 0x%02x (%s)\n",
1554 info->
fmt = &ov7670_formats[0];
1561 static int ov7670_remove(
struct i2c_client *client)
1563 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1566 kfree(to_state(sd));
1581 .probe = ov7670_probe,
1582 .remove = ov7670_remove,
1583 .id_table = ov7670_id,