162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * OV519 driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr>
662306a36Sopenharmony_ci * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This module is adapted from the ov51x-jpeg package, which itself
962306a36Sopenharmony_ci * was adapted from the ov511 driver.
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Original copyright for the ov511 driver is:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * Copyright (c) 1999-2006 Mark W. McClelland
1462306a36Sopenharmony_ci * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach
1562306a36Sopenharmony_ci * Many improvements by Bret Wallach <bwallac1@san.rr.com>
1662306a36Sopenharmony_ci * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
1762306a36Sopenharmony_ci * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
1862306a36Sopenharmony_ci * Changes by Claudio Matsuoka <claudio@conectiva.com>
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * ov51x-jpeg original copyright is:
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org>
2362306a36Sopenharmony_ci * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.com>
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define MODULE_NAME "ov519"
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <linux/input.h>
3162306a36Sopenharmony_ci#include "gspca.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* The jpeg_hdr is used by w996Xcf only */
3462306a36Sopenharmony_ci/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
3562306a36Sopenharmony_ci#define CONEX_CAM
3662306a36Sopenharmony_ci#include "jpeg.h"
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ciMODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
3962306a36Sopenharmony_ciMODULE_DESCRIPTION("OV519 USB Camera Driver");
4062306a36Sopenharmony_ciMODULE_LICENSE("GPL");
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* global parameters */
4362306a36Sopenharmony_cistatic int frame_rate;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* Number of times to retry a failed I2C transaction. Increase this if you
4662306a36Sopenharmony_ci * are getting "Failed to read sensor ID..." */
4762306a36Sopenharmony_cistatic int i2c_detect_tries = 10;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* ov519 device descriptor */
5062306a36Sopenharmony_cistruct sd {
5162306a36Sopenharmony_ci	struct gspca_dev gspca_dev;		/* !! must be the first item */
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	struct v4l2_ctrl *jpegqual;
5462306a36Sopenharmony_ci	struct v4l2_ctrl *freq;
5562306a36Sopenharmony_ci	struct { /* h/vflip control cluster */
5662306a36Sopenharmony_ci		struct v4l2_ctrl *hflip;
5762306a36Sopenharmony_ci		struct v4l2_ctrl *vflip;
5862306a36Sopenharmony_ci	};
5962306a36Sopenharmony_ci	struct { /* autobrightness/brightness control cluster */
6062306a36Sopenharmony_ci		struct v4l2_ctrl *autobright;
6162306a36Sopenharmony_ci		struct v4l2_ctrl *brightness;
6262306a36Sopenharmony_ci	};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	u8 revision;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	u8 packet_nr;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	char bridge;
6962306a36Sopenharmony_ci#define BRIDGE_OV511		0
7062306a36Sopenharmony_ci#define BRIDGE_OV511PLUS	1
7162306a36Sopenharmony_ci#define BRIDGE_OV518		2
7262306a36Sopenharmony_ci#define BRIDGE_OV518PLUS	3
7362306a36Sopenharmony_ci#define BRIDGE_OV519		4		/* = ov530 */
7462306a36Sopenharmony_ci#define BRIDGE_OVFX2		5
7562306a36Sopenharmony_ci#define BRIDGE_W9968CF		6
7662306a36Sopenharmony_ci#define BRIDGE_MASK		7
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	char invert_led;
7962306a36Sopenharmony_ci#define BRIDGE_INVERT_LED	8
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	char snapshot_pressed;
8262306a36Sopenharmony_ci	char snapshot_needs_reset;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	/* Determined by sensor type */
8562306a36Sopenharmony_ci	u8 sif;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define QUALITY_MIN 50
8862306a36Sopenharmony_ci#define QUALITY_MAX 70
8962306a36Sopenharmony_ci#define QUALITY_DEF 50
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	u8 stopped;		/* Streaming is temporarily paused */
9262306a36Sopenharmony_ci	u8 first_frame;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	u8 frame_rate;		/* current Framerate */
9562306a36Sopenharmony_ci	u8 clockdiv;		/* clockdiv override */
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	s8 sensor;		/* Type of image sensor chip (SEN_*) */
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	u8 sensor_addr;
10062306a36Sopenharmony_ci	u16 sensor_width;
10162306a36Sopenharmony_ci	u16 sensor_height;
10262306a36Sopenharmony_ci	s16 sensor_reg_cache[256];
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	u8 jpeg_hdr[JPEG_HDR_SZ];
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_cienum sensors {
10762306a36Sopenharmony_ci	SEN_OV2610,
10862306a36Sopenharmony_ci	SEN_OV2610AE,
10962306a36Sopenharmony_ci	SEN_OV3610,
11062306a36Sopenharmony_ci	SEN_OV6620,
11162306a36Sopenharmony_ci	SEN_OV6630,
11262306a36Sopenharmony_ci	SEN_OV66308AF,
11362306a36Sopenharmony_ci	SEN_OV7610,
11462306a36Sopenharmony_ci	SEN_OV7620,
11562306a36Sopenharmony_ci	SEN_OV7620AE,
11662306a36Sopenharmony_ci	SEN_OV7640,
11762306a36Sopenharmony_ci	SEN_OV7648,
11862306a36Sopenharmony_ci	SEN_OV7660,
11962306a36Sopenharmony_ci	SEN_OV7670,
12062306a36Sopenharmony_ci	SEN_OV76BE,
12162306a36Sopenharmony_ci	SEN_OV8610,
12262306a36Sopenharmony_ci	SEN_OV9600,
12362306a36Sopenharmony_ci};
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
12662306a36Sopenharmony_ci   the ov sensors which is already present here. When we have the time we
12762306a36Sopenharmony_ci   really should move the sensor drivers to v4l2 sub drivers. */
12862306a36Sopenharmony_ci#include "w996Xcf.c"
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/* table of the disabled controls */
13162306a36Sopenharmony_cistruct ctrl_valid {
13262306a36Sopenharmony_ci	unsigned int has_brightness:1;
13362306a36Sopenharmony_ci	unsigned int has_contrast:1;
13462306a36Sopenharmony_ci	unsigned int has_exposure:1;
13562306a36Sopenharmony_ci	unsigned int has_autogain:1;
13662306a36Sopenharmony_ci	unsigned int has_sat:1;
13762306a36Sopenharmony_ci	unsigned int has_hvflip:1;
13862306a36Sopenharmony_ci	unsigned int has_autobright:1;
13962306a36Sopenharmony_ci	unsigned int has_freq:1;
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic const struct ctrl_valid valid_controls[] = {
14362306a36Sopenharmony_ci	[SEN_OV2610] = {
14462306a36Sopenharmony_ci		.has_exposure = 1,
14562306a36Sopenharmony_ci		.has_autogain = 1,
14662306a36Sopenharmony_ci	},
14762306a36Sopenharmony_ci	[SEN_OV2610AE] = {
14862306a36Sopenharmony_ci		.has_exposure = 1,
14962306a36Sopenharmony_ci		.has_autogain = 1,
15062306a36Sopenharmony_ci	},
15162306a36Sopenharmony_ci	[SEN_OV3610] = {
15262306a36Sopenharmony_ci		/* No controls */
15362306a36Sopenharmony_ci	},
15462306a36Sopenharmony_ci	[SEN_OV6620] = {
15562306a36Sopenharmony_ci		.has_brightness = 1,
15662306a36Sopenharmony_ci		.has_contrast = 1,
15762306a36Sopenharmony_ci		.has_sat = 1,
15862306a36Sopenharmony_ci		.has_autobright = 1,
15962306a36Sopenharmony_ci		.has_freq = 1,
16062306a36Sopenharmony_ci	},
16162306a36Sopenharmony_ci	[SEN_OV6630] = {
16262306a36Sopenharmony_ci		.has_brightness = 1,
16362306a36Sopenharmony_ci		.has_contrast = 1,
16462306a36Sopenharmony_ci		.has_sat = 1,
16562306a36Sopenharmony_ci		.has_autobright = 1,
16662306a36Sopenharmony_ci		.has_freq = 1,
16762306a36Sopenharmony_ci	},
16862306a36Sopenharmony_ci	[SEN_OV66308AF] = {
16962306a36Sopenharmony_ci		.has_brightness = 1,
17062306a36Sopenharmony_ci		.has_contrast = 1,
17162306a36Sopenharmony_ci		.has_sat = 1,
17262306a36Sopenharmony_ci		.has_autobright = 1,
17362306a36Sopenharmony_ci		.has_freq = 1,
17462306a36Sopenharmony_ci	},
17562306a36Sopenharmony_ci	[SEN_OV7610] = {
17662306a36Sopenharmony_ci		.has_brightness = 1,
17762306a36Sopenharmony_ci		.has_contrast = 1,
17862306a36Sopenharmony_ci		.has_sat = 1,
17962306a36Sopenharmony_ci		.has_autobright = 1,
18062306a36Sopenharmony_ci		.has_freq = 1,
18162306a36Sopenharmony_ci	},
18262306a36Sopenharmony_ci	[SEN_OV7620] = {
18362306a36Sopenharmony_ci		.has_brightness = 1,
18462306a36Sopenharmony_ci		.has_contrast = 1,
18562306a36Sopenharmony_ci		.has_sat = 1,
18662306a36Sopenharmony_ci		.has_autobright = 1,
18762306a36Sopenharmony_ci		.has_freq = 1,
18862306a36Sopenharmony_ci	},
18962306a36Sopenharmony_ci	[SEN_OV7620AE] = {
19062306a36Sopenharmony_ci		.has_brightness = 1,
19162306a36Sopenharmony_ci		.has_contrast = 1,
19262306a36Sopenharmony_ci		.has_sat = 1,
19362306a36Sopenharmony_ci		.has_autobright = 1,
19462306a36Sopenharmony_ci		.has_freq = 1,
19562306a36Sopenharmony_ci	},
19662306a36Sopenharmony_ci	[SEN_OV7640] = {
19762306a36Sopenharmony_ci		.has_brightness = 1,
19862306a36Sopenharmony_ci		.has_sat = 1,
19962306a36Sopenharmony_ci		.has_freq = 1,
20062306a36Sopenharmony_ci	},
20162306a36Sopenharmony_ci	[SEN_OV7648] = {
20262306a36Sopenharmony_ci		.has_brightness = 1,
20362306a36Sopenharmony_ci		.has_sat = 1,
20462306a36Sopenharmony_ci		.has_freq = 1,
20562306a36Sopenharmony_ci	},
20662306a36Sopenharmony_ci	[SEN_OV7660] = {
20762306a36Sopenharmony_ci		.has_brightness = 1,
20862306a36Sopenharmony_ci		.has_contrast = 1,
20962306a36Sopenharmony_ci		.has_sat = 1,
21062306a36Sopenharmony_ci		.has_hvflip = 1,
21162306a36Sopenharmony_ci		.has_freq = 1,
21262306a36Sopenharmony_ci	},
21362306a36Sopenharmony_ci	[SEN_OV7670] = {
21462306a36Sopenharmony_ci		.has_brightness = 1,
21562306a36Sopenharmony_ci		.has_contrast = 1,
21662306a36Sopenharmony_ci		.has_hvflip = 1,
21762306a36Sopenharmony_ci		.has_freq = 1,
21862306a36Sopenharmony_ci	},
21962306a36Sopenharmony_ci	[SEN_OV76BE] = {
22062306a36Sopenharmony_ci		.has_brightness = 1,
22162306a36Sopenharmony_ci		.has_contrast = 1,
22262306a36Sopenharmony_ci		.has_sat = 1,
22362306a36Sopenharmony_ci		.has_autobright = 1,
22462306a36Sopenharmony_ci		.has_freq = 1,
22562306a36Sopenharmony_ci	},
22662306a36Sopenharmony_ci	[SEN_OV8610] = {
22762306a36Sopenharmony_ci		.has_brightness = 1,
22862306a36Sopenharmony_ci		.has_contrast = 1,
22962306a36Sopenharmony_ci		.has_sat = 1,
23062306a36Sopenharmony_ci		.has_autobright = 1,
23162306a36Sopenharmony_ci	},
23262306a36Sopenharmony_ci	[SEN_OV9600] = {
23362306a36Sopenharmony_ci		.has_exposure = 1,
23462306a36Sopenharmony_ci		.has_autogain = 1,
23562306a36Sopenharmony_ci	},
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic const struct v4l2_pix_format ov519_vga_mode[] = {
23962306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
24062306a36Sopenharmony_ci		.bytesperline = 320,
24162306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
24262306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
24362306a36Sopenharmony_ci		.priv = 1},
24462306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
24562306a36Sopenharmony_ci		.bytesperline = 640,
24662306a36Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 8 + 590,
24762306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
24862306a36Sopenharmony_ci		.priv = 0},
24962306a36Sopenharmony_ci};
25062306a36Sopenharmony_cistatic const struct v4l2_pix_format ov519_sif_mode[] = {
25162306a36Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
25262306a36Sopenharmony_ci		.bytesperline = 160,
25362306a36Sopenharmony_ci		.sizeimage = 160 * 120 * 3 / 8 + 590,
25462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
25562306a36Sopenharmony_ci		.priv = 3},
25662306a36Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
25762306a36Sopenharmony_ci		.bytesperline = 176,
25862306a36Sopenharmony_ci		.sizeimage = 176 * 144 * 3 / 8 + 590,
25962306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
26062306a36Sopenharmony_ci		.priv = 1},
26162306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
26262306a36Sopenharmony_ci		.bytesperline = 320,
26362306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
26462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
26562306a36Sopenharmony_ci		.priv = 2},
26662306a36Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
26762306a36Sopenharmony_ci		.bytesperline = 352,
26862306a36Sopenharmony_ci		.sizeimage = 352 * 288 * 3 / 8 + 590,
26962306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
27062306a36Sopenharmony_ci		.priv = 0},
27162306a36Sopenharmony_ci};
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/* Note some of the sizeimage values for the ov511 / ov518 may seem
27462306a36Sopenharmony_ci   larger then necessary, however they need to be this big as the ov511 /
27562306a36Sopenharmony_ci   ov518 always fills the entire isoc frame, using 0 padding bytes when
27662306a36Sopenharmony_ci   it doesn't have any data. So with low framerates the amount of data
27762306a36Sopenharmony_ci   transferred can become quite large (libv4l will remove all the 0 padding
27862306a36Sopenharmony_ci   in userspace). */
27962306a36Sopenharmony_cistatic const struct v4l2_pix_format ov518_vga_mode[] = {
28062306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
28162306a36Sopenharmony_ci		.bytesperline = 320,
28262306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3,
28362306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
28462306a36Sopenharmony_ci		.priv = 1},
28562306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
28662306a36Sopenharmony_ci		.bytesperline = 640,
28762306a36Sopenharmony_ci		.sizeimage = 640 * 480 * 2,
28862306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
28962306a36Sopenharmony_ci		.priv = 0},
29062306a36Sopenharmony_ci};
29162306a36Sopenharmony_cistatic const struct v4l2_pix_format ov518_sif_mode[] = {
29262306a36Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
29362306a36Sopenharmony_ci		.bytesperline = 160,
29462306a36Sopenharmony_ci		.sizeimage = 70000,
29562306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
29662306a36Sopenharmony_ci		.priv = 3},
29762306a36Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
29862306a36Sopenharmony_ci		.bytesperline = 176,
29962306a36Sopenharmony_ci		.sizeimage = 70000,
30062306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
30162306a36Sopenharmony_ci		.priv = 1},
30262306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
30362306a36Sopenharmony_ci		.bytesperline = 320,
30462306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3,
30562306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
30662306a36Sopenharmony_ci		.priv = 2},
30762306a36Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
30862306a36Sopenharmony_ci		.bytesperline = 352,
30962306a36Sopenharmony_ci		.sizeimage = 352 * 288 * 3,
31062306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
31162306a36Sopenharmony_ci		.priv = 0},
31262306a36Sopenharmony_ci};
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_cistatic const struct v4l2_pix_format ov511_vga_mode[] = {
31562306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
31662306a36Sopenharmony_ci		.bytesperline = 320,
31762306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3,
31862306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
31962306a36Sopenharmony_ci		.priv = 1},
32062306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
32162306a36Sopenharmony_ci		.bytesperline = 640,
32262306a36Sopenharmony_ci		.sizeimage = 640 * 480 * 2,
32362306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
32462306a36Sopenharmony_ci		.priv = 0},
32562306a36Sopenharmony_ci};
32662306a36Sopenharmony_cistatic const struct v4l2_pix_format ov511_sif_mode[] = {
32762306a36Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
32862306a36Sopenharmony_ci		.bytesperline = 160,
32962306a36Sopenharmony_ci		.sizeimage = 70000,
33062306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
33162306a36Sopenharmony_ci		.priv = 3},
33262306a36Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
33362306a36Sopenharmony_ci		.bytesperline = 176,
33462306a36Sopenharmony_ci		.sizeimage = 70000,
33562306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
33662306a36Sopenharmony_ci		.priv = 1},
33762306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
33862306a36Sopenharmony_ci		.bytesperline = 320,
33962306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3,
34062306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
34162306a36Sopenharmony_ci		.priv = 2},
34262306a36Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
34362306a36Sopenharmony_ci		.bytesperline = 352,
34462306a36Sopenharmony_ci		.sizeimage = 352 * 288 * 3,
34562306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
34662306a36Sopenharmony_ci		.priv = 0},
34762306a36Sopenharmony_ci};
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
35062306a36Sopenharmony_ci	{800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
35162306a36Sopenharmony_ci		.bytesperline = 800,
35262306a36Sopenharmony_ci		.sizeimage = 800 * 600,
35362306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
35462306a36Sopenharmony_ci		.priv = 1},
35562306a36Sopenharmony_ci	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
35662306a36Sopenharmony_ci		.bytesperline = 1600,
35762306a36Sopenharmony_ci		.sizeimage = 1600 * 1200,
35862306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB},
35962306a36Sopenharmony_ci};
36062306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
36162306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
36262306a36Sopenharmony_ci		.bytesperline = 640,
36362306a36Sopenharmony_ci		.sizeimage = 640 * 480,
36462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
36562306a36Sopenharmony_ci		.priv = 1},
36662306a36Sopenharmony_ci	{800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
36762306a36Sopenharmony_ci		.bytesperline = 800,
36862306a36Sopenharmony_ci		.sizeimage = 800 * 600,
36962306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
37062306a36Sopenharmony_ci		.priv = 1},
37162306a36Sopenharmony_ci	{1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
37262306a36Sopenharmony_ci		.bytesperline = 1024,
37362306a36Sopenharmony_ci		.sizeimage = 1024 * 768,
37462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
37562306a36Sopenharmony_ci		.priv = 1},
37662306a36Sopenharmony_ci	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
37762306a36Sopenharmony_ci		.bytesperline = 1600,
37862306a36Sopenharmony_ci		.sizeimage = 1600 * 1200,
37962306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
38062306a36Sopenharmony_ci		.priv = 0},
38162306a36Sopenharmony_ci	{2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
38262306a36Sopenharmony_ci		.bytesperline = 2048,
38362306a36Sopenharmony_ci		.sizeimage = 2048 * 1536,
38462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
38562306a36Sopenharmony_ci		.priv = 0},
38662306a36Sopenharmony_ci};
38762306a36Sopenharmony_cistatic const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
38862306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
38962306a36Sopenharmony_ci		.bytesperline = 640,
39062306a36Sopenharmony_ci		.sizeimage = 640 * 480,
39162306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
39262306a36Sopenharmony_ci		.priv = 1},
39362306a36Sopenharmony_ci	{1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
39462306a36Sopenharmony_ci		.bytesperline = 1280,
39562306a36Sopenharmony_ci		.sizeimage = 1280 * 1024,
39662306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB},
39762306a36Sopenharmony_ci};
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci/* Registers common to OV511 / OV518 */
40062306a36Sopenharmony_ci#define R51x_FIFO_PSIZE			0x30	/* 2 bytes wide w/ OV518(+) */
40162306a36Sopenharmony_ci#define R51x_SYS_RESET			0x50
40262306a36Sopenharmony_ci	/* Reset type flags */
40362306a36Sopenharmony_ci	#define	OV511_RESET_OMNICE	0x08
40462306a36Sopenharmony_ci#define R51x_SYS_INIT			0x53
40562306a36Sopenharmony_ci#define R51x_SYS_SNAP			0x52
40662306a36Sopenharmony_ci#define R51x_SYS_CUST_ID		0x5f
40762306a36Sopenharmony_ci#define R51x_COMP_LUT_BEGIN		0x80
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci/* OV511 Camera interface register numbers */
41062306a36Sopenharmony_ci#define R511_CAM_DELAY			0x10
41162306a36Sopenharmony_ci#define R511_CAM_EDGE			0x11
41262306a36Sopenharmony_ci#define R511_CAM_PXCNT			0x12
41362306a36Sopenharmony_ci#define R511_CAM_LNCNT			0x13
41462306a36Sopenharmony_ci#define R511_CAM_PXDIV			0x14
41562306a36Sopenharmony_ci#define R511_CAM_LNDIV			0x15
41662306a36Sopenharmony_ci#define R511_CAM_UV_EN			0x16
41762306a36Sopenharmony_ci#define R511_CAM_LINE_MODE		0x17
41862306a36Sopenharmony_ci#define R511_CAM_OPTS			0x18
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci#define R511_SNAP_FRAME			0x19
42162306a36Sopenharmony_ci#define R511_SNAP_PXCNT			0x1a
42262306a36Sopenharmony_ci#define R511_SNAP_LNCNT			0x1b
42362306a36Sopenharmony_ci#define R511_SNAP_PXDIV			0x1c
42462306a36Sopenharmony_ci#define R511_SNAP_LNDIV			0x1d
42562306a36Sopenharmony_ci#define R511_SNAP_UV_EN			0x1e
42662306a36Sopenharmony_ci#define R511_SNAP_OPTS			0x1f
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci#define R511_DRAM_FLOW_CTL		0x20
42962306a36Sopenharmony_ci#define R511_FIFO_OPTS			0x31
43062306a36Sopenharmony_ci#define R511_I2C_CTL			0x40
43162306a36Sopenharmony_ci#define R511_SYS_LED_CTL		0x55	/* OV511+ only */
43262306a36Sopenharmony_ci#define R511_COMP_EN			0x78
43362306a36Sopenharmony_ci#define R511_COMP_LUT_EN		0x79
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci/* OV518 Camera interface register numbers */
43662306a36Sopenharmony_ci#define R518_GPIO_OUT			0x56	/* OV518(+) only */
43762306a36Sopenharmony_ci#define R518_GPIO_CTL			0x57	/* OV518(+) only */
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci/* OV519 Camera interface register numbers */
44062306a36Sopenharmony_ci#define OV519_R10_H_SIZE		0x10
44162306a36Sopenharmony_ci#define OV519_R11_V_SIZE		0x11
44262306a36Sopenharmony_ci#define OV519_R12_X_OFFSETL		0x12
44362306a36Sopenharmony_ci#define OV519_R13_X_OFFSETH		0x13
44462306a36Sopenharmony_ci#define OV519_R14_Y_OFFSETL		0x14
44562306a36Sopenharmony_ci#define OV519_R15_Y_OFFSETH		0x15
44662306a36Sopenharmony_ci#define OV519_R16_DIVIDER		0x16
44762306a36Sopenharmony_ci#define OV519_R20_DFR			0x20
44862306a36Sopenharmony_ci#define OV519_R25_FORMAT		0x25
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci/* OV519 System Controller register numbers */
45162306a36Sopenharmony_ci#define OV519_R51_RESET1		0x51
45262306a36Sopenharmony_ci#define OV519_R54_EN_CLK1		0x54
45362306a36Sopenharmony_ci#define OV519_R57_SNAPSHOT		0x57
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci#define OV519_GPIO_DATA_OUT0		0x71
45662306a36Sopenharmony_ci#define OV519_GPIO_IO_CTRL0		0x72
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci/*#define OV511_ENDPOINT_ADDRESS 1	 * Isoc endpoint number */
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci/*
46162306a36Sopenharmony_ci * The FX2 chip does not give us a zero length read at end of frame.
46262306a36Sopenharmony_ci * It does, however, give a short read at the end of a frame, if
46362306a36Sopenharmony_ci * necessary, rather than run two frames together.
46462306a36Sopenharmony_ci *
46562306a36Sopenharmony_ci * By choosing the right bulk transfer size, we are guaranteed to always
46662306a36Sopenharmony_ci * get a short read for the last read of each frame.  Frame sizes are
46762306a36Sopenharmony_ci * always a composite number (width * height, or a multiple) so if we
46862306a36Sopenharmony_ci * choose a prime number, we are guaranteed that the last read of a
46962306a36Sopenharmony_ci * frame will be short.
47062306a36Sopenharmony_ci *
47162306a36Sopenharmony_ci * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB,
47262306a36Sopenharmony_ci * otherwise EOVERFLOW "babbling" errors occur.  I have not been able
47362306a36Sopenharmony_ci * to figure out why.  [PMiller]
47462306a36Sopenharmony_ci *
47562306a36Sopenharmony_ci * The constant (13 * 4096) is the largest "prime enough" number less than 64KB.
47662306a36Sopenharmony_ci *
47762306a36Sopenharmony_ci * It isn't enough to know the number of bytes per frame, in case we
47862306a36Sopenharmony_ci * have data dropouts or buffer overruns (even though the FX2 double
47962306a36Sopenharmony_ci * buffers, there are some pretty strict real time constraints for
48062306a36Sopenharmony_ci * isochronous transfer for larger frame sizes).
48162306a36Sopenharmony_ci */
48262306a36Sopenharmony_ci/*jfm: this value does not work for 800x600 - see isoc_init */
48362306a36Sopenharmony_ci#define OVFX2_BULK_SIZE (13 * 4096)
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci/* I2C registers */
48662306a36Sopenharmony_ci#define R51x_I2C_W_SID		0x41
48762306a36Sopenharmony_ci#define R51x_I2C_SADDR_3	0x42
48862306a36Sopenharmony_ci#define R51x_I2C_SADDR_2	0x43
48962306a36Sopenharmony_ci#define R51x_I2C_R_SID		0x44
49062306a36Sopenharmony_ci#define R51x_I2C_DATA		0x45
49162306a36Sopenharmony_ci#define R518_I2C_CTL		0x47	/* OV518(+) only */
49262306a36Sopenharmony_ci#define OVFX2_I2C_ADDR		0x00
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci/* I2C ADDRESSES */
49562306a36Sopenharmony_ci#define OV7xx0_SID   0x42
49662306a36Sopenharmony_ci#define OV_HIRES_SID 0x60		/* OV9xxx / OV2xxx / OV3xxx */
49762306a36Sopenharmony_ci#define OV8xx0_SID   0xa0
49862306a36Sopenharmony_ci#define OV6xx0_SID   0xc0
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci/* OV7610 registers */
50162306a36Sopenharmony_ci#define OV7610_REG_GAIN		0x00	/* gain setting (5:0) */
50262306a36Sopenharmony_ci#define OV7610_REG_BLUE		0x01	/* blue channel balance */
50362306a36Sopenharmony_ci#define OV7610_REG_RED		0x02	/* red channel balance */
50462306a36Sopenharmony_ci#define OV7610_REG_SAT		0x03	/* saturation */
50562306a36Sopenharmony_ci#define OV8610_REG_HUE		0x04	/* 04 reserved */
50662306a36Sopenharmony_ci#define OV7610_REG_CNT		0x05	/* Y contrast */
50762306a36Sopenharmony_ci#define OV7610_REG_BRT		0x06	/* Y brightness */
50862306a36Sopenharmony_ci#define OV7610_REG_COM_C	0x14	/* misc common regs */
50962306a36Sopenharmony_ci#define OV7610_REG_ID_HIGH	0x1c	/* manufacturer ID MSB */
51062306a36Sopenharmony_ci#define OV7610_REG_ID_LOW	0x1d	/* manufacturer ID LSB */
51162306a36Sopenharmony_ci#define OV7610_REG_COM_I	0x29	/* misc settings */
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci/* OV7660 and OV7670 registers */
51462306a36Sopenharmony_ci#define OV7670_R00_GAIN		0x00	/* Gain lower 8 bits (rest in vref) */
51562306a36Sopenharmony_ci#define OV7670_R01_BLUE		0x01	/* blue gain */
51662306a36Sopenharmony_ci#define OV7670_R02_RED		0x02	/* red gain */
51762306a36Sopenharmony_ci#define OV7670_R03_VREF		0x03	/* Pieces of GAIN, VSTART, VSTOP */
51862306a36Sopenharmony_ci#define OV7670_R04_COM1		0x04	/* Control 1 */
51962306a36Sopenharmony_ci/*#define OV7670_R07_AECHH	0x07	 * AEC MS 5 bits */
52062306a36Sopenharmony_ci#define OV7670_R0C_COM3		0x0c	/* Control 3 */
52162306a36Sopenharmony_ci#define OV7670_R0D_COM4		0x0d	/* Control 4 */
52262306a36Sopenharmony_ci#define OV7670_R0E_COM5		0x0e	/* All "reserved" */
52362306a36Sopenharmony_ci#define OV7670_R0F_COM6		0x0f	/* Control 6 */
52462306a36Sopenharmony_ci#define OV7670_R10_AECH		0x10	/* More bits of AEC value */
52562306a36Sopenharmony_ci#define OV7670_R11_CLKRC	0x11	/* Clock control */
52662306a36Sopenharmony_ci#define OV7670_R12_COM7		0x12	/* Control 7 */
52762306a36Sopenharmony_ci#define   OV7670_COM7_FMT_VGA	 0x00
52862306a36Sopenharmony_ci/*#define   OV7670_COM7_YUV	 0x00	 * YUV */
52962306a36Sopenharmony_ci#define   OV7670_COM7_FMT_QVGA	 0x10	/* QVGA format */
53062306a36Sopenharmony_ci#define   OV7670_COM7_FMT_MASK	 0x38
53162306a36Sopenharmony_ci#define   OV7670_COM7_RESET	 0x80	/* Register reset */
53262306a36Sopenharmony_ci#define OV7670_R13_COM8		0x13	/* Control 8 */
53362306a36Sopenharmony_ci#define   OV7670_COM8_AEC	 0x01	/* Auto exposure enable */
53462306a36Sopenharmony_ci#define   OV7670_COM8_AWB	 0x02	/* White balance enable */
53562306a36Sopenharmony_ci#define   OV7670_COM8_AGC	 0x04	/* Auto gain enable */
53662306a36Sopenharmony_ci#define   OV7670_COM8_BFILT	 0x20	/* Band filter enable */
53762306a36Sopenharmony_ci#define   OV7670_COM8_AECSTEP	 0x40	/* Unlimited AEC step size */
53862306a36Sopenharmony_ci#define   OV7670_COM8_FASTAEC	 0x80	/* Enable fast AGC/AEC */
53962306a36Sopenharmony_ci#define OV7670_R14_COM9		0x14	/* Control 9 - gain ceiling */
54062306a36Sopenharmony_ci#define OV7670_R15_COM10	0x15	/* Control 10 */
54162306a36Sopenharmony_ci#define OV7670_R17_HSTART	0x17	/* Horiz start high bits */
54262306a36Sopenharmony_ci#define OV7670_R18_HSTOP	0x18	/* Horiz stop high bits */
54362306a36Sopenharmony_ci#define OV7670_R19_VSTART	0x19	/* Vert start high bits */
54462306a36Sopenharmony_ci#define OV7670_R1A_VSTOP	0x1a	/* Vert stop high bits */
54562306a36Sopenharmony_ci#define OV7670_R1E_MVFP		0x1e	/* Mirror / vflip */
54662306a36Sopenharmony_ci#define   OV7670_MVFP_VFLIP	 0x10	/* vertical flip */
54762306a36Sopenharmony_ci#define   OV7670_MVFP_MIRROR	 0x20	/* Mirror image */
54862306a36Sopenharmony_ci#define OV7670_R24_AEW		0x24	/* AGC upper limit */
54962306a36Sopenharmony_ci#define OV7670_R25_AEB		0x25	/* AGC lower limit */
55062306a36Sopenharmony_ci#define OV7670_R26_VPT		0x26	/* AGC/AEC fast mode op region */
55162306a36Sopenharmony_ci#define OV7670_R32_HREF		0x32	/* HREF pieces */
55262306a36Sopenharmony_ci#define OV7670_R3A_TSLB		0x3a	/* lots of stuff */
55362306a36Sopenharmony_ci#define OV7670_R3B_COM11	0x3b	/* Control 11 */
55462306a36Sopenharmony_ci#define   OV7670_COM11_EXP	 0x02
55562306a36Sopenharmony_ci#define   OV7670_COM11_HZAUTO	 0x10	/* Auto detect 50/60 Hz */
55662306a36Sopenharmony_ci#define OV7670_R3C_COM12	0x3c	/* Control 12 */
55762306a36Sopenharmony_ci#define OV7670_R3D_COM13	0x3d	/* Control 13 */
55862306a36Sopenharmony_ci#define   OV7670_COM13_GAMMA	 0x80	/* Gamma enable */
55962306a36Sopenharmony_ci#define   OV7670_COM13_UVSAT	 0x40	/* UV saturation auto adjustment */
56062306a36Sopenharmony_ci#define OV7670_R3E_COM14	0x3e	/* Control 14 */
56162306a36Sopenharmony_ci#define OV7670_R3F_EDGE		0x3f	/* Edge enhancement factor */
56262306a36Sopenharmony_ci#define OV7670_R40_COM15	0x40	/* Control 15 */
56362306a36Sopenharmony_ci/*#define   OV7670_COM15_R00FF	 0xc0	 *	00 to FF */
56462306a36Sopenharmony_ci#define OV7670_R41_COM16	0x41	/* Control 16 */
56562306a36Sopenharmony_ci#define   OV7670_COM16_AWBGAIN	 0x08	/* AWB gain enable */
56662306a36Sopenharmony_ci/* end of ov7660 common registers */
56762306a36Sopenharmony_ci#define OV7670_R55_BRIGHT	0x55	/* Brightness */
56862306a36Sopenharmony_ci#define OV7670_R56_CONTRAS	0x56	/* Contrast control */
56962306a36Sopenharmony_ci#define OV7670_R69_GFIX		0x69	/* Fix gain control */
57062306a36Sopenharmony_ci/*#define OV7670_R8C_RGB444	0x8c	 * RGB 444 control */
57162306a36Sopenharmony_ci#define OV7670_R9F_HAECC1	0x9f	/* Hist AEC/AGC control 1 */
57262306a36Sopenharmony_ci#define OV7670_RA0_HAECC2	0xa0	/* Hist AEC/AGC control 2 */
57362306a36Sopenharmony_ci#define OV7670_RA5_BD50MAX	0xa5	/* 50hz banding step limit */
57462306a36Sopenharmony_ci#define OV7670_RA6_HAECC3	0xa6	/* Hist AEC/AGC control 3 */
57562306a36Sopenharmony_ci#define OV7670_RA7_HAECC4	0xa7	/* Hist AEC/AGC control 4 */
57662306a36Sopenharmony_ci#define OV7670_RA8_HAECC5	0xa8	/* Hist AEC/AGC control 5 */
57762306a36Sopenharmony_ci#define OV7670_RA9_HAECC6	0xa9	/* Hist AEC/AGC control 6 */
57862306a36Sopenharmony_ci#define OV7670_RAA_HAECC7	0xaa	/* Hist AEC/AGC control 7 */
57962306a36Sopenharmony_ci#define OV7670_RAB_BD60MAX	0xab	/* 60hz banding step limit */
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_cistruct ov_regvals {
58262306a36Sopenharmony_ci	u8 reg;
58362306a36Sopenharmony_ci	u8 val;
58462306a36Sopenharmony_ci};
58562306a36Sopenharmony_cistruct ov_i2c_regvals {
58662306a36Sopenharmony_ci	u8 reg;
58762306a36Sopenharmony_ci	u8 val;
58862306a36Sopenharmony_ci};
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci/* Settings for OV2610 camera chip */
59162306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610[] = {
59262306a36Sopenharmony_ci	{ 0x12, 0x80 },	/* reset */
59362306a36Sopenharmony_ci};
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_2610ae[] = {
59662306a36Sopenharmony_ci	{0x12, 0x80},	/* reset */
59762306a36Sopenharmony_ci	{0x13, 0xcd},
59862306a36Sopenharmony_ci	{0x09, 0x01},
59962306a36Sopenharmony_ci	{0x0d, 0x00},
60062306a36Sopenharmony_ci	{0x11, 0x80},
60162306a36Sopenharmony_ci	{0x12, 0x20},	/* 1600x1200 */
60262306a36Sopenharmony_ci	{0x33, 0x0c},
60362306a36Sopenharmony_ci	{0x35, 0x90},
60462306a36Sopenharmony_ci	{0x36, 0x37},
60562306a36Sopenharmony_ci/* ms-win traces */
60662306a36Sopenharmony_ci	{0x11, 0x83},	/* clock / 3 ? */
60762306a36Sopenharmony_ci	{0x2d, 0x00},	/* 60 Hz filter */
60862306a36Sopenharmony_ci	{0x24, 0xb0},	/* normal colors */
60962306a36Sopenharmony_ci	{0x25, 0x90},
61062306a36Sopenharmony_ci	{0x10, 0x43},
61162306a36Sopenharmony_ci};
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_3620b[] = {
61462306a36Sopenharmony_ci	/*
61562306a36Sopenharmony_ci	 * From the datasheet: "Note that after writing to register COMH
61662306a36Sopenharmony_ci	 * (0x12) to change the sensor mode, registers related to the
61762306a36Sopenharmony_ci	 * sensor's cropping window will be reset back to their default
61862306a36Sopenharmony_ci	 * values."
61962306a36Sopenharmony_ci	 *
62062306a36Sopenharmony_ci	 * "wait 4096 external clock ... to make sure the sensor is
62162306a36Sopenharmony_ci	 * stable and ready to access registers" i.e. 160us at 24MHz
62262306a36Sopenharmony_ci	 */
62362306a36Sopenharmony_ci	{ 0x12, 0x80 }, /* COMH reset */
62462306a36Sopenharmony_ci	{ 0x12, 0x00 }, /* QXGA, master */
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	/*
62762306a36Sopenharmony_ci	 * 11 CLKRC "Clock Rate Control"
62862306a36Sopenharmony_ci	 * [7] internal frequency doublers: on
62962306a36Sopenharmony_ci	 * [6] video port mode: master
63062306a36Sopenharmony_ci	 * [5:0] clock divider: 1
63162306a36Sopenharmony_ci	 */
63262306a36Sopenharmony_ci	{ 0x11, 0x80 },
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/*
63562306a36Sopenharmony_ci	 * 13 COMI "Common Control I"
63662306a36Sopenharmony_ci	 *                  = 192 (0xC0) 11000000
63762306a36Sopenharmony_ci	 *    COMI[7] "AEC speed selection"
63862306a36Sopenharmony_ci	 *                  =   1 (0x01) 1....... "Faster AEC correction"
63962306a36Sopenharmony_ci	 *    COMI[6] "AEC speed step selection"
64062306a36Sopenharmony_ci	 *                  =   1 (0x01) .1...... "Big steps, fast"
64162306a36Sopenharmony_ci	 *    COMI[5] "Banding filter on off"
64262306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "Off"
64362306a36Sopenharmony_ci	 *    COMI[4] "Banding filter option"
64462306a36Sopenharmony_ci	 *                  =   0 (0x00) ...0.... "Main clock is 48 MHz and
64562306a36Sopenharmony_ci	 *                                         the PLL is ON"
64662306a36Sopenharmony_ci	 *    COMI[3] "Reserved"
64762306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0...
64862306a36Sopenharmony_ci	 *    COMI[2] "AGC auto manual control selection"
64962306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "Manual"
65062306a36Sopenharmony_ci	 *    COMI[1] "AWB auto manual control selection"
65162306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Manual"
65262306a36Sopenharmony_ci	 *    COMI[0] "Exposure control"
65362306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0 "Manual"
65462306a36Sopenharmony_ci	 */
65562306a36Sopenharmony_ci	{ 0x13, 0xc0 },
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/*
65862306a36Sopenharmony_ci	 * 09 COMC "Common Control C"
65962306a36Sopenharmony_ci	 *                  =   8 (0x08) 00001000
66062306a36Sopenharmony_ci	 *    COMC[7:5] "Reserved"
66162306a36Sopenharmony_ci	 *                  =   0 (0x00) 000.....
66262306a36Sopenharmony_ci	 *    COMC[4] "Sleep Mode Enable"
66362306a36Sopenharmony_ci	 *                  =   0 (0x00) ...0.... "Normal mode"
66462306a36Sopenharmony_ci	 *    COMC[3:2] "Sensor sampling reset timing selection"
66562306a36Sopenharmony_ci	 *                  =   2 (0x02) ....10.. "Longer reset time"
66662306a36Sopenharmony_ci	 *    COMC[1:0] "Output drive current select"
66762306a36Sopenharmony_ci	 *                  =   0 (0x00) ......00 "Weakest"
66862306a36Sopenharmony_ci	 */
66962306a36Sopenharmony_ci	{ 0x09, 0x08 },
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	/*
67262306a36Sopenharmony_ci	 * 0C COMD "Common Control D"
67362306a36Sopenharmony_ci	 *                  =   8 (0x08) 00001000
67462306a36Sopenharmony_ci	 *    COMD[7] "Reserved"
67562306a36Sopenharmony_ci	 *                  =   0 (0x00) 0.......
67662306a36Sopenharmony_ci	 *    COMD[6] "Swap MSB and LSB at the output port"
67762306a36Sopenharmony_ci	 *                  =   0 (0x00) .0...... "False"
67862306a36Sopenharmony_ci	 *    COMD[5:3] "Reserved"
67962306a36Sopenharmony_ci	 *                  =   1 (0x01) ..001...
68062306a36Sopenharmony_ci	 *    COMD[2] "Output Average On Off"
68162306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "Output Normal"
68262306a36Sopenharmony_ci	 *    COMD[1] "Sensor precharge voltage selection"
68362306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Selects internal
68462306a36Sopenharmony_ci	 *                                         reference precharge
68562306a36Sopenharmony_ci	 *                                         voltage"
68662306a36Sopenharmony_ci	 *    COMD[0] "Snapshot option"
68762306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0 "Enable live video output
68862306a36Sopenharmony_ci	 *                                         after snapshot sequence"
68962306a36Sopenharmony_ci	 */
69062306a36Sopenharmony_ci	{ 0x0c, 0x08 },
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	/*
69362306a36Sopenharmony_ci	 * 0D COME "Common Control E"
69462306a36Sopenharmony_ci	 *                  = 161 (0xA1) 10100001
69562306a36Sopenharmony_ci	 *    COME[7] "Output average option"
69662306a36Sopenharmony_ci	 *                  =   1 (0x01) 1....... "Output average of 4 pixels"
69762306a36Sopenharmony_ci	 *    COME[6] "Anti-blooming control"
69862306a36Sopenharmony_ci	 *                  =   0 (0x00) .0...... "Off"
69962306a36Sopenharmony_ci	 *    COME[5:3] "Reserved"
70062306a36Sopenharmony_ci	 *                  =   4 (0x04) ..100...
70162306a36Sopenharmony_ci	 *    COME[2] "Clock output power down pin status"
70262306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "Tri-state data output pin
70362306a36Sopenharmony_ci	 *                                         on power down"
70462306a36Sopenharmony_ci	 *    COME[1] "Data output pin status selection at power down"
70562306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Tri-state VSYNC, PCLK,
70662306a36Sopenharmony_ci	 *                                         HREF, and CHSYNC pins on
70762306a36Sopenharmony_ci	 *                                         power down"
70862306a36Sopenharmony_ci	 *    COME[0] "Auto zero circuit select"
70962306a36Sopenharmony_ci	 *                  =   1 (0x01) .......1 "On"
71062306a36Sopenharmony_ci	 */
71162306a36Sopenharmony_ci	{ 0x0d, 0xa1 },
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	/*
71462306a36Sopenharmony_ci	 * 0E COMF "Common Control F"
71562306a36Sopenharmony_ci	 *                  = 112 (0x70) 01110000
71662306a36Sopenharmony_ci	 *    COMF[7] "System clock selection"
71762306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Use 24 MHz system clock"
71862306a36Sopenharmony_ci	 *    COMF[6:4] "Reserved"
71962306a36Sopenharmony_ci	 *                  =   7 (0x07) .111....
72062306a36Sopenharmony_ci	 *    COMF[3] "Manual auto negative offset canceling selection"
72162306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Auto detect negative
72262306a36Sopenharmony_ci	 *                                         offset and cancel it"
72362306a36Sopenharmony_ci	 *    COMF[2:0] "Reserved"
72462306a36Sopenharmony_ci	 *                  =   0 (0x00) .....000
72562306a36Sopenharmony_ci	 */
72662306a36Sopenharmony_ci	{ 0x0e, 0x70 },
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	/*
72962306a36Sopenharmony_ci	 * 0F COMG "Common Control G"
73062306a36Sopenharmony_ci	 *                  =  66 (0x42) 01000010
73162306a36Sopenharmony_ci	 *    COMG[7] "Optical black output selection"
73262306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Disable"
73362306a36Sopenharmony_ci	 *    COMG[6] "Black level calibrate selection"
73462306a36Sopenharmony_ci	 *                  =   1 (0x01) .1...... "Use optical black pixels
73562306a36Sopenharmony_ci	 *                                         to calibrate"
73662306a36Sopenharmony_ci	 *    COMG[5:4] "Reserved"
73762306a36Sopenharmony_ci	 *                  =   0 (0x00) ..00....
73862306a36Sopenharmony_ci	 *    COMG[3] "Channel offset adjustment"
73962306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Disable offset adjustment"
74062306a36Sopenharmony_ci	 *    COMG[2] "ADC black level calibration option"
74162306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "Use B/G line and G/R
74262306a36Sopenharmony_ci	 *                                         line to calibrate each
74362306a36Sopenharmony_ci	 *                                         channel's black level"
74462306a36Sopenharmony_ci	 *    COMG[1] "Reserved"
74562306a36Sopenharmony_ci	 *                  =   1 (0x01) ......1.
74662306a36Sopenharmony_ci	 *    COMG[0] "ADC black level calibration enable"
74762306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0 "Disable"
74862306a36Sopenharmony_ci	 */
74962306a36Sopenharmony_ci	{ 0x0f, 0x42 },
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/*
75262306a36Sopenharmony_ci	 * 14 COMJ "Common Control J"
75362306a36Sopenharmony_ci	 *                  = 198 (0xC6) 11000110
75462306a36Sopenharmony_ci	 *    COMJ[7:6] "AGC gain ceiling"
75562306a36Sopenharmony_ci	 *                  =   3 (0x03) 11...... "8x"
75662306a36Sopenharmony_ci	 *    COMJ[5:4] "Reserved"
75762306a36Sopenharmony_ci	 *                  =   0 (0x00) ..00....
75862306a36Sopenharmony_ci	 *    COMJ[3] "Auto banding filter"
75962306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Banding filter is always
76062306a36Sopenharmony_ci	 *                                         on off depending on
76162306a36Sopenharmony_ci	 *                                         COMI[5] setting"
76262306a36Sopenharmony_ci	 *    COMJ[2] "VSYNC drop option"
76362306a36Sopenharmony_ci	 *                  =   1 (0x01) .....1.. "SYNC is dropped if frame
76462306a36Sopenharmony_ci	 *                                         data is dropped"
76562306a36Sopenharmony_ci	 *    COMJ[1] "Frame data drop"
76662306a36Sopenharmony_ci	 *                  =   1 (0x01) ......1. "Drop frame data if
76762306a36Sopenharmony_ci	 *                                         exposure is not within
76862306a36Sopenharmony_ci	 *                                         tolerance.  In AEC mode,
76962306a36Sopenharmony_ci	 *                                         data is normally dropped
77062306a36Sopenharmony_ci	 *                                         when data is out of
77162306a36Sopenharmony_ci	 *                                         range."
77262306a36Sopenharmony_ci	 *    COMJ[0] "Reserved"
77362306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0
77462306a36Sopenharmony_ci	 */
77562306a36Sopenharmony_ci	{ 0x14, 0xc6 },
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	/*
77862306a36Sopenharmony_ci	 * 15 COMK "Common Control K"
77962306a36Sopenharmony_ci	 *                  =   2 (0x02) 00000010
78062306a36Sopenharmony_ci	 *    COMK[7] "CHSYNC pin output swap"
78162306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "CHSYNC"
78262306a36Sopenharmony_ci	 *    COMK[6] "HREF pin output swap"
78362306a36Sopenharmony_ci	 *                  =   0 (0x00) .0...... "HREF"
78462306a36Sopenharmony_ci	 *    COMK[5] "PCLK output selection"
78562306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "PCLK always output"
78662306a36Sopenharmony_ci	 *    COMK[4] "PCLK edge selection"
78762306a36Sopenharmony_ci	 *                  =   0 (0x00) ...0.... "Data valid on falling edge"
78862306a36Sopenharmony_ci	 *    COMK[3] "HREF output polarity"
78962306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "positive"
79062306a36Sopenharmony_ci	 *    COMK[2] "Reserved"
79162306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0..
79262306a36Sopenharmony_ci	 *    COMK[1] "VSYNC polarity"
79362306a36Sopenharmony_ci	 *                  =   1 (0x01) ......1. "negative"
79462306a36Sopenharmony_ci	 *    COMK[0] "HSYNC polarity"
79562306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0 "positive"
79662306a36Sopenharmony_ci	 */
79762306a36Sopenharmony_ci	{ 0x15, 0x02 },
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	/*
80062306a36Sopenharmony_ci	 * 33 CHLF "Current Control"
80162306a36Sopenharmony_ci	 *                  =   9 (0x09) 00001001
80262306a36Sopenharmony_ci	 *    CHLF[7:6] "Sensor current control"
80362306a36Sopenharmony_ci	 *                  =   0 (0x00) 00......
80462306a36Sopenharmony_ci	 *    CHLF[5] "Sensor current range control"
80562306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "normal range"
80662306a36Sopenharmony_ci	 *    CHLF[4] "Sensor current"
80762306a36Sopenharmony_ci	 *                  =   0 (0x00) ...0.... "normal current"
80862306a36Sopenharmony_ci	 *    CHLF[3] "Sensor buffer current control"
80962306a36Sopenharmony_ci	 *                  =   1 (0x01) ....1... "half current"
81062306a36Sopenharmony_ci	 *    CHLF[2] "Column buffer current control"
81162306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "normal current"
81262306a36Sopenharmony_ci	 *    CHLF[1] "Analog DSP current control"
81362306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
81462306a36Sopenharmony_ci	 *    CHLF[1] "ADC current control"
81562306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
81662306a36Sopenharmony_ci	 */
81762306a36Sopenharmony_ci	{ 0x33, 0x09 },
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	/*
82062306a36Sopenharmony_ci	 * 34 VBLM "Blooming Control"
82162306a36Sopenharmony_ci	 *                  =  80 (0x50) 01010000
82262306a36Sopenharmony_ci	 *    VBLM[7] "Hard soft reset switch"
82362306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Hard reset"
82462306a36Sopenharmony_ci	 *    VBLM[6:4] "Blooming voltage selection"
82562306a36Sopenharmony_ci	 *                  =   5 (0x05) .101....
82662306a36Sopenharmony_ci	 *    VBLM[3:0] "Sensor current control"
82762306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0000
82862306a36Sopenharmony_ci	 */
82962306a36Sopenharmony_ci	{ 0x34, 0x50 },
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	/*
83262306a36Sopenharmony_ci	 * 36 VCHG "Sensor Precharge Voltage Control"
83362306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
83462306a36Sopenharmony_ci	 *    VCHG[7] "Reserved"
83562306a36Sopenharmony_ci	 *                  =   0 (0x00) 0.......
83662306a36Sopenharmony_ci	 *    VCHG[6:4] "Sensor precharge voltage control"
83762306a36Sopenharmony_ci	 *                  =   0 (0x00) .000....
83862306a36Sopenharmony_ci	 *    VCHG[3:0] "Sensor array common reference"
83962306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0000
84062306a36Sopenharmony_ci	 */
84162306a36Sopenharmony_ci	{ 0x36, 0x00 },
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	/*
84462306a36Sopenharmony_ci	 * 37 ADC "ADC Reference Control"
84562306a36Sopenharmony_ci	 *                  =   4 (0x04) 00000100
84662306a36Sopenharmony_ci	 *    ADC[7:4] "Reserved"
84762306a36Sopenharmony_ci	 *                  =   0 (0x00) 0000....
84862306a36Sopenharmony_ci	 *    ADC[3] "ADC input signal range"
84962306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Input signal 1.0x"
85062306a36Sopenharmony_ci	 *    ADC[2:0] "ADC range control"
85162306a36Sopenharmony_ci	 *                  =   4 (0x04) .....100
85262306a36Sopenharmony_ci	 */
85362306a36Sopenharmony_ci	{ 0x37, 0x04 },
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	/*
85662306a36Sopenharmony_ci	 * 38 ACOM "Analog Common Ground"
85762306a36Sopenharmony_ci	 *                  =  82 (0x52) 01010010
85862306a36Sopenharmony_ci	 *    ACOM[7] "Analog gain control"
85962306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Gain 1x"
86062306a36Sopenharmony_ci	 *    ACOM[6] "Analog black level calibration"
86162306a36Sopenharmony_ci	 *                  =   1 (0x01) .1...... "On"
86262306a36Sopenharmony_ci	 *    ACOM[5:0] "Reserved"
86362306a36Sopenharmony_ci	 *                  =  18 (0x12) ..010010
86462306a36Sopenharmony_ci	 */
86562306a36Sopenharmony_ci	{ 0x38, 0x52 },
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	/*
86862306a36Sopenharmony_ci	 * 3A FREFA "Internal Reference Adjustment"
86962306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
87062306a36Sopenharmony_ci	 *    FREFA[7:0] "Range"
87162306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
87262306a36Sopenharmony_ci	 */
87362306a36Sopenharmony_ci	{ 0x3a, 0x00 },
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/*
87662306a36Sopenharmony_ci	 * 3C FVOPT "Internal Reference Adjustment"
87762306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
87862306a36Sopenharmony_ci	 *    FVOPT[7:0] "Range"
87962306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
88062306a36Sopenharmony_ci	 */
88162306a36Sopenharmony_ci	{ 0x3c, 0x1f },
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	/*
88462306a36Sopenharmony_ci	 * 44 Undocumented  =   0 (0x00) 00000000
88562306a36Sopenharmony_ci	 *    44[7:0] "It's a secret"
88662306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
88762306a36Sopenharmony_ci	 */
88862306a36Sopenharmony_ci	{ 0x44, 0x00 },
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	/*
89162306a36Sopenharmony_ci	 * 40 Undocumented  =   0 (0x00) 00000000
89262306a36Sopenharmony_ci	 *    40[7:0] "It's a secret"
89362306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
89462306a36Sopenharmony_ci	 */
89562306a36Sopenharmony_ci	{ 0x40, 0x00 },
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	/*
89862306a36Sopenharmony_ci	 * 41 Undocumented  =   0 (0x00) 00000000
89962306a36Sopenharmony_ci	 *    41[7:0] "It's a secret"
90062306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
90162306a36Sopenharmony_ci	 */
90262306a36Sopenharmony_ci	{ 0x41, 0x00 },
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	/*
90562306a36Sopenharmony_ci	 * 42 Undocumented  =   0 (0x00) 00000000
90662306a36Sopenharmony_ci	 *    42[7:0] "It's a secret"
90762306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
90862306a36Sopenharmony_ci	 */
90962306a36Sopenharmony_ci	{ 0x42, 0x00 },
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	/*
91262306a36Sopenharmony_ci	 * 43 Undocumented  =   0 (0x00) 00000000
91362306a36Sopenharmony_ci	 *    43[7:0] "It's a secret"
91462306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
91562306a36Sopenharmony_ci	 */
91662306a36Sopenharmony_ci	{ 0x43, 0x00 },
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	/*
91962306a36Sopenharmony_ci	 * 45 Undocumented  = 128 (0x80) 10000000
92062306a36Sopenharmony_ci	 *    45[7:0] "It's a secret"
92162306a36Sopenharmony_ci	 *                  = 128 (0x80) 10000000
92262306a36Sopenharmony_ci	 */
92362306a36Sopenharmony_ci	{ 0x45, 0x80 },
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci	/*
92662306a36Sopenharmony_ci	 * 48 Undocumented  = 192 (0xC0) 11000000
92762306a36Sopenharmony_ci	 *    48[7:0] "It's a secret"
92862306a36Sopenharmony_ci	 *                  = 192 (0xC0) 11000000
92962306a36Sopenharmony_ci	 */
93062306a36Sopenharmony_ci	{ 0x48, 0xc0 },
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	/*
93362306a36Sopenharmony_ci	 * 49 Undocumented  =  25 (0x19) 00011001
93462306a36Sopenharmony_ci	 *    49[7:0] "It's a secret"
93562306a36Sopenharmony_ci	 *                  =  25 (0x19) 00011001
93662306a36Sopenharmony_ci	 */
93762306a36Sopenharmony_ci	{ 0x49, 0x19 },
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	/*
94062306a36Sopenharmony_ci	 * 4B Undocumented  = 128 (0x80) 10000000
94162306a36Sopenharmony_ci	 *    4B[7:0] "It's a secret"
94262306a36Sopenharmony_ci	 *                  = 128 (0x80) 10000000
94362306a36Sopenharmony_ci	 */
94462306a36Sopenharmony_ci	{ 0x4b, 0x80 },
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	/*
94762306a36Sopenharmony_ci	 * 4D Undocumented  = 196 (0xC4) 11000100
94862306a36Sopenharmony_ci	 *    4D[7:0] "It's a secret"
94962306a36Sopenharmony_ci	 *                  = 196 (0xC4) 11000100
95062306a36Sopenharmony_ci	 */
95162306a36Sopenharmony_ci	{ 0x4d, 0xc4 },
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	/*
95462306a36Sopenharmony_ci	 * 35 VREF "Reference Voltage Control"
95562306a36Sopenharmony_ci	 *                  =  76 (0x4c) 01001100
95662306a36Sopenharmony_ci	 *    VREF[7:5] "Column high reference control"
95762306a36Sopenharmony_ci	 *                  =   2 (0x02) 010..... "higher voltage"
95862306a36Sopenharmony_ci	 *    VREF[4:2] "Column low reference control"
95962306a36Sopenharmony_ci	 *                  =   3 (0x03) ...011.. "Highest voltage"
96062306a36Sopenharmony_ci	 *    VREF[1:0] "Reserved"
96162306a36Sopenharmony_ci	 *                  =   0 (0x00) ......00
96262306a36Sopenharmony_ci	 */
96362306a36Sopenharmony_ci	{ 0x35, 0x4c },
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/*
96662306a36Sopenharmony_ci	 * 3D Undocumented  =   0 (0x00) 00000000
96762306a36Sopenharmony_ci	 *    3D[7:0] "It's a secret"
96862306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
96962306a36Sopenharmony_ci	 */
97062306a36Sopenharmony_ci	{ 0x3d, 0x00 },
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	/*
97362306a36Sopenharmony_ci	 * 3E Undocumented  =   0 (0x00) 00000000
97462306a36Sopenharmony_ci	 *    3E[7:0] "It's a secret"
97562306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
97662306a36Sopenharmony_ci	 */
97762306a36Sopenharmony_ci	{ 0x3e, 0x00 },
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	/*
98062306a36Sopenharmony_ci	 * 3B FREFB "Internal Reference Adjustment"
98162306a36Sopenharmony_ci	 *                  =  24 (0x18) 00011000
98262306a36Sopenharmony_ci	 *    FREFB[7:0] "Range"
98362306a36Sopenharmony_ci	 *                  =  24 (0x18) 00011000
98462306a36Sopenharmony_ci	 */
98562306a36Sopenharmony_ci	{ 0x3b, 0x18 },
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	/*
98862306a36Sopenharmony_ci	 * 33 CHLF "Current Control"
98962306a36Sopenharmony_ci	 *                  =  25 (0x19) 00011001
99062306a36Sopenharmony_ci	 *    CHLF[7:6] "Sensor current control"
99162306a36Sopenharmony_ci	 *                  =   0 (0x00) 00......
99262306a36Sopenharmony_ci	 *    CHLF[5] "Sensor current range control"
99362306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "normal range"
99462306a36Sopenharmony_ci	 *    CHLF[4] "Sensor current"
99562306a36Sopenharmony_ci	 *                  =   1 (0x01) ...1.... "double current"
99662306a36Sopenharmony_ci	 *    CHLF[3] "Sensor buffer current control"
99762306a36Sopenharmony_ci	 *                  =   1 (0x01) ....1... "half current"
99862306a36Sopenharmony_ci	 *    CHLF[2] "Column buffer current control"
99962306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "normal current"
100062306a36Sopenharmony_ci	 *    CHLF[1] "Analog DSP current control"
100162306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
100262306a36Sopenharmony_ci	 *    CHLF[1] "ADC current control"
100362306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
100462306a36Sopenharmony_ci	 */
100562306a36Sopenharmony_ci	{ 0x33, 0x19 },
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	/*
100862306a36Sopenharmony_ci	 * 34 VBLM "Blooming Control"
100962306a36Sopenharmony_ci	 *                  =  90 (0x5A) 01011010
101062306a36Sopenharmony_ci	 *    VBLM[7] "Hard soft reset switch"
101162306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Hard reset"
101262306a36Sopenharmony_ci	 *    VBLM[6:4] "Blooming voltage selection"
101362306a36Sopenharmony_ci	 *                  =   5 (0x05) .101....
101462306a36Sopenharmony_ci	 *    VBLM[3:0] "Sensor current control"
101562306a36Sopenharmony_ci	 *                  =  10 (0x0A) ....1010
101662306a36Sopenharmony_ci	 */
101762306a36Sopenharmony_ci	{ 0x34, 0x5a },
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	/*
102062306a36Sopenharmony_ci	 * 3B FREFB "Internal Reference Adjustment"
102162306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
102262306a36Sopenharmony_ci	 *    FREFB[7:0] "Range"
102362306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
102462306a36Sopenharmony_ci	 */
102562306a36Sopenharmony_ci	{ 0x3b, 0x00 },
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	/*
102862306a36Sopenharmony_ci	 * 33 CHLF "Current Control"
102962306a36Sopenharmony_ci	 *                  =   9 (0x09) 00001001
103062306a36Sopenharmony_ci	 *    CHLF[7:6] "Sensor current control"
103162306a36Sopenharmony_ci	 *                  =   0 (0x00) 00......
103262306a36Sopenharmony_ci	 *    CHLF[5] "Sensor current range control"
103362306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "normal range"
103462306a36Sopenharmony_ci	 *    CHLF[4] "Sensor current"
103562306a36Sopenharmony_ci	 *                  =   0 (0x00) ...0.... "normal current"
103662306a36Sopenharmony_ci	 *    CHLF[3] "Sensor buffer current control"
103762306a36Sopenharmony_ci	 *                  =   1 (0x01) ....1... "half current"
103862306a36Sopenharmony_ci	 *    CHLF[2] "Column buffer current control"
103962306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "normal current"
104062306a36Sopenharmony_ci	 *    CHLF[1] "Analog DSP current control"
104162306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
104262306a36Sopenharmony_ci	 *    CHLF[1] "ADC current control"
104362306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "normal current"
104462306a36Sopenharmony_ci	 */
104562306a36Sopenharmony_ci	{ 0x33, 0x09 },
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	/*
104862306a36Sopenharmony_ci	 * 34 VBLM "Blooming Control"
104962306a36Sopenharmony_ci	 *                  =  80 (0x50) 01010000
105062306a36Sopenharmony_ci	 *    VBLM[7] "Hard soft reset switch"
105162306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "Hard reset"
105262306a36Sopenharmony_ci	 *    VBLM[6:4] "Blooming voltage selection"
105362306a36Sopenharmony_ci	 *                  =   5 (0x05) .101....
105462306a36Sopenharmony_ci	 *    VBLM[3:0] "Sensor current control"
105562306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0000
105662306a36Sopenharmony_ci	 */
105762306a36Sopenharmony_ci	{ 0x34, 0x50 },
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	/*
106062306a36Sopenharmony_ci	 * 12 COMH "Common Control H"
106162306a36Sopenharmony_ci	 *                  =  64 (0x40) 01000000
106262306a36Sopenharmony_ci	 *    COMH[7] "SRST"
106362306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "No-op"
106462306a36Sopenharmony_ci	 *    COMH[6:4] "Resolution selection"
106562306a36Sopenharmony_ci	 *                  =   4 (0x04) .100.... "XGA"
106662306a36Sopenharmony_ci	 *    COMH[3] "Master slave selection"
106762306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Master mode"
106862306a36Sopenharmony_ci	 *    COMH[2] "Internal B/R channel option"
106962306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "B/R use same channel"
107062306a36Sopenharmony_ci	 *    COMH[1] "Color bar test pattern"
107162306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Off"
107262306a36Sopenharmony_ci	 *    COMH[0] "Reserved"
107362306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0
107462306a36Sopenharmony_ci	 */
107562306a36Sopenharmony_ci	{ 0x12, 0x40 },
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	/*
107862306a36Sopenharmony_ci	 * 17 HREFST "Horizontal window start"
107962306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
108062306a36Sopenharmony_ci	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
108162306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
108262306a36Sopenharmony_ci	 */
108362306a36Sopenharmony_ci	{ 0x17, 0x1f },
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/*
108662306a36Sopenharmony_ci	 * 18 HREFEND "Horizontal window end"
108762306a36Sopenharmony_ci	 *                  =  95 (0x5F) 01011111
108862306a36Sopenharmony_ci	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
108962306a36Sopenharmony_ci	 *                  =  95 (0x5F) 01011111
109062306a36Sopenharmony_ci	 */
109162306a36Sopenharmony_ci	{ 0x18, 0x5f },
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	/*
109462306a36Sopenharmony_ci	 * 19 VSTRT "Vertical window start"
109562306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
109662306a36Sopenharmony_ci	 *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
109762306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
109862306a36Sopenharmony_ci	 */
109962306a36Sopenharmony_ci	{ 0x19, 0x00 },
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	/*
110262306a36Sopenharmony_ci	 * 1A VEND "Vertical window end"
110362306a36Sopenharmony_ci	 *                  =  96 (0x60) 01100000
110462306a36Sopenharmony_ci	 *    VEND[7:0] "Vertical Window End, 8 MSBs"
110562306a36Sopenharmony_ci	 *                  =  96 (0x60) 01100000
110662306a36Sopenharmony_ci	 */
110762306a36Sopenharmony_ci	{ 0x1a, 0x60 },
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	/*
111062306a36Sopenharmony_ci	 * 32 COMM "Common Control M"
111162306a36Sopenharmony_ci	 *                  =  18 (0x12) 00010010
111262306a36Sopenharmony_ci	 *    COMM[7:6] "Pixel clock divide option"
111362306a36Sopenharmony_ci	 *                  =   0 (0x00) 00...... "/1"
111462306a36Sopenharmony_ci	 *    COMM[5:3] "Horizontal window end position, 3 LSBs"
111562306a36Sopenharmony_ci	 *                  =   2 (0x02) ..010...
111662306a36Sopenharmony_ci	 *    COMM[2:0] "Horizontal window start position, 3 LSBs"
111762306a36Sopenharmony_ci	 *                  =   2 (0x02) .....010
111862306a36Sopenharmony_ci	 */
111962306a36Sopenharmony_ci	{ 0x32, 0x12 },
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	/*
112262306a36Sopenharmony_ci	 * 03 COMA "Common Control A"
112362306a36Sopenharmony_ci	 *                  =  74 (0x4A) 01001010
112462306a36Sopenharmony_ci	 *    COMA[7:4] "AWB Update Threshold"
112562306a36Sopenharmony_ci	 *                  =   4 (0x04) 0100....
112662306a36Sopenharmony_ci	 *    COMA[3:2] "Vertical window end line control 2 LSBs"
112762306a36Sopenharmony_ci	 *                  =   2 (0x02) ....10..
112862306a36Sopenharmony_ci	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
112962306a36Sopenharmony_ci	 *                  =   2 (0x02) ......10
113062306a36Sopenharmony_ci	 */
113162306a36Sopenharmony_ci	{ 0x03, 0x4a },
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	/*
113462306a36Sopenharmony_ci	 * 11 CLKRC "Clock Rate Control"
113562306a36Sopenharmony_ci	 *                  = 128 (0x80) 10000000
113662306a36Sopenharmony_ci	 *    CLKRC[7] "Internal frequency doublers on off seclection"
113762306a36Sopenharmony_ci	 *                  =   1 (0x01) 1....... "On"
113862306a36Sopenharmony_ci	 *    CLKRC[6] "Digital video master slave selection"
113962306a36Sopenharmony_ci	 *                  =   0 (0x00) .0...... "Master mode, sensor
114062306a36Sopenharmony_ci	 *                                         provides PCLK"
114162306a36Sopenharmony_ci	 *    CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }"
114262306a36Sopenharmony_ci	 *                  =   0 (0x00) ..000000
114362306a36Sopenharmony_ci	 */
114462306a36Sopenharmony_ci	{ 0x11, 0x80 },
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	/*
114762306a36Sopenharmony_ci	 * 12 COMH "Common Control H"
114862306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
114962306a36Sopenharmony_ci	 *    COMH[7] "SRST"
115062306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "No-op"
115162306a36Sopenharmony_ci	 *    COMH[6:4] "Resolution selection"
115262306a36Sopenharmony_ci	 *                  =   0 (0x00) .000.... "QXGA"
115362306a36Sopenharmony_ci	 *    COMH[3] "Master slave selection"
115462306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Master mode"
115562306a36Sopenharmony_ci	 *    COMH[2] "Internal B/R channel option"
115662306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "B/R use same channel"
115762306a36Sopenharmony_ci	 *    COMH[1] "Color bar test pattern"
115862306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Off"
115962306a36Sopenharmony_ci	 *    COMH[0] "Reserved"
116062306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0
116162306a36Sopenharmony_ci	 */
116262306a36Sopenharmony_ci	{ 0x12, 0x00 },
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	/*
116562306a36Sopenharmony_ci	 * 12 COMH "Common Control H"
116662306a36Sopenharmony_ci	 *                  =  64 (0x40) 01000000
116762306a36Sopenharmony_ci	 *    COMH[7] "SRST"
116862306a36Sopenharmony_ci	 *                  =   0 (0x00) 0....... "No-op"
116962306a36Sopenharmony_ci	 *    COMH[6:4] "Resolution selection"
117062306a36Sopenharmony_ci	 *                  =   4 (0x04) .100.... "XGA"
117162306a36Sopenharmony_ci	 *    COMH[3] "Master slave selection"
117262306a36Sopenharmony_ci	 *                  =   0 (0x00) ....0... "Master mode"
117362306a36Sopenharmony_ci	 *    COMH[2] "Internal B/R channel option"
117462306a36Sopenharmony_ci	 *                  =   0 (0x00) .....0.. "B/R use same channel"
117562306a36Sopenharmony_ci	 *    COMH[1] "Color bar test pattern"
117662306a36Sopenharmony_ci	 *                  =   0 (0x00) ......0. "Off"
117762306a36Sopenharmony_ci	 *    COMH[0] "Reserved"
117862306a36Sopenharmony_ci	 *                  =   0 (0x00) .......0
117962306a36Sopenharmony_ci	 */
118062306a36Sopenharmony_ci	{ 0x12, 0x40 },
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	/*
118362306a36Sopenharmony_ci	 * 17 HREFST "Horizontal window start"
118462306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
118562306a36Sopenharmony_ci	 *    HREFST[7:0] "Horizontal window start, 8 MSBs"
118662306a36Sopenharmony_ci	 *                  =  31 (0x1F) 00011111
118762306a36Sopenharmony_ci	 */
118862306a36Sopenharmony_ci	{ 0x17, 0x1f },
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	/*
119162306a36Sopenharmony_ci	 * 18 HREFEND "Horizontal window end"
119262306a36Sopenharmony_ci	 *                  =  95 (0x5F) 01011111
119362306a36Sopenharmony_ci	 *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
119462306a36Sopenharmony_ci	 *                  =  95 (0x5F) 01011111
119562306a36Sopenharmony_ci	 */
119662306a36Sopenharmony_ci	{ 0x18, 0x5f },
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	/*
119962306a36Sopenharmony_ci	 * 19 VSTRT "Vertical window start"
120062306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
120162306a36Sopenharmony_ci	 *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
120262306a36Sopenharmony_ci	 *                  =   0 (0x00) 00000000
120362306a36Sopenharmony_ci	 */
120462306a36Sopenharmony_ci	{ 0x19, 0x00 },
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	/*
120762306a36Sopenharmony_ci	 * 1A VEND "Vertical window end"
120862306a36Sopenharmony_ci	 *                  =  96 (0x60) 01100000
120962306a36Sopenharmony_ci	 *    VEND[7:0] "Vertical Window End, 8 MSBs"
121062306a36Sopenharmony_ci	 *                  =  96 (0x60) 01100000
121162306a36Sopenharmony_ci	 */
121262306a36Sopenharmony_ci	{ 0x1a, 0x60 },
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/*
121562306a36Sopenharmony_ci	 * 32 COMM "Common Control M"
121662306a36Sopenharmony_ci	 *                  =  18 (0x12) 00010010
121762306a36Sopenharmony_ci	 *    COMM[7:6] "Pixel clock divide option"
121862306a36Sopenharmony_ci	 *                  =   0 (0x00) 00...... "/1"
121962306a36Sopenharmony_ci	 *    COMM[5:3] "Horizontal window end position, 3 LSBs"
122062306a36Sopenharmony_ci	 *                  =   2 (0x02) ..010...
122162306a36Sopenharmony_ci	 *    COMM[2:0] "Horizontal window start position, 3 LSBs"
122262306a36Sopenharmony_ci	 *                  =   2 (0x02) .....010
122362306a36Sopenharmony_ci	 */
122462306a36Sopenharmony_ci	{ 0x32, 0x12 },
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	/*
122762306a36Sopenharmony_ci	 * 03 COMA "Common Control A"
122862306a36Sopenharmony_ci	 *                  =  74 (0x4A) 01001010
122962306a36Sopenharmony_ci	 *    COMA[7:4] "AWB Update Threshold"
123062306a36Sopenharmony_ci	 *                  =   4 (0x04) 0100....
123162306a36Sopenharmony_ci	 *    COMA[3:2] "Vertical window end line control 2 LSBs"
123262306a36Sopenharmony_ci	 *                  =   2 (0x02) ....10..
123362306a36Sopenharmony_ci	 *    COMA[1:0] "Vertical window start line control 2 LSBs"
123462306a36Sopenharmony_ci	 *                  =   2 (0x02) ......10
123562306a36Sopenharmony_ci	 */
123662306a36Sopenharmony_ci	{ 0x03, 0x4a },
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	/*
123962306a36Sopenharmony_ci	 * 02 RED "Red Gain Control"
124062306a36Sopenharmony_ci	 *                  = 175 (0xAF) 10101111
124162306a36Sopenharmony_ci	 *    RED[7] "Action"
124262306a36Sopenharmony_ci	 *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
124362306a36Sopenharmony_ci	 *    RED[6:0] "Value"
124462306a36Sopenharmony_ci	 *                  =  47 (0x2F) .0101111
124562306a36Sopenharmony_ci	 */
124662306a36Sopenharmony_ci	{ 0x02, 0xaf },
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	/*
124962306a36Sopenharmony_ci	 * 2D ADDVSL "VSYNC Pulse Width"
125062306a36Sopenharmony_ci	 *                  = 210 (0xD2) 11010010
125162306a36Sopenharmony_ci	 *    ADDVSL[7:0] "VSYNC pulse width, LSB"
125262306a36Sopenharmony_ci	 *                  = 210 (0xD2) 11010010
125362306a36Sopenharmony_ci	 */
125462306a36Sopenharmony_ci	{ 0x2d, 0xd2 },
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	/*
125762306a36Sopenharmony_ci	 * 00 GAIN          =  24 (0x18) 00011000
125862306a36Sopenharmony_ci	 *    GAIN[7:6] "Reserved"
125962306a36Sopenharmony_ci	 *                  =   0 (0x00) 00......
126062306a36Sopenharmony_ci	 *    GAIN[5] "Double"
126162306a36Sopenharmony_ci	 *                  =   0 (0x00) ..0..... "False"
126262306a36Sopenharmony_ci	 *    GAIN[4] "Double"
126362306a36Sopenharmony_ci	 *                  =   1 (0x01) ...1.... "True"
126462306a36Sopenharmony_ci	 *    GAIN[3:0] "Range"
126562306a36Sopenharmony_ci	 *                  =   8 (0x08) ....1000
126662306a36Sopenharmony_ci	 */
126762306a36Sopenharmony_ci	{ 0x00, 0x18 },
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	/*
127062306a36Sopenharmony_ci	 * 01 BLUE "Blue Gain Control"
127162306a36Sopenharmony_ci	 *                  = 240 (0xF0) 11110000
127262306a36Sopenharmony_ci	 *    BLUE[7] "Action"
127362306a36Sopenharmony_ci	 *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
127462306a36Sopenharmony_ci	 *    BLUE[6:0] "Value"
127562306a36Sopenharmony_ci	 *                  = 112 (0x70) .1110000
127662306a36Sopenharmony_ci	 */
127762306a36Sopenharmony_ci	{ 0x01, 0xf0 },
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	/*
128062306a36Sopenharmony_ci	 * 10 AEC "Automatic Exposure Control"
128162306a36Sopenharmony_ci	 *                  =  10 (0x0A) 00001010
128262306a36Sopenharmony_ci	 *    AEC[7:0] "Automatic Exposure Control, 8 MSBs"
128362306a36Sopenharmony_ci	 *                  =  10 (0x0A) 00001010
128462306a36Sopenharmony_ci	 */
128562306a36Sopenharmony_ci	{ 0x10, 0x0a },
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	{ 0xe1, 0x67 },
128862306a36Sopenharmony_ci	{ 0xe3, 0x03 },
128962306a36Sopenharmony_ci	{ 0xe4, 0x26 },
129062306a36Sopenharmony_ci	{ 0xe5, 0x3e },
129162306a36Sopenharmony_ci	{ 0xf8, 0x01 },
129262306a36Sopenharmony_ci	{ 0xff, 0x01 },
129362306a36Sopenharmony_ci};
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x20[] = {
129662306a36Sopenharmony_ci	{ 0x12, 0x80 }, /* reset */
129762306a36Sopenharmony_ci	{ 0x11, 0x01 },
129862306a36Sopenharmony_ci	{ 0x03, 0x60 },
129962306a36Sopenharmony_ci	{ 0x05, 0x7f }, /* For when autoadjust is off */
130062306a36Sopenharmony_ci	{ 0x07, 0xa8 },
130162306a36Sopenharmony_ci	/* The ratio of 0x0c and 0x0d controls the white point */
130262306a36Sopenharmony_ci	{ 0x0c, 0x24 },
130362306a36Sopenharmony_ci	{ 0x0d, 0x24 },
130462306a36Sopenharmony_ci	{ 0x0f, 0x15 }, /* COMS */
130562306a36Sopenharmony_ci	{ 0x10, 0x75 }, /* AEC Exposure time */
130662306a36Sopenharmony_ci	{ 0x12, 0x24 }, /* Enable AGC */
130762306a36Sopenharmony_ci	{ 0x14, 0x04 },
130862306a36Sopenharmony_ci	/* 0x16: 0x06 helps frame stability with moving objects */
130962306a36Sopenharmony_ci	{ 0x16, 0x06 },
131062306a36Sopenharmony_ci/*	{ 0x20, 0x30 },  * Aperture correction enable */
131162306a36Sopenharmony_ci	{ 0x26, 0xb2 }, /* BLC enable */
131262306a36Sopenharmony_ci	/* 0x28: 0x05 Selects RGB format if RGB on */
131362306a36Sopenharmony_ci	{ 0x28, 0x05 },
131462306a36Sopenharmony_ci	{ 0x2a, 0x04 }, /* Disable framerate adjust */
131562306a36Sopenharmony_ci/*	{ 0x2b, 0xac },  * Framerate; Set 2a[7] first */
131662306a36Sopenharmony_ci	{ 0x2d, 0x85 },
131762306a36Sopenharmony_ci	{ 0x33, 0xa0 }, /* Color Processing Parameter */
131862306a36Sopenharmony_ci	{ 0x34, 0xd2 }, /* Max A/D range */
131962306a36Sopenharmony_ci	{ 0x38, 0x8b },
132062306a36Sopenharmony_ci	{ 0x39, 0x40 },
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	{ 0x3c, 0x39 }, /* Enable AEC mode changing */
132362306a36Sopenharmony_ci	{ 0x3c, 0x3c }, /* Change AEC mode */
132462306a36Sopenharmony_ci	{ 0x3c, 0x24 }, /* Disable AEC mode changing */
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci	{ 0x3d, 0x80 },
132762306a36Sopenharmony_ci	/* These next two registers (0x4a, 0x4b) are undocumented.
132862306a36Sopenharmony_ci	 * They control the color balance */
132962306a36Sopenharmony_ci	{ 0x4a, 0x80 },
133062306a36Sopenharmony_ci	{ 0x4b, 0x80 },
133162306a36Sopenharmony_ci	{ 0x4d, 0xd2 }, /* This reduces noise a bit */
133262306a36Sopenharmony_ci	{ 0x4e, 0xc1 },
133362306a36Sopenharmony_ci	{ 0x4f, 0x04 },
133462306a36Sopenharmony_ci/* Do 50-53 have any effect? */
133562306a36Sopenharmony_ci/* Toggle 0x12[2] off and on here? */
133662306a36Sopenharmony_ci};
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_6x30[] = {
133962306a36Sopenharmony_ci	{ 0x12, 0x80 }, /* Reset */
134062306a36Sopenharmony_ci	{ 0x00, 0x1f }, /* Gain */
134162306a36Sopenharmony_ci	{ 0x01, 0x99 }, /* Blue gain */
134262306a36Sopenharmony_ci	{ 0x02, 0x7c }, /* Red gain */
134362306a36Sopenharmony_ci	{ 0x03, 0xc0 }, /* Saturation */
134462306a36Sopenharmony_ci	{ 0x05, 0x0a }, /* Contrast */
134562306a36Sopenharmony_ci	{ 0x06, 0x95 }, /* Brightness */
134662306a36Sopenharmony_ci	{ 0x07, 0x2d }, /* Sharpness */
134762306a36Sopenharmony_ci	{ 0x0c, 0x20 },
134862306a36Sopenharmony_ci	{ 0x0d, 0x20 },
134962306a36Sopenharmony_ci	{ 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
135062306a36Sopenharmony_ci	{ 0x0f, 0x05 },
135162306a36Sopenharmony_ci	{ 0x10, 0x9a },
135262306a36Sopenharmony_ci	{ 0x11, 0x00 }, /* Pixel clock = fastest */
135362306a36Sopenharmony_ci	{ 0x12, 0x24 }, /* Enable AGC and AWB */
135462306a36Sopenharmony_ci	{ 0x13, 0x21 },
135562306a36Sopenharmony_ci	{ 0x14, 0x80 },
135662306a36Sopenharmony_ci	{ 0x15, 0x01 },
135762306a36Sopenharmony_ci	{ 0x16, 0x03 },
135862306a36Sopenharmony_ci	{ 0x17, 0x38 },
135962306a36Sopenharmony_ci	{ 0x18, 0xea },
136062306a36Sopenharmony_ci	{ 0x19, 0x04 },
136162306a36Sopenharmony_ci	{ 0x1a, 0x93 },
136262306a36Sopenharmony_ci	{ 0x1b, 0x00 },
136362306a36Sopenharmony_ci	{ 0x1e, 0xc4 },
136462306a36Sopenharmony_ci	{ 0x1f, 0x04 },
136562306a36Sopenharmony_ci	{ 0x20, 0x20 },
136662306a36Sopenharmony_ci	{ 0x21, 0x10 },
136762306a36Sopenharmony_ci	{ 0x22, 0x88 },
136862306a36Sopenharmony_ci	{ 0x23, 0xc0 }, /* Crystal circuit power level */
136962306a36Sopenharmony_ci	{ 0x25, 0x9a }, /* Increase AEC black ratio */
137062306a36Sopenharmony_ci	{ 0x26, 0xb2 }, /* BLC enable */
137162306a36Sopenharmony_ci	{ 0x27, 0xa2 },
137262306a36Sopenharmony_ci	{ 0x28, 0x00 },
137362306a36Sopenharmony_ci	{ 0x29, 0x00 },
137462306a36Sopenharmony_ci	{ 0x2a, 0x84 }, /* 60 Hz power */
137562306a36Sopenharmony_ci	{ 0x2b, 0xa8 }, /* 60 Hz power */
137662306a36Sopenharmony_ci	{ 0x2c, 0xa0 },
137762306a36Sopenharmony_ci	{ 0x2d, 0x95 }, /* Enable auto-brightness */
137862306a36Sopenharmony_ci	{ 0x2e, 0x88 },
137962306a36Sopenharmony_ci	{ 0x33, 0x26 },
138062306a36Sopenharmony_ci	{ 0x34, 0x03 },
138162306a36Sopenharmony_ci	{ 0x36, 0x8f },
138262306a36Sopenharmony_ci	{ 0x37, 0x80 },
138362306a36Sopenharmony_ci	{ 0x38, 0x83 },
138462306a36Sopenharmony_ci	{ 0x39, 0x80 },
138562306a36Sopenharmony_ci	{ 0x3a, 0x0f },
138662306a36Sopenharmony_ci	{ 0x3b, 0x3c },
138762306a36Sopenharmony_ci	{ 0x3c, 0x1a },
138862306a36Sopenharmony_ci	{ 0x3d, 0x80 },
138962306a36Sopenharmony_ci	{ 0x3e, 0x80 },
139062306a36Sopenharmony_ci	{ 0x3f, 0x0e },
139162306a36Sopenharmony_ci	{ 0x40, 0x00 }, /* White bal */
139262306a36Sopenharmony_ci	{ 0x41, 0x00 }, /* White bal */
139362306a36Sopenharmony_ci	{ 0x42, 0x80 },
139462306a36Sopenharmony_ci	{ 0x43, 0x3f }, /* White bal */
139562306a36Sopenharmony_ci	{ 0x44, 0x80 },
139662306a36Sopenharmony_ci	{ 0x45, 0x20 },
139762306a36Sopenharmony_ci	{ 0x46, 0x20 },
139862306a36Sopenharmony_ci	{ 0x47, 0x80 },
139962306a36Sopenharmony_ci	{ 0x48, 0x7f },
140062306a36Sopenharmony_ci	{ 0x49, 0x00 },
140162306a36Sopenharmony_ci	{ 0x4a, 0x00 },
140262306a36Sopenharmony_ci	{ 0x4b, 0x80 },
140362306a36Sopenharmony_ci	{ 0x4c, 0xd0 },
140462306a36Sopenharmony_ci	{ 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
140562306a36Sopenharmony_ci	{ 0x4e, 0x40 },
140662306a36Sopenharmony_ci	{ 0x4f, 0x07 }, /* UV avg., col. killer: max */
140762306a36Sopenharmony_ci	{ 0x50, 0xff },
140862306a36Sopenharmony_ci	{ 0x54, 0x23 }, /* Max AGC gain: 18dB */
140962306a36Sopenharmony_ci	{ 0x55, 0xff },
141062306a36Sopenharmony_ci	{ 0x56, 0x12 },
141162306a36Sopenharmony_ci	{ 0x57, 0x81 },
141262306a36Sopenharmony_ci	{ 0x58, 0x75 },
141362306a36Sopenharmony_ci	{ 0x59, 0x01 }, /* AGC dark current comp.: +1 */
141462306a36Sopenharmony_ci	{ 0x5a, 0x2c },
141562306a36Sopenharmony_ci	{ 0x5b, 0x0f }, /* AWB chrominance levels */
141662306a36Sopenharmony_ci	{ 0x5c, 0x10 },
141762306a36Sopenharmony_ci	{ 0x3d, 0x80 },
141862306a36Sopenharmony_ci	{ 0x27, 0xa6 },
141962306a36Sopenharmony_ci	{ 0x12, 0x20 }, /* Toggle AWB */
142062306a36Sopenharmony_ci	{ 0x12, 0x24 },
142162306a36Sopenharmony_ci};
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci/* Lawrence Glaister <lg@jfm.bc.ca> reports:
142462306a36Sopenharmony_ci *
142562306a36Sopenharmony_ci * Register 0x0f in the 7610 has the following effects:
142662306a36Sopenharmony_ci *
142762306a36Sopenharmony_ci * 0x85 (AEC method 1): Best overall, good contrast range
142862306a36Sopenharmony_ci * 0x45 (AEC method 2): Very overexposed
142962306a36Sopenharmony_ci * 0xa5 (spec sheet default): Ok, but the black level is
143062306a36Sopenharmony_ci *	shifted resulting in loss of contrast
143162306a36Sopenharmony_ci * 0x05 (old driver setting): very overexposed, too much
143262306a36Sopenharmony_ci *	contrast
143362306a36Sopenharmony_ci */
143462306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7610[] = {
143562306a36Sopenharmony_ci	{ 0x10, 0xff },
143662306a36Sopenharmony_ci	{ 0x16, 0x06 },
143762306a36Sopenharmony_ci	{ 0x28, 0x24 },
143862306a36Sopenharmony_ci	{ 0x2b, 0xac },
143962306a36Sopenharmony_ci	{ 0x12, 0x00 },
144062306a36Sopenharmony_ci	{ 0x38, 0x81 },
144162306a36Sopenharmony_ci	{ 0x28, 0x24 },	/* 0c */
144262306a36Sopenharmony_ci	{ 0x0f, 0x85 },	/* lg's setting */
144362306a36Sopenharmony_ci	{ 0x15, 0x01 },
144462306a36Sopenharmony_ci	{ 0x20, 0x1c },
144562306a36Sopenharmony_ci	{ 0x23, 0x2a },
144662306a36Sopenharmony_ci	{ 0x24, 0x10 },
144762306a36Sopenharmony_ci	{ 0x25, 0x8a },
144862306a36Sopenharmony_ci	{ 0x26, 0xa2 },
144962306a36Sopenharmony_ci	{ 0x27, 0xc2 },
145062306a36Sopenharmony_ci	{ 0x2a, 0x04 },
145162306a36Sopenharmony_ci	{ 0x2c, 0xfe },
145262306a36Sopenharmony_ci	{ 0x2d, 0x93 },
145362306a36Sopenharmony_ci	{ 0x30, 0x71 },
145462306a36Sopenharmony_ci	{ 0x31, 0x60 },
145562306a36Sopenharmony_ci	{ 0x32, 0x26 },
145662306a36Sopenharmony_ci	{ 0x33, 0x20 },
145762306a36Sopenharmony_ci	{ 0x34, 0x48 },
145862306a36Sopenharmony_ci	{ 0x12, 0x24 },
145962306a36Sopenharmony_ci	{ 0x11, 0x01 },
146062306a36Sopenharmony_ci	{ 0x0c, 0x24 },
146162306a36Sopenharmony_ci	{ 0x0d, 0x24 },
146262306a36Sopenharmony_ci};
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7620[] = {
146562306a36Sopenharmony_ci	{ 0x12, 0x80 },		/* reset */
146662306a36Sopenharmony_ci	{ 0x00, 0x00 },		/* gain */
146762306a36Sopenharmony_ci	{ 0x01, 0x80 },		/* blue gain */
146862306a36Sopenharmony_ci	{ 0x02, 0x80 },		/* red gain */
146962306a36Sopenharmony_ci	{ 0x03, 0xc0 },		/* OV7670_R03_VREF */
147062306a36Sopenharmony_ci	{ 0x06, 0x60 },
147162306a36Sopenharmony_ci	{ 0x07, 0x00 },
147262306a36Sopenharmony_ci	{ 0x0c, 0x24 },
147362306a36Sopenharmony_ci	{ 0x0c, 0x24 },
147462306a36Sopenharmony_ci	{ 0x0d, 0x24 },
147562306a36Sopenharmony_ci	{ 0x11, 0x01 },
147662306a36Sopenharmony_ci	{ 0x12, 0x24 },
147762306a36Sopenharmony_ci	{ 0x13, 0x01 },
147862306a36Sopenharmony_ci	{ 0x14, 0x84 },
147962306a36Sopenharmony_ci	{ 0x15, 0x01 },
148062306a36Sopenharmony_ci	{ 0x16, 0x03 },
148162306a36Sopenharmony_ci	{ 0x17, 0x2f },
148262306a36Sopenharmony_ci	{ 0x18, 0xcf },
148362306a36Sopenharmony_ci	{ 0x19, 0x06 },
148462306a36Sopenharmony_ci	{ 0x1a, 0xf5 },
148562306a36Sopenharmony_ci	{ 0x1b, 0x00 },
148662306a36Sopenharmony_ci	{ 0x20, 0x18 },
148762306a36Sopenharmony_ci	{ 0x21, 0x80 },
148862306a36Sopenharmony_ci	{ 0x22, 0x80 },
148962306a36Sopenharmony_ci	{ 0x23, 0x00 },
149062306a36Sopenharmony_ci	{ 0x26, 0xa2 },
149162306a36Sopenharmony_ci	{ 0x27, 0xea },
149262306a36Sopenharmony_ci	{ 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
149362306a36Sopenharmony_ci	{ 0x29, 0x00 },
149462306a36Sopenharmony_ci	{ 0x2a, 0x10 },
149562306a36Sopenharmony_ci	{ 0x2b, 0x00 },
149662306a36Sopenharmony_ci	{ 0x2c, 0x88 },
149762306a36Sopenharmony_ci	{ 0x2d, 0x91 },
149862306a36Sopenharmony_ci	{ 0x2e, 0x80 },
149962306a36Sopenharmony_ci	{ 0x2f, 0x44 },
150062306a36Sopenharmony_ci	{ 0x60, 0x27 },
150162306a36Sopenharmony_ci	{ 0x61, 0x02 },
150262306a36Sopenharmony_ci	{ 0x62, 0x5f },
150362306a36Sopenharmony_ci	{ 0x63, 0xd5 },
150462306a36Sopenharmony_ci	{ 0x64, 0x57 },
150562306a36Sopenharmony_ci	{ 0x65, 0x83 },
150662306a36Sopenharmony_ci	{ 0x66, 0x55 },
150762306a36Sopenharmony_ci	{ 0x67, 0x92 },
150862306a36Sopenharmony_ci	{ 0x68, 0xcf },
150962306a36Sopenharmony_ci	{ 0x69, 0x76 },
151062306a36Sopenharmony_ci	{ 0x6a, 0x22 },
151162306a36Sopenharmony_ci	{ 0x6b, 0x00 },
151262306a36Sopenharmony_ci	{ 0x6c, 0x02 },
151362306a36Sopenharmony_ci	{ 0x6d, 0x44 },
151462306a36Sopenharmony_ci	{ 0x6e, 0x80 },
151562306a36Sopenharmony_ci	{ 0x6f, 0x1d },
151662306a36Sopenharmony_ci	{ 0x70, 0x8b },
151762306a36Sopenharmony_ci	{ 0x71, 0x00 },
151862306a36Sopenharmony_ci	{ 0x72, 0x14 },
151962306a36Sopenharmony_ci	{ 0x73, 0x54 },
152062306a36Sopenharmony_ci	{ 0x74, 0x00 },
152162306a36Sopenharmony_ci	{ 0x75, 0x8e },
152262306a36Sopenharmony_ci	{ 0x76, 0x00 },
152362306a36Sopenharmony_ci	{ 0x77, 0xff },
152462306a36Sopenharmony_ci	{ 0x78, 0x80 },
152562306a36Sopenharmony_ci	{ 0x79, 0x80 },
152662306a36Sopenharmony_ci	{ 0x7a, 0x80 },
152762306a36Sopenharmony_ci	{ 0x7b, 0xe2 },
152862306a36Sopenharmony_ci	{ 0x7c, 0x00 },
152962306a36Sopenharmony_ci};
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci/* 7640 and 7648. The defaults should be OK for most registers. */
153262306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7640[] = {
153362306a36Sopenharmony_ci	{ 0x12, 0x80 },
153462306a36Sopenharmony_ci	{ 0x12, 0x14 },
153562306a36Sopenharmony_ci};
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_cistatic const struct ov_regvals init_519_ov7660[] = {
153862306a36Sopenharmony_ci	{ 0x5d,	0x03 }, /* Turn off suspend mode */
153962306a36Sopenharmony_ci	{ 0x53,	0x9b }, /* 0x9f enables the (unused) microcontroller */
154062306a36Sopenharmony_ci	{ 0x54,	0x0f }, /* bit2 (jpeg enable) */
154162306a36Sopenharmony_ci	{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
154262306a36Sopenharmony_ci	{ 0xa3,	0x18 },
154362306a36Sopenharmony_ci	{ 0xa4,	0x04 },
154462306a36Sopenharmony_ci	{ 0xa5,	0x28 },
154562306a36Sopenharmony_ci	{ 0x37,	0x00 },	/* SetUsbInit */
154662306a36Sopenharmony_ci	{ 0x55,	0x02 }, /* 4.096 Mhz audio clock */
154762306a36Sopenharmony_ci	/* Enable both fields, YUV Input, disable defect comp (why?) */
154862306a36Sopenharmony_ci	{ 0x20,	0x0c },	/* 0x0d does U <-> V swap */
154962306a36Sopenharmony_ci	{ 0x21,	0x38 },
155062306a36Sopenharmony_ci	{ 0x22,	0x1d },
155162306a36Sopenharmony_ci	{ 0x17,	0x50 }, /* undocumented */
155262306a36Sopenharmony_ci	{ 0x37,	0x00 }, /* undocumented */
155362306a36Sopenharmony_ci	{ 0x40,	0xff }, /* I2C timeout counter */
155462306a36Sopenharmony_ci	{ 0x46,	0x00 }, /* I2C clock prescaler */
155562306a36Sopenharmony_ci};
155662306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7660[] = {
155762306a36Sopenharmony_ci	{OV7670_R12_COM7, OV7670_COM7_RESET},
155862306a36Sopenharmony_ci	{OV7670_R11_CLKRC, 0x81},
155962306a36Sopenharmony_ci	{0x92, 0x00},			/* DM_LNL */
156062306a36Sopenharmony_ci	{0x93, 0x00},			/* DM_LNH */
156162306a36Sopenharmony_ci	{0x9d, 0x4c},			/* BD50ST */
156262306a36Sopenharmony_ci	{0x9e, 0x3f},			/* BD60ST */
156362306a36Sopenharmony_ci	{OV7670_R3B_COM11, 0x02},
156462306a36Sopenharmony_ci	{OV7670_R13_COM8, 0xf5},
156562306a36Sopenharmony_ci	{OV7670_R10_AECH, 0x00},
156662306a36Sopenharmony_ci	{OV7670_R00_GAIN, 0x00},
156762306a36Sopenharmony_ci	{OV7670_R01_BLUE, 0x7c},
156862306a36Sopenharmony_ci	{OV7670_R02_RED, 0x9d},
156962306a36Sopenharmony_ci	{OV7670_R12_COM7, 0x00},
157062306a36Sopenharmony_ci	{OV7670_R04_COM1, 00},
157162306a36Sopenharmony_ci	{OV7670_R18_HSTOP, 0x01},
157262306a36Sopenharmony_ci	{OV7670_R17_HSTART, 0x13},
157362306a36Sopenharmony_ci	{OV7670_R32_HREF, 0x92},
157462306a36Sopenharmony_ci	{OV7670_R19_VSTART, 0x02},
157562306a36Sopenharmony_ci	{OV7670_R1A_VSTOP, 0x7a},
157662306a36Sopenharmony_ci	{OV7670_R03_VREF, 0x00},
157762306a36Sopenharmony_ci	{OV7670_R0E_COM5, 0x04},
157862306a36Sopenharmony_ci	{OV7670_R0F_COM6, 0x62},
157962306a36Sopenharmony_ci	{OV7670_R15_COM10, 0x00},
158062306a36Sopenharmony_ci	{0x16, 0x02},			/* RSVD */
158162306a36Sopenharmony_ci	{0x1b, 0x00},			/* PSHFT */
158262306a36Sopenharmony_ci	{OV7670_R1E_MVFP, 0x01},
158362306a36Sopenharmony_ci	{0x29, 0x3c},			/* RSVD */
158462306a36Sopenharmony_ci	{0x33, 0x00},			/* CHLF */
158562306a36Sopenharmony_ci	{0x34, 0x07},			/* ARBLM */
158662306a36Sopenharmony_ci	{0x35, 0x84},			/* RSVD */
158762306a36Sopenharmony_ci	{0x36, 0x00},			/* RSVD */
158862306a36Sopenharmony_ci	{0x37, 0x04},			/* ADC */
158962306a36Sopenharmony_ci	{0x39, 0x43},			/* OFON */
159062306a36Sopenharmony_ci	{OV7670_R3A_TSLB, 0x00},
159162306a36Sopenharmony_ci	{OV7670_R3C_COM12, 0x6c},
159262306a36Sopenharmony_ci	{OV7670_R3D_COM13, 0x98},
159362306a36Sopenharmony_ci	{OV7670_R3F_EDGE, 0x23},
159462306a36Sopenharmony_ci	{OV7670_R40_COM15, 0xc1},
159562306a36Sopenharmony_ci	{OV7670_R41_COM16, 0x22},
159662306a36Sopenharmony_ci	{0x6b, 0x0a},			/* DBLV */
159762306a36Sopenharmony_ci	{0xa1, 0x08},			/* RSVD */
159862306a36Sopenharmony_ci	{0x69, 0x80},			/* HV */
159962306a36Sopenharmony_ci	{0x43, 0xf0},			/* RSVD.. */
160062306a36Sopenharmony_ci	{0x44, 0x10},
160162306a36Sopenharmony_ci	{0x45, 0x78},
160262306a36Sopenharmony_ci	{0x46, 0xa8},
160362306a36Sopenharmony_ci	{0x47, 0x60},
160462306a36Sopenharmony_ci	{0x48, 0x80},
160562306a36Sopenharmony_ci	{0x59, 0xba},
160662306a36Sopenharmony_ci	{0x5a, 0x9a},
160762306a36Sopenharmony_ci	{0x5b, 0x22},
160862306a36Sopenharmony_ci	{0x5c, 0xb9},
160962306a36Sopenharmony_ci	{0x5d, 0x9b},
161062306a36Sopenharmony_ci	{0x5e, 0x10},
161162306a36Sopenharmony_ci	{0x5f, 0xe0},
161262306a36Sopenharmony_ci	{0x60, 0x85},
161362306a36Sopenharmony_ci	{0x61, 0x60},
161462306a36Sopenharmony_ci	{0x9f, 0x9d},			/* RSVD */
161562306a36Sopenharmony_ci	{0xa0, 0xa0},			/* DSPC2 */
161662306a36Sopenharmony_ci	{0x4f, 0x60},			/* matrix */
161762306a36Sopenharmony_ci	{0x50, 0x64},
161862306a36Sopenharmony_ci	{0x51, 0x04},
161962306a36Sopenharmony_ci	{0x52, 0x18},
162062306a36Sopenharmony_ci	{0x53, 0x3c},
162162306a36Sopenharmony_ci	{0x54, 0x54},
162262306a36Sopenharmony_ci	{0x55, 0x40},
162362306a36Sopenharmony_ci	{0x56, 0x40},
162462306a36Sopenharmony_ci	{0x57, 0x40},
162562306a36Sopenharmony_ci	{0x58, 0x0d},			/* matrix sign */
162662306a36Sopenharmony_ci	{0x8b, 0xcc},			/* RSVD */
162762306a36Sopenharmony_ci	{0x8c, 0xcc},
162862306a36Sopenharmony_ci	{0x8d, 0xcf},
162962306a36Sopenharmony_ci	{0x6c, 0x40},			/* gamma curve */
163062306a36Sopenharmony_ci	{0x6d, 0xe0},
163162306a36Sopenharmony_ci	{0x6e, 0xa0},
163262306a36Sopenharmony_ci	{0x6f, 0x80},
163362306a36Sopenharmony_ci	{0x70, 0x70},
163462306a36Sopenharmony_ci	{0x71, 0x80},
163562306a36Sopenharmony_ci	{0x72, 0x60},
163662306a36Sopenharmony_ci	{0x73, 0x60},
163762306a36Sopenharmony_ci	{0x74, 0x50},
163862306a36Sopenharmony_ci	{0x75, 0x40},
163962306a36Sopenharmony_ci	{0x76, 0x38},
164062306a36Sopenharmony_ci	{0x77, 0x3c},
164162306a36Sopenharmony_ci	{0x78, 0x32},
164262306a36Sopenharmony_ci	{0x79, 0x1a},
164362306a36Sopenharmony_ci	{0x7a, 0x28},
164462306a36Sopenharmony_ci	{0x7b, 0x24},
164562306a36Sopenharmony_ci	{0x7c, 0x04},			/* gamma curve */
164662306a36Sopenharmony_ci	{0x7d, 0x12},
164762306a36Sopenharmony_ci	{0x7e, 0x26},
164862306a36Sopenharmony_ci	{0x7f, 0x46},
164962306a36Sopenharmony_ci	{0x80, 0x54},
165062306a36Sopenharmony_ci	{0x81, 0x64},
165162306a36Sopenharmony_ci	{0x82, 0x70},
165262306a36Sopenharmony_ci	{0x83, 0x7c},
165362306a36Sopenharmony_ci	{0x84, 0x86},
165462306a36Sopenharmony_ci	{0x85, 0x8e},
165562306a36Sopenharmony_ci	{0x86, 0x9c},
165662306a36Sopenharmony_ci	{0x87, 0xab},
165762306a36Sopenharmony_ci	{0x88, 0xc4},
165862306a36Sopenharmony_ci	{0x89, 0xd1},
165962306a36Sopenharmony_ci	{0x8a, 0xe5},
166062306a36Sopenharmony_ci	{OV7670_R14_COM9, 0x1e},
166162306a36Sopenharmony_ci	{OV7670_R24_AEW, 0x80},
166262306a36Sopenharmony_ci	{OV7670_R25_AEB, 0x72},
166362306a36Sopenharmony_ci	{OV7670_R26_VPT, 0xb3},
166462306a36Sopenharmony_ci	{0x62, 0x80},			/* LCC1 */
166562306a36Sopenharmony_ci	{0x63, 0x80},			/* LCC2 */
166662306a36Sopenharmony_ci	{0x64, 0x06},			/* LCC3 */
166762306a36Sopenharmony_ci	{0x65, 0x00},			/* LCC4 */
166862306a36Sopenharmony_ci	{0x66, 0x01},			/* LCC5 */
166962306a36Sopenharmony_ci	{0x94, 0x0e},			/* RSVD.. */
167062306a36Sopenharmony_ci	{0x95, 0x14},
167162306a36Sopenharmony_ci	{OV7670_R13_COM8, OV7670_COM8_FASTAEC
167262306a36Sopenharmony_ci			| OV7670_COM8_AECSTEP
167362306a36Sopenharmony_ci			| OV7670_COM8_BFILT
167462306a36Sopenharmony_ci			| 0x10
167562306a36Sopenharmony_ci			| OV7670_COM8_AGC
167662306a36Sopenharmony_ci			| OV7670_COM8_AWB
167762306a36Sopenharmony_ci			| OV7670_COM8_AEC},
167862306a36Sopenharmony_ci	{0xa1, 0xc8}
167962306a36Sopenharmony_ci};
168062306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_9600[] = {
168162306a36Sopenharmony_ci	{0x12, 0x80},
168262306a36Sopenharmony_ci	{0x0c, 0x28},
168362306a36Sopenharmony_ci	{0x11, 0x80},
168462306a36Sopenharmony_ci	{0x13, 0xb5},
168562306a36Sopenharmony_ci	{0x14, 0x3e},
168662306a36Sopenharmony_ci	{0x1b, 0x04},
168762306a36Sopenharmony_ci	{0x24, 0xb0},
168862306a36Sopenharmony_ci	{0x25, 0x90},
168962306a36Sopenharmony_ci	{0x26, 0x94},
169062306a36Sopenharmony_ci	{0x35, 0x90},
169162306a36Sopenharmony_ci	{0x37, 0x07},
169262306a36Sopenharmony_ci	{0x38, 0x08},
169362306a36Sopenharmony_ci	{0x01, 0x8e},
169462306a36Sopenharmony_ci	{0x02, 0x85}
169562306a36Sopenharmony_ci};
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci/* 7670. Defaults taken from OmniVision provided data,
169862306a36Sopenharmony_ci*  as provided by Jonathan Corbet of OLPC		*/
169962306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_7670[] = {
170062306a36Sopenharmony_ci	{ OV7670_R12_COM7, OV7670_COM7_RESET },
170162306a36Sopenharmony_ci	{ OV7670_R3A_TSLB, 0x04 },		/* OV */
170262306a36Sopenharmony_ci	{ OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
170362306a36Sopenharmony_ci	{ OV7670_R11_CLKRC, 0x01 },
170462306a36Sopenharmony_ci/*
170562306a36Sopenharmony_ci * Set the hardware window.  These values from OV don't entirely
170662306a36Sopenharmony_ci * make sense - hstop is less than hstart.  But they work...
170762306a36Sopenharmony_ci */
170862306a36Sopenharmony_ci	{ OV7670_R17_HSTART, 0x13 },
170962306a36Sopenharmony_ci	{ OV7670_R18_HSTOP, 0x01 },
171062306a36Sopenharmony_ci	{ OV7670_R32_HREF, 0xb6 },
171162306a36Sopenharmony_ci	{ OV7670_R19_VSTART, 0x02 },
171262306a36Sopenharmony_ci	{ OV7670_R1A_VSTOP, 0x7a },
171362306a36Sopenharmony_ci	{ OV7670_R03_VREF, 0x0a },
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	{ OV7670_R0C_COM3, 0x00 },
171662306a36Sopenharmony_ci	{ OV7670_R3E_COM14, 0x00 },
171762306a36Sopenharmony_ci/* Mystery scaling numbers */
171862306a36Sopenharmony_ci	{ 0x70, 0x3a },
171962306a36Sopenharmony_ci	{ 0x71, 0x35 },
172062306a36Sopenharmony_ci	{ 0x72, 0x11 },
172162306a36Sopenharmony_ci	{ 0x73, 0xf0 },
172262306a36Sopenharmony_ci	{ 0xa2, 0x02 },
172362306a36Sopenharmony_ci/*	{ OV7670_R15_COM10, 0x0 }, */
172462306a36Sopenharmony_ci
172562306a36Sopenharmony_ci/* Gamma curve values */
172662306a36Sopenharmony_ci	{ 0x7a, 0x20 },
172762306a36Sopenharmony_ci	{ 0x7b, 0x10 },
172862306a36Sopenharmony_ci	{ 0x7c, 0x1e },
172962306a36Sopenharmony_ci	{ 0x7d, 0x35 },
173062306a36Sopenharmony_ci	{ 0x7e, 0x5a },
173162306a36Sopenharmony_ci	{ 0x7f, 0x69 },
173262306a36Sopenharmony_ci	{ 0x80, 0x76 },
173362306a36Sopenharmony_ci	{ 0x81, 0x80 },
173462306a36Sopenharmony_ci	{ 0x82, 0x88 },
173562306a36Sopenharmony_ci	{ 0x83, 0x8f },
173662306a36Sopenharmony_ci	{ 0x84, 0x96 },
173762306a36Sopenharmony_ci	{ 0x85, 0xa3 },
173862306a36Sopenharmony_ci	{ 0x86, 0xaf },
173962306a36Sopenharmony_ci	{ 0x87, 0xc4 },
174062306a36Sopenharmony_ci	{ 0x88, 0xd7 },
174162306a36Sopenharmony_ci	{ 0x89, 0xe8 },
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci/* AGC and AEC parameters.  Note we start by disabling those features,
174462306a36Sopenharmony_ci   then turn them only after tweaking the values. */
174562306a36Sopenharmony_ci	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
174662306a36Sopenharmony_ci			 | OV7670_COM8_AECSTEP
174762306a36Sopenharmony_ci			 | OV7670_COM8_BFILT },
174862306a36Sopenharmony_ci	{ OV7670_R00_GAIN, 0x00 },
174962306a36Sopenharmony_ci	{ OV7670_R10_AECH, 0x00 },
175062306a36Sopenharmony_ci	{ OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
175162306a36Sopenharmony_ci	{ OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
175262306a36Sopenharmony_ci	{ OV7670_RA5_BD50MAX, 0x05 },
175362306a36Sopenharmony_ci	{ OV7670_RAB_BD60MAX, 0x07 },
175462306a36Sopenharmony_ci	{ OV7670_R24_AEW, 0x95 },
175562306a36Sopenharmony_ci	{ OV7670_R25_AEB, 0x33 },
175662306a36Sopenharmony_ci	{ OV7670_R26_VPT, 0xe3 },
175762306a36Sopenharmony_ci	{ OV7670_R9F_HAECC1, 0x78 },
175862306a36Sopenharmony_ci	{ OV7670_RA0_HAECC2, 0x68 },
175962306a36Sopenharmony_ci	{ 0xa1, 0x03 }, /* magic */
176062306a36Sopenharmony_ci	{ OV7670_RA6_HAECC3, 0xd8 },
176162306a36Sopenharmony_ci	{ OV7670_RA7_HAECC4, 0xd8 },
176262306a36Sopenharmony_ci	{ OV7670_RA8_HAECC5, 0xf0 },
176362306a36Sopenharmony_ci	{ OV7670_RA9_HAECC6, 0x90 },
176462306a36Sopenharmony_ci	{ OV7670_RAA_HAECC7, 0x94 },
176562306a36Sopenharmony_ci	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
176662306a36Sopenharmony_ci			| OV7670_COM8_AECSTEP
176762306a36Sopenharmony_ci			| OV7670_COM8_BFILT
176862306a36Sopenharmony_ci			| OV7670_COM8_AGC
176962306a36Sopenharmony_ci			| OV7670_COM8_AEC },
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci/* Almost all of these are magic "reserved" values.  */
177262306a36Sopenharmony_ci	{ OV7670_R0E_COM5, 0x61 },
177362306a36Sopenharmony_ci	{ OV7670_R0F_COM6, 0x4b },
177462306a36Sopenharmony_ci	{ 0x16, 0x02 },
177562306a36Sopenharmony_ci	{ OV7670_R1E_MVFP, 0x07 },
177662306a36Sopenharmony_ci	{ 0x21, 0x02 },
177762306a36Sopenharmony_ci	{ 0x22, 0x91 },
177862306a36Sopenharmony_ci	{ 0x29, 0x07 },
177962306a36Sopenharmony_ci	{ 0x33, 0x0b },
178062306a36Sopenharmony_ci	{ 0x35, 0x0b },
178162306a36Sopenharmony_ci	{ 0x37, 0x1d },
178262306a36Sopenharmony_ci	{ 0x38, 0x71 },
178362306a36Sopenharmony_ci	{ 0x39, 0x2a },
178462306a36Sopenharmony_ci	{ OV7670_R3C_COM12, 0x78 },
178562306a36Sopenharmony_ci	{ 0x4d, 0x40 },
178662306a36Sopenharmony_ci	{ 0x4e, 0x20 },
178762306a36Sopenharmony_ci	{ OV7670_R69_GFIX, 0x00 },
178862306a36Sopenharmony_ci	{ 0x6b, 0x4a },
178962306a36Sopenharmony_ci	{ 0x74, 0x10 },
179062306a36Sopenharmony_ci	{ 0x8d, 0x4f },
179162306a36Sopenharmony_ci	{ 0x8e, 0x00 },
179262306a36Sopenharmony_ci	{ 0x8f, 0x00 },
179362306a36Sopenharmony_ci	{ 0x90, 0x00 },
179462306a36Sopenharmony_ci	{ 0x91, 0x00 },
179562306a36Sopenharmony_ci	{ 0x96, 0x00 },
179662306a36Sopenharmony_ci	{ 0x9a, 0x00 },
179762306a36Sopenharmony_ci	{ 0xb0, 0x84 },
179862306a36Sopenharmony_ci	{ 0xb1, 0x0c },
179962306a36Sopenharmony_ci	{ 0xb2, 0x0e },
180062306a36Sopenharmony_ci	{ 0xb3, 0x82 },
180162306a36Sopenharmony_ci	{ 0xb8, 0x0a },
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci/* More reserved magic, some of which tweaks white balance */
180462306a36Sopenharmony_ci	{ 0x43, 0x0a },
180562306a36Sopenharmony_ci	{ 0x44, 0xf0 },
180662306a36Sopenharmony_ci	{ 0x45, 0x34 },
180762306a36Sopenharmony_ci	{ 0x46, 0x58 },
180862306a36Sopenharmony_ci	{ 0x47, 0x28 },
180962306a36Sopenharmony_ci	{ 0x48, 0x3a },
181062306a36Sopenharmony_ci	{ 0x59, 0x88 },
181162306a36Sopenharmony_ci	{ 0x5a, 0x88 },
181262306a36Sopenharmony_ci	{ 0x5b, 0x44 },
181362306a36Sopenharmony_ci	{ 0x5c, 0x67 },
181462306a36Sopenharmony_ci	{ 0x5d, 0x49 },
181562306a36Sopenharmony_ci	{ 0x5e, 0x0e },
181662306a36Sopenharmony_ci	{ 0x6c, 0x0a },
181762306a36Sopenharmony_ci	{ 0x6d, 0x55 },
181862306a36Sopenharmony_ci	{ 0x6e, 0x11 },
181962306a36Sopenharmony_ci	{ 0x6f, 0x9f },			/* "9e for advance AWB" */
182062306a36Sopenharmony_ci	{ 0x6a, 0x40 },
182162306a36Sopenharmony_ci	{ OV7670_R01_BLUE, 0x40 },
182262306a36Sopenharmony_ci	{ OV7670_R02_RED, 0x60 },
182362306a36Sopenharmony_ci	{ OV7670_R13_COM8, OV7670_COM8_FASTAEC
182462306a36Sopenharmony_ci			| OV7670_COM8_AECSTEP
182562306a36Sopenharmony_ci			| OV7670_COM8_BFILT
182662306a36Sopenharmony_ci			| OV7670_COM8_AGC
182762306a36Sopenharmony_ci			| OV7670_COM8_AEC
182862306a36Sopenharmony_ci			| OV7670_COM8_AWB },
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci/* Matrix coefficients */
183162306a36Sopenharmony_ci	{ 0x4f, 0x80 },
183262306a36Sopenharmony_ci	{ 0x50, 0x80 },
183362306a36Sopenharmony_ci	{ 0x51, 0x00 },
183462306a36Sopenharmony_ci	{ 0x52, 0x22 },
183562306a36Sopenharmony_ci	{ 0x53, 0x5e },
183662306a36Sopenharmony_ci	{ 0x54, 0x80 },
183762306a36Sopenharmony_ci	{ 0x58, 0x9e },
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci	{ OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
184062306a36Sopenharmony_ci	{ OV7670_R3F_EDGE, 0x00 },
184162306a36Sopenharmony_ci	{ 0x75, 0x05 },
184262306a36Sopenharmony_ci	{ 0x76, 0xe1 },
184362306a36Sopenharmony_ci	{ 0x4c, 0x00 },
184462306a36Sopenharmony_ci	{ 0x77, 0x01 },
184562306a36Sopenharmony_ci	{ OV7670_R3D_COM13, OV7670_COM13_GAMMA
184662306a36Sopenharmony_ci			  | OV7670_COM13_UVSAT
184762306a36Sopenharmony_ci			  | 2},		/* was 3 */
184862306a36Sopenharmony_ci	{ 0x4b, 0x09 },
184962306a36Sopenharmony_ci	{ 0xc9, 0x60 },
185062306a36Sopenharmony_ci	{ OV7670_R41_COM16, 0x38 },
185162306a36Sopenharmony_ci	{ 0x56, 0x40 },
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	{ 0x34, 0x11 },
185462306a36Sopenharmony_ci	{ OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
185562306a36Sopenharmony_ci	{ 0xa4, 0x88 },
185662306a36Sopenharmony_ci	{ 0x96, 0x00 },
185762306a36Sopenharmony_ci	{ 0x97, 0x30 },
185862306a36Sopenharmony_ci	{ 0x98, 0x20 },
185962306a36Sopenharmony_ci	{ 0x99, 0x30 },
186062306a36Sopenharmony_ci	{ 0x9a, 0x84 },
186162306a36Sopenharmony_ci	{ 0x9b, 0x29 },
186262306a36Sopenharmony_ci	{ 0x9c, 0x03 },
186362306a36Sopenharmony_ci	{ 0x9d, 0x4c },
186462306a36Sopenharmony_ci	{ 0x9e, 0x3f },
186562306a36Sopenharmony_ci	{ 0x78, 0x04 },
186662306a36Sopenharmony_ci
186762306a36Sopenharmony_ci/* Extra-weird stuff.  Some sort of multiplexor register */
186862306a36Sopenharmony_ci	{ 0x79, 0x01 },
186962306a36Sopenharmony_ci	{ 0xc8, 0xf0 },
187062306a36Sopenharmony_ci	{ 0x79, 0x0f },
187162306a36Sopenharmony_ci	{ 0xc8, 0x00 },
187262306a36Sopenharmony_ci	{ 0x79, 0x10 },
187362306a36Sopenharmony_ci	{ 0xc8, 0x7e },
187462306a36Sopenharmony_ci	{ 0x79, 0x0a },
187562306a36Sopenharmony_ci	{ 0xc8, 0x80 },
187662306a36Sopenharmony_ci	{ 0x79, 0x0b },
187762306a36Sopenharmony_ci	{ 0xc8, 0x01 },
187862306a36Sopenharmony_ci	{ 0x79, 0x0c },
187962306a36Sopenharmony_ci	{ 0xc8, 0x0f },
188062306a36Sopenharmony_ci	{ 0x79, 0x0d },
188162306a36Sopenharmony_ci	{ 0xc8, 0x20 },
188262306a36Sopenharmony_ci	{ 0x79, 0x09 },
188362306a36Sopenharmony_ci	{ 0xc8, 0x80 },
188462306a36Sopenharmony_ci	{ 0x79, 0x02 },
188562306a36Sopenharmony_ci	{ 0xc8, 0xc0 },
188662306a36Sopenharmony_ci	{ 0x79, 0x03 },
188762306a36Sopenharmony_ci	{ 0xc8, 0x40 },
188862306a36Sopenharmony_ci	{ 0x79, 0x05 },
188962306a36Sopenharmony_ci	{ 0xc8, 0x30 },
189062306a36Sopenharmony_ci	{ 0x79, 0x26 },
189162306a36Sopenharmony_ci};
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_cistatic const struct ov_i2c_regvals norm_8610[] = {
189462306a36Sopenharmony_ci	{ 0x12, 0x80 },
189562306a36Sopenharmony_ci	{ 0x00, 0x00 },
189662306a36Sopenharmony_ci	{ 0x01, 0x80 },
189762306a36Sopenharmony_ci	{ 0x02, 0x80 },
189862306a36Sopenharmony_ci	{ 0x03, 0xc0 },
189962306a36Sopenharmony_ci	{ 0x04, 0x30 },
190062306a36Sopenharmony_ci	{ 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
190162306a36Sopenharmony_ci	{ 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
190262306a36Sopenharmony_ci	{ 0x0a, 0x86 },
190362306a36Sopenharmony_ci	{ 0x0b, 0xb0 },
190462306a36Sopenharmony_ci	{ 0x0c, 0x20 },
190562306a36Sopenharmony_ci	{ 0x0d, 0x20 },
190662306a36Sopenharmony_ci	{ 0x11, 0x01 },
190762306a36Sopenharmony_ci	{ 0x12, 0x25 },
190862306a36Sopenharmony_ci	{ 0x13, 0x01 },
190962306a36Sopenharmony_ci	{ 0x14, 0x04 },
191062306a36Sopenharmony_ci	{ 0x15, 0x01 }, /* Lin and Win think different about UV order */
191162306a36Sopenharmony_ci	{ 0x16, 0x03 },
191262306a36Sopenharmony_ci	{ 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
191362306a36Sopenharmony_ci	{ 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
191462306a36Sopenharmony_ci	{ 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
191562306a36Sopenharmony_ci	{ 0x1a, 0xf5 },
191662306a36Sopenharmony_ci	{ 0x1b, 0x00 },
191762306a36Sopenharmony_ci	{ 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
191862306a36Sopenharmony_ci	{ 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
191962306a36Sopenharmony_ci	{ 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
192062306a36Sopenharmony_ci	{ 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
192162306a36Sopenharmony_ci	{ 0x26, 0xa2 },
192262306a36Sopenharmony_ci	{ 0x27, 0xea },
192362306a36Sopenharmony_ci	{ 0x28, 0x00 },
192462306a36Sopenharmony_ci	{ 0x29, 0x00 },
192562306a36Sopenharmony_ci	{ 0x2a, 0x80 },
192662306a36Sopenharmony_ci	{ 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
192762306a36Sopenharmony_ci	{ 0x2c, 0xac },
192862306a36Sopenharmony_ci	{ 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
192962306a36Sopenharmony_ci	{ 0x2e, 0x80 },
193062306a36Sopenharmony_ci	{ 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
193162306a36Sopenharmony_ci	{ 0x4c, 0x00 },
193262306a36Sopenharmony_ci	{ 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
193362306a36Sopenharmony_ci	{ 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
193462306a36Sopenharmony_ci	{ 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
193562306a36Sopenharmony_ci	{ 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
193662306a36Sopenharmony_ci	{ 0x63, 0xff },
193762306a36Sopenharmony_ci	{ 0x64, 0x53 }, /* new windrv 090403 says 0x57,
193862306a36Sopenharmony_ci			 * maybe that's wrong */
193962306a36Sopenharmony_ci	{ 0x65, 0x00 },
194062306a36Sopenharmony_ci	{ 0x66, 0x55 },
194162306a36Sopenharmony_ci	{ 0x67, 0xb0 },
194262306a36Sopenharmony_ci	{ 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
194362306a36Sopenharmony_ci	{ 0x69, 0x02 },
194462306a36Sopenharmony_ci	{ 0x6a, 0x22 },
194562306a36Sopenharmony_ci	{ 0x6b, 0x00 },
194662306a36Sopenharmony_ci	{ 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
194762306a36Sopenharmony_ci			 * deleting bit7 colors the first images red */
194862306a36Sopenharmony_ci	{ 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
194962306a36Sopenharmony_ci	{ 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
195062306a36Sopenharmony_ci	{ 0x6f, 0x01 },
195162306a36Sopenharmony_ci	{ 0x70, 0x8b },
195262306a36Sopenharmony_ci	{ 0x71, 0x00 },
195362306a36Sopenharmony_ci	{ 0x72, 0x14 },
195462306a36Sopenharmony_ci	{ 0x73, 0x54 },
195562306a36Sopenharmony_ci	{ 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
195662306a36Sopenharmony_ci	{ 0x75, 0x0e },
195762306a36Sopenharmony_ci	{ 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
195862306a36Sopenharmony_ci	{ 0x77, 0xff },
195962306a36Sopenharmony_ci	{ 0x78, 0x80 },
196062306a36Sopenharmony_ci	{ 0x79, 0x80 },
196162306a36Sopenharmony_ci	{ 0x7a, 0x80 },
196262306a36Sopenharmony_ci	{ 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
196362306a36Sopenharmony_ci	{ 0x7c, 0x00 },
196462306a36Sopenharmony_ci	{ 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
196562306a36Sopenharmony_ci	{ 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
196662306a36Sopenharmony_ci	{ 0x7f, 0xfb },
196762306a36Sopenharmony_ci	{ 0x80, 0x28 },
196862306a36Sopenharmony_ci	{ 0x81, 0x00 },
196962306a36Sopenharmony_ci	{ 0x82, 0x23 },
197062306a36Sopenharmony_ci	{ 0x83, 0x0b },
197162306a36Sopenharmony_ci	{ 0x84, 0x00 },
197262306a36Sopenharmony_ci	{ 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
197362306a36Sopenharmony_ci	{ 0x86, 0xc9 },
197462306a36Sopenharmony_ci	{ 0x87, 0x00 },
197562306a36Sopenharmony_ci	{ 0x88, 0x00 },
197662306a36Sopenharmony_ci	{ 0x89, 0x01 },
197762306a36Sopenharmony_ci	{ 0x12, 0x20 },
197862306a36Sopenharmony_ci	{ 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
197962306a36Sopenharmony_ci};
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_cistatic unsigned char ov7670_abs_to_sm(unsigned char v)
198262306a36Sopenharmony_ci{
198362306a36Sopenharmony_ci	if (v > 127)
198462306a36Sopenharmony_ci		return v & 0x7f;
198562306a36Sopenharmony_ci	return (128 - v) | 0x80;
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_ci/* Write a OV519 register */
198962306a36Sopenharmony_cistatic void reg_w(struct sd *sd, u16 index, u16 value)
199062306a36Sopenharmony_ci{
199162306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
199262306a36Sopenharmony_ci	int ret, req = 0;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
199562306a36Sopenharmony_ci		return;
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	/* Avoid things going to fast for the bridge with a xhci host */
199862306a36Sopenharmony_ci	udelay(150);
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	switch (sd->bridge) {
200162306a36Sopenharmony_ci	case BRIDGE_OV511:
200262306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
200362306a36Sopenharmony_ci		req = 2;
200462306a36Sopenharmony_ci		break;
200562306a36Sopenharmony_ci	case BRIDGE_OVFX2:
200662306a36Sopenharmony_ci		req = 0x0a;
200762306a36Sopenharmony_ci		fallthrough;
200862306a36Sopenharmony_ci	case BRIDGE_W9968CF:
200962306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_USBO, "SET %02x %04x %04x\n",
201062306a36Sopenharmony_ci			  req, value, index);
201162306a36Sopenharmony_ci		ret = usb_control_msg(sd->gspca_dev.dev,
201262306a36Sopenharmony_ci			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
201362306a36Sopenharmony_ci			req,
201462306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
201562306a36Sopenharmony_ci			value, index, NULL, 0, 500);
201662306a36Sopenharmony_ci		goto leave;
201762306a36Sopenharmony_ci	default:
201862306a36Sopenharmony_ci		req = 1;
201962306a36Sopenharmony_ci	}
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "SET %02x 0000 %04x %02x\n",
202262306a36Sopenharmony_ci		  req, index, value);
202362306a36Sopenharmony_ci	sd->gspca_dev.usb_buf[0] = value;
202462306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
202562306a36Sopenharmony_ci			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
202662306a36Sopenharmony_ci			req,
202762306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
202862306a36Sopenharmony_ci			0, index,
202962306a36Sopenharmony_ci			sd->gspca_dev.usb_buf, 1, 500);
203062306a36Sopenharmony_cileave:
203162306a36Sopenharmony_ci	if (ret < 0) {
203262306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_w %02x failed %d\n", index, ret);
203362306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
203462306a36Sopenharmony_ci		return;
203562306a36Sopenharmony_ci	}
203662306a36Sopenharmony_ci}
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci/* Read from a OV519 register, note not valid for the w9968cf!! */
203962306a36Sopenharmony_ci/* returns: negative is error, pos or zero is data */
204062306a36Sopenharmony_cistatic int reg_r(struct sd *sd, u16 index)
204162306a36Sopenharmony_ci{
204262306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
204362306a36Sopenharmony_ci	int ret;
204462306a36Sopenharmony_ci	int req;
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
204762306a36Sopenharmony_ci		return -1;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	switch (sd->bridge) {
205062306a36Sopenharmony_ci	case BRIDGE_OV511:
205162306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
205262306a36Sopenharmony_ci		req = 3;
205362306a36Sopenharmony_ci		break;
205462306a36Sopenharmony_ci	case BRIDGE_OVFX2:
205562306a36Sopenharmony_ci		req = 0x0b;
205662306a36Sopenharmony_ci		break;
205762306a36Sopenharmony_ci	default:
205862306a36Sopenharmony_ci		req = 1;
205962306a36Sopenharmony_ci	}
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci	/* Avoid things going to fast for the bridge with a xhci host */
206262306a36Sopenharmony_ci	udelay(150);
206362306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
206462306a36Sopenharmony_ci			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
206562306a36Sopenharmony_ci			req,
206662306a36Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
206762306a36Sopenharmony_ci			0, index, sd->gspca_dev.usb_buf, 1, 500);
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	if (ret >= 0) {
207062306a36Sopenharmony_ci		ret = sd->gspca_dev.usb_buf[0];
207162306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_USBI, "GET %02x 0000 %04x %02x\n",
207262306a36Sopenharmony_ci			  req, index, ret);
207362306a36Sopenharmony_ci	} else {
207462306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_r %02x failed %d\n", index, ret);
207562306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
207662306a36Sopenharmony_ci		/*
207762306a36Sopenharmony_ci		 * Make sure the result is zeroed to avoid uninitialized
207862306a36Sopenharmony_ci		 * values.
207962306a36Sopenharmony_ci		 */
208062306a36Sopenharmony_ci		gspca_dev->usb_buf[0] = 0;
208162306a36Sopenharmony_ci	}
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	return ret;
208462306a36Sopenharmony_ci}
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_ci/* Read 8 values from a OV519 register */
208762306a36Sopenharmony_cistatic int reg_r8(struct sd *sd,
208862306a36Sopenharmony_ci		  u16 index)
208962306a36Sopenharmony_ci{
209062306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
209162306a36Sopenharmony_ci	int ret;
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
209462306a36Sopenharmony_ci		return -1;
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci	/* Avoid things going to fast for the bridge with a xhci host */
209762306a36Sopenharmony_ci	udelay(150);
209862306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
209962306a36Sopenharmony_ci			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
210062306a36Sopenharmony_ci			1,			/* REQ_IO */
210162306a36Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
210262306a36Sopenharmony_ci			0, index, sd->gspca_dev.usb_buf, 8, 500);
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	if (ret >= 0) {
210562306a36Sopenharmony_ci		ret = sd->gspca_dev.usb_buf[0];
210662306a36Sopenharmony_ci	} else {
210762306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_r8 %02x failed %d\n", index, ret);
210862306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
210962306a36Sopenharmony_ci		/*
211062306a36Sopenharmony_ci		 * Make sure the buffer is zeroed to avoid uninitialized
211162306a36Sopenharmony_ci		 * values.
211262306a36Sopenharmony_ci		 */
211362306a36Sopenharmony_ci		memset(gspca_dev->usb_buf, 0, 8);
211462306a36Sopenharmony_ci	}
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	return ret;
211762306a36Sopenharmony_ci}
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_ci/*
212062306a36Sopenharmony_ci * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
212162306a36Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits
212262306a36Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless
212362306a36Sopenharmony_ci * of their respective state in "value".
212462306a36Sopenharmony_ci */
212562306a36Sopenharmony_cistatic void reg_w_mask(struct sd *sd,
212662306a36Sopenharmony_ci			u16 index,
212762306a36Sopenharmony_ci			u8 value,
212862306a36Sopenharmony_ci			u8 mask)
212962306a36Sopenharmony_ci{
213062306a36Sopenharmony_ci	int ret;
213162306a36Sopenharmony_ci	u8 oldval;
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci	if (mask != 0xff) {
213462306a36Sopenharmony_ci		value &= mask;			/* Enforce mask on value */
213562306a36Sopenharmony_ci		ret = reg_r(sd, index);
213662306a36Sopenharmony_ci		if (ret < 0)
213762306a36Sopenharmony_ci			return;
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci		oldval = ret & ~mask;		/* Clear the masked bits */
214062306a36Sopenharmony_ci		value |= oldval;		/* Set the desired bits */
214162306a36Sopenharmony_ci	}
214262306a36Sopenharmony_ci	reg_w(sd, index, value);
214362306a36Sopenharmony_ci}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci/*
214662306a36Sopenharmony_ci * Writes multiple (n) byte value to a single register. Only valid with certain
214762306a36Sopenharmony_ci * registers (0x30 and 0xc4 - 0xce).
214862306a36Sopenharmony_ci */
214962306a36Sopenharmony_cistatic void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
215062306a36Sopenharmony_ci{
215162306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
215262306a36Sopenharmony_ci	int ret;
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
215562306a36Sopenharmony_ci		return;
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	*((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	/* Avoid things going to fast for the bridge with a xhci host */
216062306a36Sopenharmony_ci	udelay(150);
216162306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
216262306a36Sopenharmony_ci			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
216362306a36Sopenharmony_ci			1 /* REG_IO */,
216462306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
216562306a36Sopenharmony_ci			0, index,
216662306a36Sopenharmony_ci			sd->gspca_dev.usb_buf, n, 500);
216762306a36Sopenharmony_ci	if (ret < 0) {
216862306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_w32 %02x failed %d\n", index, ret);
216962306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
217062306a36Sopenharmony_ci	}
217162306a36Sopenharmony_ci}
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_cistatic void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
217462306a36Sopenharmony_ci{
217562306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
217662306a36Sopenharmony_ci	int rc, retries;
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "ov511_i2c_w %02x %02x\n", reg, value);
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci	/* Three byte write cycle */
218162306a36Sopenharmony_ci	for (retries = 6; ; ) {
218262306a36Sopenharmony_ci		/* Select camera register */
218362306a36Sopenharmony_ci		reg_w(sd, R51x_I2C_SADDR_3, reg);
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci		/* Write "value" to I2C data port of OV511 */
218662306a36Sopenharmony_ci		reg_w(sd, R51x_I2C_DATA, value);
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci		/* Initiate 3-byte write cycle */
218962306a36Sopenharmony_ci		reg_w(sd, R511_I2C_CTL, 0x01);
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci		do {
219262306a36Sopenharmony_ci			rc = reg_r(sd, R511_I2C_CTL);
219362306a36Sopenharmony_ci		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci		if (rc < 0)
219662306a36Sopenharmony_ci			return;
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci		if ((rc & 2) == 0) /* Ack? */
219962306a36Sopenharmony_ci			break;
220062306a36Sopenharmony_ci		if (--retries < 0) {
220162306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_USBO, "i2c write retries exhausted\n");
220262306a36Sopenharmony_ci			return;
220362306a36Sopenharmony_ci		}
220462306a36Sopenharmony_ci	}
220562306a36Sopenharmony_ci}
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_cistatic int ov511_i2c_r(struct sd *sd, u8 reg)
220862306a36Sopenharmony_ci{
220962306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
221062306a36Sopenharmony_ci	int rc, value, retries;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	/* Two byte write cycle */
221362306a36Sopenharmony_ci	for (retries = 6; ; ) {
221462306a36Sopenharmony_ci		/* Select camera register */
221562306a36Sopenharmony_ci		reg_w(sd, R51x_I2C_SADDR_2, reg);
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci		/* Initiate 2-byte write cycle */
221862306a36Sopenharmony_ci		reg_w(sd, R511_I2C_CTL, 0x03);
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_ci		do {
222162306a36Sopenharmony_ci			rc = reg_r(sd, R511_I2C_CTL);
222262306a36Sopenharmony_ci		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
222362306a36Sopenharmony_ci
222462306a36Sopenharmony_ci		if (rc < 0)
222562306a36Sopenharmony_ci			return rc;
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_ci		if ((rc & 2) == 0) /* Ack? */
222862306a36Sopenharmony_ci			break;
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci		/* I2C abort */
223162306a36Sopenharmony_ci		reg_w(sd, R511_I2C_CTL, 0x10);
223262306a36Sopenharmony_ci
223362306a36Sopenharmony_ci		if (--retries < 0) {
223462306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_USBI, "i2c write retries exhausted\n");
223562306a36Sopenharmony_ci			return -1;
223662306a36Sopenharmony_ci		}
223762306a36Sopenharmony_ci	}
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci	/* Two byte read cycle */
224062306a36Sopenharmony_ci	for (retries = 6; ; ) {
224162306a36Sopenharmony_ci		/* Initiate 2-byte read cycle */
224262306a36Sopenharmony_ci		reg_w(sd, R511_I2C_CTL, 0x05);
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci		do {
224562306a36Sopenharmony_ci			rc = reg_r(sd, R511_I2C_CTL);
224662306a36Sopenharmony_ci		} while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci		if (rc < 0)
224962306a36Sopenharmony_ci			return rc;
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci		if ((rc & 2) == 0) /* Ack? */
225262306a36Sopenharmony_ci			break;
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_ci		/* I2C abort */
225562306a36Sopenharmony_ci		reg_w(sd, R511_I2C_CTL, 0x10);
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci		if (--retries < 0) {
225862306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_USBI, "i2c read retries exhausted\n");
225962306a36Sopenharmony_ci			return -1;
226062306a36Sopenharmony_ci		}
226162306a36Sopenharmony_ci	}
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	value = reg_r(sd, R51x_I2C_DATA);
226462306a36Sopenharmony_ci
226562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBI, "ov511_i2c_r %02x %02x\n", reg, value);
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	/* This is needed to make i2c_w() work */
226862306a36Sopenharmony_ci	reg_w(sd, R511_I2C_CTL, 0x05);
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_ci	return value;
227162306a36Sopenharmony_ci}
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci/*
227462306a36Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function.
227562306a36Sopenharmony_ci * This is normally only called from i2c_w(). Note that this function
227662306a36Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working.
227762306a36Sopenharmony_ci */
227862306a36Sopenharmony_cistatic void ov518_i2c_w(struct sd *sd,
227962306a36Sopenharmony_ci		u8 reg,
228062306a36Sopenharmony_ci		u8 value)
228162306a36Sopenharmony_ci{
228262306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "ov518_i2c_w %02x %02x\n", reg, value);
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	/* Select camera register */
228762306a36Sopenharmony_ci	reg_w(sd, R51x_I2C_SADDR_3, reg);
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	/* Write "value" to I2C data port of OV511 */
229062306a36Sopenharmony_ci	reg_w(sd, R51x_I2C_DATA, value);
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	/* Initiate 3-byte write cycle */
229362306a36Sopenharmony_ci	reg_w(sd, R518_I2C_CTL, 0x01);
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	/* wait for write complete */
229662306a36Sopenharmony_ci	msleep(4);
229762306a36Sopenharmony_ci	reg_r8(sd, R518_I2C_CTL);
229862306a36Sopenharmony_ci}
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci/*
230162306a36Sopenharmony_ci * returns: negative is error, pos or zero is data
230262306a36Sopenharmony_ci *
230362306a36Sopenharmony_ci * The OV518 I2C I/O procedure is different, hence, this function.
230462306a36Sopenharmony_ci * This is normally only called from i2c_r(). Note that this function
230562306a36Sopenharmony_ci * always succeeds regardless of whether the sensor is present and working.
230662306a36Sopenharmony_ci */
230762306a36Sopenharmony_cistatic int ov518_i2c_r(struct sd *sd, u8 reg)
230862306a36Sopenharmony_ci{
230962306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
231062306a36Sopenharmony_ci	int value;
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci	/* Select camera register */
231362306a36Sopenharmony_ci	reg_w(sd, R51x_I2C_SADDR_2, reg);
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci	/* Initiate 2-byte write cycle */
231662306a36Sopenharmony_ci	reg_w(sd, R518_I2C_CTL, 0x03);
231762306a36Sopenharmony_ci	reg_r8(sd, R518_I2C_CTL);
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	/* Initiate 2-byte read cycle */
232062306a36Sopenharmony_ci	reg_w(sd, R518_I2C_CTL, 0x05);
232162306a36Sopenharmony_ci	reg_r8(sd, R518_I2C_CTL);
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci	value = reg_r(sd, R51x_I2C_DATA);
232462306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBI, "ov518_i2c_r %02x %02x\n", reg, value);
232562306a36Sopenharmony_ci	return value;
232662306a36Sopenharmony_ci}
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_cistatic void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
232962306a36Sopenharmony_ci{
233062306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
233162306a36Sopenharmony_ci	int ret;
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
233462306a36Sopenharmony_ci		return;
233562306a36Sopenharmony_ci
233662306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
233762306a36Sopenharmony_ci			usb_sndctrlpipe(sd->gspca_dev.dev, 0),
233862306a36Sopenharmony_ci			0x02,
233962306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
234062306a36Sopenharmony_ci			(u16) value, (u16) reg, NULL, 0, 500);
234162306a36Sopenharmony_ci
234262306a36Sopenharmony_ci	if (ret < 0) {
234362306a36Sopenharmony_ci		gspca_err(gspca_dev, "ovfx2_i2c_w %02x failed %d\n", reg, ret);
234462306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
234562306a36Sopenharmony_ci	}
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "ovfx2_i2c_w %02x %02x\n", reg, value);
234862306a36Sopenharmony_ci}
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_cistatic int ovfx2_i2c_r(struct sd *sd, u8 reg)
235162306a36Sopenharmony_ci{
235262306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
235362306a36Sopenharmony_ci	int ret;
235462306a36Sopenharmony_ci
235562306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err < 0)
235662306a36Sopenharmony_ci		return -1;
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci	ret = usb_control_msg(sd->gspca_dev.dev,
235962306a36Sopenharmony_ci			usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
236062306a36Sopenharmony_ci			0x03,
236162306a36Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
236262306a36Sopenharmony_ci			0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	if (ret >= 0) {
236562306a36Sopenharmony_ci		ret = sd->gspca_dev.usb_buf[0];
236662306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_USBI, "ovfx2_i2c_r %02x %02x\n",
236762306a36Sopenharmony_ci			  reg, ret);
236862306a36Sopenharmony_ci	} else {
236962306a36Sopenharmony_ci		gspca_err(gspca_dev, "ovfx2_i2c_r %02x failed %d\n", reg, ret);
237062306a36Sopenharmony_ci		sd->gspca_dev.usb_err = ret;
237162306a36Sopenharmony_ci	}
237262306a36Sopenharmony_ci
237362306a36Sopenharmony_ci	return ret;
237462306a36Sopenharmony_ci}
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_cistatic void i2c_w(struct sd *sd, u8 reg, u8 value)
237762306a36Sopenharmony_ci{
237862306a36Sopenharmony_ci	if (sd->sensor_reg_cache[reg] == value)
237962306a36Sopenharmony_ci		return;
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	switch (sd->bridge) {
238262306a36Sopenharmony_ci	case BRIDGE_OV511:
238362306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
238462306a36Sopenharmony_ci		ov511_i2c_w(sd, reg, value);
238562306a36Sopenharmony_ci		break;
238662306a36Sopenharmony_ci	case BRIDGE_OV518:
238762306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
238862306a36Sopenharmony_ci	case BRIDGE_OV519:
238962306a36Sopenharmony_ci		ov518_i2c_w(sd, reg, value);
239062306a36Sopenharmony_ci		break;
239162306a36Sopenharmony_ci	case BRIDGE_OVFX2:
239262306a36Sopenharmony_ci		ovfx2_i2c_w(sd, reg, value);
239362306a36Sopenharmony_ci		break;
239462306a36Sopenharmony_ci	case BRIDGE_W9968CF:
239562306a36Sopenharmony_ci		w9968cf_i2c_w(sd, reg, value);
239662306a36Sopenharmony_ci		break;
239762306a36Sopenharmony_ci	}
239862306a36Sopenharmony_ci
239962306a36Sopenharmony_ci	if (sd->gspca_dev.usb_err >= 0) {
240062306a36Sopenharmony_ci		/* Up on sensor reset empty the register cache */
240162306a36Sopenharmony_ci		if (reg == 0x12 && (value & 0x80))
240262306a36Sopenharmony_ci			memset(sd->sensor_reg_cache, -1,
240362306a36Sopenharmony_ci				sizeof(sd->sensor_reg_cache));
240462306a36Sopenharmony_ci		else
240562306a36Sopenharmony_ci			sd->sensor_reg_cache[reg] = value;
240662306a36Sopenharmony_ci	}
240762306a36Sopenharmony_ci}
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_cistatic int i2c_r(struct sd *sd, u8 reg)
241062306a36Sopenharmony_ci{
241162306a36Sopenharmony_ci	int ret = -1;
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	if (sd->sensor_reg_cache[reg] != -1)
241462306a36Sopenharmony_ci		return sd->sensor_reg_cache[reg];
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci	switch (sd->bridge) {
241762306a36Sopenharmony_ci	case BRIDGE_OV511:
241862306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
241962306a36Sopenharmony_ci		ret = ov511_i2c_r(sd, reg);
242062306a36Sopenharmony_ci		break;
242162306a36Sopenharmony_ci	case BRIDGE_OV518:
242262306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
242362306a36Sopenharmony_ci	case BRIDGE_OV519:
242462306a36Sopenharmony_ci		ret = ov518_i2c_r(sd, reg);
242562306a36Sopenharmony_ci		break;
242662306a36Sopenharmony_ci	case BRIDGE_OVFX2:
242762306a36Sopenharmony_ci		ret = ovfx2_i2c_r(sd, reg);
242862306a36Sopenharmony_ci		break;
242962306a36Sopenharmony_ci	case BRIDGE_W9968CF:
243062306a36Sopenharmony_ci		ret = w9968cf_i2c_r(sd, reg);
243162306a36Sopenharmony_ci		break;
243262306a36Sopenharmony_ci	}
243362306a36Sopenharmony_ci
243462306a36Sopenharmony_ci	if (ret >= 0)
243562306a36Sopenharmony_ci		sd->sensor_reg_cache[reg] = ret;
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci	return ret;
243862306a36Sopenharmony_ci}
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
244162306a36Sopenharmony_ci * the same position as 1's in "mask" are cleared and set to "value". Bits
244262306a36Sopenharmony_ci * that are in the same position as 0's in "mask" are preserved, regardless
244362306a36Sopenharmony_ci * of their respective state in "value".
244462306a36Sopenharmony_ci */
244562306a36Sopenharmony_cistatic void i2c_w_mask(struct sd *sd,
244662306a36Sopenharmony_ci			u8 reg,
244762306a36Sopenharmony_ci			u8 value,
244862306a36Sopenharmony_ci			u8 mask)
244962306a36Sopenharmony_ci{
245062306a36Sopenharmony_ci	int rc;
245162306a36Sopenharmony_ci	u8 oldval;
245262306a36Sopenharmony_ci
245362306a36Sopenharmony_ci	value &= mask;			/* Enforce mask on value */
245462306a36Sopenharmony_ci	rc = i2c_r(sd, reg);
245562306a36Sopenharmony_ci	if (rc < 0)
245662306a36Sopenharmony_ci		return;
245762306a36Sopenharmony_ci	oldval = rc & ~mask;		/* Clear the masked bits */
245862306a36Sopenharmony_ci	value |= oldval;		/* Set the desired bits */
245962306a36Sopenharmony_ci	i2c_w(sd, reg, value);
246062306a36Sopenharmony_ci}
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci/* Temporarily stops OV511 from functioning. Must do this before changing
246362306a36Sopenharmony_ci * registers while the camera is streaming */
246462306a36Sopenharmony_cistatic inline void ov51x_stop(struct sd *sd)
246562306a36Sopenharmony_ci{
246662306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "stopping\n");
246962306a36Sopenharmony_ci	sd->stopped = 1;
247062306a36Sopenharmony_ci	switch (sd->bridge) {
247162306a36Sopenharmony_ci	case BRIDGE_OV511:
247262306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
247362306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_RESET, 0x3d);
247462306a36Sopenharmony_ci		break;
247562306a36Sopenharmony_ci	case BRIDGE_OV518:
247662306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
247762306a36Sopenharmony_ci		reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
247862306a36Sopenharmony_ci		break;
247962306a36Sopenharmony_ci	case BRIDGE_OV519:
248062306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x0f);
248162306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x00);
248262306a36Sopenharmony_ci		reg_w(sd, 0x22, 0x00);		/* FRAR */
248362306a36Sopenharmony_ci		break;
248462306a36Sopenharmony_ci	case BRIDGE_OVFX2:
248562306a36Sopenharmony_ci		reg_w_mask(sd, 0x0f, 0x00, 0x02);
248662306a36Sopenharmony_ci		break;
248762306a36Sopenharmony_ci	case BRIDGE_W9968CF:
248862306a36Sopenharmony_ci		reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
248962306a36Sopenharmony_ci		break;
249062306a36Sopenharmony_ci	}
249162306a36Sopenharmony_ci}
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ci/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
249462306a36Sopenharmony_ci * actually stopped (for performance). */
249562306a36Sopenharmony_cistatic inline void ov51x_restart(struct sd *sd)
249662306a36Sopenharmony_ci{
249762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "restarting\n");
250062306a36Sopenharmony_ci	if (!sd->stopped)
250162306a36Sopenharmony_ci		return;
250262306a36Sopenharmony_ci	sd->stopped = 0;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	/* Reinitialize the stream */
250562306a36Sopenharmony_ci	switch (sd->bridge) {
250662306a36Sopenharmony_ci	case BRIDGE_OV511:
250762306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
250862306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_RESET, 0x00);
250962306a36Sopenharmony_ci		break;
251062306a36Sopenharmony_ci	case BRIDGE_OV518:
251162306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
251262306a36Sopenharmony_ci		reg_w(sd, 0x2f, 0x80);
251362306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_RESET, 0x00);
251462306a36Sopenharmony_ci		break;
251562306a36Sopenharmony_ci	case BRIDGE_OV519:
251662306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x0f);
251762306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x00);
251862306a36Sopenharmony_ci		reg_w(sd, 0x22, 0x1d);		/* FRAR */
251962306a36Sopenharmony_ci		break;
252062306a36Sopenharmony_ci	case BRIDGE_OVFX2:
252162306a36Sopenharmony_ci		reg_w_mask(sd, 0x0f, 0x02, 0x02);
252262306a36Sopenharmony_ci		break;
252362306a36Sopenharmony_ci	case BRIDGE_W9968CF:
252462306a36Sopenharmony_ci		reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
252562306a36Sopenharmony_ci		break;
252662306a36Sopenharmony_ci	}
252762306a36Sopenharmony_ci}
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd, u8 slave);
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_ci/* This does an initial reset of an OmniVision sensor and ensures that I2C
253262306a36Sopenharmony_ci * is synchronized. Returns <0 on failure.
253362306a36Sopenharmony_ci */
253462306a36Sopenharmony_cistatic int init_ov_sensor(struct sd *sd, u8 slave)
253562306a36Sopenharmony_ci{
253662306a36Sopenharmony_ci	int i;
253762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci	ov51x_set_slave_ids(sd, slave);
254062306a36Sopenharmony_ci
254162306a36Sopenharmony_ci	/* Reset the sensor */
254262306a36Sopenharmony_ci	i2c_w(sd, 0x12, 0x80);
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci	/* Wait for it to initialize */
254562306a36Sopenharmony_ci	msleep(150);
254662306a36Sopenharmony_ci
254762306a36Sopenharmony_ci	for (i = 0; i < i2c_detect_tries; i++) {
254862306a36Sopenharmony_ci		if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
254962306a36Sopenharmony_ci		    i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
255062306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "I2C synced in %d attempt(s)\n",
255162306a36Sopenharmony_ci				  i);
255262306a36Sopenharmony_ci			return 0;
255362306a36Sopenharmony_ci		}
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci		/* Reset the sensor */
255662306a36Sopenharmony_ci		i2c_w(sd, 0x12, 0x80);
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci		/* Wait for it to initialize */
255962306a36Sopenharmony_ci		msleep(150);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci		/* Dummy read to sync I2C */
256262306a36Sopenharmony_ci		if (i2c_r(sd, 0x00) < 0)
256362306a36Sopenharmony_ci			return -1;
256462306a36Sopenharmony_ci	}
256562306a36Sopenharmony_ci	return -1;
256662306a36Sopenharmony_ci}
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci/* Set the read and write slave IDs. The "slave" argument is the write slave,
256962306a36Sopenharmony_ci * and the read slave will be set to (slave + 1).
257062306a36Sopenharmony_ci * This should not be called from outside the i2c I/O functions.
257162306a36Sopenharmony_ci * Sets I2C read and write slave IDs. Returns <0 for error
257262306a36Sopenharmony_ci */
257362306a36Sopenharmony_cistatic void ov51x_set_slave_ids(struct sd *sd,
257462306a36Sopenharmony_ci				u8 slave)
257562306a36Sopenharmony_ci{
257662306a36Sopenharmony_ci	switch (sd->bridge) {
257762306a36Sopenharmony_ci	case BRIDGE_OVFX2:
257862306a36Sopenharmony_ci		reg_w(sd, OVFX2_I2C_ADDR, slave);
257962306a36Sopenharmony_ci		return;
258062306a36Sopenharmony_ci	case BRIDGE_W9968CF:
258162306a36Sopenharmony_ci		sd->sensor_addr = slave;
258262306a36Sopenharmony_ci		return;
258362306a36Sopenharmony_ci	}
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	reg_w(sd, R51x_I2C_W_SID, slave);
258662306a36Sopenharmony_ci	reg_w(sd, R51x_I2C_R_SID, slave + 1);
258762306a36Sopenharmony_ci}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_cistatic void write_regvals(struct sd *sd,
259062306a36Sopenharmony_ci			 const struct ov_regvals *regvals,
259162306a36Sopenharmony_ci			 int n)
259262306a36Sopenharmony_ci{
259362306a36Sopenharmony_ci	while (--n >= 0) {
259462306a36Sopenharmony_ci		reg_w(sd, regvals->reg, regvals->val);
259562306a36Sopenharmony_ci		regvals++;
259662306a36Sopenharmony_ci	}
259762306a36Sopenharmony_ci}
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_cistatic void write_i2c_regvals(struct sd *sd,
260062306a36Sopenharmony_ci			const struct ov_i2c_regvals *regvals,
260162306a36Sopenharmony_ci			int n)
260262306a36Sopenharmony_ci{
260362306a36Sopenharmony_ci	while (--n >= 0) {
260462306a36Sopenharmony_ci		i2c_w(sd, regvals->reg, regvals->val);
260562306a36Sopenharmony_ci		regvals++;
260662306a36Sopenharmony_ci	}
260762306a36Sopenharmony_ci}
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci/****************************************************************************
261062306a36Sopenharmony_ci *
261162306a36Sopenharmony_ci * OV511 and sensor configuration
261262306a36Sopenharmony_ci *
261362306a36Sopenharmony_ci ***************************************************************************/
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_ci/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
261662306a36Sopenharmony_cistatic void ov_hires_configure(struct sd *sd)
261762306a36Sopenharmony_ci{
261862306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
261962306a36Sopenharmony_ci	int high, low;
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	if (sd->bridge != BRIDGE_OVFX2) {
262262306a36Sopenharmony_ci		gspca_err(gspca_dev, "error hires sensors only supported with ovfx2\n");
262362306a36Sopenharmony_ci		return;
262462306a36Sopenharmony_ci	}
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "starting ov hires configuration\n");
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	/* Detect sensor (sub)type */
262962306a36Sopenharmony_ci	high = i2c_r(sd, 0x0a);
263062306a36Sopenharmony_ci	low = i2c_r(sd, 0x0b);
263162306a36Sopenharmony_ci	/* info("%x, %x", high, low); */
263262306a36Sopenharmony_ci	switch (high) {
263362306a36Sopenharmony_ci	case 0x96:
263462306a36Sopenharmony_ci		switch (low) {
263562306a36Sopenharmony_ci		case 0x40:
263662306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610\n");
263762306a36Sopenharmony_ci			sd->sensor = SEN_OV2610;
263862306a36Sopenharmony_ci			return;
263962306a36Sopenharmony_ci		case 0x41:
264062306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV2610AE\n");
264162306a36Sopenharmony_ci			sd->sensor = SEN_OV2610AE;
264262306a36Sopenharmony_ci			return;
264362306a36Sopenharmony_ci		case 0xb1:
264462306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV9600\n");
264562306a36Sopenharmony_ci			sd->sensor = SEN_OV9600;
264662306a36Sopenharmony_ci			return;
264762306a36Sopenharmony_ci		}
264862306a36Sopenharmony_ci		break;
264962306a36Sopenharmony_ci	case 0x36:
265062306a36Sopenharmony_ci		if ((low & 0x0f) == 0x00) {
265162306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV3610\n");
265262306a36Sopenharmony_ci			sd->sensor = SEN_OV3610;
265362306a36Sopenharmony_ci			return;
265462306a36Sopenharmony_ci		}
265562306a36Sopenharmony_ci		break;
265662306a36Sopenharmony_ci	}
265762306a36Sopenharmony_ci	gspca_err(gspca_dev, "Error unknown sensor type: %02x%02x\n",
265862306a36Sopenharmony_ci		  high, low);
265962306a36Sopenharmony_ci}
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
266262306a36Sopenharmony_ci * the same register settings as the OV8610, since they are very similar.
266362306a36Sopenharmony_ci */
266462306a36Sopenharmony_cistatic void ov8xx0_configure(struct sd *sd)
266562306a36Sopenharmony_ci{
266662306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
266762306a36Sopenharmony_ci	int rc;
266862306a36Sopenharmony_ci
266962306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "starting ov8xx0 configuration\n");
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci	/* Detect sensor (sub)type */
267262306a36Sopenharmony_ci	rc = i2c_r(sd, OV7610_REG_COM_I);
267362306a36Sopenharmony_ci	if (rc < 0) {
267462306a36Sopenharmony_ci		gspca_err(gspca_dev, "Error detecting sensor type\n");
267562306a36Sopenharmony_ci		return;
267662306a36Sopenharmony_ci	}
267762306a36Sopenharmony_ci	if ((rc & 3) == 1)
267862306a36Sopenharmony_ci		sd->sensor = SEN_OV8610;
267962306a36Sopenharmony_ci	else
268062306a36Sopenharmony_ci		gspca_err(gspca_dev, "Unknown image sensor version: %d\n",
268162306a36Sopenharmony_ci			  rc & 3);
268262306a36Sopenharmony_ci}
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
268562306a36Sopenharmony_ci * the same register settings as the OV7610, since they are very similar.
268662306a36Sopenharmony_ci */
268762306a36Sopenharmony_cistatic void ov7xx0_configure(struct sd *sd)
268862306a36Sopenharmony_ci{
268962306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
269062306a36Sopenharmony_ci	int rc, high, low;
269162306a36Sopenharmony_ci
269262306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "starting OV7xx0 configuration\n");
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	/* Detect sensor (sub)type */
269562306a36Sopenharmony_ci	rc = i2c_r(sd, OV7610_REG_COM_I);
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	/* add OV7670 here
269862306a36Sopenharmony_ci	 * it appears to be wrongly detected as a 7610 by default */
269962306a36Sopenharmony_ci	if (rc < 0) {
270062306a36Sopenharmony_ci		gspca_err(gspca_dev, "Error detecting sensor type\n");
270162306a36Sopenharmony_ci		return;
270262306a36Sopenharmony_ci	}
270362306a36Sopenharmony_ci	if ((rc & 3) == 3) {
270462306a36Sopenharmony_ci		/* quick hack to make OV7670s work */
270562306a36Sopenharmony_ci		high = i2c_r(sd, 0x0a);
270662306a36Sopenharmony_ci		low = i2c_r(sd, 0x0b);
270762306a36Sopenharmony_ci		/* info("%x, %x", high, low); */
270862306a36Sopenharmony_ci		if (high == 0x76 && (low & 0xf0) == 0x70) {
270962306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76%02x\n",
271062306a36Sopenharmony_ci				  low);
271162306a36Sopenharmony_ci			sd->sensor = SEN_OV7670;
271262306a36Sopenharmony_ci		} else {
271362306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7610\n");
271462306a36Sopenharmony_ci			sd->sensor = SEN_OV7610;
271562306a36Sopenharmony_ci		}
271662306a36Sopenharmony_ci	} else if ((rc & 3) == 1) {
271762306a36Sopenharmony_ci		/* I don't know what's different about the 76BE yet. */
271862306a36Sopenharmony_ci		if (i2c_r(sd, 0x15) & 1) {
271962306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620AE\n");
272062306a36Sopenharmony_ci			sd->sensor = SEN_OV7620AE;
272162306a36Sopenharmony_ci		} else {
272262306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV76BE\n");
272362306a36Sopenharmony_ci			sd->sensor = SEN_OV76BE;
272462306a36Sopenharmony_ci		}
272562306a36Sopenharmony_ci	} else if ((rc & 3) == 0) {
272662306a36Sopenharmony_ci		/* try to read product id registers */
272762306a36Sopenharmony_ci		high = i2c_r(sd, 0x0a);
272862306a36Sopenharmony_ci		if (high < 0) {
272962306a36Sopenharmony_ci			gspca_err(gspca_dev, "Error detecting camera chip PID\n");
273062306a36Sopenharmony_ci			return;
273162306a36Sopenharmony_ci		}
273262306a36Sopenharmony_ci		low = i2c_r(sd, 0x0b);
273362306a36Sopenharmony_ci		if (low < 0) {
273462306a36Sopenharmony_ci			gspca_err(gspca_dev, "Error detecting camera chip VER\n");
273562306a36Sopenharmony_ci			return;
273662306a36Sopenharmony_ci		}
273762306a36Sopenharmony_ci		if (high == 0x76) {
273862306a36Sopenharmony_ci			switch (low) {
273962306a36Sopenharmony_ci			case 0x30:
274062306a36Sopenharmony_ci				gspca_err(gspca_dev, "Sensor is an OV7630/OV7635\n");
274162306a36Sopenharmony_ci				gspca_err(gspca_dev, "7630 is not supported by this driver\n");
274262306a36Sopenharmony_ci				return;
274362306a36Sopenharmony_ci			case 0x40:
274462306a36Sopenharmony_ci				gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645\n");
274562306a36Sopenharmony_ci				sd->sensor = SEN_OV7640; /* FIXME */
274662306a36Sopenharmony_ci				break;
274762306a36Sopenharmony_ci			case 0x45:
274862306a36Sopenharmony_ci				gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7645B\n");
274962306a36Sopenharmony_ci				sd->sensor = SEN_OV7640; /* FIXME */
275062306a36Sopenharmony_ci				break;
275162306a36Sopenharmony_ci			case 0x48:
275262306a36Sopenharmony_ci				gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7648\n");
275362306a36Sopenharmony_ci				sd->sensor = SEN_OV7648;
275462306a36Sopenharmony_ci				break;
275562306a36Sopenharmony_ci			case 0x60:
275662306a36Sopenharmony_ci				gspca_dbg(gspca_dev, D_PROBE, "Sensor is a OV7660\n");
275762306a36Sopenharmony_ci				sd->sensor = SEN_OV7660;
275862306a36Sopenharmony_ci				break;
275962306a36Sopenharmony_ci			default:
276062306a36Sopenharmony_ci				gspca_err(gspca_dev, "Unknown sensor: 0x76%02x\n",
276162306a36Sopenharmony_ci					  low);
276262306a36Sopenharmony_ci				return;
276362306a36Sopenharmony_ci			}
276462306a36Sopenharmony_ci		} else {
276562306a36Sopenharmony_ci			gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV7620\n");
276662306a36Sopenharmony_ci			sd->sensor = SEN_OV7620;
276762306a36Sopenharmony_ci		}
276862306a36Sopenharmony_ci	} else {
276962306a36Sopenharmony_ci		gspca_err(gspca_dev, "Unknown image sensor version: %d\n",
277062306a36Sopenharmony_ci			  rc & 3);
277162306a36Sopenharmony_ci	}
277262306a36Sopenharmony_ci}
277362306a36Sopenharmony_ci
277462306a36Sopenharmony_ci/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
277562306a36Sopenharmony_cistatic void ov6xx0_configure(struct sd *sd)
277662306a36Sopenharmony_ci{
277762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
277862306a36Sopenharmony_ci	int rc;
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "starting OV6xx0 configuration\n");
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	/* Detect sensor (sub)type */
278362306a36Sopenharmony_ci	rc = i2c_r(sd, OV7610_REG_COM_I);
278462306a36Sopenharmony_ci	if (rc < 0) {
278562306a36Sopenharmony_ci		gspca_err(gspca_dev, "Error detecting sensor type\n");
278662306a36Sopenharmony_ci		return;
278762306a36Sopenharmony_ci	}
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	/* Ugh. The first two bits are the version bits, but
279062306a36Sopenharmony_ci	 * the entire register value must be used. I guess OVT
279162306a36Sopenharmony_ci	 * underestimated how many variants they would make. */
279262306a36Sopenharmony_ci	switch (rc) {
279362306a36Sopenharmony_ci	case 0x00:
279462306a36Sopenharmony_ci		sd->sensor = SEN_OV6630;
279562306a36Sopenharmony_ci		pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
279662306a36Sopenharmony_ci		break;
279762306a36Sopenharmony_ci	case 0x01:
279862306a36Sopenharmony_ci		sd->sensor = SEN_OV6620;
279962306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV6620\n");
280062306a36Sopenharmony_ci		break;
280162306a36Sopenharmony_ci	case 0x02:
280262306a36Sopenharmony_ci		sd->sensor = SEN_OV6630;
280362306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AE\n");
280462306a36Sopenharmony_ci		break;
280562306a36Sopenharmony_ci	case 0x03:
280662306a36Sopenharmony_ci		sd->sensor = SEN_OV66308AF;
280762306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor is an OV66308AF\n");
280862306a36Sopenharmony_ci		break;
280962306a36Sopenharmony_ci	case 0x90:
281062306a36Sopenharmony_ci		sd->sensor = SEN_OV6630;
281162306a36Sopenharmony_ci		pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
281262306a36Sopenharmony_ci		break;
281362306a36Sopenharmony_ci	default:
281462306a36Sopenharmony_ci		gspca_err(gspca_dev, "FATAL: Unknown sensor version: 0x%02x\n",
281562306a36Sopenharmony_ci			  rc);
281662306a36Sopenharmony_ci		return;
281762306a36Sopenharmony_ci	}
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	/* Set sensor-specific vars */
282062306a36Sopenharmony_ci	sd->sif = 1;
282162306a36Sopenharmony_ci}
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
282462306a36Sopenharmony_cistatic void ov51x_led_control(struct sd *sd, int on)
282562306a36Sopenharmony_ci{
282662306a36Sopenharmony_ci	if (sd->invert_led)
282762306a36Sopenharmony_ci		on = !on;
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci	switch (sd->bridge) {
283062306a36Sopenharmony_ci	/* OV511 has no LED control */
283162306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
283262306a36Sopenharmony_ci		reg_w(sd, R511_SYS_LED_CTL, on);
283362306a36Sopenharmony_ci		break;
283462306a36Sopenharmony_ci	case BRIDGE_OV518:
283562306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
283662306a36Sopenharmony_ci		reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
283762306a36Sopenharmony_ci		break;
283862306a36Sopenharmony_ci	case BRIDGE_OV519:
283962306a36Sopenharmony_ci		reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
284062306a36Sopenharmony_ci		break;
284162306a36Sopenharmony_ci	}
284262306a36Sopenharmony_ci}
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_cistatic void sd_reset_snapshot(struct gspca_dev *gspca_dev)
284562306a36Sopenharmony_ci{
284662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	if (!sd->snapshot_needs_reset)
284962306a36Sopenharmony_ci		return;
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	/* Note it is important that we clear sd->snapshot_needs_reset,
285262306a36Sopenharmony_ci	   before actually clearing the snapshot state in the bridge
285362306a36Sopenharmony_ci	   otherwise we might race with the pkt_scan interrupt handler */
285462306a36Sopenharmony_ci	sd->snapshot_needs_reset = 0;
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci	switch (sd->bridge) {
285762306a36Sopenharmony_ci	case BRIDGE_OV511:
285862306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
285962306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_SNAP, 0x02);
286062306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_SNAP, 0x00);
286162306a36Sopenharmony_ci		break;
286262306a36Sopenharmony_ci	case BRIDGE_OV518:
286362306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
286462306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
286562306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
286662306a36Sopenharmony_ci		break;
286762306a36Sopenharmony_ci	case BRIDGE_OV519:
286862306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_RESET, 0x40);
286962306a36Sopenharmony_ci		reg_w(sd, R51x_SYS_RESET, 0x00);
287062306a36Sopenharmony_ci		break;
287162306a36Sopenharmony_ci	}
287262306a36Sopenharmony_ci}
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_cistatic void ov51x_upload_quan_tables(struct sd *sd)
287562306a36Sopenharmony_ci{
287662306a36Sopenharmony_ci	static const unsigned char yQuanTable511[] = {
287762306a36Sopenharmony_ci		0, 1, 1, 2, 2, 3, 3, 4,
287862306a36Sopenharmony_ci		1, 1, 1, 2, 2, 3, 4, 4,
287962306a36Sopenharmony_ci		1, 1, 2, 2, 3, 4, 4, 4,
288062306a36Sopenharmony_ci		2, 2, 2, 3, 4, 4, 4, 4,
288162306a36Sopenharmony_ci		2, 2, 3, 4, 4, 5, 5, 5,
288262306a36Sopenharmony_ci		3, 3, 4, 4, 5, 5, 5, 5,
288362306a36Sopenharmony_ci		3, 4, 4, 4, 5, 5, 5, 5,
288462306a36Sopenharmony_ci		4, 4, 4, 4, 5, 5, 5, 5
288562306a36Sopenharmony_ci	};
288662306a36Sopenharmony_ci
288762306a36Sopenharmony_ci	static const unsigned char uvQuanTable511[] = {
288862306a36Sopenharmony_ci		0, 2, 2, 3, 4, 4, 4, 4,
288962306a36Sopenharmony_ci		2, 2, 2, 4, 4, 4, 4, 4,
289062306a36Sopenharmony_ci		2, 2, 3, 4, 4, 4, 4, 4,
289162306a36Sopenharmony_ci		3, 4, 4, 4, 4, 4, 4, 4,
289262306a36Sopenharmony_ci		4, 4, 4, 4, 4, 4, 4, 4,
289362306a36Sopenharmony_ci		4, 4, 4, 4, 4, 4, 4, 4,
289462306a36Sopenharmony_ci		4, 4, 4, 4, 4, 4, 4, 4,
289562306a36Sopenharmony_ci		4, 4, 4, 4, 4, 4, 4, 4
289662306a36Sopenharmony_ci	};
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	/* OV518 quantization tables are 8x4 (instead of 8x8) */
289962306a36Sopenharmony_ci	static const unsigned char yQuanTable518[] = {
290062306a36Sopenharmony_ci		5, 4, 5, 6, 6, 7, 7, 7,
290162306a36Sopenharmony_ci		5, 5, 5, 5, 6, 7, 7, 7,
290262306a36Sopenharmony_ci		6, 6, 6, 6, 7, 7, 7, 8,
290362306a36Sopenharmony_ci		7, 7, 6, 7, 7, 7, 8, 8
290462306a36Sopenharmony_ci	};
290562306a36Sopenharmony_ci	static const unsigned char uvQuanTable518[] = {
290662306a36Sopenharmony_ci		6, 6, 6, 7, 7, 7, 7, 7,
290762306a36Sopenharmony_ci		6, 6, 6, 7, 7, 7, 7, 7,
290862306a36Sopenharmony_ci		6, 6, 6, 7, 7, 7, 7, 8,
290962306a36Sopenharmony_ci		7, 7, 7, 7, 7, 7, 8, 8
291062306a36Sopenharmony_ci	};
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
291362306a36Sopenharmony_ci	const unsigned char *pYTable, *pUVTable;
291462306a36Sopenharmony_ci	unsigned char val0, val1;
291562306a36Sopenharmony_ci	int i, size, reg = R51x_COMP_LUT_BEGIN;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Uploading quantization tables\n");
291862306a36Sopenharmony_ci
291962306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
292062306a36Sopenharmony_ci		pYTable = yQuanTable511;
292162306a36Sopenharmony_ci		pUVTable = uvQuanTable511;
292262306a36Sopenharmony_ci		size = 32;
292362306a36Sopenharmony_ci	} else {
292462306a36Sopenharmony_ci		pYTable = yQuanTable518;
292562306a36Sopenharmony_ci		pUVTable = uvQuanTable518;
292662306a36Sopenharmony_ci		size = 16;
292762306a36Sopenharmony_ci	}
292862306a36Sopenharmony_ci
292962306a36Sopenharmony_ci	for (i = 0; i < size; i++) {
293062306a36Sopenharmony_ci		val0 = *pYTable++;
293162306a36Sopenharmony_ci		val1 = *pYTable++;
293262306a36Sopenharmony_ci		val0 &= 0x0f;
293362306a36Sopenharmony_ci		val1 &= 0x0f;
293462306a36Sopenharmony_ci		val0 |= val1 << 4;
293562306a36Sopenharmony_ci		reg_w(sd, reg, val0);
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci		val0 = *pUVTable++;
293862306a36Sopenharmony_ci		val1 = *pUVTable++;
293962306a36Sopenharmony_ci		val0 &= 0x0f;
294062306a36Sopenharmony_ci		val1 &= 0x0f;
294162306a36Sopenharmony_ci		val0 |= val1 << 4;
294262306a36Sopenharmony_ci		reg_w(sd, reg + size, val0);
294362306a36Sopenharmony_ci
294462306a36Sopenharmony_ci		reg++;
294562306a36Sopenharmony_ci	}
294662306a36Sopenharmony_ci}
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci/* This initializes the OV511/OV511+ and the sensor */
294962306a36Sopenharmony_cistatic void ov511_configure(struct gspca_dev *gspca_dev)
295062306a36Sopenharmony_ci{
295162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
295262306a36Sopenharmony_ci
295362306a36Sopenharmony_ci	/* For 511 and 511+ */
295462306a36Sopenharmony_ci	static const struct ov_regvals init_511[] = {
295562306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x7f },
295662306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0x01 },
295762306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x7f },
295862306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0x01 },
295962306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x3f },
296062306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0x01 },
296162306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x3d },
296262306a36Sopenharmony_ci	};
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci	static const struct ov_regvals norm_511[] = {
296562306a36Sopenharmony_ci		{ R511_DRAM_FLOW_CTL,	0x01 },
296662306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x00 },
296762306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x02 },
296862306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x00 },
296962306a36Sopenharmony_ci		{ R511_FIFO_OPTS,	0x1f },
297062306a36Sopenharmony_ci		{ R511_COMP_EN,		0x00 },
297162306a36Sopenharmony_ci		{ R511_COMP_LUT_EN,	0x03 },
297262306a36Sopenharmony_ci	};
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	static const struct ov_regvals norm_511_p[] = {
297562306a36Sopenharmony_ci		{ R511_DRAM_FLOW_CTL,	0xff },
297662306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x00 },
297762306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x02 },
297862306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x00 },
297962306a36Sopenharmony_ci		{ R511_FIFO_OPTS,	0xff },
298062306a36Sopenharmony_ci		{ R511_COMP_EN,		0x00 },
298162306a36Sopenharmony_ci		{ R511_COMP_LUT_EN,	0x03 },
298262306a36Sopenharmony_ci	};
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	static const struct ov_regvals compress_511[] = {
298562306a36Sopenharmony_ci		{ 0x70, 0x1f },
298662306a36Sopenharmony_ci		{ 0x71, 0x05 },
298762306a36Sopenharmony_ci		{ 0x72, 0x06 },
298862306a36Sopenharmony_ci		{ 0x73, 0x06 },
298962306a36Sopenharmony_ci		{ 0x74, 0x14 },
299062306a36Sopenharmony_ci		{ 0x75, 0x03 },
299162306a36Sopenharmony_ci		{ 0x76, 0x04 },
299262306a36Sopenharmony_ci		{ 0x77, 0x04 },
299362306a36Sopenharmony_ci	};
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Device custom id %x\n",
299662306a36Sopenharmony_ci		  reg_r(sd, R51x_SYS_CUST_ID));
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	write_regvals(sd, init_511, ARRAY_SIZE(init_511));
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci	switch (sd->bridge) {
300162306a36Sopenharmony_ci	case BRIDGE_OV511:
300262306a36Sopenharmony_ci		write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
300362306a36Sopenharmony_ci		break;
300462306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
300562306a36Sopenharmony_ci		write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
300662306a36Sopenharmony_ci		break;
300762306a36Sopenharmony_ci	}
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_ci	/* Init compression */
301062306a36Sopenharmony_ci	write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
301162306a36Sopenharmony_ci
301262306a36Sopenharmony_ci	ov51x_upload_quan_tables(sd);
301362306a36Sopenharmony_ci}
301462306a36Sopenharmony_ci
301562306a36Sopenharmony_ci/* This initializes the OV518/OV518+ and the sensor */
301662306a36Sopenharmony_cistatic void ov518_configure(struct gspca_dev *gspca_dev)
301762306a36Sopenharmony_ci{
301862306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_ci	/* For 518 and 518+ */
302162306a36Sopenharmony_ci	static const struct ov_regvals init_518[] = {
302262306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x40 },
302362306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0xe1 },
302462306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x3e },
302562306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0xe1 },
302662306a36Sopenharmony_ci		{ R51x_SYS_RESET,	0x00 },
302762306a36Sopenharmony_ci		{ R51x_SYS_INIT,	0xe1 },
302862306a36Sopenharmony_ci		{ 0x46,			0x00 },
302962306a36Sopenharmony_ci		{ 0x5d,			0x03 },
303062306a36Sopenharmony_ci	};
303162306a36Sopenharmony_ci
303262306a36Sopenharmony_ci	static const struct ov_regvals norm_518[] = {
303362306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x02 }, /* Reset */
303462306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x01 }, /* Enable */
303562306a36Sopenharmony_ci		{ 0x31,			0x0f },
303662306a36Sopenharmony_ci		{ 0x5d,			0x03 },
303762306a36Sopenharmony_ci		{ 0x24,			0x9f },
303862306a36Sopenharmony_ci		{ 0x25,			0x90 },
303962306a36Sopenharmony_ci		{ 0x20,			0x00 },
304062306a36Sopenharmony_ci		{ 0x51,			0x04 },
304162306a36Sopenharmony_ci		{ 0x71,			0x19 },
304262306a36Sopenharmony_ci		{ 0x2f,			0x80 },
304362306a36Sopenharmony_ci	};
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci	static const struct ov_regvals norm_518_p[] = {
304662306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x02 }, /* Reset */
304762306a36Sopenharmony_ci		{ R51x_SYS_SNAP,	0x01 }, /* Enable */
304862306a36Sopenharmony_ci		{ 0x31,			0x0f },
304962306a36Sopenharmony_ci		{ 0x5d,			0x03 },
305062306a36Sopenharmony_ci		{ 0x24,			0x9f },
305162306a36Sopenharmony_ci		{ 0x25,			0x90 },
305262306a36Sopenharmony_ci		{ 0x20,			0x60 },
305362306a36Sopenharmony_ci		{ 0x51,			0x02 },
305462306a36Sopenharmony_ci		{ 0x71,			0x19 },
305562306a36Sopenharmony_ci		{ 0x40,			0xff },
305662306a36Sopenharmony_ci		{ 0x41,			0x42 },
305762306a36Sopenharmony_ci		{ 0x46,			0x00 },
305862306a36Sopenharmony_ci		{ 0x33,			0x04 },
305962306a36Sopenharmony_ci		{ 0x21,			0x19 },
306062306a36Sopenharmony_ci		{ 0x3f,			0x10 },
306162306a36Sopenharmony_ci		{ 0x2f,			0x80 },
306262306a36Sopenharmony_ci	};
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_ci	/* First 5 bits of custom ID reg are a revision ID on OV518 */
306562306a36Sopenharmony_ci	sd->revision = reg_r(sd, R51x_SYS_CUST_ID) & 0x1f;
306662306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Device revision %d\n", sd->revision);
306762306a36Sopenharmony_ci
306862306a36Sopenharmony_ci	write_regvals(sd, init_518, ARRAY_SIZE(init_518));
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci	/* Set LED GPIO pin to output mode */
307162306a36Sopenharmony_ci	reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci	switch (sd->bridge) {
307462306a36Sopenharmony_ci	case BRIDGE_OV518:
307562306a36Sopenharmony_ci		write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
307662306a36Sopenharmony_ci		break;
307762306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
307862306a36Sopenharmony_ci		write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
307962306a36Sopenharmony_ci		break;
308062306a36Sopenharmony_ci	}
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci	ov51x_upload_quan_tables(sd);
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci	reg_w(sd, 0x2f, 0x80);
308562306a36Sopenharmony_ci}
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_cistatic void ov519_configure(struct sd *sd)
308862306a36Sopenharmony_ci{
308962306a36Sopenharmony_ci	static const struct ov_regvals init_519[] = {
309062306a36Sopenharmony_ci		{ 0x5a, 0x6d }, /* EnableSystem */
309162306a36Sopenharmony_ci		{ 0x53, 0x9b }, /* don't enable the microcontroller */
309262306a36Sopenharmony_ci		{ OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
309362306a36Sopenharmony_ci		{ 0x5d, 0x03 },
309462306a36Sopenharmony_ci		{ 0x49, 0x01 },
309562306a36Sopenharmony_ci		{ 0x48, 0x00 },
309662306a36Sopenharmony_ci		/* Set LED pin to output mode. Bit 4 must be cleared or sensor
309762306a36Sopenharmony_ci		 * detection will fail. This deserves further investigation. */
309862306a36Sopenharmony_ci		{ OV519_GPIO_IO_CTRL0,   0xee },
309962306a36Sopenharmony_ci		{ OV519_R51_RESET1, 0x0f },
310062306a36Sopenharmony_ci		{ OV519_R51_RESET1, 0x00 },
310162306a36Sopenharmony_ci		{ 0x22, 0x00 },
310262306a36Sopenharmony_ci		/* windows reads 0x55 at this point*/
310362306a36Sopenharmony_ci	};
310462306a36Sopenharmony_ci
310562306a36Sopenharmony_ci	write_regvals(sd, init_519, ARRAY_SIZE(init_519));
310662306a36Sopenharmony_ci}
310762306a36Sopenharmony_ci
310862306a36Sopenharmony_cistatic void ovfx2_configure(struct sd *sd)
310962306a36Sopenharmony_ci{
311062306a36Sopenharmony_ci	static const struct ov_regvals init_fx2[] = {
311162306a36Sopenharmony_ci		{ 0x00, 0x60 },
311262306a36Sopenharmony_ci		{ 0x02, 0x01 },
311362306a36Sopenharmony_ci		{ 0x0f, 0x1d },
311462306a36Sopenharmony_ci		{ 0xe9, 0x82 },
311562306a36Sopenharmony_ci		{ 0xea, 0xc7 },
311662306a36Sopenharmony_ci		{ 0xeb, 0x10 },
311762306a36Sopenharmony_ci		{ 0xec, 0xf6 },
311862306a36Sopenharmony_ci	};
311962306a36Sopenharmony_ci
312062306a36Sopenharmony_ci	sd->stopped = 1;
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci	write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
312362306a36Sopenharmony_ci}
312462306a36Sopenharmony_ci
312562306a36Sopenharmony_ci/* set the mode */
312662306a36Sopenharmony_ci/* This function works for ov7660 only */
312762306a36Sopenharmony_cistatic void ov519_set_mode(struct sd *sd)
312862306a36Sopenharmony_ci{
312962306a36Sopenharmony_ci	static const struct ov_regvals bridge_ov7660[2][10] = {
313062306a36Sopenharmony_ci		{{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
313162306a36Sopenharmony_ci		 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
313262306a36Sopenharmony_ci		 {0x25, 0x01}, {0x26, 0x00}},
313362306a36Sopenharmony_ci		{{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
313462306a36Sopenharmony_ci		 {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
313562306a36Sopenharmony_ci		 {0x25, 0x03}, {0x26, 0x00}}
313662306a36Sopenharmony_ci	};
313762306a36Sopenharmony_ci	static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
313862306a36Sopenharmony_ci		{{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
313962306a36Sopenharmony_ci		{{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
314062306a36Sopenharmony_ci	};
314162306a36Sopenharmony_ci	static const struct ov_i2c_regvals sensor_ov7660_2[] = {
314262306a36Sopenharmony_ci		{OV7670_R17_HSTART, 0x13},
314362306a36Sopenharmony_ci		{OV7670_R18_HSTOP, 0x01},
314462306a36Sopenharmony_ci		{OV7670_R32_HREF, 0x92},
314562306a36Sopenharmony_ci		{OV7670_R19_VSTART, 0x02},
314662306a36Sopenharmony_ci		{OV7670_R1A_VSTOP, 0x7a},
314762306a36Sopenharmony_ci		{OV7670_R03_VREF, 0x00},
314862306a36Sopenharmony_ci/*		{0x33, 0x00}, */
314962306a36Sopenharmony_ci/*		{0x34, 0x07}, */
315062306a36Sopenharmony_ci/*		{0x36, 0x00}, */
315162306a36Sopenharmony_ci/*		{0x6b, 0x0a}, */
315262306a36Sopenharmony_ci	};
315362306a36Sopenharmony_ci
315462306a36Sopenharmony_ci	write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
315562306a36Sopenharmony_ci			ARRAY_SIZE(bridge_ov7660[0]));
315662306a36Sopenharmony_ci	write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
315762306a36Sopenharmony_ci			ARRAY_SIZE(sensor_ov7660[0]));
315862306a36Sopenharmony_ci	write_i2c_regvals(sd, sensor_ov7660_2,
315962306a36Sopenharmony_ci			ARRAY_SIZE(sensor_ov7660_2));
316062306a36Sopenharmony_ci}
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci/* set the frame rate */
316362306a36Sopenharmony_ci/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
316462306a36Sopenharmony_cistatic void ov519_set_fr(struct sd *sd)
316562306a36Sopenharmony_ci{
316662306a36Sopenharmony_ci	int fr;
316762306a36Sopenharmony_ci	u8 clock;
316862306a36Sopenharmony_ci	/* frame rate table with indices:
316962306a36Sopenharmony_ci	 *	- mode = 0: 320x240, 1: 640x480
317062306a36Sopenharmony_ci	 *	- fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
317162306a36Sopenharmony_ci	 *	- reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
317262306a36Sopenharmony_ci	 */
317362306a36Sopenharmony_ci	static const u8 fr_tb[2][6][3] = {
317462306a36Sopenharmony_ci		{{0x04, 0xff, 0x00},
317562306a36Sopenharmony_ci		 {0x04, 0x1f, 0x00},
317662306a36Sopenharmony_ci		 {0x04, 0x1b, 0x00},
317762306a36Sopenharmony_ci		 {0x04, 0x15, 0x00},
317862306a36Sopenharmony_ci		 {0x04, 0x09, 0x00},
317962306a36Sopenharmony_ci		 {0x04, 0x01, 0x00}},
318062306a36Sopenharmony_ci		{{0x0c, 0xff, 0x00},
318162306a36Sopenharmony_ci		 {0x0c, 0x1f, 0x00},
318262306a36Sopenharmony_ci		 {0x0c, 0x1b, 0x00},
318362306a36Sopenharmony_ci		 {0x04, 0xff, 0x01},
318462306a36Sopenharmony_ci		 {0x04, 0x1f, 0x01},
318562306a36Sopenharmony_ci		 {0x04, 0x1b, 0x01}},
318662306a36Sopenharmony_ci	};
318762306a36Sopenharmony_ci
318862306a36Sopenharmony_ci	if (frame_rate > 0)
318962306a36Sopenharmony_ci		sd->frame_rate = frame_rate;
319062306a36Sopenharmony_ci	if (sd->frame_rate >= 30)
319162306a36Sopenharmony_ci		fr = 0;
319262306a36Sopenharmony_ci	else if (sd->frame_rate >= 25)
319362306a36Sopenharmony_ci		fr = 1;
319462306a36Sopenharmony_ci	else if (sd->frame_rate >= 20)
319562306a36Sopenharmony_ci		fr = 2;
319662306a36Sopenharmony_ci	else if (sd->frame_rate >= 15)
319762306a36Sopenharmony_ci		fr = 3;
319862306a36Sopenharmony_ci	else if (sd->frame_rate >= 10)
319962306a36Sopenharmony_ci		fr = 4;
320062306a36Sopenharmony_ci	else
320162306a36Sopenharmony_ci		fr = 5;
320262306a36Sopenharmony_ci	reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
320362306a36Sopenharmony_ci	reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
320462306a36Sopenharmony_ci	clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
320562306a36Sopenharmony_ci	if (sd->sensor == SEN_OV7660)
320662306a36Sopenharmony_ci		clock |= 0x80;		/* enable double clock */
320762306a36Sopenharmony_ci	ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
320862306a36Sopenharmony_ci}
320962306a36Sopenharmony_ci
321062306a36Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev, s32 val)
321162306a36Sopenharmony_ci{
321262306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci	i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05);
321562306a36Sopenharmony_ci}
321662306a36Sopenharmony_ci
321762306a36Sopenharmony_ci/* this function is called at probe time */
321862306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
321962306a36Sopenharmony_ci			const struct usb_device_id *id)
322062306a36Sopenharmony_ci{
322162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
322262306a36Sopenharmony_ci	struct cam *cam = &gspca_dev->cam;
322362306a36Sopenharmony_ci
322462306a36Sopenharmony_ci	sd->bridge = id->driver_info & BRIDGE_MASK;
322562306a36Sopenharmony_ci	sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
322662306a36Sopenharmony_ci
322762306a36Sopenharmony_ci	switch (sd->bridge) {
322862306a36Sopenharmony_ci	case BRIDGE_OV511:
322962306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
323062306a36Sopenharmony_ci		cam->cam_mode = ov511_vga_mode;
323162306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
323262306a36Sopenharmony_ci		break;
323362306a36Sopenharmony_ci	case BRIDGE_OV518:
323462306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
323562306a36Sopenharmony_ci		cam->cam_mode = ov518_vga_mode;
323662306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
323762306a36Sopenharmony_ci		break;
323862306a36Sopenharmony_ci	case BRIDGE_OV519:
323962306a36Sopenharmony_ci		cam->cam_mode = ov519_vga_mode;
324062306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
324162306a36Sopenharmony_ci		break;
324262306a36Sopenharmony_ci	case BRIDGE_OVFX2:
324362306a36Sopenharmony_ci		cam->cam_mode = ov519_vga_mode;
324462306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
324562306a36Sopenharmony_ci		cam->bulk_size = OVFX2_BULK_SIZE;
324662306a36Sopenharmony_ci		cam->bulk_nurbs = MAX_NURBS;
324762306a36Sopenharmony_ci		cam->bulk = 1;
324862306a36Sopenharmony_ci		break;
324962306a36Sopenharmony_ci	case BRIDGE_W9968CF:
325062306a36Sopenharmony_ci		cam->cam_mode = w9968cf_vga_mode;
325162306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
325262306a36Sopenharmony_ci		break;
325362306a36Sopenharmony_ci	}
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	sd->frame_rate = 15;
325662306a36Sopenharmony_ci
325762306a36Sopenharmony_ci	return 0;
325862306a36Sopenharmony_ci}
325962306a36Sopenharmony_ci
326062306a36Sopenharmony_ci/* this function is called at probe and resume time */
326162306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
326262306a36Sopenharmony_ci{
326362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
326462306a36Sopenharmony_ci	struct cam *cam = &gspca_dev->cam;
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	switch (sd->bridge) {
326762306a36Sopenharmony_ci	case BRIDGE_OV511:
326862306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
326962306a36Sopenharmony_ci		ov511_configure(gspca_dev);
327062306a36Sopenharmony_ci		break;
327162306a36Sopenharmony_ci	case BRIDGE_OV518:
327262306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
327362306a36Sopenharmony_ci		ov518_configure(gspca_dev);
327462306a36Sopenharmony_ci		break;
327562306a36Sopenharmony_ci	case BRIDGE_OV519:
327662306a36Sopenharmony_ci		ov519_configure(sd);
327762306a36Sopenharmony_ci		break;
327862306a36Sopenharmony_ci	case BRIDGE_OVFX2:
327962306a36Sopenharmony_ci		ovfx2_configure(sd);
328062306a36Sopenharmony_ci		break;
328162306a36Sopenharmony_ci	case BRIDGE_W9968CF:
328262306a36Sopenharmony_ci		w9968cf_configure(sd);
328362306a36Sopenharmony_ci		break;
328462306a36Sopenharmony_ci	}
328562306a36Sopenharmony_ci
328662306a36Sopenharmony_ci	/* The OV519 must be more aggressive about sensor detection since
328762306a36Sopenharmony_ci	 * I2C write will never fail if the sensor is not present. We have
328862306a36Sopenharmony_ci	 * to try to initialize the sensor to detect its presence */
328962306a36Sopenharmony_ci	sd->sensor = -1;
329062306a36Sopenharmony_ci
329162306a36Sopenharmony_ci	/* Test for 76xx */
329262306a36Sopenharmony_ci	if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
329362306a36Sopenharmony_ci		ov7xx0_configure(sd);
329462306a36Sopenharmony_ci
329562306a36Sopenharmony_ci	/* Test for 6xx0 */
329662306a36Sopenharmony_ci	} else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
329762306a36Sopenharmony_ci		ov6xx0_configure(sd);
329862306a36Sopenharmony_ci
329962306a36Sopenharmony_ci	/* Test for 8xx0 */
330062306a36Sopenharmony_ci	} else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
330162306a36Sopenharmony_ci		ov8xx0_configure(sd);
330262306a36Sopenharmony_ci
330362306a36Sopenharmony_ci	/* Test for 3xxx / 2xxx */
330462306a36Sopenharmony_ci	} else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
330562306a36Sopenharmony_ci		ov_hires_configure(sd);
330662306a36Sopenharmony_ci	} else {
330762306a36Sopenharmony_ci		gspca_err(gspca_dev, "Can't determine sensor slave IDs\n");
330862306a36Sopenharmony_ci		goto error;
330962306a36Sopenharmony_ci	}
331062306a36Sopenharmony_ci
331162306a36Sopenharmony_ci	if (sd->sensor < 0)
331262306a36Sopenharmony_ci		goto error;
331362306a36Sopenharmony_ci
331462306a36Sopenharmony_ci	ov51x_led_control(sd, 0);	/* turn LED off */
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_ci	switch (sd->bridge) {
331762306a36Sopenharmony_ci	case BRIDGE_OV511:
331862306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
331962306a36Sopenharmony_ci		if (sd->sif) {
332062306a36Sopenharmony_ci			cam->cam_mode = ov511_sif_mode;
332162306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
332262306a36Sopenharmony_ci		}
332362306a36Sopenharmony_ci		break;
332462306a36Sopenharmony_ci	case BRIDGE_OV518:
332562306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
332662306a36Sopenharmony_ci		if (sd->sif) {
332762306a36Sopenharmony_ci			cam->cam_mode = ov518_sif_mode;
332862306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
332962306a36Sopenharmony_ci		}
333062306a36Sopenharmony_ci		break;
333162306a36Sopenharmony_ci	case BRIDGE_OV519:
333262306a36Sopenharmony_ci		if (sd->sif) {
333362306a36Sopenharmony_ci			cam->cam_mode = ov519_sif_mode;
333462306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
333562306a36Sopenharmony_ci		}
333662306a36Sopenharmony_ci		break;
333762306a36Sopenharmony_ci	case BRIDGE_OVFX2:
333862306a36Sopenharmony_ci		switch (sd->sensor) {
333962306a36Sopenharmony_ci		case SEN_OV2610:
334062306a36Sopenharmony_ci		case SEN_OV2610AE:
334162306a36Sopenharmony_ci			cam->cam_mode = ovfx2_ov2610_mode;
334262306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
334362306a36Sopenharmony_ci			break;
334462306a36Sopenharmony_ci		case SEN_OV3610:
334562306a36Sopenharmony_ci			cam->cam_mode = ovfx2_ov3610_mode;
334662306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
334762306a36Sopenharmony_ci			break;
334862306a36Sopenharmony_ci		case SEN_OV9600:
334962306a36Sopenharmony_ci			cam->cam_mode = ovfx2_ov9600_mode;
335062306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
335162306a36Sopenharmony_ci			break;
335262306a36Sopenharmony_ci		default:
335362306a36Sopenharmony_ci			if (sd->sif) {
335462306a36Sopenharmony_ci				cam->cam_mode = ov519_sif_mode;
335562306a36Sopenharmony_ci				cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
335662306a36Sopenharmony_ci			}
335762306a36Sopenharmony_ci			break;
335862306a36Sopenharmony_ci		}
335962306a36Sopenharmony_ci		break;
336062306a36Sopenharmony_ci	case BRIDGE_W9968CF:
336162306a36Sopenharmony_ci		if (sd->sif)
336262306a36Sopenharmony_ci			cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci		/* w9968cf needs initialisation once the sensor is known */
336562306a36Sopenharmony_ci		w9968cf_init(sd);
336662306a36Sopenharmony_ci		break;
336762306a36Sopenharmony_ci	}
336862306a36Sopenharmony_ci
336962306a36Sopenharmony_ci	/* initialize the sensor */
337062306a36Sopenharmony_ci	switch (sd->sensor) {
337162306a36Sopenharmony_ci	case SEN_OV2610:
337262306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
337362306a36Sopenharmony_ci
337462306a36Sopenharmony_ci		/* Enable autogain, autoexpo, awb, bandfilter */
337562306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x27, 0x27);
337662306a36Sopenharmony_ci		break;
337762306a36Sopenharmony_ci	case SEN_OV2610AE:
337862306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_ci		/* enable autoexpo */
338162306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x05, 0x05);
338262306a36Sopenharmony_ci		break;
338362306a36Sopenharmony_ci	case SEN_OV3610:
338462306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci		/* Enable autogain, autoexpo, awb, bandfilter */
338762306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x27, 0x27);
338862306a36Sopenharmony_ci		break;
338962306a36Sopenharmony_ci	case SEN_OV6620:
339062306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
339162306a36Sopenharmony_ci		break;
339262306a36Sopenharmony_ci	case SEN_OV6630:
339362306a36Sopenharmony_ci	case SEN_OV66308AF:
339462306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
339562306a36Sopenharmony_ci		break;
339662306a36Sopenharmony_ci	default:
339762306a36Sopenharmony_ci/*	case SEN_OV7610: */
339862306a36Sopenharmony_ci/*	case SEN_OV76BE: */
339962306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
340062306a36Sopenharmony_ci		i2c_w_mask(sd, 0x0e, 0x00, 0x40);
340162306a36Sopenharmony_ci		break;
340262306a36Sopenharmony_ci	case SEN_OV7620:
340362306a36Sopenharmony_ci	case SEN_OV7620AE:
340462306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
340562306a36Sopenharmony_ci		break;
340662306a36Sopenharmony_ci	case SEN_OV7640:
340762306a36Sopenharmony_ci	case SEN_OV7648:
340862306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
340962306a36Sopenharmony_ci		break;
341062306a36Sopenharmony_ci	case SEN_OV7660:
341162306a36Sopenharmony_ci		i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
341262306a36Sopenharmony_ci		msleep(14);
341362306a36Sopenharmony_ci		reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
341462306a36Sopenharmony_ci		write_regvals(sd, init_519_ov7660,
341562306a36Sopenharmony_ci				ARRAY_SIZE(init_519_ov7660));
341662306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
341762306a36Sopenharmony_ci		sd->gspca_dev.curr_mode = 1;	/* 640x480 */
341862306a36Sopenharmony_ci		ov519_set_mode(sd);
341962306a36Sopenharmony_ci		ov519_set_fr(sd);
342062306a36Sopenharmony_ci		sd_reset_snapshot(gspca_dev);
342162306a36Sopenharmony_ci		ov51x_restart(sd);
342262306a36Sopenharmony_ci		ov51x_stop(sd);			/* not in win traces */
342362306a36Sopenharmony_ci		ov51x_led_control(sd, 0);
342462306a36Sopenharmony_ci		break;
342562306a36Sopenharmony_ci	case SEN_OV7670:
342662306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
342762306a36Sopenharmony_ci		break;
342862306a36Sopenharmony_ci	case SEN_OV8610:
342962306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
343062306a36Sopenharmony_ci		break;
343162306a36Sopenharmony_ci	case SEN_OV9600:
343262306a36Sopenharmony_ci		write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
343362306a36Sopenharmony_ci
343462306a36Sopenharmony_ci		/* enable autoexpo */
343562306a36Sopenharmony_ci/*		i2c_w_mask(sd, 0x13, 0x05, 0x05); */
343662306a36Sopenharmony_ci		break;
343762306a36Sopenharmony_ci	}
343862306a36Sopenharmony_ci	return gspca_dev->usb_err;
343962306a36Sopenharmony_cierror:
344062306a36Sopenharmony_ci	gspca_err(gspca_dev, "OV519 Config failed\n");
344162306a36Sopenharmony_ci	return -EINVAL;
344262306a36Sopenharmony_ci}
344362306a36Sopenharmony_ci
344462306a36Sopenharmony_ci/* function called at start time before URB creation */
344562306a36Sopenharmony_cistatic int sd_isoc_init(struct gspca_dev *gspca_dev)
344662306a36Sopenharmony_ci{
344762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ci	switch (sd->bridge) {
345062306a36Sopenharmony_ci	case BRIDGE_OVFX2:
345162306a36Sopenharmony_ci		if (gspca_dev->pixfmt.width != 800)
345262306a36Sopenharmony_ci			gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
345362306a36Sopenharmony_ci		else
345462306a36Sopenharmony_ci			gspca_dev->cam.bulk_size = 7 * 4096;
345562306a36Sopenharmony_ci		break;
345662306a36Sopenharmony_ci	}
345762306a36Sopenharmony_ci	return 0;
345862306a36Sopenharmony_ci}
345962306a36Sopenharmony_ci
346062306a36Sopenharmony_ci/* Set up the OV511/OV511+ with the given image parameters.
346162306a36Sopenharmony_ci *
346262306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions)
346362306a36Sopenharmony_ci */
346462306a36Sopenharmony_cistatic void ov511_mode_init_regs(struct sd *sd)
346562306a36Sopenharmony_ci{
346662306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
346762306a36Sopenharmony_ci	int hsegs, vsegs, packet_size, fps, needed;
346862306a36Sopenharmony_ci	int interlaced = 0;
346962306a36Sopenharmony_ci	struct usb_host_interface *alt;
347062306a36Sopenharmony_ci	struct usb_interface *intf;
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_ci	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
347362306a36Sopenharmony_ci	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
347462306a36Sopenharmony_ci	if (!alt) {
347562306a36Sopenharmony_ci		gspca_err(gspca_dev, "Couldn't get altsetting\n");
347662306a36Sopenharmony_ci		sd->gspca_dev.usb_err = -EIO;
347762306a36Sopenharmony_ci		return;
347862306a36Sopenharmony_ci	}
347962306a36Sopenharmony_ci
348062306a36Sopenharmony_ci	if (alt->desc.bNumEndpoints < 1) {
348162306a36Sopenharmony_ci		sd->gspca_dev.usb_err = -ENODEV;
348262306a36Sopenharmony_ci		return;
348362306a36Sopenharmony_ci	}
348462306a36Sopenharmony_ci
348562306a36Sopenharmony_ci	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
348662306a36Sopenharmony_ci	reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
348762306a36Sopenharmony_ci
348862306a36Sopenharmony_ci	reg_w(sd, R511_CAM_UV_EN, 0x01);
348962306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_UV_EN, 0x01);
349062306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_OPTS, 0x03);
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci	/* Here I'm assuming that snapshot size == image size.
349362306a36Sopenharmony_ci	 * I hope that's always true. --claudio
349462306a36Sopenharmony_ci	 */
349562306a36Sopenharmony_ci	hsegs = (sd->gspca_dev.pixfmt.width >> 3) - 1;
349662306a36Sopenharmony_ci	vsegs = (sd->gspca_dev.pixfmt.height >> 3) - 1;
349762306a36Sopenharmony_ci
349862306a36Sopenharmony_ci	reg_w(sd, R511_CAM_PXCNT, hsegs);
349962306a36Sopenharmony_ci	reg_w(sd, R511_CAM_LNCNT, vsegs);
350062306a36Sopenharmony_ci	reg_w(sd, R511_CAM_PXDIV, 0x00);
350162306a36Sopenharmony_ci	reg_w(sd, R511_CAM_LNDIV, 0x00);
350262306a36Sopenharmony_ci
350362306a36Sopenharmony_ci	/* YUV420, low pass filter on */
350462306a36Sopenharmony_ci	reg_w(sd, R511_CAM_OPTS, 0x03);
350562306a36Sopenharmony_ci
350662306a36Sopenharmony_ci	/* Snapshot additions */
350762306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_PXCNT, hsegs);
350862306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_LNCNT, vsegs);
350962306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_PXDIV, 0x00);
351062306a36Sopenharmony_ci	reg_w(sd, R511_SNAP_LNDIV, 0x00);
351162306a36Sopenharmony_ci
351262306a36Sopenharmony_ci	/******** Set the framerate ********/
351362306a36Sopenharmony_ci	if (frame_rate > 0)
351462306a36Sopenharmony_ci		sd->frame_rate = frame_rate;
351562306a36Sopenharmony_ci
351662306a36Sopenharmony_ci	switch (sd->sensor) {
351762306a36Sopenharmony_ci	case SEN_OV6620:
351862306a36Sopenharmony_ci		/* No framerate control, doesn't like higher rates yet */
351962306a36Sopenharmony_ci		sd->clockdiv = 3;
352062306a36Sopenharmony_ci		break;
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci	/* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
352362306a36Sopenharmony_ci	   for more sensors we need to do this for them too */
352462306a36Sopenharmony_ci	case SEN_OV7620:
352562306a36Sopenharmony_ci	case SEN_OV7620AE:
352662306a36Sopenharmony_ci	case SEN_OV7640:
352762306a36Sopenharmony_ci	case SEN_OV7648:
352862306a36Sopenharmony_ci	case SEN_OV76BE:
352962306a36Sopenharmony_ci		if (sd->gspca_dev.pixfmt.width == 320)
353062306a36Sopenharmony_ci			interlaced = 1;
353162306a36Sopenharmony_ci		fallthrough;
353262306a36Sopenharmony_ci	case SEN_OV6630:
353362306a36Sopenharmony_ci	case SEN_OV7610:
353462306a36Sopenharmony_ci	case SEN_OV7670:
353562306a36Sopenharmony_ci		switch (sd->frame_rate) {
353662306a36Sopenharmony_ci		case 30:
353762306a36Sopenharmony_ci		case 25:
353862306a36Sopenharmony_ci			/* Not enough bandwidth to do 640x480 @ 30 fps */
353962306a36Sopenharmony_ci			if (sd->gspca_dev.pixfmt.width != 640) {
354062306a36Sopenharmony_ci				sd->clockdiv = 0;
354162306a36Sopenharmony_ci				break;
354262306a36Sopenharmony_ci			}
354362306a36Sopenharmony_ci			/* For 640x480 case */
354462306a36Sopenharmony_ci			fallthrough;
354562306a36Sopenharmony_ci		default:
354662306a36Sopenharmony_ci/*		case 20: */
354762306a36Sopenharmony_ci/*		case 15: */
354862306a36Sopenharmony_ci			sd->clockdiv = 1;
354962306a36Sopenharmony_ci			break;
355062306a36Sopenharmony_ci		case 10:
355162306a36Sopenharmony_ci			sd->clockdiv = 2;
355262306a36Sopenharmony_ci			break;
355362306a36Sopenharmony_ci		case 5:
355462306a36Sopenharmony_ci			sd->clockdiv = 5;
355562306a36Sopenharmony_ci			break;
355662306a36Sopenharmony_ci		}
355762306a36Sopenharmony_ci		if (interlaced) {
355862306a36Sopenharmony_ci			sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
355962306a36Sopenharmony_ci			/* Higher then 10 does not work */
356062306a36Sopenharmony_ci			if (sd->clockdiv > 10)
356162306a36Sopenharmony_ci				sd->clockdiv = 10;
356262306a36Sopenharmony_ci		}
356362306a36Sopenharmony_ci		break;
356462306a36Sopenharmony_ci
356562306a36Sopenharmony_ci	case SEN_OV8610:
356662306a36Sopenharmony_ci		/* No framerate control ?? */
356762306a36Sopenharmony_ci		sd->clockdiv = 0;
356862306a36Sopenharmony_ci		break;
356962306a36Sopenharmony_ci	}
357062306a36Sopenharmony_ci
357162306a36Sopenharmony_ci	/* Check if we have enough bandwidth to disable compression */
357262306a36Sopenharmony_ci	fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
357362306a36Sopenharmony_ci	needed = fps * sd->gspca_dev.pixfmt.width *
357462306a36Sopenharmony_ci			sd->gspca_dev.pixfmt.height * 3 / 2;
357562306a36Sopenharmony_ci	/* 1000 isoc packets/sec */
357662306a36Sopenharmony_ci	if (needed > 1000 * packet_size) {
357762306a36Sopenharmony_ci		/* Enable Y and UV quantization and compression */
357862306a36Sopenharmony_ci		reg_w(sd, R511_COMP_EN, 0x07);
357962306a36Sopenharmony_ci		reg_w(sd, R511_COMP_LUT_EN, 0x03);
358062306a36Sopenharmony_ci	} else {
358162306a36Sopenharmony_ci		reg_w(sd, R511_COMP_EN, 0x06);
358262306a36Sopenharmony_ci		reg_w(sd, R511_COMP_LUT_EN, 0x00);
358362306a36Sopenharmony_ci	}
358462306a36Sopenharmony_ci
358562306a36Sopenharmony_ci	reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
358662306a36Sopenharmony_ci	reg_w(sd, R51x_SYS_RESET, 0);
358762306a36Sopenharmony_ci}
358862306a36Sopenharmony_ci
358962306a36Sopenharmony_ci/* Sets up the OV518/OV518+ with the given image parameters
359062306a36Sopenharmony_ci *
359162306a36Sopenharmony_ci * OV518 needs a completely different approach, until we can figure out what
359262306a36Sopenharmony_ci * the individual registers do. Also, only 15 FPS is supported now.
359362306a36Sopenharmony_ci *
359462306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions)
359562306a36Sopenharmony_ci */
359662306a36Sopenharmony_cistatic void ov518_mode_init_regs(struct sd *sd)
359762306a36Sopenharmony_ci{
359862306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
359962306a36Sopenharmony_ci	int hsegs, vsegs, packet_size;
360062306a36Sopenharmony_ci	struct usb_host_interface *alt;
360162306a36Sopenharmony_ci	struct usb_interface *intf;
360262306a36Sopenharmony_ci
360362306a36Sopenharmony_ci	intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
360462306a36Sopenharmony_ci	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
360562306a36Sopenharmony_ci	if (!alt) {
360662306a36Sopenharmony_ci		gspca_err(gspca_dev, "Couldn't get altsetting\n");
360762306a36Sopenharmony_ci		sd->gspca_dev.usb_err = -EIO;
360862306a36Sopenharmony_ci		return;
360962306a36Sopenharmony_ci	}
361062306a36Sopenharmony_ci
361162306a36Sopenharmony_ci	if (alt->desc.bNumEndpoints < 1) {
361262306a36Sopenharmony_ci		sd->gspca_dev.usb_err = -ENODEV;
361362306a36Sopenharmony_ci		return;
361462306a36Sopenharmony_ci	}
361562306a36Sopenharmony_ci
361662306a36Sopenharmony_ci	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
361762306a36Sopenharmony_ci	ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
361862306a36Sopenharmony_ci
361962306a36Sopenharmony_ci	/******** Set the mode ********/
362062306a36Sopenharmony_ci	reg_w(sd, 0x2b, 0);
362162306a36Sopenharmony_ci	reg_w(sd, 0x2c, 0);
362262306a36Sopenharmony_ci	reg_w(sd, 0x2d, 0);
362362306a36Sopenharmony_ci	reg_w(sd, 0x2e, 0);
362462306a36Sopenharmony_ci	reg_w(sd, 0x3b, 0);
362562306a36Sopenharmony_ci	reg_w(sd, 0x3c, 0);
362662306a36Sopenharmony_ci	reg_w(sd, 0x3d, 0);
362762306a36Sopenharmony_ci	reg_w(sd, 0x3e, 0);
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV518) {
363062306a36Sopenharmony_ci		/* Set 8-bit (YVYU) input format */
363162306a36Sopenharmony_ci		reg_w_mask(sd, 0x20, 0x08, 0x08);
363262306a36Sopenharmony_ci
363362306a36Sopenharmony_ci		/* Set 12-bit (4:2:0) output format */
363462306a36Sopenharmony_ci		reg_w_mask(sd, 0x28, 0x80, 0xf0);
363562306a36Sopenharmony_ci		reg_w_mask(sd, 0x38, 0x80, 0xf0);
363662306a36Sopenharmony_ci	} else {
363762306a36Sopenharmony_ci		reg_w(sd, 0x28, 0x80);
363862306a36Sopenharmony_ci		reg_w(sd, 0x38, 0x80);
363962306a36Sopenharmony_ci	}
364062306a36Sopenharmony_ci
364162306a36Sopenharmony_ci	hsegs = sd->gspca_dev.pixfmt.width / 16;
364262306a36Sopenharmony_ci	vsegs = sd->gspca_dev.pixfmt.height / 4;
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_ci	reg_w(sd, 0x29, hsegs);
364562306a36Sopenharmony_ci	reg_w(sd, 0x2a, vsegs);
364662306a36Sopenharmony_ci
364762306a36Sopenharmony_ci	reg_w(sd, 0x39, hsegs);
364862306a36Sopenharmony_ci	reg_w(sd, 0x3a, vsegs);
364962306a36Sopenharmony_ci
365062306a36Sopenharmony_ci	/* Windows driver does this here; who knows why */
365162306a36Sopenharmony_ci	reg_w(sd, 0x2f, 0x80);
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci	/******** Set the framerate ********/
365462306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV518PLUS && sd->revision == 0 &&
365562306a36Sopenharmony_ci					      sd->sensor == SEN_OV7620AE)
365662306a36Sopenharmony_ci		sd->clockdiv = 0;
365762306a36Sopenharmony_ci	else
365862306a36Sopenharmony_ci		sd->clockdiv = 1;
365962306a36Sopenharmony_ci
366062306a36Sopenharmony_ci	/* Mode independent, but framerate dependent, regs */
366162306a36Sopenharmony_ci	/* 0x51: Clock divider; Only works on some cams which use 2 crystals */
366262306a36Sopenharmony_ci	reg_w(sd, 0x51, 0x04);
366362306a36Sopenharmony_ci	reg_w(sd, 0x22, 0x18);
366462306a36Sopenharmony_ci	reg_w(sd, 0x23, 0xff);
366562306a36Sopenharmony_ci
366662306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV518PLUS) {
366762306a36Sopenharmony_ci		switch (sd->sensor) {
366862306a36Sopenharmony_ci		case SEN_OV7620AE:
366962306a36Sopenharmony_ci			/*
367062306a36Sopenharmony_ci			 * HdG: 640x480 needs special handling on device
367162306a36Sopenharmony_ci			 * revision 2, we check for device revision > 0 to
367262306a36Sopenharmony_ci			 * avoid regressions, as we don't know the correct
367362306a36Sopenharmony_ci			 * thing todo for revision 1.
367462306a36Sopenharmony_ci			 *
367562306a36Sopenharmony_ci			 * Also this likely means we don't need to
367662306a36Sopenharmony_ci			 * differentiate between the OV7620 and OV7620AE,
367762306a36Sopenharmony_ci			 * earlier testing hitting this same problem likely
367862306a36Sopenharmony_ci			 * happened to be with revision < 2 cams using an
367962306a36Sopenharmony_ci			 * OV7620 and revision 2 cams using an OV7620AE.
368062306a36Sopenharmony_ci			 */
368162306a36Sopenharmony_ci			if (sd->revision > 0 &&
368262306a36Sopenharmony_ci					sd->gspca_dev.pixfmt.width == 640) {
368362306a36Sopenharmony_ci				reg_w(sd, 0x20, 0x60);
368462306a36Sopenharmony_ci				reg_w(sd, 0x21, 0x1f);
368562306a36Sopenharmony_ci			} else {
368662306a36Sopenharmony_ci				reg_w(sd, 0x20, 0x00);
368762306a36Sopenharmony_ci				reg_w(sd, 0x21, 0x19);
368862306a36Sopenharmony_ci			}
368962306a36Sopenharmony_ci			break;
369062306a36Sopenharmony_ci		case SEN_OV7620:
369162306a36Sopenharmony_ci			reg_w(sd, 0x20, 0x00);
369262306a36Sopenharmony_ci			reg_w(sd, 0x21, 0x19);
369362306a36Sopenharmony_ci			break;
369462306a36Sopenharmony_ci		default:
369562306a36Sopenharmony_ci			reg_w(sd, 0x21, 0x19);
369662306a36Sopenharmony_ci		}
369762306a36Sopenharmony_ci	} else
369862306a36Sopenharmony_ci		reg_w(sd, 0x71, 0x17);	/* Compression-related? */
369962306a36Sopenharmony_ci
370062306a36Sopenharmony_ci	/* FIXME: Sensor-specific */
370162306a36Sopenharmony_ci	/* Bit 5 is what matters here. Of course, it is "reserved" */
370262306a36Sopenharmony_ci	i2c_w(sd, 0x54, 0x23);
370362306a36Sopenharmony_ci
370462306a36Sopenharmony_ci	reg_w(sd, 0x2f, 0x80);
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV518PLUS) {
370762306a36Sopenharmony_ci		reg_w(sd, 0x24, 0x94);
370862306a36Sopenharmony_ci		reg_w(sd, 0x25, 0x90);
370962306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc4,    400, 2);	/* 190h   */
371062306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc6,    540, 2);	/* 21ch   */
371162306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc7,    540, 2);	/* 21ch   */
371262306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc8,    108, 2);	/* 6ch    */
371362306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xca, 131098, 3);	/* 2001ah */
371462306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcb,    532, 2);	/* 214h   */
371562306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcc,   2400, 2);	/* 960h   */
371662306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcd,     32, 2);	/* 20h    */
371762306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xce,    608, 2);	/* 260h   */
371862306a36Sopenharmony_ci	} else {
371962306a36Sopenharmony_ci		reg_w(sd, 0x24, 0x9f);
372062306a36Sopenharmony_ci		reg_w(sd, 0x25, 0x90);
372162306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc4,    400, 2);	/* 190h   */
372262306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc6,    381, 2);	/* 17dh   */
372362306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc7,    381, 2);	/* 17dh   */
372462306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xc8,    128, 2);	/* 80h    */
372562306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xca, 183331, 3);	/* 2cc23h */
372662306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcb,    746, 2);	/* 2eah   */
372762306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcc,   1750, 2);	/* 6d6h   */
372862306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xcd,     45, 2);	/* 2dh    */
372962306a36Sopenharmony_ci		ov518_reg_w32(sd, 0xce,    851, 2);	/* 353h   */
373062306a36Sopenharmony_ci	}
373162306a36Sopenharmony_ci
373262306a36Sopenharmony_ci	reg_w(sd, 0x2f, 0x80);
373362306a36Sopenharmony_ci}
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_ci/* Sets up the OV519 with the given image parameters
373662306a36Sopenharmony_ci *
373762306a36Sopenharmony_ci * OV519 needs a completely different approach, until we can figure out what
373862306a36Sopenharmony_ci * the individual registers do.
373962306a36Sopenharmony_ci *
374062306a36Sopenharmony_ci * Do not put any sensor-specific code in here (including I2C I/O functions)
374162306a36Sopenharmony_ci */
374262306a36Sopenharmony_cistatic void ov519_mode_init_regs(struct sd *sd)
374362306a36Sopenharmony_ci{
374462306a36Sopenharmony_ci	static const struct ov_regvals mode_init_519_ov7670[] = {
374562306a36Sopenharmony_ci		{ 0x5d,	0x03 }, /* Turn off suspend mode */
374662306a36Sopenharmony_ci		{ 0x53,	0x9f }, /* was 9b in 1.65-1.08 */
374762306a36Sopenharmony_ci		{ OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
374862306a36Sopenharmony_ci		{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
374962306a36Sopenharmony_ci		{ 0xa3,	0x18 },
375062306a36Sopenharmony_ci		{ 0xa4,	0x04 },
375162306a36Sopenharmony_ci		{ 0xa5,	0x28 },
375262306a36Sopenharmony_ci		{ 0x37,	0x00 },	/* SetUsbInit */
375362306a36Sopenharmony_ci		{ 0x55,	0x02 }, /* 4.096 Mhz audio clock */
375462306a36Sopenharmony_ci		/* Enable both fields, YUV Input, disable defect comp (why?) */
375562306a36Sopenharmony_ci		{ 0x20,	0x0c },
375662306a36Sopenharmony_ci		{ 0x21,	0x38 },
375762306a36Sopenharmony_ci		{ 0x22,	0x1d },
375862306a36Sopenharmony_ci		{ 0x17,	0x50 }, /* undocumented */
375962306a36Sopenharmony_ci		{ 0x37,	0x00 }, /* undocumented */
376062306a36Sopenharmony_ci		{ 0x40,	0xff }, /* I2C timeout counter */
376162306a36Sopenharmony_ci		{ 0x46,	0x00 }, /* I2C clock prescaler */
376262306a36Sopenharmony_ci		{ 0x59,	0x04 },	/* new from windrv 090403 */
376362306a36Sopenharmony_ci		{ 0xff,	0x00 }, /* undocumented */
376462306a36Sopenharmony_ci		/* windows reads 0x55 at this point, why? */
376562306a36Sopenharmony_ci	};
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci	static const struct ov_regvals mode_init_519[] = {
376862306a36Sopenharmony_ci		{ 0x5d,	0x03 }, /* Turn off suspend mode */
376962306a36Sopenharmony_ci		{ 0x53,	0x9f }, /* was 9b in 1.65-1.08 */
377062306a36Sopenharmony_ci		{ OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
377162306a36Sopenharmony_ci		{ 0xa2,	0x20 }, /* a2-a5 are undocumented */
377262306a36Sopenharmony_ci		{ 0xa3,	0x18 },
377362306a36Sopenharmony_ci		{ 0xa4,	0x04 },
377462306a36Sopenharmony_ci		{ 0xa5,	0x28 },
377562306a36Sopenharmony_ci		{ 0x37,	0x00 },	/* SetUsbInit */
377662306a36Sopenharmony_ci		{ 0x55,	0x02 }, /* 4.096 Mhz audio clock */
377762306a36Sopenharmony_ci		/* Enable both fields, YUV Input, disable defect comp (why?) */
377862306a36Sopenharmony_ci		{ 0x22,	0x1d },
377962306a36Sopenharmony_ci		{ 0x17,	0x50 }, /* undocumented */
378062306a36Sopenharmony_ci		{ 0x37,	0x00 }, /* undocumented */
378162306a36Sopenharmony_ci		{ 0x40,	0xff }, /* I2C timeout counter */
378262306a36Sopenharmony_ci		{ 0x46,	0x00 }, /* I2C clock prescaler */
378362306a36Sopenharmony_ci		{ 0x59,	0x04 },	/* new from windrv 090403 */
378462306a36Sopenharmony_ci		{ 0xff,	0x00 }, /* undocumented */
378562306a36Sopenharmony_ci		/* windows reads 0x55 at this point, why? */
378662306a36Sopenharmony_ci	};
378762306a36Sopenharmony_ci
378862306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
378962306a36Sopenharmony_ci
379062306a36Sopenharmony_ci	/******** Set the mode ********/
379162306a36Sopenharmony_ci	switch (sd->sensor) {
379262306a36Sopenharmony_ci	default:
379362306a36Sopenharmony_ci		write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
379462306a36Sopenharmony_ci		if (sd->sensor == SEN_OV7640 ||
379562306a36Sopenharmony_ci		    sd->sensor == SEN_OV7648) {
379662306a36Sopenharmony_ci			/* Select 8-bit input mode */
379762306a36Sopenharmony_ci			reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
379862306a36Sopenharmony_ci		}
379962306a36Sopenharmony_ci		break;
380062306a36Sopenharmony_ci	case SEN_OV7660:
380162306a36Sopenharmony_ci		return;		/* done by ov519_set_mode/fr() */
380262306a36Sopenharmony_ci	case SEN_OV7670:
380362306a36Sopenharmony_ci		write_regvals(sd, mode_init_519_ov7670,
380462306a36Sopenharmony_ci				ARRAY_SIZE(mode_init_519_ov7670));
380562306a36Sopenharmony_ci		break;
380662306a36Sopenharmony_ci	}
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci	reg_w(sd, OV519_R10_H_SIZE,	sd->gspca_dev.pixfmt.width >> 4);
380962306a36Sopenharmony_ci	reg_w(sd, OV519_R11_V_SIZE,	sd->gspca_dev.pixfmt.height >> 3);
381062306a36Sopenharmony_ci	if (sd->sensor == SEN_OV7670 &&
381162306a36Sopenharmony_ci	    sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
381262306a36Sopenharmony_ci		reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
381362306a36Sopenharmony_ci	else if (sd->sensor == SEN_OV7648 &&
381462306a36Sopenharmony_ci	    sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
381562306a36Sopenharmony_ci		reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
381662306a36Sopenharmony_ci	else
381762306a36Sopenharmony_ci		reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
381862306a36Sopenharmony_ci	reg_w(sd, OV519_R13_X_OFFSETH,	0x00);
381962306a36Sopenharmony_ci	reg_w(sd, OV519_R14_Y_OFFSETL,	0x00);
382062306a36Sopenharmony_ci	reg_w(sd, OV519_R15_Y_OFFSETH,	0x00);
382162306a36Sopenharmony_ci	reg_w(sd, OV519_R16_DIVIDER,	0x00);
382262306a36Sopenharmony_ci	reg_w(sd, OV519_R25_FORMAT,	0x03); /* YUV422 */
382362306a36Sopenharmony_ci	reg_w(sd, 0x26,			0x00); /* Undocumented */
382462306a36Sopenharmony_ci
382562306a36Sopenharmony_ci	/******** Set the framerate ********/
382662306a36Sopenharmony_ci	if (frame_rate > 0)
382762306a36Sopenharmony_ci		sd->frame_rate = frame_rate;
382862306a36Sopenharmony_ci
382962306a36Sopenharmony_ci/* FIXME: These are only valid at the max resolution. */
383062306a36Sopenharmony_ci	sd->clockdiv = 0;
383162306a36Sopenharmony_ci	switch (sd->sensor) {
383262306a36Sopenharmony_ci	case SEN_OV7640:
383362306a36Sopenharmony_ci	case SEN_OV7648:
383462306a36Sopenharmony_ci		switch (sd->frame_rate) {
383562306a36Sopenharmony_ci		default:
383662306a36Sopenharmony_ci/*		case 30: */
383762306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x0c);
383862306a36Sopenharmony_ci			reg_w(sd, 0x23, 0xff);
383962306a36Sopenharmony_ci			break;
384062306a36Sopenharmony_ci		case 25:
384162306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x0c);
384262306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1f);
384362306a36Sopenharmony_ci			break;
384462306a36Sopenharmony_ci		case 20:
384562306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x0c);
384662306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1b);
384762306a36Sopenharmony_ci			break;
384862306a36Sopenharmony_ci		case 15:
384962306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x04);
385062306a36Sopenharmony_ci			reg_w(sd, 0x23, 0xff);
385162306a36Sopenharmony_ci			sd->clockdiv = 1;
385262306a36Sopenharmony_ci			break;
385362306a36Sopenharmony_ci		case 10:
385462306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x04);
385562306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1f);
385662306a36Sopenharmony_ci			sd->clockdiv = 1;
385762306a36Sopenharmony_ci			break;
385862306a36Sopenharmony_ci		case 5:
385962306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x04);
386062306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1b);
386162306a36Sopenharmony_ci			sd->clockdiv = 1;
386262306a36Sopenharmony_ci			break;
386362306a36Sopenharmony_ci		}
386462306a36Sopenharmony_ci		break;
386562306a36Sopenharmony_ci	case SEN_OV8610:
386662306a36Sopenharmony_ci		switch (sd->frame_rate) {
386762306a36Sopenharmony_ci		default:	/* 15 fps */
386862306a36Sopenharmony_ci/*		case 15: */
386962306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x06);
387062306a36Sopenharmony_ci			reg_w(sd, 0x23, 0xff);
387162306a36Sopenharmony_ci			break;
387262306a36Sopenharmony_ci		case 10:
387362306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x06);
387462306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1f);
387562306a36Sopenharmony_ci			break;
387662306a36Sopenharmony_ci		case 5:
387762306a36Sopenharmony_ci			reg_w(sd, 0xa4, 0x06);
387862306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1b);
387962306a36Sopenharmony_ci			break;
388062306a36Sopenharmony_ci		}
388162306a36Sopenharmony_ci		break;
388262306a36Sopenharmony_ci	case SEN_OV7670:		/* guesses, based on 7640 */
388362306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_STREAM, "Setting framerate to %d fps\n",
388462306a36Sopenharmony_ci			  (sd->frame_rate == 0) ? 15 : sd->frame_rate);
388562306a36Sopenharmony_ci		reg_w(sd, 0xa4, 0x10);
388662306a36Sopenharmony_ci		switch (sd->frame_rate) {
388762306a36Sopenharmony_ci		case 30:
388862306a36Sopenharmony_ci			reg_w(sd, 0x23, 0xff);
388962306a36Sopenharmony_ci			break;
389062306a36Sopenharmony_ci		case 20:
389162306a36Sopenharmony_ci			reg_w(sd, 0x23, 0x1b);
389262306a36Sopenharmony_ci			break;
389362306a36Sopenharmony_ci		default:
389462306a36Sopenharmony_ci/*		case 15: */
389562306a36Sopenharmony_ci			reg_w(sd, 0x23, 0xff);
389662306a36Sopenharmony_ci			sd->clockdiv = 1;
389762306a36Sopenharmony_ci			break;
389862306a36Sopenharmony_ci		}
389962306a36Sopenharmony_ci		break;
390062306a36Sopenharmony_ci	}
390162306a36Sopenharmony_ci}
390262306a36Sopenharmony_ci
390362306a36Sopenharmony_cistatic void mode_init_ov_sensor_regs(struct sd *sd)
390462306a36Sopenharmony_ci{
390562306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
390662306a36Sopenharmony_ci	int qvga, xstart, xend, ystart, yend;
390762306a36Sopenharmony_ci	u8 v;
390862306a36Sopenharmony_ci
390962306a36Sopenharmony_ci	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
391062306a36Sopenharmony_ci
391162306a36Sopenharmony_ci	/******** Mode (VGA/QVGA) and sensor specific regs ********/
391262306a36Sopenharmony_ci	switch (sd->sensor) {
391362306a36Sopenharmony_ci	case SEN_OV2610:
391462306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
391562306a36Sopenharmony_ci		i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
391662306a36Sopenharmony_ci		i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
391762306a36Sopenharmony_ci		i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
391862306a36Sopenharmony_ci		i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
391962306a36Sopenharmony_ci		i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
392062306a36Sopenharmony_ci		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
392162306a36Sopenharmony_ci		return;
392262306a36Sopenharmony_ci	case SEN_OV2610AE: {
392362306a36Sopenharmony_ci		u8 v;
392462306a36Sopenharmony_ci
392562306a36Sopenharmony_ci		/* frame rates:
392662306a36Sopenharmony_ci		 *	10fps / 5 fps for 1600x1200
392762306a36Sopenharmony_ci		 *	40fps / 20fps for 800x600
392862306a36Sopenharmony_ci		 */
392962306a36Sopenharmony_ci		v = 80;
393062306a36Sopenharmony_ci		if (qvga) {
393162306a36Sopenharmony_ci			if (sd->frame_rate < 25)
393262306a36Sopenharmony_ci				v = 0x81;
393362306a36Sopenharmony_ci		} else {
393462306a36Sopenharmony_ci			if (sd->frame_rate < 10)
393562306a36Sopenharmony_ci				v = 0x81;
393662306a36Sopenharmony_ci		}
393762306a36Sopenharmony_ci		i2c_w(sd, 0x11, v);
393862306a36Sopenharmony_ci		i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
393962306a36Sopenharmony_ci		return;
394062306a36Sopenharmony_ci	    }
394162306a36Sopenharmony_ci	case SEN_OV3610:
394262306a36Sopenharmony_ci		if (qvga) {
394362306a36Sopenharmony_ci			xstart = (1040 - gspca_dev->pixfmt.width) / 2 +
394462306a36Sopenharmony_ci				(0x1f << 4);
394562306a36Sopenharmony_ci			ystart = (776 - gspca_dev->pixfmt.height) / 2;
394662306a36Sopenharmony_ci		} else {
394762306a36Sopenharmony_ci			xstart = (2076 - gspca_dev->pixfmt.width) / 2 +
394862306a36Sopenharmony_ci				(0x10 << 4);
394962306a36Sopenharmony_ci			ystart = (1544 - gspca_dev->pixfmt.height) / 2;
395062306a36Sopenharmony_ci		}
395162306a36Sopenharmony_ci		xend = xstart + gspca_dev->pixfmt.width;
395262306a36Sopenharmony_ci		yend = ystart + gspca_dev->pixfmt.height;
395362306a36Sopenharmony_ci		/* Writing to the COMH register resets the other windowing regs
395462306a36Sopenharmony_ci		   to their default values, so we must do this first. */
395562306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
395662306a36Sopenharmony_ci		i2c_w_mask(sd, 0x32,
395762306a36Sopenharmony_ci			   (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7),
395862306a36Sopenharmony_ci			   0x3f);
395962306a36Sopenharmony_ci		i2c_w_mask(sd, 0x03,
396062306a36Sopenharmony_ci			   (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3),
396162306a36Sopenharmony_ci			   0x0f);
396262306a36Sopenharmony_ci		i2c_w(sd, 0x17, xstart >> 4);
396362306a36Sopenharmony_ci		i2c_w(sd, 0x18, xend >> 4);
396462306a36Sopenharmony_ci		i2c_w(sd, 0x19, ystart >> 3);
396562306a36Sopenharmony_ci		i2c_w(sd, 0x1a, yend >> 3);
396662306a36Sopenharmony_ci		return;
396762306a36Sopenharmony_ci	case SEN_OV8610:
396862306a36Sopenharmony_ci		/* For OV8610 qvga means qsvga */
396962306a36Sopenharmony_ci		i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
397062306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
397162306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
397262306a36Sopenharmony_ci		i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
397362306a36Sopenharmony_ci		i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */
397462306a36Sopenharmony_ci		break;
397562306a36Sopenharmony_ci	case SEN_OV7610:
397662306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
397762306a36Sopenharmony_ci		i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
397862306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
397962306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
398062306a36Sopenharmony_ci		break;
398162306a36Sopenharmony_ci	case SEN_OV7620:
398262306a36Sopenharmony_ci	case SEN_OV7620AE:
398362306a36Sopenharmony_ci	case SEN_OV76BE:
398462306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
398562306a36Sopenharmony_ci		i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
398662306a36Sopenharmony_ci		i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
398762306a36Sopenharmony_ci		i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
398862306a36Sopenharmony_ci		i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
398962306a36Sopenharmony_ci		i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
399062306a36Sopenharmony_ci		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
399162306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
399262306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
399362306a36Sopenharmony_ci		if (sd->sensor == SEN_OV76BE)
399462306a36Sopenharmony_ci			i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
399562306a36Sopenharmony_ci		break;
399662306a36Sopenharmony_ci	case SEN_OV7640:
399762306a36Sopenharmony_ci	case SEN_OV7648:
399862306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
399962306a36Sopenharmony_ci		i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
400062306a36Sopenharmony_ci		/* Setting this undocumented bit in qvga mode removes a very
400162306a36Sopenharmony_ci		   annoying vertical shaking of the image */
400262306a36Sopenharmony_ci		i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
400362306a36Sopenharmony_ci		/* Unknown */
400462306a36Sopenharmony_ci		i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
400562306a36Sopenharmony_ci		/* Allow higher automatic gain (to allow higher framerates) */
400662306a36Sopenharmony_ci		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
400762306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
400862306a36Sopenharmony_ci		break;
400962306a36Sopenharmony_ci	case SEN_OV7670:
401062306a36Sopenharmony_ci		/* set COM7_FMT_VGA or COM7_FMT_QVGA
401162306a36Sopenharmony_ci		 * do we need to set anything else?
401262306a36Sopenharmony_ci		 *	HSTART etc are set in set_ov_sensor_window itself */
401362306a36Sopenharmony_ci		i2c_w_mask(sd, OV7670_R12_COM7,
401462306a36Sopenharmony_ci			 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
401562306a36Sopenharmony_ci			 OV7670_COM7_FMT_MASK);
401662306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
401762306a36Sopenharmony_ci		i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
401862306a36Sopenharmony_ci				OV7670_COM8_AWB);
401962306a36Sopenharmony_ci		if (qvga) {		/* QVGA from ov7670.c by
402062306a36Sopenharmony_ci					 * Jonathan Corbet */
402162306a36Sopenharmony_ci			xstart = 164;
402262306a36Sopenharmony_ci			xend = 28;
402362306a36Sopenharmony_ci			ystart = 14;
402462306a36Sopenharmony_ci			yend = 494;
402562306a36Sopenharmony_ci		} else {		/* VGA */
402662306a36Sopenharmony_ci			xstart = 158;
402762306a36Sopenharmony_ci			xend = 14;
402862306a36Sopenharmony_ci			ystart = 10;
402962306a36Sopenharmony_ci			yend = 490;
403062306a36Sopenharmony_ci		}
403162306a36Sopenharmony_ci		/* OV7670 hardware window registers are split across
403262306a36Sopenharmony_ci		 * multiple locations */
403362306a36Sopenharmony_ci		i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
403462306a36Sopenharmony_ci		i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
403562306a36Sopenharmony_ci		v = i2c_r(sd, OV7670_R32_HREF);
403662306a36Sopenharmony_ci		v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
403762306a36Sopenharmony_ci		msleep(10);	/* need to sleep between read and write to
403862306a36Sopenharmony_ci				 * same reg! */
403962306a36Sopenharmony_ci		i2c_w(sd, OV7670_R32_HREF, v);
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci		i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
404262306a36Sopenharmony_ci		i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
404362306a36Sopenharmony_ci		v = i2c_r(sd, OV7670_R03_VREF);
404462306a36Sopenharmony_ci		v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
404562306a36Sopenharmony_ci		msleep(10);	/* need to sleep between read and write to
404662306a36Sopenharmony_ci				 * same reg! */
404762306a36Sopenharmony_ci		i2c_w(sd, OV7670_R03_VREF, v);
404862306a36Sopenharmony_ci		break;
404962306a36Sopenharmony_ci	case SEN_OV6620:
405062306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
405162306a36Sopenharmony_ci		i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
405262306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
405362306a36Sopenharmony_ci		break;
405462306a36Sopenharmony_ci	case SEN_OV6630:
405562306a36Sopenharmony_ci	case SEN_OV66308AF:
405662306a36Sopenharmony_ci		i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
405762306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
405862306a36Sopenharmony_ci		break;
405962306a36Sopenharmony_ci	case SEN_OV9600: {
406062306a36Sopenharmony_ci		const struct ov_i2c_regvals *vals;
406162306a36Sopenharmony_ci		static const struct ov_i2c_regvals sxga_15[] = {
406262306a36Sopenharmony_ci			{0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
406362306a36Sopenharmony_ci		};
406462306a36Sopenharmony_ci		static const struct ov_i2c_regvals sxga_7_5[] = {
406562306a36Sopenharmony_ci			{0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
406662306a36Sopenharmony_ci		};
406762306a36Sopenharmony_ci		static const struct ov_i2c_regvals vga_30[] = {
406862306a36Sopenharmony_ci			{0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
406962306a36Sopenharmony_ci		};
407062306a36Sopenharmony_ci		static const struct ov_i2c_regvals vga_15[] = {
407162306a36Sopenharmony_ci			{0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
407262306a36Sopenharmony_ci		};
407362306a36Sopenharmony_ci
407462306a36Sopenharmony_ci		/* frame rates:
407562306a36Sopenharmony_ci		 *	15fps / 7.5 fps for 1280x1024
407662306a36Sopenharmony_ci		 *	30fps / 15fps for 640x480
407762306a36Sopenharmony_ci		 */
407862306a36Sopenharmony_ci		i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
407962306a36Sopenharmony_ci		if (qvga)
408062306a36Sopenharmony_ci			vals = sd->frame_rate < 30 ? vga_15 : vga_30;
408162306a36Sopenharmony_ci		else
408262306a36Sopenharmony_ci			vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
408362306a36Sopenharmony_ci		write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
408462306a36Sopenharmony_ci		return;
408562306a36Sopenharmony_ci	    }
408662306a36Sopenharmony_ci	default:
408762306a36Sopenharmony_ci		return;
408862306a36Sopenharmony_ci	}
408962306a36Sopenharmony_ci
409062306a36Sopenharmony_ci	/******** Clock programming ********/
409162306a36Sopenharmony_ci	i2c_w(sd, 0x11, sd->clockdiv);
409262306a36Sopenharmony_ci}
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
409562306a36Sopenharmony_cistatic void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
409662306a36Sopenharmony_ci{
409762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci	if (sd->gspca_dev.streaming)
410062306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x0f);	/* block stream */
410162306a36Sopenharmony_ci	i2c_w_mask(sd, OV7670_R1E_MVFP,
410262306a36Sopenharmony_ci		OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip,
410362306a36Sopenharmony_ci		OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
410462306a36Sopenharmony_ci	if (sd->gspca_dev.streaming)
410562306a36Sopenharmony_ci		reg_w(sd, OV519_R51_RESET1, 0x00);	/* restart stream */
410662306a36Sopenharmony_ci}
410762306a36Sopenharmony_ci
410862306a36Sopenharmony_cistatic void set_ov_sensor_window(struct sd *sd)
410962306a36Sopenharmony_ci{
411062306a36Sopenharmony_ci	struct gspca_dev *gspca_dev;
411162306a36Sopenharmony_ci	int qvga, crop;
411262306a36Sopenharmony_ci	int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
411362306a36Sopenharmony_ci
411462306a36Sopenharmony_ci	/* mode setup is fully handled in mode_init_ov_sensor_regs for these */
411562306a36Sopenharmony_ci	switch (sd->sensor) {
411662306a36Sopenharmony_ci	case SEN_OV2610:
411762306a36Sopenharmony_ci	case SEN_OV2610AE:
411862306a36Sopenharmony_ci	case SEN_OV3610:
411962306a36Sopenharmony_ci	case SEN_OV7670:
412062306a36Sopenharmony_ci	case SEN_OV9600:
412162306a36Sopenharmony_ci		mode_init_ov_sensor_regs(sd);
412262306a36Sopenharmony_ci		return;
412362306a36Sopenharmony_ci	case SEN_OV7660:
412462306a36Sopenharmony_ci		ov519_set_mode(sd);
412562306a36Sopenharmony_ci		ov519_set_fr(sd);
412662306a36Sopenharmony_ci		return;
412762306a36Sopenharmony_ci	}
412862306a36Sopenharmony_ci
412962306a36Sopenharmony_ci	gspca_dev = &sd->gspca_dev;
413062306a36Sopenharmony_ci	qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
413162306a36Sopenharmony_ci	crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
413262306a36Sopenharmony_ci
413362306a36Sopenharmony_ci	/* The different sensor ICs handle setting up of window differently.
413462306a36Sopenharmony_ci	 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
413562306a36Sopenharmony_ci	switch (sd->sensor) {
413662306a36Sopenharmony_ci	case SEN_OV8610:
413762306a36Sopenharmony_ci		hwsbase = 0x1e;
413862306a36Sopenharmony_ci		hwebase = 0x1e;
413962306a36Sopenharmony_ci		vwsbase = 0x02;
414062306a36Sopenharmony_ci		vwebase = 0x02;
414162306a36Sopenharmony_ci		break;
414262306a36Sopenharmony_ci	case SEN_OV7610:
414362306a36Sopenharmony_ci	case SEN_OV76BE:
414462306a36Sopenharmony_ci		hwsbase = 0x38;
414562306a36Sopenharmony_ci		hwebase = 0x3a;
414662306a36Sopenharmony_ci		vwsbase = vwebase = 0x05;
414762306a36Sopenharmony_ci		break;
414862306a36Sopenharmony_ci	case SEN_OV6620:
414962306a36Sopenharmony_ci	case SEN_OV6630:
415062306a36Sopenharmony_ci	case SEN_OV66308AF:
415162306a36Sopenharmony_ci		hwsbase = 0x38;
415262306a36Sopenharmony_ci		hwebase = 0x3a;
415362306a36Sopenharmony_ci		vwsbase = 0x05;
415462306a36Sopenharmony_ci		vwebase = 0x06;
415562306a36Sopenharmony_ci		if (sd->sensor == SEN_OV66308AF && qvga)
415662306a36Sopenharmony_ci			/* HDG: this fixes U and V getting swapped */
415762306a36Sopenharmony_ci			hwsbase++;
415862306a36Sopenharmony_ci		if (crop) {
415962306a36Sopenharmony_ci			hwsbase += 8;
416062306a36Sopenharmony_ci			hwebase += 8;
416162306a36Sopenharmony_ci			vwsbase += 11;
416262306a36Sopenharmony_ci			vwebase += 11;
416362306a36Sopenharmony_ci		}
416462306a36Sopenharmony_ci		break;
416562306a36Sopenharmony_ci	case SEN_OV7620:
416662306a36Sopenharmony_ci	case SEN_OV7620AE:
416762306a36Sopenharmony_ci		hwsbase = 0x2f;		/* From 7620.SET (spec is wrong) */
416862306a36Sopenharmony_ci		hwebase = 0x2f;
416962306a36Sopenharmony_ci		vwsbase = vwebase = 0x05;
417062306a36Sopenharmony_ci		break;
417162306a36Sopenharmony_ci	case SEN_OV7640:
417262306a36Sopenharmony_ci	case SEN_OV7648:
417362306a36Sopenharmony_ci		hwsbase = 0x1a;
417462306a36Sopenharmony_ci		hwebase = 0x1a;
417562306a36Sopenharmony_ci		vwsbase = vwebase = 0x03;
417662306a36Sopenharmony_ci		break;
417762306a36Sopenharmony_ci	default:
417862306a36Sopenharmony_ci		return;
417962306a36Sopenharmony_ci	}
418062306a36Sopenharmony_ci
418162306a36Sopenharmony_ci	switch (sd->sensor) {
418262306a36Sopenharmony_ci	case SEN_OV6620:
418362306a36Sopenharmony_ci	case SEN_OV6630:
418462306a36Sopenharmony_ci	case SEN_OV66308AF:
418562306a36Sopenharmony_ci		if (qvga) {		/* QCIF */
418662306a36Sopenharmony_ci			hwscale = 0;
418762306a36Sopenharmony_ci			vwscale = 0;
418862306a36Sopenharmony_ci		} else {		/* CIF */
418962306a36Sopenharmony_ci			hwscale = 1;
419062306a36Sopenharmony_ci			vwscale = 1;	/* The datasheet says 0;
419162306a36Sopenharmony_ci					 * it's wrong */
419262306a36Sopenharmony_ci		}
419362306a36Sopenharmony_ci		break;
419462306a36Sopenharmony_ci	case SEN_OV8610:
419562306a36Sopenharmony_ci		if (qvga) {		/* QSVGA */
419662306a36Sopenharmony_ci			hwscale = 1;
419762306a36Sopenharmony_ci			vwscale = 1;
419862306a36Sopenharmony_ci		} else {		/* SVGA */
419962306a36Sopenharmony_ci			hwscale = 2;
420062306a36Sopenharmony_ci			vwscale = 2;
420162306a36Sopenharmony_ci		}
420262306a36Sopenharmony_ci		break;
420362306a36Sopenharmony_ci	default:			/* SEN_OV7xx0 */
420462306a36Sopenharmony_ci		if (qvga) {		/* QVGA */
420562306a36Sopenharmony_ci			hwscale = 1;
420662306a36Sopenharmony_ci			vwscale = 0;
420762306a36Sopenharmony_ci		} else {		/* VGA */
420862306a36Sopenharmony_ci			hwscale = 2;
420962306a36Sopenharmony_ci			vwscale = 1;
421062306a36Sopenharmony_ci		}
421162306a36Sopenharmony_ci	}
421262306a36Sopenharmony_ci
421362306a36Sopenharmony_ci	mode_init_ov_sensor_regs(sd);
421462306a36Sopenharmony_ci
421562306a36Sopenharmony_ci	i2c_w(sd, 0x17, hwsbase);
421662306a36Sopenharmony_ci	i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
421762306a36Sopenharmony_ci	i2c_w(sd, 0x19, vwsbase);
421862306a36Sopenharmony_ci	i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
421962306a36Sopenharmony_ci}
422062306a36Sopenharmony_ci
422162306a36Sopenharmony_ci/* -- start the camera -- */
422262306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
422362306a36Sopenharmony_ci{
422462306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
422562306a36Sopenharmony_ci
422662306a36Sopenharmony_ci	/* Default for most bridges, allow bridge_mode_init_regs to override */
422762306a36Sopenharmony_ci	sd->sensor_width = sd->gspca_dev.pixfmt.width;
422862306a36Sopenharmony_ci	sd->sensor_height = sd->gspca_dev.pixfmt.height;
422962306a36Sopenharmony_ci
423062306a36Sopenharmony_ci	switch (sd->bridge) {
423162306a36Sopenharmony_ci	case BRIDGE_OV511:
423262306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
423362306a36Sopenharmony_ci		ov511_mode_init_regs(sd);
423462306a36Sopenharmony_ci		break;
423562306a36Sopenharmony_ci	case BRIDGE_OV518:
423662306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
423762306a36Sopenharmony_ci		ov518_mode_init_regs(sd);
423862306a36Sopenharmony_ci		break;
423962306a36Sopenharmony_ci	case BRIDGE_OV519:
424062306a36Sopenharmony_ci		ov519_mode_init_regs(sd);
424162306a36Sopenharmony_ci		break;
424262306a36Sopenharmony_ci	/* case BRIDGE_OVFX2: nothing to do */
424362306a36Sopenharmony_ci	case BRIDGE_W9968CF:
424462306a36Sopenharmony_ci		w9968cf_mode_init_regs(sd);
424562306a36Sopenharmony_ci		break;
424662306a36Sopenharmony_ci	}
424762306a36Sopenharmony_ci
424862306a36Sopenharmony_ci	set_ov_sensor_window(sd);
424962306a36Sopenharmony_ci
425062306a36Sopenharmony_ci	/* Force clear snapshot state in case the snapshot button was
425162306a36Sopenharmony_ci	   pressed while we weren't streaming */
425262306a36Sopenharmony_ci	sd->snapshot_needs_reset = 1;
425362306a36Sopenharmony_ci	sd_reset_snapshot(gspca_dev);
425462306a36Sopenharmony_ci
425562306a36Sopenharmony_ci	sd->first_frame = 3;
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_ci	ov51x_restart(sd);
425862306a36Sopenharmony_ci	ov51x_led_control(sd, 1);
425962306a36Sopenharmony_ci	return gspca_dev->usb_err;
426062306a36Sopenharmony_ci}
426162306a36Sopenharmony_ci
426262306a36Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
426362306a36Sopenharmony_ci{
426462306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
426562306a36Sopenharmony_ci
426662306a36Sopenharmony_ci	ov51x_stop(sd);
426762306a36Sopenharmony_ci	ov51x_led_control(sd, 0);
426862306a36Sopenharmony_ci}
426962306a36Sopenharmony_ci
427062306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
427162306a36Sopenharmony_ci{
427262306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
427362306a36Sopenharmony_ci
427462306a36Sopenharmony_ci	if (!sd->gspca_dev.present)
427562306a36Sopenharmony_ci		return;
427662306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_W9968CF)
427762306a36Sopenharmony_ci		w9968cf_stop0(sd);
427862306a36Sopenharmony_ci
427962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
428062306a36Sopenharmony_ci	/* If the last button state is pressed, release it now! */
428162306a36Sopenharmony_ci	if (sd->snapshot_pressed) {
428262306a36Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
428362306a36Sopenharmony_ci		input_sync(gspca_dev->input_dev);
428462306a36Sopenharmony_ci		sd->snapshot_pressed = 0;
428562306a36Sopenharmony_ci	}
428662306a36Sopenharmony_ci#endif
428762306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_OV519)
428862306a36Sopenharmony_ci		reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
428962306a36Sopenharmony_ci}
429062306a36Sopenharmony_ci
429162306a36Sopenharmony_cistatic void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
429262306a36Sopenharmony_ci{
429362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
429462306a36Sopenharmony_ci
429562306a36Sopenharmony_ci	if (sd->snapshot_pressed != state) {
429662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
429762306a36Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
429862306a36Sopenharmony_ci		input_sync(gspca_dev->input_dev);
429962306a36Sopenharmony_ci#endif
430062306a36Sopenharmony_ci		if (state)
430162306a36Sopenharmony_ci			sd->snapshot_needs_reset = 1;
430262306a36Sopenharmony_ci
430362306a36Sopenharmony_ci		sd->snapshot_pressed = state;
430462306a36Sopenharmony_ci	} else {
430562306a36Sopenharmony_ci		/* On the ov511 / ov519 we need to reset the button state
430662306a36Sopenharmony_ci		   multiple times, as resetting does not work as long as the
430762306a36Sopenharmony_ci		   button stays pressed */
430862306a36Sopenharmony_ci		switch (sd->bridge) {
430962306a36Sopenharmony_ci		case BRIDGE_OV511:
431062306a36Sopenharmony_ci		case BRIDGE_OV511PLUS:
431162306a36Sopenharmony_ci		case BRIDGE_OV519:
431262306a36Sopenharmony_ci			if (state)
431362306a36Sopenharmony_ci				sd->snapshot_needs_reset = 1;
431462306a36Sopenharmony_ci			break;
431562306a36Sopenharmony_ci		}
431662306a36Sopenharmony_ci	}
431762306a36Sopenharmony_ci}
431862306a36Sopenharmony_ci
431962306a36Sopenharmony_cistatic void ov511_pkt_scan(struct gspca_dev *gspca_dev,
432062306a36Sopenharmony_ci			u8 *in,			/* isoc packet */
432162306a36Sopenharmony_ci			int len)		/* iso packet length */
432262306a36Sopenharmony_ci{
432362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
432462306a36Sopenharmony_ci
432562306a36Sopenharmony_ci	/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
432662306a36Sopenharmony_ci	 * byte non-zero. The EOF packet has image width/height in the
432762306a36Sopenharmony_ci	 * 10th and 11th bytes. The 9th byte is given as follows:
432862306a36Sopenharmony_ci	 *
432962306a36Sopenharmony_ci	 * bit 7: EOF
433062306a36Sopenharmony_ci	 *     6: compression enabled
433162306a36Sopenharmony_ci	 *     5: 422/420/400 modes
433262306a36Sopenharmony_ci	 *     4: 422/420/400 modes
433362306a36Sopenharmony_ci	 *     3: 1
433462306a36Sopenharmony_ci	 *     2: snapshot button on
433562306a36Sopenharmony_ci	 *     1: snapshot frame
433662306a36Sopenharmony_ci	 *     0: even/odd field
433762306a36Sopenharmony_ci	 */
433862306a36Sopenharmony_ci	if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
433962306a36Sopenharmony_ci	    (in[8] & 0x08)) {
434062306a36Sopenharmony_ci		ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
434162306a36Sopenharmony_ci		if (in[8] & 0x80) {
434262306a36Sopenharmony_ci			/* Frame end */
434362306a36Sopenharmony_ci			if ((in[9] + 1) * 8 != gspca_dev->pixfmt.width ||
434462306a36Sopenharmony_ci			    (in[10] + 1) * 8 != gspca_dev->pixfmt.height) {
434562306a36Sopenharmony_ci				gspca_err(gspca_dev, "Invalid frame size, got: %dx%d, requested: %dx%d\n",
434662306a36Sopenharmony_ci					  (in[9] + 1) * 8, (in[10] + 1) * 8,
434762306a36Sopenharmony_ci					  gspca_dev->pixfmt.width,
434862306a36Sopenharmony_ci					  gspca_dev->pixfmt.height);
434962306a36Sopenharmony_ci				gspca_dev->last_packet_type = DISCARD_PACKET;
435062306a36Sopenharmony_ci				return;
435162306a36Sopenharmony_ci			}
435262306a36Sopenharmony_ci			/* Add 11 byte footer to frame, might be useful */
435362306a36Sopenharmony_ci			gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
435462306a36Sopenharmony_ci			return;
435562306a36Sopenharmony_ci		} else {
435662306a36Sopenharmony_ci			/* Frame start */
435762306a36Sopenharmony_ci			gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0);
435862306a36Sopenharmony_ci			sd->packet_nr = 0;
435962306a36Sopenharmony_ci		}
436062306a36Sopenharmony_ci	}
436162306a36Sopenharmony_ci
436262306a36Sopenharmony_ci	/* Ignore the packet number */
436362306a36Sopenharmony_ci	len--;
436462306a36Sopenharmony_ci
436562306a36Sopenharmony_ci	/* intermediate packet */
436662306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, in, len);
436762306a36Sopenharmony_ci}
436862306a36Sopenharmony_ci
436962306a36Sopenharmony_cistatic void ov518_pkt_scan(struct gspca_dev *gspca_dev,
437062306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
437162306a36Sopenharmony_ci			int len)			/* iso packet length */
437262306a36Sopenharmony_ci{
437362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
437462306a36Sopenharmony_ci
437562306a36Sopenharmony_ci	/* A false positive here is likely, until OVT gives me
437662306a36Sopenharmony_ci	 * the definitive SOF/EOF format */
437762306a36Sopenharmony_ci	if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
437862306a36Sopenharmony_ci		ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
437962306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
438062306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
438162306a36Sopenharmony_ci		sd->packet_nr = 0;
438262306a36Sopenharmony_ci	}
438362306a36Sopenharmony_ci
438462306a36Sopenharmony_ci	if (gspca_dev->last_packet_type == DISCARD_PACKET)
438562306a36Sopenharmony_ci		return;
438662306a36Sopenharmony_ci
438762306a36Sopenharmony_ci	/* Does this device use packet numbers ? */
438862306a36Sopenharmony_ci	if (len & 7) {
438962306a36Sopenharmony_ci		len--;
439062306a36Sopenharmony_ci		if (sd->packet_nr == data[len])
439162306a36Sopenharmony_ci			sd->packet_nr++;
439262306a36Sopenharmony_ci		/* The last few packets of the frame (which are all 0's
439362306a36Sopenharmony_ci		   except that they may contain part of the footer), are
439462306a36Sopenharmony_ci		   numbered 0 */
439562306a36Sopenharmony_ci		else if (sd->packet_nr == 0 || data[len]) {
439662306a36Sopenharmony_ci			gspca_err(gspca_dev, "Invalid packet nr: %d (expect: %d)\n",
439762306a36Sopenharmony_ci				  (int)data[len], (int)sd->packet_nr);
439862306a36Sopenharmony_ci			gspca_dev->last_packet_type = DISCARD_PACKET;
439962306a36Sopenharmony_ci			return;
440062306a36Sopenharmony_ci		}
440162306a36Sopenharmony_ci	}
440262306a36Sopenharmony_ci
440362306a36Sopenharmony_ci	/* intermediate packet */
440462306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
440562306a36Sopenharmony_ci}
440662306a36Sopenharmony_ci
440762306a36Sopenharmony_cistatic void ov519_pkt_scan(struct gspca_dev *gspca_dev,
440862306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
440962306a36Sopenharmony_ci			int len)			/* iso packet length */
441062306a36Sopenharmony_ci{
441162306a36Sopenharmony_ci	/* Header of ov519 is 16 bytes:
441262306a36Sopenharmony_ci	 *     Byte     Value      Description
441362306a36Sopenharmony_ci	 *	0	0xff	magic
441462306a36Sopenharmony_ci	 *	1	0xff	magic
441562306a36Sopenharmony_ci	 *	2	0xff	magic
441662306a36Sopenharmony_ci	 *	3	0xXX	0x50 = SOF, 0x51 = EOF
441762306a36Sopenharmony_ci	 *	9	0xXX	0x01 initial frame without data,
441862306a36Sopenharmony_ci	 *			0x00 standard frame with image
441962306a36Sopenharmony_ci	 *	14	Lo	in EOF: length of image data / 8
442062306a36Sopenharmony_ci	 *	15	Hi
442162306a36Sopenharmony_ci	 */
442262306a36Sopenharmony_ci
442362306a36Sopenharmony_ci	if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
442462306a36Sopenharmony_ci		switch (data[3]) {
442562306a36Sopenharmony_ci		case 0x50:		/* start of frame */
442662306a36Sopenharmony_ci			/* Don't check the button state here, as the state
442762306a36Sopenharmony_ci			   usually (always ?) changes at EOF and checking it
442862306a36Sopenharmony_ci			   here leads to unnecessary snapshot state resets. */
442962306a36Sopenharmony_ci#define HDRSZ 16
443062306a36Sopenharmony_ci			data += HDRSZ;
443162306a36Sopenharmony_ci			len -= HDRSZ;
443262306a36Sopenharmony_ci#undef HDRSZ
443362306a36Sopenharmony_ci			if (data[0] == 0xff || data[1] == 0xd8)
443462306a36Sopenharmony_ci				gspca_frame_add(gspca_dev, FIRST_PACKET,
443562306a36Sopenharmony_ci						data, len);
443662306a36Sopenharmony_ci			else
443762306a36Sopenharmony_ci				gspca_dev->last_packet_type = DISCARD_PACKET;
443862306a36Sopenharmony_ci			return;
443962306a36Sopenharmony_ci		case 0x51:		/* end of frame */
444062306a36Sopenharmony_ci			ov51x_handle_button(gspca_dev, data[11] & 1);
444162306a36Sopenharmony_ci			if (data[9] != 0)
444262306a36Sopenharmony_ci				gspca_dev->last_packet_type = DISCARD_PACKET;
444362306a36Sopenharmony_ci			gspca_frame_add(gspca_dev, LAST_PACKET,
444462306a36Sopenharmony_ci					NULL, 0);
444562306a36Sopenharmony_ci			return;
444662306a36Sopenharmony_ci		}
444762306a36Sopenharmony_ci	}
444862306a36Sopenharmony_ci
444962306a36Sopenharmony_ci	/* intermediate packet */
445062306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
445162306a36Sopenharmony_ci}
445262306a36Sopenharmony_ci
445362306a36Sopenharmony_cistatic void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
445462306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
445562306a36Sopenharmony_ci			int len)			/* iso packet length */
445662306a36Sopenharmony_ci{
445762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
445862306a36Sopenharmony_ci
445962306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
446062306a36Sopenharmony_ci
446162306a36Sopenharmony_ci	/* A short read signals EOF */
446262306a36Sopenharmony_ci	if (len < gspca_dev->cam.bulk_size) {
446362306a36Sopenharmony_ci		/* If the frame is short, and it is one of the first ones
446462306a36Sopenharmony_ci		   the sensor and bridge are still syncing, so drop it. */
446562306a36Sopenharmony_ci		if (sd->first_frame) {
446662306a36Sopenharmony_ci			sd->first_frame--;
446762306a36Sopenharmony_ci			if (gspca_dev->image_len <
446862306a36Sopenharmony_ci				  sd->gspca_dev.pixfmt.width *
446962306a36Sopenharmony_ci					sd->gspca_dev.pixfmt.height)
447062306a36Sopenharmony_ci				gspca_dev->last_packet_type = DISCARD_PACKET;
447162306a36Sopenharmony_ci		}
447262306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
447362306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
447462306a36Sopenharmony_ci	}
447562306a36Sopenharmony_ci}
447662306a36Sopenharmony_ci
447762306a36Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
447862306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
447962306a36Sopenharmony_ci			int len)			/* iso packet length */
448062306a36Sopenharmony_ci{
448162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
448262306a36Sopenharmony_ci
448362306a36Sopenharmony_ci	switch (sd->bridge) {
448462306a36Sopenharmony_ci	case BRIDGE_OV511:
448562306a36Sopenharmony_ci	case BRIDGE_OV511PLUS:
448662306a36Sopenharmony_ci		ov511_pkt_scan(gspca_dev, data, len);
448762306a36Sopenharmony_ci		break;
448862306a36Sopenharmony_ci	case BRIDGE_OV518:
448962306a36Sopenharmony_ci	case BRIDGE_OV518PLUS:
449062306a36Sopenharmony_ci		ov518_pkt_scan(gspca_dev, data, len);
449162306a36Sopenharmony_ci		break;
449262306a36Sopenharmony_ci	case BRIDGE_OV519:
449362306a36Sopenharmony_ci		ov519_pkt_scan(gspca_dev, data, len);
449462306a36Sopenharmony_ci		break;
449562306a36Sopenharmony_ci	case BRIDGE_OVFX2:
449662306a36Sopenharmony_ci		ovfx2_pkt_scan(gspca_dev, data, len);
449762306a36Sopenharmony_ci		break;
449862306a36Sopenharmony_ci	case BRIDGE_W9968CF:
449962306a36Sopenharmony_ci		w9968cf_pkt_scan(gspca_dev, data, len);
450062306a36Sopenharmony_ci		break;
450162306a36Sopenharmony_ci	}
450262306a36Sopenharmony_ci}
450362306a36Sopenharmony_ci
450462306a36Sopenharmony_ci/* -- management routines -- */
450562306a36Sopenharmony_ci
450662306a36Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 val)
450762306a36Sopenharmony_ci{
450862306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
450962306a36Sopenharmony_ci	static const struct ov_i2c_regvals brit_7660[][7] = {
451062306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
451162306a36Sopenharmony_ci			{0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
451262306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
451362306a36Sopenharmony_ci			{0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
451462306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
451562306a36Sopenharmony_ci			{0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
451662306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
451762306a36Sopenharmony_ci			{0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
451862306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
451962306a36Sopenharmony_ci			{0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
452062306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
452162306a36Sopenharmony_ci			{0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
452262306a36Sopenharmony_ci		{{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
452362306a36Sopenharmony_ci			{0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
452462306a36Sopenharmony_ci	};
452562306a36Sopenharmony_ci
452662306a36Sopenharmony_ci	switch (sd->sensor) {
452762306a36Sopenharmony_ci	case SEN_OV8610:
452862306a36Sopenharmony_ci	case SEN_OV7610:
452962306a36Sopenharmony_ci	case SEN_OV76BE:
453062306a36Sopenharmony_ci	case SEN_OV6620:
453162306a36Sopenharmony_ci	case SEN_OV6630:
453262306a36Sopenharmony_ci	case SEN_OV66308AF:
453362306a36Sopenharmony_ci	case SEN_OV7640:
453462306a36Sopenharmony_ci	case SEN_OV7648:
453562306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_BRT, val);
453662306a36Sopenharmony_ci		break;
453762306a36Sopenharmony_ci	case SEN_OV7620:
453862306a36Sopenharmony_ci	case SEN_OV7620AE:
453962306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_BRT, val);
454062306a36Sopenharmony_ci		break;
454162306a36Sopenharmony_ci	case SEN_OV7660:
454262306a36Sopenharmony_ci		write_i2c_regvals(sd, brit_7660[val],
454362306a36Sopenharmony_ci				ARRAY_SIZE(brit_7660[0]));
454462306a36Sopenharmony_ci		break;
454562306a36Sopenharmony_ci	case SEN_OV7670:
454662306a36Sopenharmony_ci/*win trace
454762306a36Sopenharmony_ci *		i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
454862306a36Sopenharmony_ci		i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
454962306a36Sopenharmony_ci		break;
455062306a36Sopenharmony_ci	}
455162306a36Sopenharmony_ci}
455262306a36Sopenharmony_ci
455362306a36Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev, s32 val)
455462306a36Sopenharmony_ci{
455562306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
455662306a36Sopenharmony_ci	static const struct ov_i2c_regvals contrast_7660[][31] = {
455762306a36Sopenharmony_ci		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
455862306a36Sopenharmony_ci		 {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
455962306a36Sopenharmony_ci		 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
456062306a36Sopenharmony_ci		 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
456162306a36Sopenharmony_ci		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
456262306a36Sopenharmony_ci		 {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
456362306a36Sopenharmony_ci		 {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
456462306a36Sopenharmony_ci		 {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
456562306a36Sopenharmony_ci		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
456662306a36Sopenharmony_ci		 {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
456762306a36Sopenharmony_ci		 {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
456862306a36Sopenharmony_ci		 {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
456962306a36Sopenharmony_ci		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
457062306a36Sopenharmony_ci		 {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
457162306a36Sopenharmony_ci		 {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
457262306a36Sopenharmony_ci		 {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
457362306a36Sopenharmony_ci		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
457462306a36Sopenharmony_ci		 {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
457562306a36Sopenharmony_ci		 {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
457662306a36Sopenharmony_ci		 {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
457762306a36Sopenharmony_ci		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
457862306a36Sopenharmony_ci		 {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
457962306a36Sopenharmony_ci		 {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
458062306a36Sopenharmony_ci		 {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
458162306a36Sopenharmony_ci		{{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
458262306a36Sopenharmony_ci		 {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
458362306a36Sopenharmony_ci		 {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
458462306a36Sopenharmony_ci		 {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
458562306a36Sopenharmony_ci		 {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
458662306a36Sopenharmony_ci		 {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
458762306a36Sopenharmony_ci		 {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
458862306a36Sopenharmony_ci		 {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
458962306a36Sopenharmony_ci		{{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
459062306a36Sopenharmony_ci		 {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
459162306a36Sopenharmony_ci		 {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
459262306a36Sopenharmony_ci		 {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
459362306a36Sopenharmony_ci		 {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
459462306a36Sopenharmony_ci		 {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
459562306a36Sopenharmony_ci		 {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
459662306a36Sopenharmony_ci		 {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
459762306a36Sopenharmony_ci		{{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
459862306a36Sopenharmony_ci		 {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
459962306a36Sopenharmony_ci		 {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
460062306a36Sopenharmony_ci		 {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
460162306a36Sopenharmony_ci		 {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
460262306a36Sopenharmony_ci		 {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
460362306a36Sopenharmony_ci		 {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
460462306a36Sopenharmony_ci		 {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
460562306a36Sopenharmony_ci		{{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
460662306a36Sopenharmony_ci		 {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
460762306a36Sopenharmony_ci		 {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
460862306a36Sopenharmony_ci		 {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
460962306a36Sopenharmony_ci		 {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
461062306a36Sopenharmony_ci		 {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
461162306a36Sopenharmony_ci		 {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
461262306a36Sopenharmony_ci		 {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
461362306a36Sopenharmony_ci	};
461462306a36Sopenharmony_ci
461562306a36Sopenharmony_ci	switch (sd->sensor) {
461662306a36Sopenharmony_ci	case SEN_OV7610:
461762306a36Sopenharmony_ci	case SEN_OV6620:
461862306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_CNT, val);
461962306a36Sopenharmony_ci		break;
462062306a36Sopenharmony_ci	case SEN_OV6630:
462162306a36Sopenharmony_ci	case SEN_OV66308AF:
462262306a36Sopenharmony_ci		i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
462362306a36Sopenharmony_ci		break;
462462306a36Sopenharmony_ci	case SEN_OV8610: {
462562306a36Sopenharmony_ci		static const u8 ctab[] = {
462662306a36Sopenharmony_ci			0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
462762306a36Sopenharmony_ci		};
462862306a36Sopenharmony_ci
462962306a36Sopenharmony_ci		/* Use Y gamma control instead. Bit 0 enables it. */
463062306a36Sopenharmony_ci		i2c_w(sd, 0x64, ctab[val >> 5]);
463162306a36Sopenharmony_ci		break;
463262306a36Sopenharmony_ci	    }
463362306a36Sopenharmony_ci	case SEN_OV7620:
463462306a36Sopenharmony_ci	case SEN_OV7620AE: {
463562306a36Sopenharmony_ci		static const u8 ctab[] = {
463662306a36Sopenharmony_ci			0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
463762306a36Sopenharmony_ci			0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
463862306a36Sopenharmony_ci		};
463962306a36Sopenharmony_ci
464062306a36Sopenharmony_ci		/* Use Y gamma control instead. Bit 0 enables it. */
464162306a36Sopenharmony_ci		i2c_w(sd, 0x64, ctab[val >> 4]);
464262306a36Sopenharmony_ci		break;
464362306a36Sopenharmony_ci	    }
464462306a36Sopenharmony_ci	case SEN_OV7660:
464562306a36Sopenharmony_ci		write_i2c_regvals(sd, contrast_7660[val],
464662306a36Sopenharmony_ci					ARRAY_SIZE(contrast_7660[0]));
464762306a36Sopenharmony_ci		break;
464862306a36Sopenharmony_ci	case SEN_OV7670:
464962306a36Sopenharmony_ci		/* check that this isn't just the same as ov7610 */
465062306a36Sopenharmony_ci		i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
465162306a36Sopenharmony_ci		break;
465262306a36Sopenharmony_ci	}
465362306a36Sopenharmony_ci}
465462306a36Sopenharmony_ci
465562306a36Sopenharmony_cistatic void setexposure(struct gspca_dev *gspca_dev, s32 val)
465662306a36Sopenharmony_ci{
465762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
465862306a36Sopenharmony_ci
465962306a36Sopenharmony_ci	i2c_w(sd, 0x10, val);
466062306a36Sopenharmony_ci}
466162306a36Sopenharmony_ci
466262306a36Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev, s32 val)
466362306a36Sopenharmony_ci{
466462306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
466562306a36Sopenharmony_ci	static const struct ov_i2c_regvals colors_7660[][6] = {
466662306a36Sopenharmony_ci		{{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
466762306a36Sopenharmony_ci		 {0x53, 0x19}, {0x54, 0x23}},
466862306a36Sopenharmony_ci		{{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
466962306a36Sopenharmony_ci		 {0x53, 0x2c}, {0x54, 0x3e}},
467062306a36Sopenharmony_ci		{{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
467162306a36Sopenharmony_ci		 {0x53, 0x40}, {0x54, 0x59}},
467262306a36Sopenharmony_ci		{{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
467362306a36Sopenharmony_ci		 {0x53, 0x53}, {0x54, 0x73}},
467462306a36Sopenharmony_ci		{{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
467562306a36Sopenharmony_ci		 {0x53, 0x66}, {0x54, 0x8e}},
467662306a36Sopenharmony_ci	};
467762306a36Sopenharmony_ci
467862306a36Sopenharmony_ci	switch (sd->sensor) {
467962306a36Sopenharmony_ci	case SEN_OV8610:
468062306a36Sopenharmony_ci	case SEN_OV7610:
468162306a36Sopenharmony_ci	case SEN_OV76BE:
468262306a36Sopenharmony_ci	case SEN_OV6620:
468362306a36Sopenharmony_ci	case SEN_OV6630:
468462306a36Sopenharmony_ci	case SEN_OV66308AF:
468562306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_SAT, val);
468662306a36Sopenharmony_ci		break;
468762306a36Sopenharmony_ci	case SEN_OV7620:
468862306a36Sopenharmony_ci	case SEN_OV7620AE:
468962306a36Sopenharmony_ci		/* Use UV gamma control instead. Bits 0 & 7 are reserved. */
469062306a36Sopenharmony_ci/*		rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
469162306a36Sopenharmony_ci		if (rc < 0)
469262306a36Sopenharmony_ci			goto out; */
469362306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_SAT, val);
469462306a36Sopenharmony_ci		break;
469562306a36Sopenharmony_ci	case SEN_OV7640:
469662306a36Sopenharmony_ci	case SEN_OV7648:
469762306a36Sopenharmony_ci		i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
469862306a36Sopenharmony_ci		break;
469962306a36Sopenharmony_ci	case SEN_OV7660:
470062306a36Sopenharmony_ci		write_i2c_regvals(sd, colors_7660[val],
470162306a36Sopenharmony_ci					ARRAY_SIZE(colors_7660[0]));
470262306a36Sopenharmony_ci		break;
470362306a36Sopenharmony_ci	case SEN_OV7670:
470462306a36Sopenharmony_ci		/* supported later once I work out how to do it
470562306a36Sopenharmony_ci		 * transparently fail now! */
470662306a36Sopenharmony_ci		/* set REG_COM13 values for UV sat auto mode */
470762306a36Sopenharmony_ci		break;
470862306a36Sopenharmony_ci	}
470962306a36Sopenharmony_ci}
471062306a36Sopenharmony_ci
471162306a36Sopenharmony_cistatic void setautobright(struct gspca_dev *gspca_dev, s32 val)
471262306a36Sopenharmony_ci{
471362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
471462306a36Sopenharmony_ci
471562306a36Sopenharmony_ci	i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10);
471662306a36Sopenharmony_ci}
471762306a36Sopenharmony_ci
471862306a36Sopenharmony_cistatic void setfreq_i(struct sd *sd, s32 val)
471962306a36Sopenharmony_ci{
472062306a36Sopenharmony_ci	if (sd->sensor == SEN_OV7660
472162306a36Sopenharmony_ci	 || sd->sensor == SEN_OV7670) {
472262306a36Sopenharmony_ci		switch (val) {
472362306a36Sopenharmony_ci		case 0: /* Banding filter disabled */
472462306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
472562306a36Sopenharmony_ci			break;
472662306a36Sopenharmony_ci		case 1: /* 50 hz */
472762306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
472862306a36Sopenharmony_ci				   OV7670_COM8_BFILT);
472962306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
473062306a36Sopenharmony_ci			break;
473162306a36Sopenharmony_ci		case 2: /* 60 hz */
473262306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
473362306a36Sopenharmony_ci				   OV7670_COM8_BFILT);
473462306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
473562306a36Sopenharmony_ci			break;
473662306a36Sopenharmony_ci		case 3: /* Auto hz - ov7670 only */
473762306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
473862306a36Sopenharmony_ci				   OV7670_COM8_BFILT);
473962306a36Sopenharmony_ci			i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
474062306a36Sopenharmony_ci				   0x18);
474162306a36Sopenharmony_ci			break;
474262306a36Sopenharmony_ci		}
474362306a36Sopenharmony_ci	} else {
474462306a36Sopenharmony_ci		switch (val) {
474562306a36Sopenharmony_ci		case 0: /* Banding filter disabled */
474662306a36Sopenharmony_ci			i2c_w_mask(sd, 0x2d, 0x00, 0x04);
474762306a36Sopenharmony_ci			i2c_w_mask(sd, 0x2a, 0x00, 0x80);
474862306a36Sopenharmony_ci			break;
474962306a36Sopenharmony_ci		case 1: /* 50 hz (filter on and framerate adj) */
475062306a36Sopenharmony_ci			i2c_w_mask(sd, 0x2d, 0x04, 0x04);
475162306a36Sopenharmony_ci			i2c_w_mask(sd, 0x2a, 0x80, 0x80);
475262306a36Sopenharmony_ci			/* 20 fps -> 16.667 fps */
475362306a36Sopenharmony_ci			if (sd->sensor == SEN_OV6620 ||
475462306a36Sopenharmony_ci			    sd->sensor == SEN_OV6630 ||
475562306a36Sopenharmony_ci			    sd->sensor == SEN_OV66308AF)
475662306a36Sopenharmony_ci				i2c_w(sd, 0x2b, 0x5e);
475762306a36Sopenharmony_ci			else
475862306a36Sopenharmony_ci				i2c_w(sd, 0x2b, 0xac);
475962306a36Sopenharmony_ci			break;
476062306a36Sopenharmony_ci		case 2: /* 60 hz (filter on, ...) */
476162306a36Sopenharmony_ci			i2c_w_mask(sd, 0x2d, 0x04, 0x04);
476262306a36Sopenharmony_ci			if (sd->sensor == SEN_OV6620 ||
476362306a36Sopenharmony_ci			    sd->sensor == SEN_OV6630 ||
476462306a36Sopenharmony_ci			    sd->sensor == SEN_OV66308AF) {
476562306a36Sopenharmony_ci				/* 20 fps -> 15 fps */
476662306a36Sopenharmony_ci				i2c_w_mask(sd, 0x2a, 0x80, 0x80);
476762306a36Sopenharmony_ci				i2c_w(sd, 0x2b, 0xa8);
476862306a36Sopenharmony_ci			} else {
476962306a36Sopenharmony_ci				/* no framerate adj. */
477062306a36Sopenharmony_ci				i2c_w_mask(sd, 0x2a, 0x00, 0x80);
477162306a36Sopenharmony_ci			}
477262306a36Sopenharmony_ci			break;
477362306a36Sopenharmony_ci		}
477462306a36Sopenharmony_ci	}
477562306a36Sopenharmony_ci}
477662306a36Sopenharmony_ci
477762306a36Sopenharmony_cistatic void setfreq(struct gspca_dev *gspca_dev, s32 val)
477862306a36Sopenharmony_ci{
477962306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
478062306a36Sopenharmony_ci
478162306a36Sopenharmony_ci	setfreq_i(sd, val);
478262306a36Sopenharmony_ci
478362306a36Sopenharmony_ci	/* Ugly but necessary */
478462306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_W9968CF)
478562306a36Sopenharmony_ci		w9968cf_set_crop_window(sd);
478662306a36Sopenharmony_ci}
478762306a36Sopenharmony_ci
478862306a36Sopenharmony_cistatic int sd_get_jcomp(struct gspca_dev *gspca_dev,
478962306a36Sopenharmony_ci			struct v4l2_jpegcompression *jcomp)
479062306a36Sopenharmony_ci{
479162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
479262306a36Sopenharmony_ci
479362306a36Sopenharmony_ci	if (sd->bridge != BRIDGE_W9968CF)
479462306a36Sopenharmony_ci		return -ENOTTY;
479562306a36Sopenharmony_ci
479662306a36Sopenharmony_ci	memset(jcomp, 0, sizeof *jcomp);
479762306a36Sopenharmony_ci	jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
479862306a36Sopenharmony_ci	jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
479962306a36Sopenharmony_ci			      V4L2_JPEG_MARKER_DRI;
480062306a36Sopenharmony_ci	return 0;
480162306a36Sopenharmony_ci}
480262306a36Sopenharmony_ci
480362306a36Sopenharmony_cistatic int sd_set_jcomp(struct gspca_dev *gspca_dev,
480462306a36Sopenharmony_ci			const struct v4l2_jpegcompression *jcomp)
480562306a36Sopenharmony_ci{
480662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
480762306a36Sopenharmony_ci
480862306a36Sopenharmony_ci	if (sd->bridge != BRIDGE_W9968CF)
480962306a36Sopenharmony_ci		return -ENOTTY;
481062306a36Sopenharmony_ci
481162306a36Sopenharmony_ci	v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
481262306a36Sopenharmony_ci	return 0;
481362306a36Sopenharmony_ci}
481462306a36Sopenharmony_ci
481562306a36Sopenharmony_cistatic int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
481662306a36Sopenharmony_ci{
481762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev =
481862306a36Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
481962306a36Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
482062306a36Sopenharmony_ci
482162306a36Sopenharmony_ci	gspca_dev->usb_err = 0;
482262306a36Sopenharmony_ci
482362306a36Sopenharmony_ci	switch (ctrl->id) {
482462306a36Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
482562306a36Sopenharmony_ci		gspca_dev->exposure->val = i2c_r(sd, 0x10);
482662306a36Sopenharmony_ci		break;
482762306a36Sopenharmony_ci	}
482862306a36Sopenharmony_ci	return 0;
482962306a36Sopenharmony_ci}
483062306a36Sopenharmony_ci
483162306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
483262306a36Sopenharmony_ci{
483362306a36Sopenharmony_ci	struct gspca_dev *gspca_dev =
483462306a36Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
483562306a36Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
483662306a36Sopenharmony_ci
483762306a36Sopenharmony_ci	gspca_dev->usb_err = 0;
483862306a36Sopenharmony_ci
483962306a36Sopenharmony_ci	if (!gspca_dev->streaming)
484062306a36Sopenharmony_ci		return 0;
484162306a36Sopenharmony_ci
484262306a36Sopenharmony_ci	switch (ctrl->id) {
484362306a36Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
484462306a36Sopenharmony_ci		setbrightness(gspca_dev, ctrl->val);
484562306a36Sopenharmony_ci		break;
484662306a36Sopenharmony_ci	case V4L2_CID_CONTRAST:
484762306a36Sopenharmony_ci		setcontrast(gspca_dev, ctrl->val);
484862306a36Sopenharmony_ci		break;
484962306a36Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:
485062306a36Sopenharmony_ci		setfreq(gspca_dev, ctrl->val);
485162306a36Sopenharmony_ci		break;
485262306a36Sopenharmony_ci	case V4L2_CID_AUTOBRIGHTNESS:
485362306a36Sopenharmony_ci		if (ctrl->is_new)
485462306a36Sopenharmony_ci			setautobright(gspca_dev, ctrl->val);
485562306a36Sopenharmony_ci		if (!ctrl->val && sd->brightness->is_new)
485662306a36Sopenharmony_ci			setbrightness(gspca_dev, sd->brightness->val);
485762306a36Sopenharmony_ci		break;
485862306a36Sopenharmony_ci	case V4L2_CID_SATURATION:
485962306a36Sopenharmony_ci		setcolors(gspca_dev, ctrl->val);
486062306a36Sopenharmony_ci		break;
486162306a36Sopenharmony_ci	case V4L2_CID_HFLIP:
486262306a36Sopenharmony_ci		sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
486362306a36Sopenharmony_ci		break;
486462306a36Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
486562306a36Sopenharmony_ci		if (ctrl->is_new)
486662306a36Sopenharmony_ci			setautogain(gspca_dev, ctrl->val);
486762306a36Sopenharmony_ci		if (!ctrl->val && gspca_dev->exposure->is_new)
486862306a36Sopenharmony_ci			setexposure(gspca_dev, gspca_dev->exposure->val);
486962306a36Sopenharmony_ci		break;
487062306a36Sopenharmony_ci	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
487162306a36Sopenharmony_ci		return -EBUSY; /* Should never happen, as we grab the ctrl */
487262306a36Sopenharmony_ci	}
487362306a36Sopenharmony_ci	return gspca_dev->usb_err;
487462306a36Sopenharmony_ci}
487562306a36Sopenharmony_ci
487662306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
487762306a36Sopenharmony_ci	.g_volatile_ctrl = sd_g_volatile_ctrl,
487862306a36Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
487962306a36Sopenharmony_ci};
488062306a36Sopenharmony_ci
488162306a36Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
488262306a36Sopenharmony_ci{
488362306a36Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
488462306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
488562306a36Sopenharmony_ci
488662306a36Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
488762306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 10);
488862306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_brightness)
488962306a36Sopenharmony_ci		sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
489062306a36Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0,
489162306a36Sopenharmony_ci			sd->sensor == SEN_OV7660 ? 6 : 255, 1,
489262306a36Sopenharmony_ci			sd->sensor == SEN_OV7660 ? 3 : 127);
489362306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_contrast) {
489462306a36Sopenharmony_ci		if (sd->sensor == SEN_OV7660)
489562306a36Sopenharmony_ci			v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
489662306a36Sopenharmony_ci				V4L2_CID_CONTRAST, 0, 6, 1, 3);
489762306a36Sopenharmony_ci		else
489862306a36Sopenharmony_ci			v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
489962306a36Sopenharmony_ci				V4L2_CID_CONTRAST, 0, 255, 1,
490062306a36Sopenharmony_ci				(sd->sensor == SEN_OV6630 ||
490162306a36Sopenharmony_ci				 sd->sensor == SEN_OV66308AF) ? 200 : 127);
490262306a36Sopenharmony_ci	}
490362306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_sat)
490462306a36Sopenharmony_ci		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
490562306a36Sopenharmony_ci			V4L2_CID_SATURATION, 0,
490662306a36Sopenharmony_ci			sd->sensor == SEN_OV7660 ? 4 : 255, 1,
490762306a36Sopenharmony_ci			sd->sensor == SEN_OV7660 ? 2 : 127);
490862306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_exposure)
490962306a36Sopenharmony_ci		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
491062306a36Sopenharmony_ci			V4L2_CID_EXPOSURE, 0, 255, 1, 127);
491162306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_hvflip) {
491262306a36Sopenharmony_ci		sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
491362306a36Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
491462306a36Sopenharmony_ci		sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
491562306a36Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
491662306a36Sopenharmony_ci	}
491762306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_autobright)
491862306a36Sopenharmony_ci		sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
491962306a36Sopenharmony_ci			V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1);
492062306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_autogain)
492162306a36Sopenharmony_ci		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
492262306a36Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
492362306a36Sopenharmony_ci	if (valid_controls[sd->sensor].has_freq) {
492462306a36Sopenharmony_ci		if (sd->sensor == SEN_OV7670)
492562306a36Sopenharmony_ci			sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
492662306a36Sopenharmony_ci				V4L2_CID_POWER_LINE_FREQUENCY,
492762306a36Sopenharmony_ci				V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
492862306a36Sopenharmony_ci				V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
492962306a36Sopenharmony_ci		else
493062306a36Sopenharmony_ci			sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
493162306a36Sopenharmony_ci				V4L2_CID_POWER_LINE_FREQUENCY,
493262306a36Sopenharmony_ci				V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
493362306a36Sopenharmony_ci	}
493462306a36Sopenharmony_ci	if (sd->bridge == BRIDGE_W9968CF)
493562306a36Sopenharmony_ci		sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
493662306a36Sopenharmony_ci			V4L2_CID_JPEG_COMPRESSION_QUALITY,
493762306a36Sopenharmony_ci			QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
493862306a36Sopenharmony_ci
493962306a36Sopenharmony_ci	if (hdl->error) {
494062306a36Sopenharmony_ci		gspca_err(gspca_dev, "Could not initialize controls\n");
494162306a36Sopenharmony_ci		return hdl->error;
494262306a36Sopenharmony_ci	}
494362306a36Sopenharmony_ci	if (gspca_dev->autogain)
494462306a36Sopenharmony_ci		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true);
494562306a36Sopenharmony_ci	if (sd->autobright)
494662306a36Sopenharmony_ci		v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false);
494762306a36Sopenharmony_ci	if (sd->hflip)
494862306a36Sopenharmony_ci		v4l2_ctrl_cluster(2, &sd->hflip);
494962306a36Sopenharmony_ci	return 0;
495062306a36Sopenharmony_ci}
495162306a36Sopenharmony_ci
495262306a36Sopenharmony_ci/* sub-driver description */
495362306a36Sopenharmony_cistatic const struct sd_desc sd_desc = {
495462306a36Sopenharmony_ci	.name = MODULE_NAME,
495562306a36Sopenharmony_ci	.config = sd_config,
495662306a36Sopenharmony_ci	.init = sd_init,
495762306a36Sopenharmony_ci	.init_controls = sd_init_controls,
495862306a36Sopenharmony_ci	.isoc_init = sd_isoc_init,
495962306a36Sopenharmony_ci	.start = sd_start,
496062306a36Sopenharmony_ci	.stopN = sd_stopN,
496162306a36Sopenharmony_ci	.stop0 = sd_stop0,
496262306a36Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
496362306a36Sopenharmony_ci	.dq_callback = sd_reset_snapshot,
496462306a36Sopenharmony_ci	.get_jcomp = sd_get_jcomp,
496562306a36Sopenharmony_ci	.set_jcomp = sd_set_jcomp,
496662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
496762306a36Sopenharmony_ci	.other_input = 1,
496862306a36Sopenharmony_ci#endif
496962306a36Sopenharmony_ci};
497062306a36Sopenharmony_ci
497162306a36Sopenharmony_ci/* -- module initialisation -- */
497262306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = {
497362306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
497462306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4052),
497562306a36Sopenharmony_ci		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
497662306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
497762306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
497862306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
497962306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
498062306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
498162306a36Sopenharmony_ci	{USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
498262306a36Sopenharmony_ci	{USB_DEVICE(0x045e, 0x028c),
498362306a36Sopenharmony_ci		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
498462306a36Sopenharmony_ci	{USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
498562306a36Sopenharmony_ci	{USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
498662306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
498762306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
498862306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x0519),
498962306a36Sopenharmony_ci		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
499062306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x0530),
499162306a36Sopenharmony_ci		.driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
499262306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
499362306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
499462306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
499562306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
499662306a36Sopenharmony_ci	{USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
499762306a36Sopenharmony_ci	{USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
499862306a36Sopenharmony_ci	{USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
499962306a36Sopenharmony_ci	{USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
500062306a36Sopenharmony_ci	{USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
500162306a36Sopenharmony_ci	{USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
500262306a36Sopenharmony_ci	{}
500362306a36Sopenharmony_ci};
500462306a36Sopenharmony_ci
500562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
500662306a36Sopenharmony_ci
500762306a36Sopenharmony_ci/* -- device connect -- */
500862306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
500962306a36Sopenharmony_ci			const struct usb_device_id *id)
501062306a36Sopenharmony_ci{
501162306a36Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
501262306a36Sopenharmony_ci				THIS_MODULE);
501362306a36Sopenharmony_ci}
501462306a36Sopenharmony_ci
501562306a36Sopenharmony_cistatic struct usb_driver sd_driver = {
501662306a36Sopenharmony_ci	.name = MODULE_NAME,
501762306a36Sopenharmony_ci	.id_table = device_table,
501862306a36Sopenharmony_ci	.probe = sd_probe,
501962306a36Sopenharmony_ci	.disconnect = gspca_disconnect,
502062306a36Sopenharmony_ci#ifdef CONFIG_PM
502162306a36Sopenharmony_ci	.suspend = gspca_suspend,
502262306a36Sopenharmony_ci	.resume = gspca_resume,
502362306a36Sopenharmony_ci	.reset_resume = gspca_resume,
502462306a36Sopenharmony_ci#endif
502562306a36Sopenharmony_ci};
502662306a36Sopenharmony_ci
502762306a36Sopenharmony_cimodule_usb_driver(sd_driver);
502862306a36Sopenharmony_ci
502962306a36Sopenharmony_cimodule_param(frame_rate, int, 0644);
503062306a36Sopenharmony_ciMODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
5031