19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/i2c.h>
22 #include <linux/slab.h>
25 #include <linux/videodev2.h>
117 #define LC_COEFB 0x4B
118 #define LC_COEFR 0x4C
131 #define AWBB_BLK 0x62
132 #define AWB_CTRL0 0x63
133 #define DSP_CTRL1 0x64
134 #define DSP_CTRL2 0x65
135 #define DSP_CTRL3 0x66
136 #define DSP_CTRL4 0x67
137 #define AWB_BIAS 0x68
138 #define AWB_CTRL1 0x69
139 #define AWB_CTRL2 0x6A
140 #define AWB_CTRL3 0x6B
141 #define AWB_CTRL4 0x6C
142 #define AWB_CTRL5 0x6D
143 #define AWB_CTRL6 0x6E
144 #define AWB_CTRL7 0x6F
145 #define AWB_CTRL8 0x70
146 #define AWB_CTRL9 0x71
147 #define AWB_CTRL10 0x72
148 #define AWB_CTRL11 0x73
149 #define AWB_CTRL12 0x74
150 #define AWB_CTRL13 0x75
151 #define AWB_CTRL14 0x76
152 #define AWB_CTRL15 0x77
153 #define AWB_CTRL16 0x78
154 #define AWB_CTRL17 0x79
155 #define AWB_CTRL18 0x7A
156 #define AWB_CTRL19 0x7B
157 #define AWB_CTRL20 0x7C
158 #define AWB_CTRL21 0x7D
176 #define EDGE_STRNGT 0x8F
177 #define EDGE_TRSHLD 0x90
179 #define EDGE_UPPER 0x92
180 #define EDGE_LOWER 0x93
187 #define MTX_CTRL 0x9A
190 #define CNTRST_CTRL 0x9D
196 #define FIFODLYM 0xA3
197 #define FIFODLYA 0xA4
216 #define SOFT_SLEEP_MODE 0x10
224 #define SWAP_MASK (SWAP_RGB | SWAP_YUV | SWAP_ML)
225 #define IMG_MASK (VFLIP_IMG | HFLIP_IMG)
227 #define VFLIP_IMG 0x80
228 #define HFLIP_IMG 0x40
229 #define SWAP_RGB 0x20
230 #define SWAP_YUV 0x10
233 #define NOTRI_CLOCK 0x04
236 #define NOTRI_DATA 0x02
238 #define SCOLOR_TEST 0x01
242 #define PLL_BYPASS 0x00
247 #define AEC_FULL 0x00
253 #define AFR_ON_OFF 0x80
254 #define AFR_SPPED 0x40
256 #define AFR_NO_RATE 0x00
266 #define AEC_NO_LIMIT 0x01
271 #define SCCB_RESET 0x80
274 #define SLCT_MASK 0x40
275 #define SLCT_VGA 0x00
276 #define SLCT_QVGA 0x40
277 #define ITU656_ON_OFF 0x20
278 #define SENSOR_RAW 0x10
280 #define FMT_MASK 0x0c
281 #define FMT_GBR422 0x00
282 #define FMT_RGB565 0x04
283 #define FMT_RGB555 0x08
284 #define FMT_RGB444 0x0c
286 #define OFMT_MASK 0x03
287 #define OFMT_YUV 0x00
288 #define OFMT_P_BRAW 0x01
289 #define OFMT_RGB 0x02
290 #define OFMT_BRAW 0x03
293 #define FAST_ALGO 0x80
295 #define UNLMT_STEP 0x40
297 #define BNDF_ON_OFF 0x20
299 #define AEC_ON_OFF 0x08
305 #define BASE_AECAGC 0x80
310 #define GAIN_16x 0x30
311 #define GAIN_32x 0x40
312 #define GAIN_64x 0x50
313 #define GAIN_128x 0x60
314 #define DROP_VSYNC 0x04
315 #define DROP_HREF 0x02
318 #define SGLF_ON_OFF 0x02
319 #define SGLF_TRIG 0x01
322 #define HREF_VSTART_SHIFT 6
323 #define HREF_HSTART_SHIFT 4
324 #define HREF_VSIZE_SHIFT 2
325 #define HREF_HSIZE_SHIFT 0
328 #define EXHCH_VSIZE_SHIFT 2
329 #define EXHCH_HSIZE_SHIFT 0
333 #define UV_ON_OFF 0x40
334 #define YUV444_2_422 0x20
335 #define CLR_MTRX_ON_OFF 0x10
336 #define INTPLT_ON_OFF 0x08
337 #define GMM_ON_OFF 0x04
338 #define AUTO_BLK_ON_OFF 0x02
339 #define AUTO_WHT_ON_OFF 0x01
345 #define CBAR_MASK 0x20
347 #define CBAR_OFF 0x00
350 #define DSP_OFMT_YUV 0x00
351 #define DSP_OFMT_RGB 0x00
352 #define DSP_OFMT_RAW8 0x02
353 #define DSP_OFMT_RAW10 0x03
356 #define AWB_ACTRL 0x80
357 #define DENOISE_ACTRL 0x40
358 #define EDGE_ACTRL 0x20
359 #define UV_ACTRL 0x10
360 #define SCAL0_ACTRL 0x08
361 #define SCAL1_2_ACTRL 0x04
363 #define VGA_WIDTH 640
364 #define VGA_HEIGHT 480
365 #define QVGA_WIDTH 320
366 #define QVGA_HEIGHT 240
367 #define OV772X_MAX_WIDTH VGA_WIDTH
368 #define OV772X_MAX_HEIGHT VGA_HEIGHT
373 #define OV7720 0x7720
374 #define OV7725 0x7721
375 #define VERSION(pid, ver) ((pid<<8)|(ver&0xFF))
532 s32 val = ov772x_read(client, command);
539 return ov772x_write(client, command, val);
542 static int ov772x_reset(
struct i2c_client *client)
561 struct i2c_client *client = v4l2_get_subdevdata(sd);
572 priv->
cfmt->code, priv->
win->name);
582 struct i2c_client *client = v4l2_get_subdevdata(sd);
602 ret = ov772x_mask_set(client,
BDBASE, 0xff, 0xff);
604 ret = ov772x_mask_set(client,
COM8,
608 val = 256 - ctrl->
val;
609 ret = ov772x_mask_set(client,
COM8,
612 ret = ov772x_mask_set(client,
BDBASE,
623 static int ov772x_g_chip_ident(
struct v4l2_subdev *sd,
628 id->ident = priv->
model;
634 #ifdef CONFIG_VIDEO_ADV_DEBUG
635 static int ov772x_g_register(
struct v4l2_subdev *sd,
638 struct i2c_client *client = v4l2_get_subdevdata(sd);
645 ret = ov772x_read(client, reg->
reg);
654 static int ov772x_s_register(
struct v4l2_subdev *sd,
657 struct i2c_client *client = v4l2_get_subdevdata(sd);
659 if (reg->
reg > 0xff ||
663 return ov772x_write(client, reg->
reg, reg->
val);
667 static int ov772x_s_power(
struct v4l2_subdev *sd,
int on)
669 struct i2c_client *client = v4l2_get_subdevdata(sd);
672 return soc_camera_set_power(&client->
dev, icl, on);
681 for (i = 0; i <
ARRAY_SIZE(ov772x_win_sizes); ++
i) {
682 u32 diff =
abs(width - ov772x_win_sizes[i].
rect.width)
683 +
abs(height - ov772x_win_sizes[i].
rect.height);
684 if (diff < best_diff) {
686 win = &ov772x_win_sizes[
i];
693 static void ov772x_select_params(
const struct v4l2_mbus_framefmt *mf,
700 *cfmt = &ov772x_cfmts[0];
702 for (i = 0; i <
ARRAY_SIZE(ov772x_cfmts); i++) {
703 if (mf->code == ov772x_cfmts[i].
code) {
704 *cfmt = &ov772x_cfmts[
i];
710 *win = ov772x_select_win(mf->width, mf->height);
713 static int ov772x_set_params(
struct ov772x_priv *priv,
724 ov772x_reset(client);
740 goto ov772x_set_fmt_error;
742 ret = ov772x_mask_set(client,
744 priv->
info->edgectrl.threshold);
746 goto ov772x_set_fmt_error;
748 ret = ov772x_mask_set(client,
750 priv->
info->edgectrl.strength);
752 goto ov772x_set_fmt_error;
754 }
else if (priv->
info->edgectrl.upper > priv->
info->edgectrl.lower) {
760 ret = ov772x_mask_set(client,
762 priv->
info->edgectrl.upper);
764 goto ov772x_set_fmt_error;
766 ret = ov772x_mask_set(client,
768 priv->
info->edgectrl.lower);
770 goto ov772x_set_fmt_error;
774 ret = ov772x_write(client,
HSTART, win->
rect.left >> 2);
776 goto ov772x_set_fmt_error;
777 ret = ov772x_write(client,
HSIZE, win->
rect.width >> 2);
779 goto ov772x_set_fmt_error;
780 ret = ov772x_write(client,
VSTART, win->
rect.top >> 1);
782 goto ov772x_set_fmt_error;
783 ret = ov772x_write(client,
VSIZE, win->
rect.height >> 1);
785 goto ov772x_set_fmt_error;
786 ret = ov772x_write(client,
HOUTSIZE, win->
rect.width >> 2);
788 goto ov772x_set_fmt_error;
789 ret = ov772x_write(client,
VOUTSIZE, win->
rect.height >> 1);
791 goto ov772x_set_fmt_error;
792 ret = ov772x_write(client,
HREF,
798 goto ov772x_set_fmt_error;
799 ret = ov772x_write(client,
EXHCH,
803 goto ov772x_set_fmt_error;
810 ret = ov772x_mask_set(client,
813 goto ov772x_set_fmt_error;
820 goto ov772x_set_fmt_error;
836 ret = ov772x_mask_set(client,
839 goto ov772x_set_fmt_error;
844 goto ov772x_set_fmt_error;
852 ret = ov772x_mask_set(client,
BDBASE,
855 goto ov772x_set_fmt_error;
860 ov772x_set_fmt_error:
862 ov772x_reset(client);
893 struct v4l2_mbus_framefmt *mf)
897 mf->width = priv->
win->rect.width;
898 mf->height = priv->
win->rect.height;
899 mf->code = priv->
cfmt->code;
900 mf->colorspace = priv->
cfmt->colorspace;
906 static int ov772x_s_fmt(
struct v4l2_subdev *sd,
struct v4l2_mbus_framefmt *mf)
913 ov772x_select_params(mf, &cfmt, &win);
915 ret = ov772x_set_params(priv, cfmt, win);
923 mf->width = win->
rect.width;
924 mf->height = win->
rect.height;
932 struct v4l2_mbus_framefmt *mf)
937 ov772x_select_params(mf, &cfmt, &win);
939 mf->code = cfmt->
code;
940 mf->width = win->
rect.width;
941 mf->height = win->
rect.height;
948 static int ov772x_video_probe(
struct ov772x_priv *priv)
955 ret = ov772x_s_power(&priv->
subdev, 1);
962 pid = ov772x_read(client,
PID);
963 ver = ov772x_read(client,
VER);
976 "Product ID error %x:%x\n", pid, ver);
982 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
986 ov772x_read(client,
MIDH),
987 ov772x_read(client,
MIDL));
991 ov772x_s_power(&priv->
subdev, 0);
996 .s_ctrl = ov772x_s_ctrl,
1000 .g_chip_ident = ov772x_g_chip_ident,
1001 #ifdef CONFIG_VIDEO_ADV_DEBUG
1002 .g_register = ov772x_g_register,
1003 .s_register = ov772x_s_register,
1005 .s_power = ov772x_s_power,
1018 static int ov772x_g_mbus_config(
struct v4l2_subdev *sd,
1021 struct i2c_client *client = v4l2_get_subdevdata(sd);
1034 .s_stream = ov772x_s_stream,
1035 .g_mbus_fmt = ov772x_g_fmt,
1036 .s_mbus_fmt = ov772x_s_fmt,
1037 .try_mbus_fmt = ov772x_try_fmt,
1038 .cropcap = ov772x_cropcap,
1039 .g_crop = ov772x_g_crop,
1040 .enum_mbus_fmt = ov772x_enum_fmt,
1041 .g_mbus_config = ov772x_g_mbus_config,
1045 .core = &ov772x_subdev_core_ops,
1046 .video = &ov772x_subdev_video_ops,
1053 static int ov772x_probe(
struct i2c_client *client,
1061 if (!icl || !icl->
priv) {
1062 dev_err(&client->
dev,
"OV772X: missing platform data!\n");
1068 "I2C-Adapter doesn't support "
1069 "I2C_FUNC_SMBUS_BYTE_DATA\n");
1088 if (priv->
hdl.error) {
1089 ret = priv->
hdl.error;
1093 ret = ov772x_video_probe(priv);
1097 priv->
cfmt = &ov772x_cfmts[0];
1098 priv->
win = &ov772x_win_sizes[0];
1108 static int ov772x_remove(
struct i2c_client *client)
1110 struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client));
1124 static struct i2c_driver ov772x_i2c_driver = {
1128 .probe = ov772x_probe,
1129 .remove = ov772x_remove,
1130 .id_table = ov772x_id,