xref: /linux/drivers/media/usb/gspca/ov534_9.c (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
1fd9871f7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c52af799SJean-Francois Moine /*
38d64d4f6SJean-François Moine  * ov534-ov9xxx gspca driver
4c52af799SJean-Francois Moine  *
58d64d4f6SJean-François Moine  * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
6c52af799SJean-Francois Moine  * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
7c52af799SJean-Francois Moine  * Copyright (C) 2008 Jim Paris <jim@jtan.com>
8c52af799SJean-Francois Moine  *
9c52af799SJean-Francois Moine  * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
10c52af799SJean-Francois Moine  * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
11c52af799SJean-Francois Moine  * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
12c52af799SJean-Francois Moine  */
13c52af799SJean-Francois Moine 
14133a9fe9SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15133a9fe9SJoe Perches 
16c52af799SJean-Francois Moine #define MODULE_NAME "ov534_9"
17c52af799SJean-Francois Moine 
18c52af799SJean-Francois Moine #include "gspca.h"
19c52af799SJean-Francois Moine 
20c52af799SJean-Francois Moine #define OV534_REG_ADDRESS	0xf1	/* sensor address */
21c52af799SJean-Francois Moine #define OV534_REG_SUBADDR	0xf2
22c52af799SJean-Francois Moine #define OV534_REG_WRITE		0xf3
23c52af799SJean-Francois Moine #define OV534_REG_READ		0xf4
24c52af799SJean-Francois Moine #define OV534_REG_OPERATION	0xf5
25c52af799SJean-Francois Moine #define OV534_REG_STATUS	0xf6
26c52af799SJean-Francois Moine 
27c52af799SJean-Francois Moine #define OV534_OP_WRITE_3	0x37
28c52af799SJean-Francois Moine #define OV534_OP_WRITE_2	0x33
29c52af799SJean-Francois Moine #define OV534_OP_READ_2		0xf9
30c52af799SJean-Francois Moine 
31c52af799SJean-Francois Moine #define CTRL_TIMEOUT 500
32c52af799SJean-Francois Moine 
33c52af799SJean-Francois Moine MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
34c52af799SJean-Francois Moine MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
35c52af799SJean-Francois Moine MODULE_LICENSE("GPL");
36c52af799SJean-Francois Moine 
37c52af799SJean-Francois Moine /* specific webcam descriptor */
38c52af799SJean-Francois Moine struct sd {
39c52af799SJean-Francois Moine 	struct gspca_dev gspca_dev;	/* !! must be the first item */
40c52af799SJean-Francois Moine 	__u32 last_pts;
41c52af799SJean-Francois Moine 	u8 last_fid;
428d64d4f6SJean-François Moine 
438d64d4f6SJean-François Moine 	u8 sensor;
448d64d4f6SJean-François Moine };
458d64d4f6SJean-François Moine enum sensors {
468d64d4f6SJean-François Moine 	SENSOR_OV965x,		/* ov9657 */
478d64d4f6SJean-François Moine 	SENSOR_OV971x,		/* ov9712 */
48965b37a4SJose Alberto Reguero 	SENSOR_OV562x,		/* ov5621 */
4915807765SVladik Aranov 	SENSOR_OV361x,		/* ov3610 */
508d64d4f6SJean-François Moine 	NSENSORS
51c52af799SJean-Francois Moine };
52c52af799SJean-Francois Moine 
53c52af799SJean-Francois Moine static const struct v4l2_pix_format ov965x_mode[] = {
54c52af799SJean-Francois Moine #define QVGA_MODE 0
55c52af799SJean-Francois Moine 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
56c52af799SJean-Francois Moine 		.bytesperline = 320,
57c52af799SJean-Francois Moine 		.sizeimage = 320 * 240 * 3 / 8 + 590,
58c52af799SJean-Francois Moine 		.colorspace = V4L2_COLORSPACE_JPEG},
59c52af799SJean-Francois Moine #define VGA_MODE 1
60c52af799SJean-Francois Moine 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
61c52af799SJean-Francois Moine 		.bytesperline = 640,
62c52af799SJean-Francois Moine 		.sizeimage = 640 * 480 * 3 / 8 + 590,
63c52af799SJean-Francois Moine 		.colorspace = V4L2_COLORSPACE_JPEG},
64c52af799SJean-Francois Moine #define SVGA_MODE 2
65c52af799SJean-Francois Moine 	{800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
66c52af799SJean-Francois Moine 		.bytesperline = 800,
67c52af799SJean-Francois Moine 		.sizeimage = 800 * 600 * 3 / 8 + 590,
68c52af799SJean-Francois Moine 		.colorspace = V4L2_COLORSPACE_JPEG},
69c52af799SJean-Francois Moine #define XGA_MODE 3
70c52af799SJean-Francois Moine 	{1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
71c52af799SJean-Francois Moine 		.bytesperline = 1024,
72c52af799SJean-Francois Moine 		.sizeimage = 1024 * 768 * 3 / 8 + 590,
73c52af799SJean-Francois Moine 		.colorspace = V4L2_COLORSPACE_JPEG},
74c52af799SJean-Francois Moine #define SXGA_MODE 4
75c52af799SJean-Francois Moine 	{1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
76c52af799SJean-Francois Moine 		.bytesperline = 1280,
77c52af799SJean-Francois Moine 		.sizeimage = 1280 * 1024 * 3 / 8 + 590,
78c52af799SJean-Francois Moine 		.colorspace = V4L2_COLORSPACE_JPEG},
79c52af799SJean-Francois Moine };
80c52af799SJean-Francois Moine 
818d64d4f6SJean-François Moine static const struct v4l2_pix_format ov971x_mode[] = {
828d64d4f6SJean-François Moine 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
838d64d4f6SJean-François Moine 		.bytesperline = 640,
848d64d4f6SJean-François Moine 		.sizeimage = 640 * 480,
858d64d4f6SJean-François Moine 		.colorspace = V4L2_COLORSPACE_SRGB
868d64d4f6SJean-François Moine 	}
878d64d4f6SJean-François Moine };
888d64d4f6SJean-François Moine 
89965b37a4SJose Alberto Reguero static const struct v4l2_pix_format ov562x_mode[] = {
90965b37a4SJose Alberto Reguero 	{2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
91965b37a4SJose Alberto Reguero 		.bytesperline = 2592,
92965b37a4SJose Alberto Reguero 		.sizeimage = 2592 * 1680,
93965b37a4SJose Alberto Reguero 		.colorspace = V4L2_COLORSPACE_SRGB
94965b37a4SJose Alberto Reguero 	}
95965b37a4SJose Alberto Reguero };
96965b37a4SJose Alberto Reguero 
9715807765SVladik Aranov enum ov361x {
9815807765SVladik Aranov 	ov361x_2048 = 0,
9915807765SVladik Aranov 	ov361x_1600,
10015807765SVladik Aranov 	ov361x_1024,
10115807765SVladik Aranov 	ov361x_640,
10215807765SVladik Aranov 	ov361x_320,
10315807765SVladik Aranov 	ov361x_160,
10415807765SVladik Aranov 	ov361x_last
10515807765SVladik Aranov };
10615807765SVladik Aranov 
10715807765SVladik Aranov static const struct v4l2_pix_format ov361x_mode[] = {
10815807765SVladik Aranov 	{0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
10915807765SVladik Aranov 		.bytesperline = 0x800,
11015807765SVladik Aranov 		.sizeimage = 0x800 * 0x600,
11115807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB},
11215807765SVladik Aranov 	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
11315807765SVladik Aranov 		.bytesperline = 1600,
11415807765SVladik Aranov 		.sizeimage = 1600 * 1200,
11515807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB},
11615807765SVladik Aranov 	{1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
11715807765SVladik Aranov 		.bytesperline = 768,
11815807765SVladik Aranov 		.sizeimage = 1024 * 768,
11915807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB},
12015807765SVladik Aranov 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
12115807765SVladik Aranov 		.bytesperline = 640,
12215807765SVladik Aranov 		.sizeimage = 640 * 480,
12315807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB},
12415807765SVladik Aranov 	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
12515807765SVladik Aranov 		.bytesperline = 320,
12615807765SVladik Aranov 		.sizeimage = 320 * 240,
12715807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB},
12815807765SVladik Aranov 	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
12915807765SVladik Aranov 		.bytesperline = 160,
13015807765SVladik Aranov 		.sizeimage = 160 * 120,
13115807765SVladik Aranov 		.colorspace = V4L2_COLORSPACE_SRGB}
13215807765SVladik Aranov };
13315807765SVladik Aranov 
13415807765SVladik Aranov static const u8 ov361x_start_2048[][2] = {
13515807765SVladik Aranov 	{0x12, 0x80},
13615807765SVladik Aranov 	{0x13, 0xcf},
13715807765SVladik Aranov 	{0x14, 0x40},
13815807765SVladik Aranov 	{0x15, 0x00},
13915807765SVladik Aranov 	{0x01, 0x80},
14015807765SVladik Aranov 	{0x02, 0x80},
14115807765SVladik Aranov 	{0x04, 0x70},
14215807765SVladik Aranov 	{0x0d, 0x40},
14315807765SVladik Aranov 	{0x0f, 0x47},
14415807765SVladik Aranov 	{0x11, 0x81},
14515807765SVladik Aranov 	{0x32, 0x36},
14615807765SVladik Aranov 	{0x33, 0x0c},
14715807765SVladik Aranov 	{0x34, 0x00},
14815807765SVladik Aranov 	{0x35, 0x90},
14915807765SVladik Aranov 	{0x12, 0x00},
15015807765SVladik Aranov 	{0x17, 0x10},
15115807765SVladik Aranov 	{0x18, 0x90},
15215807765SVladik Aranov 	{0x19, 0x00},
15315807765SVladik Aranov 	{0x1a, 0xc0},
15415807765SVladik Aranov };
15515807765SVladik Aranov static const u8 ov361x_bridge_start_2048[][2] = {
15615807765SVladik Aranov 	{0xf1, 0x60},
15715807765SVladik Aranov 	{0x88, 0x00},
15815807765SVladik Aranov 	{0x89, 0x08},
15915807765SVladik Aranov 	{0x8a, 0x00},
16015807765SVladik Aranov 	{0x8b, 0x06},
16115807765SVladik Aranov 	{0x8c, 0x01},
16215807765SVladik Aranov 	{0x8d, 0x10},
16315807765SVladik Aranov 	{0x1c, 0x00},
16415807765SVladik Aranov 	{0x1d, 0x48},
16515807765SVladik Aranov 	{0x1d, 0x00},
16615807765SVladik Aranov 	{0x1d, 0xff},
16715807765SVladik Aranov 	{0x1c, 0x0a},
16815807765SVladik Aranov 	{0x1d, 0x2e},
16915807765SVladik Aranov 	{0x1d, 0x1e},
17015807765SVladik Aranov };
17115807765SVladik Aranov 
17215807765SVladik Aranov static const u8 ov361x_start_1600[][2] = {
17315807765SVladik Aranov 	{0x12, 0x80},
17415807765SVladik Aranov 	{0x13, 0xcf},
17515807765SVladik Aranov 	{0x14, 0x40},
17615807765SVladik Aranov 	{0x15, 0x00},
17715807765SVladik Aranov 	{0x01, 0x80},
17815807765SVladik Aranov 	{0x02, 0x80},
17915807765SVladik Aranov 	{0x04, 0x70},
18015807765SVladik Aranov 	{0x0d, 0x40},
18115807765SVladik Aranov 	{0x0f, 0x47},
18215807765SVladik Aranov 	{0x11, 0x81},
18315807765SVladik Aranov 	{0x32, 0x36},
18415807765SVladik Aranov 	{0x33, 0x0C},
18515807765SVladik Aranov 	{0x34, 0x00},
18615807765SVladik Aranov 	{0x35, 0x90},
18715807765SVladik Aranov 	{0x12, 0x00},
18815807765SVladik Aranov 	{0x17, 0x10},
18915807765SVladik Aranov 	{0x18, 0x90},
19015807765SVladik Aranov 	{0x19, 0x00},
19115807765SVladik Aranov 	{0x1a, 0xc0},
19215807765SVladik Aranov };
19315807765SVladik Aranov static const u8 ov361x_bridge_start_1600[][2] = {
19415807765SVladik Aranov 	{0xf1, 0x60},  /* Hsize[7:0] */
19515807765SVladik Aranov 	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
19615807765SVladik Aranov 	{0x89, 0x08},  /* Vsize[7:0] */
19715807765SVladik Aranov 	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
19815807765SVladik Aranov 	{0x8b, 0x06},  /* for Iso */
19915807765SVladik Aranov 	{0x8c, 0x01},  /* RAW input */
20015807765SVladik Aranov 	{0x8d, 0x10},
20115807765SVladik Aranov 	{0x1c, 0x00},  /* RAW output, Iso transfer */
20215807765SVladik Aranov 	{0x1d, 0x48},
20315807765SVladik Aranov 	{0x1d, 0x00},
20415807765SVladik Aranov 	{0x1d, 0xff},
20515807765SVladik Aranov 	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
20615807765SVladik Aranov 	{0x1d, 0x2e},  /* for Iso */
20715807765SVladik Aranov 	{0x1d, 0x1e},
20815807765SVladik Aranov };
20915807765SVladik Aranov 
21015807765SVladik Aranov static const u8 ov361x_start_1024[][2] = {
21115807765SVladik Aranov 	{0x12, 0x80},
21215807765SVladik Aranov 	{0x13, 0xcf},
21315807765SVladik Aranov 	{0x14, 0x40},
21415807765SVladik Aranov 	{0x15, 0x00},
21515807765SVladik Aranov 	{0x01, 0x80},
21615807765SVladik Aranov 	{0x02, 0x80},
21715807765SVladik Aranov 	{0x04, 0x70},
21815807765SVladik Aranov 	{0x0d, 0x40},
21915807765SVladik Aranov 	{0x0f, 0x47},
22015807765SVladik Aranov 	{0x11, 0x81},
22115807765SVladik Aranov 	{0x32, 0x36},
22215807765SVladik Aranov 	{0x33, 0x0C},
22315807765SVladik Aranov 	{0x34, 0x00},
22415807765SVladik Aranov 	{0x35, 0x90},
22515807765SVladik Aranov 	{0x12, 0x40},
22615807765SVladik Aranov 	{0x17, 0x1f},
22715807765SVladik Aranov 	{0x18, 0x5f},
22815807765SVladik Aranov 	{0x19, 0x00},
22915807765SVladik Aranov 	{0x1a, 0x68},
23015807765SVladik Aranov };
23115807765SVladik Aranov static const u8 ov361x_bridge_start_1024[][2] = {
23215807765SVladik Aranov 	{0xf1, 0x60},  /* Hsize[7:0] */
23315807765SVladik Aranov 	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
23415807765SVladik Aranov 	{0x89, 0x04},  /* Vsize[7:0] */
23515807765SVladik Aranov 	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
23615807765SVladik Aranov 	{0x8b, 0x03},  /* for Iso */
23715807765SVladik Aranov 	{0x8c, 0x01},  /* RAW input  */
23815807765SVladik Aranov 	{0x8d, 0x10},
23915807765SVladik Aranov 	{0x1c, 0x00},  /* RAW output, Iso transfer */
24015807765SVladik Aranov 	{0x1d, 0x48},
24115807765SVladik Aranov 	{0x1d, 0x00},
24215807765SVladik Aranov 	{0x1d, 0xff},
24315807765SVladik Aranov 	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
24415807765SVladik Aranov 	{0x1d, 0x2e},  /* for Iso */
24515807765SVladik Aranov 	{0x1d, 0x1e},
24615807765SVladik Aranov };
24715807765SVladik Aranov 
24815807765SVladik Aranov static const u8 ov361x_start_640[][2] = {
24915807765SVladik Aranov 	{0x12, 0x80},
25015807765SVladik Aranov 	{0x13, 0xcf},
25115807765SVladik Aranov 	{0x14, 0x40},
25215807765SVladik Aranov 	{0x15, 0x00},
25315807765SVladik Aranov 	{0x01, 0x80},
25415807765SVladik Aranov 	{0x02, 0x80},
25515807765SVladik Aranov 	{0x04, 0x70},
25615807765SVladik Aranov 	{0x0d, 0x40},
25715807765SVladik Aranov 	{0x0f, 0x47},
25815807765SVladik Aranov 	{0x11, 0x81},
25915807765SVladik Aranov 	{0x32, 0x36},
26015807765SVladik Aranov 	{0x33, 0x0C},
26115807765SVladik Aranov 	{0x34, 0x00},
26215807765SVladik Aranov 	{0x35, 0x90},
26315807765SVladik Aranov 	{0x12, 0x40},
26415807765SVladik Aranov 	{0x17, 0x1f},
26515807765SVladik Aranov 	{0x18, 0x5f},
26615807765SVladik Aranov 	{0x19, 0x00},
26715807765SVladik Aranov 	{0x1a, 0x68},
26815807765SVladik Aranov };
26915807765SVladik Aranov 
27015807765SVladik Aranov static const u8 ov361x_bridge_start_640[][2] = {
27115807765SVladik Aranov 	{0xf1, 0x60},  /* Hsize[7:0]*/
27215807765SVladik Aranov 	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
27315807765SVladik Aranov 	{0x89, 0x04},  /* Vsize[7:0] */
27415807765SVladik Aranov 	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
27515807765SVladik Aranov 	{0x8b, 0x03},  /* for Iso */
27615807765SVladik Aranov 	{0x8c, 0x01},  /* RAW input */
27715807765SVladik Aranov 	{0x8d, 0x10},
27815807765SVladik Aranov 	{0x1c, 0x00},  /* RAW output, Iso transfer */
27915807765SVladik Aranov 	{0x1d, 0x48},
28015807765SVladik Aranov 	{0x1d, 0x00},
28115807765SVladik Aranov 	{0x1d, 0xff},
28215807765SVladik Aranov 	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
28315807765SVladik Aranov 	{0x1d, 0x2e},  /* for Iso */
28415807765SVladik Aranov 	{0x1d, 0x1e},
28515807765SVladik Aranov };
28615807765SVladik Aranov 
28715807765SVladik Aranov static const u8 ov361x_start_320[][2] = {
28815807765SVladik Aranov 	{0x12, 0x80},
28915807765SVladik Aranov 	{0x13, 0xcf},
29015807765SVladik Aranov 	{0x14, 0x40},
29115807765SVladik Aranov 	{0x15, 0x00},
29215807765SVladik Aranov 	{0x01, 0x80},
29315807765SVladik Aranov 	{0x02, 0x80},
29415807765SVladik Aranov 	{0x04, 0x70},
29515807765SVladik Aranov 	{0x0d, 0x40},
29615807765SVladik Aranov 	{0x0f, 0x47},
29715807765SVladik Aranov 	{0x11, 0x81},
29815807765SVladik Aranov 	{0x32, 0x36},
29915807765SVladik Aranov 	{0x33, 0x0C},
30015807765SVladik Aranov 	{0x34, 0x00},
30115807765SVladik Aranov 	{0x35, 0x90},
30215807765SVladik Aranov 	{0x12, 0x40},
30315807765SVladik Aranov 	{0x17, 0x1f},
30415807765SVladik Aranov 	{0x18, 0x5f},
30515807765SVladik Aranov 	{0x19, 0x00},
30615807765SVladik Aranov 	{0x1a, 0x68},
30715807765SVladik Aranov };
30815807765SVladik Aranov 
30915807765SVladik Aranov static const u8 ov361x_bridge_start_320[][2] = {
31015807765SVladik Aranov 	{0xf1, 0x60},  /* Hsize[7:0] */
31115807765SVladik Aranov 	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
31215807765SVladik Aranov 	{0x89, 0x04},  /* Vsize[7:0] */
31315807765SVladik Aranov 	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
31415807765SVladik Aranov 	{0x8b, 0x03},  /* for Iso */
31515807765SVladik Aranov 	{0x8c, 0x01},  /* RAW input */
31615807765SVladik Aranov 	{0x8d, 0x10},
31715807765SVladik Aranov 	{0x1c, 0x00},  /* RAW output, Iso transfer; */
31815807765SVladik Aranov 	{0x1d, 0x48},
31915807765SVladik Aranov 	{0x1d, 0x00},
32015807765SVladik Aranov 	{0x1d, 0xff},
32115807765SVladik Aranov 	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
32215807765SVladik Aranov 	{0x1d, 0x2e},  /* for Iso */
32315807765SVladik Aranov 	{0x1d, 0x1e},
32415807765SVladik Aranov };
32515807765SVladik Aranov 
32615807765SVladik Aranov static const u8 ov361x_start_160[][2] = {
32715807765SVladik Aranov 	{0x12, 0x80},
32815807765SVladik Aranov 	{0x13, 0xcf},
32915807765SVladik Aranov 	{0x14, 0x40},
33015807765SVladik Aranov 	{0x15, 0x00},
33115807765SVladik Aranov 	{0x01, 0x80},
33215807765SVladik Aranov 	{0x02, 0x80},
33315807765SVladik Aranov 	{0x04, 0x70},
33415807765SVladik Aranov 	{0x0d, 0x40},
33515807765SVladik Aranov 	{0x0f, 0x47},
33615807765SVladik Aranov 	{0x11, 0x81},
33715807765SVladik Aranov 	{0x32, 0x36},
33815807765SVladik Aranov 	{0x33, 0x0C},
33915807765SVladik Aranov 	{0x34, 0x00},
34015807765SVladik Aranov 	{0x35, 0x90},
34115807765SVladik Aranov 	{0x12, 0x40},
34215807765SVladik Aranov 	{0x17, 0x1f},
34315807765SVladik Aranov 	{0x18, 0x5f},
34415807765SVladik Aranov 	{0x19, 0x00},
34515807765SVladik Aranov 	{0x1a, 0x68},
34615807765SVladik Aranov };
34715807765SVladik Aranov 
34815807765SVladik Aranov static const u8 ov361x_bridge_start_160[][2] = {
34915807765SVladik Aranov 	{0xf1, 0x60},  /* Hsize[7:0] */
35015807765SVladik Aranov 	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
35115807765SVladik Aranov 	{0x89, 0x04},  /* Vsize[7:0] */
35215807765SVladik Aranov 	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
35315807765SVladik Aranov 	{0x8b, 0x03},  /* for Iso */
35415807765SVladik Aranov 	{0x8c, 0x01},  /* RAW input */
35515807765SVladik Aranov 	{0x8d, 0x10},
35615807765SVladik Aranov 	{0x1c, 0x00},  /* RAW output, Iso transfer */
35715807765SVladik Aranov 	{0x1d, 0x48},
35815807765SVladik Aranov 	{0x1d, 0x00},
35915807765SVladik Aranov 	{0x1d, 0xff},
36015807765SVladik Aranov 	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
36115807765SVladik Aranov 	{0x1d, 0x2e},  /* for Iso */
36215807765SVladik Aranov 	{0x1d, 0x1e},
36315807765SVladik Aranov };
36415807765SVladik Aranov 
365c52af799SJean-Francois Moine static const u8 bridge_init[][2] = {
366c52af799SJean-Francois Moine 	{0x88, 0xf8},
367c52af799SJean-Francois Moine 	{0x89, 0xff},
368c52af799SJean-Francois Moine 	{0x76, 0x03},
369c52af799SJean-Francois Moine 	{0x92, 0x03},
370c52af799SJean-Francois Moine 	{0x95, 0x10},
371c52af799SJean-Francois Moine 	{0xe2, 0x00},
372c52af799SJean-Francois Moine 	{0xe7, 0x3e},
373c52af799SJean-Francois Moine 	{0x8d, 0x1c},
374c52af799SJean-Francois Moine 	{0x8e, 0x00},
375c52af799SJean-Francois Moine 	{0x8f, 0x00},
376c52af799SJean-Francois Moine 	{0x1f, 0x00},
377c52af799SJean-Francois Moine 	{0xc3, 0xf9},
378c52af799SJean-Francois Moine 	{0x89, 0xff},
379c52af799SJean-Francois Moine 	{0x88, 0xf8},
380c52af799SJean-Francois Moine 	{0x76, 0x03},
381c52af799SJean-Francois Moine 	{0x92, 0x01},
382c52af799SJean-Francois Moine 	{0x93, 0x18},
383c52af799SJean-Francois Moine 	{0x1c, 0x0a},
384c52af799SJean-Francois Moine 	{0x1d, 0x48},
385c52af799SJean-Francois Moine 	{0xc0, 0x50},
386c52af799SJean-Francois Moine 	{0xc1, 0x3c},
387c52af799SJean-Francois Moine 	{0x34, 0x05},
388c52af799SJean-Francois Moine 	{0xc2, 0x0c},
389c52af799SJean-Francois Moine 	{0xc3, 0xf9},
390c52af799SJean-Francois Moine 	{0x34, 0x05},
391c52af799SJean-Francois Moine 	{0xe7, 0x2e},
392c52af799SJean-Francois Moine 	{0x31, 0xf9},
393c52af799SJean-Francois Moine 	{0x35, 0x02},
394c52af799SJean-Francois Moine 	{0xd9, 0x10},
395c52af799SJean-Francois Moine 	{0x25, 0x42},
396c52af799SJean-Francois Moine 	{0x94, 0x11},
397c52af799SJean-Francois Moine };
398c52af799SJean-Francois Moine 
3998d64d4f6SJean-François Moine static const u8 ov965x_init[][2] = {
400c52af799SJean-Francois Moine 	{0x12, 0x80},	/* com7 - SSCB reset */
401c52af799SJean-Francois Moine 	{0x00, 0x00},	/* gain */
402c52af799SJean-Francois Moine 	{0x01, 0x80},	/* blue */
403c52af799SJean-Francois Moine 	{0x02, 0x80},	/* red */
404c52af799SJean-Francois Moine 	{0x03, 0x1b},	/* vref */
405c52af799SJean-Francois Moine 	{0x04, 0x03},	/* com1 - exposure low bits */
406c52af799SJean-Francois Moine 	{0x0b, 0x57},	/* ver */
407c52af799SJean-Francois Moine 	{0x0e, 0x61},	/* com5 */
408c52af799SJean-Francois Moine 	{0x0f, 0x42},	/* com6 */
409c52af799SJean-Francois Moine 	{0x11, 0x00},	/* clkrc */
410c52af799SJean-Francois Moine 	{0x12, 0x02},	/* com7 - 15fps VGA YUYV */
411c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
412c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
413c52af799SJean-Francois Moine 	{0x16, 0x24},	/* reg16 */
414c52af799SJean-Francois Moine 	{0x17, 0x1d},	/* hstart*/
415c52af799SJean-Francois Moine 	{0x18, 0xbd},	/* hstop */
416c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
417c52af799SJean-Francois Moine 	{0x1a, 0x81},	/* vstop*/
418c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
419c52af799SJean-Francois Moine 	{0x24, 0x3c},	/* aew */
420c52af799SJean-Francois Moine 	{0x25, 0x36},	/* aeb */
421c52af799SJean-Francois Moine 	{0x26, 0x71},	/* vpt */
422c52af799SJean-Francois Moine 	{0x27, 0x08},	/* bbias */
423c52af799SJean-Francois Moine 	{0x28, 0x08},	/* gbbias */
424c52af799SJean-Francois Moine 	{0x29, 0x15},	/* gr com */
425c52af799SJean-Francois Moine 	{0x2a, 0x00},	/* exhch */
426c52af799SJean-Francois Moine 	{0x2b, 0x00},	/* exhcl */
427c52af799SJean-Francois Moine 	{0x2c, 0x08},	/* rbias */
428c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
429c52af799SJean-Francois Moine 	{0x33, 0x00},	/* chlf */
430c52af799SJean-Francois Moine 	{0x34, 0x3f},	/* aref1 */
431c52af799SJean-Francois Moine 	{0x35, 0x00},	/* aref2 */
432c52af799SJean-Francois Moine 	{0x36, 0xf8},	/* aref3 */
433c52af799SJean-Francois Moine 	{0x38, 0x72},	/* adc2 */
434c52af799SJean-Francois Moine 	{0x39, 0x57},	/* aref4 */
435c52af799SJean-Francois Moine 	{0x3a, 0x80},	/* tslb - yuyv */
436c52af799SJean-Francois Moine 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
437c52af799SJean-Francois Moine 	{0x3d, 0x99},	/* com13 */
438c52af799SJean-Francois Moine 	{0x3f, 0xc1},	/* edge */
439c52af799SJean-Francois Moine 	{0x40, 0xc0},	/* com15 */
440c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
441c52af799SJean-Francois Moine 	{0x42, 0xc0},	/* com17 */
442c52af799SJean-Francois Moine 	{0x43, 0x0a},	/* rsvd */
443c52af799SJean-Francois Moine 	{0x44, 0xf0},
444c52af799SJean-Francois Moine 	{0x45, 0x46},
445c52af799SJean-Francois Moine 	{0x46, 0x62},
446c52af799SJean-Francois Moine 	{0x47, 0x2a},
447c52af799SJean-Francois Moine 	{0x48, 0x3c},
448c52af799SJean-Francois Moine 	{0x4a, 0xfc},
449c52af799SJean-Francois Moine 	{0x4b, 0xfc},
450c52af799SJean-Francois Moine 	{0x4c, 0x7f},
451c52af799SJean-Francois Moine 	{0x4d, 0x7f},
452c52af799SJean-Francois Moine 	{0x4e, 0x7f},
453c52af799SJean-Francois Moine 	{0x4f, 0x98},	/* matrix */
454c52af799SJean-Francois Moine 	{0x50, 0x98},
455c52af799SJean-Francois Moine 	{0x51, 0x00},
456c52af799SJean-Francois Moine 	{0x52, 0x28},
457c52af799SJean-Francois Moine 	{0x53, 0x70},
458c52af799SJean-Francois Moine 	{0x54, 0x98},
459c52af799SJean-Francois Moine 	{0x58, 0x1a},	/* matrix coef sign */
460c52af799SJean-Francois Moine 	{0x59, 0x85},	/* AWB control */
461c52af799SJean-Francois Moine 	{0x5a, 0xa9},
462c52af799SJean-Francois Moine 	{0x5b, 0x64},
463c52af799SJean-Francois Moine 	{0x5c, 0x84},
464c52af799SJean-Francois Moine 	{0x5d, 0x53},
465c52af799SJean-Francois Moine 	{0x5e, 0x0e},
466c52af799SJean-Francois Moine 	{0x5f, 0xf0},	/* AWB blue limit */
467c52af799SJean-Francois Moine 	{0x60, 0xf0},	/* AWB red limit */
468c52af799SJean-Francois Moine 	{0x61, 0xf0},	/* AWB green limit */
469c52af799SJean-Francois Moine 	{0x62, 0x00},	/* lcc1 */
470c52af799SJean-Francois Moine 	{0x63, 0x00},	/* lcc2 */
471c52af799SJean-Francois Moine 	{0x64, 0x02},	/* lcc3 */
472c52af799SJean-Francois Moine 	{0x65, 0x16},	/* lcc4 */
473c52af799SJean-Francois Moine 	{0x66, 0x01},	/* lcc5 */
474c52af799SJean-Francois Moine 	{0x69, 0x02},	/* hv */
475c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dbvl */
476c52af799SJean-Francois Moine 	{0x6c, 0x04},
477c52af799SJean-Francois Moine 	{0x6d, 0x55},
478c52af799SJean-Francois Moine 	{0x6e, 0x00},
479c52af799SJean-Francois Moine 	{0x6f, 0x9d},
480c52af799SJean-Francois Moine 	{0x70, 0x21},	/* dnsth */
481c52af799SJean-Francois Moine 	{0x71, 0x78},
482c52af799SJean-Francois Moine 	{0x72, 0x00},	/* poidx */
483c52af799SJean-Francois Moine 	{0x73, 0x01},	/* pckdv */
484c52af799SJean-Francois Moine 	{0x74, 0x3a},	/* xindx */
485c52af799SJean-Francois Moine 	{0x75, 0x35},	/* yindx */
486c52af799SJean-Francois Moine 	{0x76, 0x01},
487c52af799SJean-Francois Moine 	{0x77, 0x02},
488c52af799SJean-Francois Moine 	{0x7a, 0x12},	/* gamma curve */
489c52af799SJean-Francois Moine 	{0x7b, 0x08},
490c52af799SJean-Francois Moine 	{0x7c, 0x16},
491c52af799SJean-Francois Moine 	{0x7d, 0x30},
492c52af799SJean-Francois Moine 	{0x7e, 0x5e},
493c52af799SJean-Francois Moine 	{0x7f, 0x72},
494c52af799SJean-Francois Moine 	{0x80, 0x82},
495c52af799SJean-Francois Moine 	{0x81, 0x8e},
496c52af799SJean-Francois Moine 	{0x82, 0x9a},
497c52af799SJean-Francois Moine 	{0x83, 0xa4},
498c52af799SJean-Francois Moine 	{0x84, 0xac},
499c52af799SJean-Francois Moine 	{0x85, 0xb8},
500c52af799SJean-Francois Moine 	{0x86, 0xc3},
501c52af799SJean-Francois Moine 	{0x87, 0xd6},
502c52af799SJean-Francois Moine 	{0x88, 0xe6},
503c52af799SJean-Francois Moine 	{0x89, 0xf2},
504c52af799SJean-Francois Moine 	{0x8a, 0x03},
505c52af799SJean-Francois Moine 	{0x8c, 0x89},	/* com19 */
506c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
507c52af799SJean-Francois Moine 	{0x90, 0x7d},
508c52af799SJean-Francois Moine 	{0x91, 0x7b},
509c52af799SJean-Francois Moine 	{0x9d, 0x03},	/* lcc6 */
510c52af799SJean-Francois Moine 	{0x9e, 0x04},	/* lcc7 */
511c52af799SJean-Francois Moine 	{0x9f, 0x7a},
512c52af799SJean-Francois Moine 	{0xa0, 0x79},
513c52af799SJean-Francois Moine 	{0xa1, 0x40},	/* aechm */
514c52af799SJean-Francois Moine 	{0xa4, 0x50},	/* com21 */
515c52af799SJean-Francois Moine 	{0xa5, 0x68},	/* com26 */
516c52af799SJean-Francois Moine 	{0xa6, 0x4a},	/* AWB green */
517c52af799SJean-Francois Moine 	{0xa8, 0xc1},	/* refa8 */
518c52af799SJean-Francois Moine 	{0xa9, 0xef},	/* refa9 */
519c52af799SJean-Francois Moine 	{0xaa, 0x92},
520c52af799SJean-Francois Moine 	{0xab, 0x04},
521c52af799SJean-Francois Moine 	{0xac, 0x80},	/* black level control */
522c52af799SJean-Francois Moine 	{0xad, 0x80},
523c52af799SJean-Francois Moine 	{0xae, 0x80},
524c52af799SJean-Francois Moine 	{0xaf, 0x80},
525c52af799SJean-Francois Moine 	{0xb2, 0xf2},
526c52af799SJean-Francois Moine 	{0xb3, 0x20},
527c52af799SJean-Francois Moine 	{0xb4, 0x20},	/* ctrlb4 */
528c52af799SJean-Francois Moine 	{0xb5, 0x00},
529c52af799SJean-Francois Moine 	{0xb6, 0xaf},
530c52af799SJean-Francois Moine 	{0xbb, 0xae},
531c52af799SJean-Francois Moine 	{0xbc, 0x7f},	/* ADC channel offsets */
532c52af799SJean-Francois Moine 	{0xdb, 0x7f},
533c52af799SJean-Francois Moine 	{0xbe, 0x7f},
534c52af799SJean-Francois Moine 	{0xbf, 0x7f},
535c52af799SJean-Francois Moine 	{0xc0, 0xe2},
536c52af799SJean-Francois Moine 	{0xc1, 0xc0},
537c52af799SJean-Francois Moine 	{0xc2, 0x01},
538c52af799SJean-Francois Moine 	{0xc3, 0x4e},
539c52af799SJean-Francois Moine 	{0xc6, 0x85},
540c52af799SJean-Francois Moine 	{0xc7, 0x80},	/* com24 */
541c52af799SJean-Francois Moine 	{0xc9, 0xe0},
542c52af799SJean-Francois Moine 	{0xca, 0xe8},
543c52af799SJean-Francois Moine 	{0xcb, 0xf0},
544c52af799SJean-Francois Moine 	{0xcc, 0xd8},
545c52af799SJean-Francois Moine 	{0xcd, 0xf1},
546c52af799SJean-Francois Moine 	{0x4f, 0x98},	/* matrix */
547c52af799SJean-Francois Moine 	{0x50, 0x98},
548c52af799SJean-Francois Moine 	{0x51, 0x00},
549c52af799SJean-Francois Moine 	{0x52, 0x28},
550c52af799SJean-Francois Moine 	{0x53, 0x70},
551c52af799SJean-Francois Moine 	{0x54, 0x98},
552c52af799SJean-Francois Moine 	{0x58, 0x1a},
553c52af799SJean-Francois Moine 	{0xff, 0x41},	/* read 41, write ff 00 */
554c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
555c52af799SJean-Francois Moine 
556c52af799SJean-Francois Moine 	{0xc5, 0x03},	/* 60 Hz banding filter */
557c52af799SJean-Francois Moine 	{0x6a, 0x02},	/* 50 Hz banding filter */
558c52af799SJean-Francois Moine 
559c52af799SJean-Francois Moine 	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
560c52af799SJean-Francois Moine 	{0x36, 0xfa},	/* aref3 */
561c52af799SJean-Francois Moine 	{0x69, 0x0a},	/* hv */
562c52af799SJean-Francois Moine 	{0x8c, 0x89},	/* com22 */
563c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
564c52af799SJean-Francois Moine 	{0x3e, 0x0c},
565c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
566c52af799SJean-Francois Moine 	{0x72, 0x00},
567c52af799SJean-Francois Moine 	{0x73, 0x00},
568c52af799SJean-Francois Moine 	{0x74, 0x3a},
569c52af799SJean-Francois Moine 	{0x75, 0x35},
570c52af799SJean-Francois Moine 	{0x76, 0x01},
571c52af799SJean-Francois Moine 	{0xc7, 0x80},
572c52af799SJean-Francois Moine 	{0x03, 0x12},	/* vref */
573c52af799SJean-Francois Moine 	{0x17, 0x16},	/* hstart */
574c52af799SJean-Francois Moine 	{0x18, 0x02},	/* hstop */
575c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
576c52af799SJean-Francois Moine 	{0x1a, 0x3d},	/* vstop */
577c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
578c52af799SJean-Francois Moine 	{0xc0, 0xaa},
579c52af799SJean-Francois Moine };
580c52af799SJean-Francois Moine 
581c52af799SJean-Francois Moine static const u8 bridge_init_2[][2] = {
582c52af799SJean-Francois Moine 	{0x94, 0xaa},
583c52af799SJean-Francois Moine 	{0xf1, 0x60},
584c52af799SJean-Francois Moine 	{0xe5, 0x04},
585c52af799SJean-Francois Moine 	{0xc0, 0x50},
586c52af799SJean-Francois Moine 	{0xc1, 0x3c},
587c52af799SJean-Francois Moine 	{0x8c, 0x00},
588c52af799SJean-Francois Moine 	{0x8d, 0x1c},
589c52af799SJean-Francois Moine 	{0x34, 0x05},
590c52af799SJean-Francois Moine 
591c52af799SJean-Francois Moine 	{0xc2, 0x0c},
592c52af799SJean-Francois Moine 	{0xc3, 0xf9},
593c52af799SJean-Francois Moine 	{0xda, 0x01},
594c52af799SJean-Francois Moine 	{0x50, 0x00},
595c52af799SJean-Francois Moine 	{0x51, 0xa0},
596c52af799SJean-Francois Moine 	{0x52, 0x3c},
597c52af799SJean-Francois Moine 	{0x53, 0x00},
598c52af799SJean-Francois Moine 	{0x54, 0x00},
599c52af799SJean-Francois Moine 	{0x55, 0x00},
600c52af799SJean-Francois Moine 	{0x57, 0x00},
601c52af799SJean-Francois Moine 	{0x5c, 0x00},
602c52af799SJean-Francois Moine 	{0x5a, 0xa0},
603c52af799SJean-Francois Moine 	{0x5b, 0x78},
604c52af799SJean-Francois Moine 	{0x35, 0x02},
605c52af799SJean-Francois Moine 	{0xd9, 0x10},
606c52af799SJean-Francois Moine 	{0x94, 0x11},
607c52af799SJean-Francois Moine };
608c52af799SJean-Francois Moine 
6098d64d4f6SJean-François Moine static const u8 ov965x_init_2[][2] = {
610c52af799SJean-Francois Moine 	{0x3b, 0xc4},
611c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
612c52af799SJean-Francois Moine 	{0x13, 0xe0},	/* com8 */
613c52af799SJean-Francois Moine 	{0x00, 0x00},	/* gain */
614c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
615c52af799SJean-Francois Moine 	{0x11, 0x03},	/* clkrc */
616c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dblv */
617c52af799SJean-Francois Moine 	{0x6a, 0x05},
618c52af799SJean-Francois Moine 	{0xc5, 0x07},
619c52af799SJean-Francois Moine 	{0xa2, 0x4b},
620c52af799SJean-Francois Moine 	{0xa3, 0x3e},
621c52af799SJean-Francois Moine 	{0x2d, 0x00},
622c52af799SJean-Francois Moine 	{0xff, 0x42},	/* read 42, write ff 00 */
623c52af799SJean-Francois Moine 	{0x42, 0xc0},	/* com17 */
624c52af799SJean-Francois Moine 	{0x2d, 0x00},
625c52af799SJean-Francois Moine 	{0xff, 0x42},	/* read 42, write ff 00 */
626c52af799SJean-Francois Moine 	{0x42, 0xc1},	/* com17 */
627c52af799SJean-Francois Moine /* sharpness */
628c52af799SJean-Francois Moine 	{0x3f, 0x01},
629c52af799SJean-Francois Moine 	{0xff, 0x42},	/* read 42, write ff 00 */
630c52af799SJean-Francois Moine 	{0x42, 0xc1},	/* com17 */
631c52af799SJean-Francois Moine /* saturation */
632c52af799SJean-Francois Moine 	{0x4f, 0x98},	/* matrix */
633c52af799SJean-Francois Moine 	{0x50, 0x98},
634c52af799SJean-Francois Moine 	{0x51, 0x00},
635c52af799SJean-Francois Moine 	{0x52, 0x28},
636c52af799SJean-Francois Moine 	{0x53, 0x70},
637c52af799SJean-Francois Moine 	{0x54, 0x98},
638c52af799SJean-Francois Moine 	{0x58, 0x1a},
639c52af799SJean-Francois Moine 	{0xff, 0x41},	/* read 41, write ff 00 */
640c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
641c52af799SJean-Francois Moine /* contrast */
642c52af799SJean-Francois Moine 	{0x56, 0x40},
643c52af799SJean-Francois Moine /* brightness */
644c52af799SJean-Francois Moine 	{0x55, 0x8f},
645c52af799SJean-Francois Moine /* expo */
646c52af799SJean-Francois Moine 	{0x10, 0x25},	/* aech - exposure high bits */
647c52af799SJean-Francois Moine 	{0xff, 0x13},	/* read 13, write ff 00 */
648c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
649c52af799SJean-Francois Moine };
650c52af799SJean-Francois Moine 
6518d64d4f6SJean-François Moine static const u8 ov971x_init[][2] = {
6528d64d4f6SJean-François Moine 	{0x12, 0x80},
6538d64d4f6SJean-François Moine 	{0x09, 0x10},
6548d64d4f6SJean-François Moine 	{0x1e, 0x07},
6558d64d4f6SJean-François Moine 	{0x5f, 0x18},
6568d64d4f6SJean-François Moine 	{0x69, 0x04},
6578d64d4f6SJean-François Moine 	{0x65, 0x2a},
6588d64d4f6SJean-François Moine 	{0x68, 0x0a},
6598d64d4f6SJean-François Moine 	{0x39, 0x28},
6608d64d4f6SJean-François Moine 	{0x4d, 0x90},
6618d64d4f6SJean-François Moine 	{0xc1, 0x80},
6628d64d4f6SJean-François Moine 	{0x0c, 0x30},
6638d64d4f6SJean-François Moine 	{0x6d, 0x02},
6648d64d4f6SJean-François Moine 	{0x96, 0xf1},
6658d64d4f6SJean-François Moine 	{0xbc, 0x68},
6668d64d4f6SJean-François Moine 	{0x12, 0x00},
6678d64d4f6SJean-François Moine 	{0x3b, 0x00},
6688d64d4f6SJean-François Moine 	{0x97, 0x80},
6698d64d4f6SJean-François Moine 	{0x17, 0x25},
6708d64d4f6SJean-François Moine 	{0x18, 0xa2},
6718d64d4f6SJean-François Moine 	{0x19, 0x01},
6728d64d4f6SJean-François Moine 	{0x1a, 0xca},
6738d64d4f6SJean-François Moine 	{0x03, 0x0a},
6748d64d4f6SJean-François Moine 	{0x32, 0x07},
6758d64d4f6SJean-François Moine 	{0x98, 0x40},	/*{0x98, 0x00},*/
6768d64d4f6SJean-François Moine 	{0x99, 0xA0},	/*{0x99, 0x00},*/
6778d64d4f6SJean-François Moine 	{0x9a, 0x01},	/*{0x9a, 0x00},*/
6788d64d4f6SJean-François Moine 	{0x57, 0x00},
6798d64d4f6SJean-François Moine 	{0x58, 0x78},	/*{0x58, 0xc8},*/
6808d64d4f6SJean-François Moine 	{0x59, 0x50},	/*{0x59, 0xa0},*/
6818d64d4f6SJean-François Moine 	{0x4c, 0x13},
6828d64d4f6SJean-François Moine 	{0x4b, 0x36},
6838d64d4f6SJean-François Moine 	{0x3d, 0x3c},
6848d64d4f6SJean-François Moine 	{0x3e, 0x03},
6858d64d4f6SJean-François Moine 	{0xbd, 0x50},	/*{0xbd, 0xa0},*/
6868d64d4f6SJean-François Moine 	{0xbe, 0x78},	/*{0xbe, 0xc8},*/
6878d64d4f6SJean-François Moine 	{0x4e, 0x55},
6888d64d4f6SJean-François Moine 	{0x4f, 0x55},
6898d64d4f6SJean-François Moine 	{0x50, 0x55},
6908d64d4f6SJean-François Moine 	{0x51, 0x55},
6918d64d4f6SJean-François Moine 	{0x24, 0x55},
6928d64d4f6SJean-François Moine 	{0x25, 0x40},
6938d64d4f6SJean-François Moine 	{0x26, 0xa1},
6948d64d4f6SJean-François Moine 	{0x5c, 0x59},
6958d64d4f6SJean-François Moine 	{0x5d, 0x00},
6968d64d4f6SJean-François Moine 	{0x11, 0x00},
6978d64d4f6SJean-François Moine 	{0x2a, 0x98},
6988d64d4f6SJean-François Moine 	{0x2b, 0x06},
6998d64d4f6SJean-François Moine 	{0x2d, 0x00},
7008d64d4f6SJean-François Moine 	{0x2e, 0x00},
7018d64d4f6SJean-François Moine 	{0x13, 0xa5},
7028d64d4f6SJean-François Moine 	{0x14, 0x40},
7038d64d4f6SJean-François Moine 	{0x4a, 0x00},
7048d64d4f6SJean-François Moine 	{0x49, 0xce},
7058d64d4f6SJean-François Moine 	{0x22, 0x03},
7068d64d4f6SJean-François Moine 	{0x09, 0x00}
7078d64d4f6SJean-François Moine };
7088d64d4f6SJean-François Moine 
7098d64d4f6SJean-François Moine static const u8 ov965x_start_1_vga[][2] = {	/* same for qvga */
710c52af799SJean-Francois Moine 	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
711c52af799SJean-Francois Moine 	{0x36, 0xfa},	/* aref3 */
712c52af799SJean-Francois Moine 	{0x69, 0x0a},	/* hv */
713c52af799SJean-Francois Moine 	{0x8c, 0x89},	/* com22 */
714c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
715c52af799SJean-Francois Moine 	{0x3e, 0x0c},	/* com14 */
716c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
717c52af799SJean-Francois Moine 	{0x72, 0x00},
718c52af799SJean-Francois Moine 	{0x73, 0x00},
719c52af799SJean-Francois Moine 	{0x74, 0x3a},
720c52af799SJean-Francois Moine 	{0x75, 0x35},
721c52af799SJean-Francois Moine 	{0x76, 0x01},
722c52af799SJean-Francois Moine 	{0xc7, 0x80},	/* com24 */
723c52af799SJean-Francois Moine 	{0x03, 0x12},	/* vref */
724c52af799SJean-Francois Moine 	{0x17, 0x16},	/* hstart */
725c52af799SJean-Francois Moine 	{0x18, 0x02},	/* hstop */
726c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
727c52af799SJean-Francois Moine 	{0x1a, 0x3d},	/* vstop */
728c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
729c52af799SJean-Francois Moine 	{0xc0, 0xaa},
730c52af799SJean-Francois Moine };
731c52af799SJean-Francois Moine 
7328d64d4f6SJean-François Moine static const u8 ov965x_start_1_svga[][2] = {
733c52af799SJean-Francois Moine 	{0x12, 0x02},	/* com7 - YUYV - VGA 15 full resolution */
734c52af799SJean-Francois Moine 	{0x36, 0xf8},	/* aref3 */
735c52af799SJean-Francois Moine 	{0x69, 0x02},	/* hv */
736c52af799SJean-Francois Moine 	{0x8c, 0x0d},	/* com22 */
737c52af799SJean-Francois Moine 	{0x3e, 0x0c},	/* com14 */
738c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
739c52af799SJean-Francois Moine 	{0x72, 0x00},
740c52af799SJean-Francois Moine 	{0x73, 0x01},
741c52af799SJean-Francois Moine 	{0x74, 0x3a},
742c52af799SJean-Francois Moine 	{0x75, 0x35},
743c52af799SJean-Francois Moine 	{0x76, 0x01},
744c52af799SJean-Francois Moine 	{0xc7, 0x80},	/* com24 */
745c52af799SJean-Francois Moine 	{0x03, 0x1b},	/* vref */
746c52af799SJean-Francois Moine 	{0x17, 0x1d},	/* hstart */
747c52af799SJean-Francois Moine 	{0x18, 0xbd},	/* hstop */
748c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
749c52af799SJean-Francois Moine 	{0x1a, 0x81},	/* vstop */
750c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
751c52af799SJean-Francois Moine 	{0xc0, 0xe2},
752c52af799SJean-Francois Moine };
753c52af799SJean-Francois Moine 
7548d64d4f6SJean-François Moine static const u8 ov965x_start_1_xga[][2] = {
755c52af799SJean-Francois Moine 	{0x12, 0x02},	/* com7 */
756c52af799SJean-Francois Moine 	{0x36, 0xf8},	/* aref3 */
757c52af799SJean-Francois Moine 	{0x69, 0x02},	/* hv */
758c52af799SJean-Francois Moine 	{0x8c, 0x89},	/* com22 */
759c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
760c52af799SJean-Francois Moine 	{0x3e, 0x0c},	/* com14 */
761c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
762c52af799SJean-Francois Moine 	{0x72, 0x00},
763c52af799SJean-Francois Moine 	{0x73, 0x01},
764c52af799SJean-Francois Moine 	{0x74, 0x3a},
765c52af799SJean-Francois Moine 	{0x75, 0x35},
766c52af799SJean-Francois Moine 	{0x76, 0x01},
767c52af799SJean-Francois Moine 	{0xc7, 0x80},	/* com24 */
768c52af799SJean-Francois Moine 	{0x03, 0x1b},	/* vref */
769c52af799SJean-Francois Moine 	{0x17, 0x1d},	/* hstart */
770c52af799SJean-Francois Moine 	{0x18, 0xbd},	/* hstop */
771c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
772c52af799SJean-Francois Moine 	{0x1a, 0x81},	/* vstop */
773c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
774c52af799SJean-Francois Moine 	{0xc0, 0xe2},
775c52af799SJean-Francois Moine };
776c52af799SJean-Francois Moine 
7778d64d4f6SJean-François Moine static const u8 ov965x_start_1_sxga[][2] = {
778c52af799SJean-Francois Moine 	{0x12, 0x02},	/* com7 */
779c52af799SJean-Francois Moine 	{0x36, 0xf8},	/* aref3 */
780c52af799SJean-Francois Moine 	{0x69, 0x02},	/* hv */
781c52af799SJean-Francois Moine 	{0x8c, 0x89},	/* com22 */
782c52af799SJean-Francois Moine 	{0x14, 0x28},	/* com9 */
783c52af799SJean-Francois Moine 	{0x3e, 0x0c},	/* com14 */
784c52af799SJean-Francois Moine 	{0x41, 0x40},	/* com16 */
785c52af799SJean-Francois Moine 	{0x72, 0x00},
786c52af799SJean-Francois Moine 	{0x73, 0x01},
787c52af799SJean-Francois Moine 	{0x74, 0x3a},
788c52af799SJean-Francois Moine 	{0x75, 0x35},
789c52af799SJean-Francois Moine 	{0x76, 0x01},
790c52af799SJean-Francois Moine 	{0xc7, 0x80},	/* com24 */
791c52af799SJean-Francois Moine 	{0x03, 0x1b},	/* vref */
792c52af799SJean-Francois Moine 	{0x17, 0x1d},	/* hstart */
793c52af799SJean-Francois Moine 	{0x18, 0x02},	/* hstop */
794c52af799SJean-Francois Moine 	{0x19, 0x01},	/* vstrt */
795c52af799SJean-Francois Moine 	{0x1a, 0x81},	/* vstop */
796c52af799SJean-Francois Moine 	{0x32, 0xff},	/* href */
797c52af799SJean-Francois Moine 	{0xc0, 0xe2},
798c52af799SJean-Francois Moine };
799c52af799SJean-Francois Moine 
800c52af799SJean-Francois Moine static const u8 bridge_start_qvga[][2] = {
801c52af799SJean-Francois Moine 	{0x94, 0xaa},
802c52af799SJean-Francois Moine 	{0xf1, 0x60},
803c52af799SJean-Francois Moine 	{0xe5, 0x04},
804c52af799SJean-Francois Moine 	{0xc0, 0x50},
805c52af799SJean-Francois Moine 	{0xc1, 0x3c},
806c52af799SJean-Francois Moine 	{0x8c, 0x00},
807c52af799SJean-Francois Moine 	{0x8d, 0x1c},
808c52af799SJean-Francois Moine 	{0x34, 0x05},
809c52af799SJean-Francois Moine 
810c52af799SJean-Francois Moine 	{0xc2, 0x4c},
811c52af799SJean-Francois Moine 	{0xc3, 0xf9},
812c52af799SJean-Francois Moine 	{0xda, 0x00},
813c52af799SJean-Francois Moine 	{0x50, 0x00},
814c52af799SJean-Francois Moine 	{0x51, 0xa0},
815c52af799SJean-Francois Moine 	{0x52, 0x78},
816c52af799SJean-Francois Moine 	{0x53, 0x00},
817c52af799SJean-Francois Moine 	{0x54, 0x00},
818c52af799SJean-Francois Moine 	{0x55, 0x00},
819c52af799SJean-Francois Moine 	{0x57, 0x00},
820c52af799SJean-Francois Moine 	{0x5c, 0x00},
821c52af799SJean-Francois Moine 	{0x5a, 0x50},
822c52af799SJean-Francois Moine 	{0x5b, 0x3c},
823c52af799SJean-Francois Moine 	{0x35, 0x02},
824c52af799SJean-Francois Moine 	{0xd9, 0x10},
825c52af799SJean-Francois Moine 	{0x94, 0x11},
826c52af799SJean-Francois Moine };
827c52af799SJean-Francois Moine 
828c52af799SJean-Francois Moine static const u8 bridge_start_vga[][2] = {
829c52af799SJean-Francois Moine 	{0x94, 0xaa},
830c52af799SJean-Francois Moine 	{0xf1, 0x60},
831c52af799SJean-Francois Moine 	{0xe5, 0x04},
832c52af799SJean-Francois Moine 	{0xc0, 0x50},
833c52af799SJean-Francois Moine 	{0xc1, 0x3c},
834c52af799SJean-Francois Moine 	{0x8c, 0x00},
835c52af799SJean-Francois Moine 	{0x8d, 0x1c},
836c52af799SJean-Francois Moine 	{0x34, 0x05},
837c52af799SJean-Francois Moine 	{0xc2, 0x0c},
838c52af799SJean-Francois Moine 	{0xc3, 0xf9},
839c52af799SJean-Francois Moine 	{0xda, 0x01},
840c52af799SJean-Francois Moine 	{0x50, 0x00},
841c52af799SJean-Francois Moine 	{0x51, 0xa0},
842c52af799SJean-Francois Moine 	{0x52, 0x3c},
843c52af799SJean-Francois Moine 	{0x53, 0x00},
844c52af799SJean-Francois Moine 	{0x54, 0x00},
845c52af799SJean-Francois Moine 	{0x55, 0x00},
846c52af799SJean-Francois Moine 	{0x57, 0x00},
847c52af799SJean-Francois Moine 	{0x5c, 0x00},
848c52af799SJean-Francois Moine 	{0x5a, 0xa0},
849c52af799SJean-Francois Moine 	{0x5b, 0x78},
850c52af799SJean-Francois Moine 	{0x35, 0x02},
851c52af799SJean-Francois Moine 	{0xd9, 0x10},
852c52af799SJean-Francois Moine 	{0x94, 0x11},
853c52af799SJean-Francois Moine };
854c52af799SJean-Francois Moine 
855c52af799SJean-Francois Moine static const u8 bridge_start_svga[][2] = {
856c52af799SJean-Francois Moine 	{0x94, 0xaa},
857c52af799SJean-Francois Moine 	{0xf1, 0x60},
858c52af799SJean-Francois Moine 	{0xe5, 0x04},
859c52af799SJean-Francois Moine 	{0xc0, 0xa0},
860c52af799SJean-Francois Moine 	{0xc1, 0x80},
861c52af799SJean-Francois Moine 	{0x8c, 0x00},
862c52af799SJean-Francois Moine 	{0x8d, 0x1c},
863c52af799SJean-Francois Moine 	{0x34, 0x05},
864c52af799SJean-Francois Moine 	{0xc2, 0x4c},
865c52af799SJean-Francois Moine 	{0xc3, 0xf9},
866c52af799SJean-Francois Moine 	{0x50, 0x00},
867c52af799SJean-Francois Moine 	{0x51, 0x40},
868c52af799SJean-Francois Moine 	{0x52, 0x00},
869c52af799SJean-Francois Moine 	{0x53, 0x00},
870c52af799SJean-Francois Moine 	{0x54, 0x00},
871c52af799SJean-Francois Moine 	{0x55, 0x88},
872c52af799SJean-Francois Moine 	{0x57, 0x00},
873c52af799SJean-Francois Moine 	{0x5c, 0x00},
874c52af799SJean-Francois Moine 	{0x5a, 0xc8},
875c52af799SJean-Francois Moine 	{0x5b, 0x96},
876c52af799SJean-Francois Moine 	{0x35, 0x02},
877c52af799SJean-Francois Moine 	{0xd9, 0x10},
878c52af799SJean-Francois Moine 	{0xda, 0x00},
879c52af799SJean-Francois Moine 	{0x94, 0x11},
880c52af799SJean-Francois Moine };
881c52af799SJean-Francois Moine 
882c52af799SJean-Francois Moine static const u8 bridge_start_xga[][2] = {
883c52af799SJean-Francois Moine 	{0x94, 0xaa},
884c52af799SJean-Francois Moine 	{0xf1, 0x60},
885c52af799SJean-Francois Moine 	{0xe5, 0x04},
886c52af799SJean-Francois Moine 	{0xc0, 0xa0},
887c52af799SJean-Francois Moine 	{0xc1, 0x80},
888c52af799SJean-Francois Moine 	{0x8c, 0x00},
889c52af799SJean-Francois Moine 	{0x8d, 0x1c},
890c52af799SJean-Francois Moine 	{0x34, 0x05},
891c52af799SJean-Francois Moine 	{0xc2, 0x4c},
892c52af799SJean-Francois Moine 	{0xc3, 0xf9},
893c52af799SJean-Francois Moine 	{0x50, 0x00},
894c52af799SJean-Francois Moine 	{0x51, 0x40},
895c52af799SJean-Francois Moine 	{0x52, 0x00},
896c52af799SJean-Francois Moine 	{0x53, 0x00},
897c52af799SJean-Francois Moine 	{0x54, 0x00},
898c52af799SJean-Francois Moine 	{0x55, 0x88},
899c52af799SJean-Francois Moine 	{0x57, 0x00},
900c52af799SJean-Francois Moine 	{0x5c, 0x01},
901c52af799SJean-Francois Moine 	{0x5a, 0x00},
902c52af799SJean-Francois Moine 	{0x5b, 0xc0},
903c52af799SJean-Francois Moine 	{0x35, 0x02},
904c52af799SJean-Francois Moine 	{0xd9, 0x10},
905c52af799SJean-Francois Moine 	{0xda, 0x01},
906c52af799SJean-Francois Moine 	{0x94, 0x11},
907c52af799SJean-Francois Moine };
908c52af799SJean-Francois Moine 
909c52af799SJean-Francois Moine static const u8 bridge_start_sxga[][2] = {
910c52af799SJean-Francois Moine 	{0x94, 0xaa},
911c52af799SJean-Francois Moine 	{0xf1, 0x60},
912c52af799SJean-Francois Moine 	{0xe5, 0x04},
913c52af799SJean-Francois Moine 	{0xc0, 0xa0},
914c52af799SJean-Francois Moine 	{0xc1, 0x80},
915c52af799SJean-Francois Moine 	{0x8c, 0x00},
916c52af799SJean-Francois Moine 	{0x8d, 0x1c},
917c52af799SJean-Francois Moine 	{0x34, 0x05},
918c52af799SJean-Francois Moine 	{0xc2, 0x0c},
919c52af799SJean-Francois Moine 	{0xc3, 0xf9},
920c52af799SJean-Francois Moine 	{0xda, 0x00},
921c52af799SJean-Francois Moine 	{0x35, 0x02},
922c52af799SJean-Francois Moine 	{0xd9, 0x10},
923c52af799SJean-Francois Moine 	{0x94, 0x11},
924c52af799SJean-Francois Moine };
925c52af799SJean-Francois Moine 
9268d64d4f6SJean-François Moine static const u8 ov965x_start_2_qvga[][2] = {
927c52af799SJean-Francois Moine 	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */
928c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
929c52af799SJean-Francois Moine 	{0x13, 0xe0},	/* com8 */
930c52af799SJean-Francois Moine 	{0x00, 0x00},
931c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
932c52af799SJean-Francois Moine 	{0x11, 0x01},	/* clkrc */
933c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dblv */
934c52af799SJean-Francois Moine 	{0x6a, 0x02},	/* 50 Hz banding filter */
935c52af799SJean-Francois Moine 	{0xc5, 0x03},	/* 60 Hz banding filter */
936c52af799SJean-Francois Moine 	{0xa2, 0x96},	/* bd50 */
937c52af799SJean-Francois Moine 	{0xa3, 0x7d},	/* bd60 */
938c52af799SJean-Francois Moine 
939c52af799SJean-Francois Moine 	{0xff, 0x13},	/* read 13, write ff 00 */
940c52af799SJean-Francois Moine 	{0x13, 0xe7},
941c52af799SJean-Francois Moine 	{0x3a, 0x80},	/* tslb - yuyv */
942c52af799SJean-Francois Moine };
943c52af799SJean-Francois Moine 
9448d64d4f6SJean-François Moine static const u8 ov965x_start_2_vga[][2] = {
945c52af799SJean-Francois Moine 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
946c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
947c52af799SJean-Francois Moine 	{0x13, 0xe0},	/* com8 */
948c52af799SJean-Francois Moine 	{0x00, 0x00},
949c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
950c52af799SJean-Francois Moine 	{0x11, 0x03},	/* clkrc */
951c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dblv */
952c52af799SJean-Francois Moine 	{0x6a, 0x05},	/* 50 Hz banding filter */
953c52af799SJean-Francois Moine 	{0xc5, 0x07},	/* 60 Hz banding filter */
954c52af799SJean-Francois Moine 	{0xa2, 0x4b},	/* bd50 */
955c52af799SJean-Francois Moine 	{0xa3, 0x3e},	/* bd60 */
956c52af799SJean-Francois Moine 
957c52af799SJean-Francois Moine 	{0x2d, 0x00},	/* advfl */
958c52af799SJean-Francois Moine };
959c52af799SJean-Francois Moine 
9608d64d4f6SJean-François Moine static const u8 ov965x_start_2_svga[][2] = {	/* same for xga */
961c52af799SJean-Francois Moine 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
962c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
963c52af799SJean-Francois Moine 	{0x13, 0xe0},	/* com8 */
964c52af799SJean-Francois Moine 	{0x00, 0x00},
965c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
966c52af799SJean-Francois Moine 	{0x11, 0x01},	/* clkrc */
967c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dblv */
968c52af799SJean-Francois Moine 	{0x6a, 0x0c},	/* 50 Hz banding filter */
969c52af799SJean-Francois Moine 	{0xc5, 0x0f},	/* 60 Hz banding filter */
970c52af799SJean-Francois Moine 	{0xa2, 0x4e},	/* bd50 */
971c52af799SJean-Francois Moine 	{0xa3, 0x41},	/* bd60 */
972c52af799SJean-Francois Moine };
973c52af799SJean-Francois Moine 
9748d64d4f6SJean-François Moine static const u8 ov965x_start_2_sxga[][2] = {
975c52af799SJean-Francois Moine 	{0x13, 0xe0},	/* com8 */
976c52af799SJean-Francois Moine 	{0x00, 0x00},
977c52af799SJean-Francois Moine 	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
978c52af799SJean-Francois Moine 	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
979c52af799SJean-Francois Moine 	{0x1e, 0x04},	/* mvfp */
980c52af799SJean-Francois Moine 	{0x11, 0x01},	/* clkrc */
981c52af799SJean-Francois Moine 	{0x6b, 0x5a},	/* dblv */
982c52af799SJean-Francois Moine 	{0x6a, 0x0c},	/* 50 Hz banding filter */
983c52af799SJean-Francois Moine 	{0xc5, 0x0f},	/* 60 Hz banding filter */
984c52af799SJean-Francois Moine 	{0xa2, 0x4e},	/* bd50 */
985c52af799SJean-Francois Moine 	{0xa3, 0x41},	/* bd60 */
986c52af799SJean-Francois Moine };
987c52af799SJean-Francois Moine 
988965b37a4SJose Alberto Reguero static const u8 ov562x_init[][2] = {
989965b37a4SJose Alberto Reguero 	{0x88, 0x20},
990965b37a4SJose Alberto Reguero 	{0x89, 0x0a},
991965b37a4SJose Alberto Reguero 	{0x8a, 0x90},
992965b37a4SJose Alberto Reguero 	{0x8b, 0x06},
993965b37a4SJose Alberto Reguero 	{0x8c, 0x01},
994965b37a4SJose Alberto Reguero 	{0x8d, 0x10},
995965b37a4SJose Alberto Reguero 	{0x1c, 0x00},
996965b37a4SJose Alberto Reguero 	{0x1d, 0x48},
997965b37a4SJose Alberto Reguero 	{0x1d, 0x00},
998965b37a4SJose Alberto Reguero 	{0x1d, 0xff},
999965b37a4SJose Alberto Reguero 	{0x1c, 0x0a},
1000965b37a4SJose Alberto Reguero 	{0x1d, 0x2e},
1001965b37a4SJose Alberto Reguero 	{0x1d, 0x1e},
1002965b37a4SJose Alberto Reguero };
1003965b37a4SJose Alberto Reguero 
1004965b37a4SJose Alberto Reguero static const u8 ov562x_init_2[][2] = {
1005965b37a4SJose Alberto Reguero 	{0x12, 0x80},
1006965b37a4SJose Alberto Reguero 	{0x11, 0x41},
1007965b37a4SJose Alberto Reguero 	{0x13, 0x00},
1008965b37a4SJose Alberto Reguero 	{0x10, 0x1e},
1009965b37a4SJose Alberto Reguero 	{0x3b, 0x07},
1010965b37a4SJose Alberto Reguero 	{0x5b, 0x40},
1011965b37a4SJose Alberto Reguero 	{0x39, 0x07},
1012965b37a4SJose Alberto Reguero 	{0x53, 0x02},
1013965b37a4SJose Alberto Reguero 	{0x54, 0x60},
1014965b37a4SJose Alberto Reguero 	{0x04, 0x20},
1015965b37a4SJose Alberto Reguero 	{0x27, 0x04},
1016965b37a4SJose Alberto Reguero 	{0x3d, 0x40},
1017965b37a4SJose Alberto Reguero 	{0x36, 0x00},
1018965b37a4SJose Alberto Reguero 	{0xc5, 0x04},
1019965b37a4SJose Alberto Reguero 	{0x4e, 0x00},
1020965b37a4SJose Alberto Reguero 	{0x4f, 0x93},
1021965b37a4SJose Alberto Reguero 	{0x50, 0x7b},
1022965b37a4SJose Alberto Reguero 	{0xca, 0x0c},
1023965b37a4SJose Alberto Reguero 	{0xcb, 0x0f},
1024965b37a4SJose Alberto Reguero 	{0x39, 0x07},
1025965b37a4SJose Alberto Reguero 	{0x4a, 0x10},
1026965b37a4SJose Alberto Reguero 	{0x3e, 0x0a},
1027965b37a4SJose Alberto Reguero 	{0x3d, 0x00},
1028965b37a4SJose Alberto Reguero 	{0x0c, 0x38},
1029965b37a4SJose Alberto Reguero 	{0x38, 0x90},
1030965b37a4SJose Alberto Reguero 	{0x46, 0x30},
1031965b37a4SJose Alberto Reguero 	{0x4f, 0x93},
1032965b37a4SJose Alberto Reguero 	{0x50, 0x7b},
1033965b37a4SJose Alberto Reguero 	{0xab, 0x00},
1034965b37a4SJose Alberto Reguero 	{0xca, 0x0c},
1035965b37a4SJose Alberto Reguero 	{0xcb, 0x0f},
1036965b37a4SJose Alberto Reguero 	{0x37, 0x02},
1037965b37a4SJose Alberto Reguero 	{0x44, 0x48},
1038965b37a4SJose Alberto Reguero 	{0x8d, 0x44},
1039965b37a4SJose Alberto Reguero 	{0x2a, 0x00},
1040965b37a4SJose Alberto Reguero 	{0x2b, 0x00},
1041965b37a4SJose Alberto Reguero 	{0x32, 0x00},
1042965b37a4SJose Alberto Reguero 	{0x38, 0x90},
1043965b37a4SJose Alberto Reguero 	{0x53, 0x02},
1044965b37a4SJose Alberto Reguero 	{0x54, 0x60},
1045965b37a4SJose Alberto Reguero 	{0x12, 0x00},
1046965b37a4SJose Alberto Reguero 	{0x17, 0x12},
1047965b37a4SJose Alberto Reguero 	{0x18, 0xb4},
1048965b37a4SJose Alberto Reguero 	{0x19, 0x0c},
1049965b37a4SJose Alberto Reguero 	{0x1a, 0xf4},
1050965b37a4SJose Alberto Reguero 	{0x03, 0x4a},
1051965b37a4SJose Alberto Reguero 	{0x89, 0x20},
1052965b37a4SJose Alberto Reguero 	{0x83, 0x80},
1053965b37a4SJose Alberto Reguero 	{0xb7, 0x9d},
1054965b37a4SJose Alberto Reguero 	{0xb6, 0x11},
1055965b37a4SJose Alberto Reguero 	{0xb5, 0x55},
1056965b37a4SJose Alberto Reguero 	{0xb4, 0x00},
1057965b37a4SJose Alberto Reguero 	{0xa9, 0xf0},
1058965b37a4SJose Alberto Reguero 	{0xa8, 0x0a},
1059965b37a4SJose Alberto Reguero 	{0xb8, 0xf0},
1060965b37a4SJose Alberto Reguero 	{0xb9, 0xf0},
1061965b37a4SJose Alberto Reguero 	{0xba, 0xf0},
1062965b37a4SJose Alberto Reguero 	{0x81, 0x07},
1063965b37a4SJose Alberto Reguero 	{0x63, 0x44},
1064965b37a4SJose Alberto Reguero 	{0x13, 0xc7},
1065965b37a4SJose Alberto Reguero 	{0x14, 0x60},
1066965b37a4SJose Alberto Reguero 	{0x33, 0x75},
1067965b37a4SJose Alberto Reguero 	{0x2c, 0x00},
1068965b37a4SJose Alberto Reguero 	{0x09, 0x00},
1069965b37a4SJose Alberto Reguero 	{0x35, 0x30},
1070965b37a4SJose Alberto Reguero 	{0x27, 0x04},
1071965b37a4SJose Alberto Reguero 	{0x3c, 0x07},
1072965b37a4SJose Alberto Reguero 	{0x3a, 0x0a},
1073965b37a4SJose Alberto Reguero 	{0x3b, 0x07},
1074965b37a4SJose Alberto Reguero 	{0x01, 0x40},
1075965b37a4SJose Alberto Reguero 	{0x02, 0x40},
1076965b37a4SJose Alberto Reguero 	{0x16, 0x40},
1077965b37a4SJose Alberto Reguero 	{0x52, 0xb0},
1078965b37a4SJose Alberto Reguero 	{0x51, 0x83},
1079965b37a4SJose Alberto Reguero 	{0x21, 0xbb},
1080965b37a4SJose Alberto Reguero 	{0x22, 0x10},
1081965b37a4SJose Alberto Reguero 	{0x23, 0x03},
1082965b37a4SJose Alberto Reguero 	{0x35, 0x38},
1083965b37a4SJose Alberto Reguero 	{0x20, 0x90},
1084965b37a4SJose Alberto Reguero 	{0x28, 0x30},
1085965b37a4SJose Alberto Reguero 	{0x73, 0xe1},
1086965b37a4SJose Alberto Reguero 	{0x6c, 0x00},
1087965b37a4SJose Alberto Reguero 	{0x6d, 0x80},
1088965b37a4SJose Alberto Reguero 	{0x6e, 0x00},
1089965b37a4SJose Alberto Reguero 	{0x70, 0x04},
1090965b37a4SJose Alberto Reguero 	{0x71, 0x00},
1091965b37a4SJose Alberto Reguero 	{0x8d, 0x04},
1092965b37a4SJose Alberto Reguero 	{0x64, 0x00},
1093965b37a4SJose Alberto Reguero 	{0x65, 0x00},
1094965b37a4SJose Alberto Reguero 	{0x66, 0x00},
1095965b37a4SJose Alberto Reguero 	{0x67, 0x00},
1096965b37a4SJose Alberto Reguero 	{0x68, 0x00},
1097965b37a4SJose Alberto Reguero 	{0x69, 0x00},
1098965b37a4SJose Alberto Reguero 	{0x6a, 0x00},
1099965b37a4SJose Alberto Reguero 	{0x6b, 0x00},
1100965b37a4SJose Alberto Reguero 	{0x71, 0x94},
1101965b37a4SJose Alberto Reguero 	{0x74, 0x20},
1102965b37a4SJose Alberto Reguero 	{0x80, 0x09},
1103965b37a4SJose Alberto Reguero 	{0x85, 0xc0},
1104965b37a4SJose Alberto Reguero };
1105965b37a4SJose Alberto Reguero 
1106c52af799SJean-Francois Moine static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
1107c52af799SJean-Francois Moine {
1108c52af799SJean-Francois Moine 	struct usb_device *udev = gspca_dev->dev;
1109c52af799SJean-Francois Moine 	int ret;
1110c52af799SJean-Francois Moine 
1111c52af799SJean-Francois Moine 	if (gspca_dev->usb_err < 0)
1112c52af799SJean-Francois Moine 		return;
1113c52af799SJean-Francois Moine 	gspca_dev->usb_buf[0] = val;
1114c52af799SJean-Francois Moine 	ret = usb_control_msg(udev,
1115c52af799SJean-Francois Moine 			      usb_sndctrlpipe(udev, 0),
1116c52af799SJean-Francois Moine 			      0x01,
1117c52af799SJean-Francois Moine 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1118c52af799SJean-Francois Moine 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
1119c52af799SJean-Francois Moine 	if (ret < 0) {
1120133a9fe9SJoe Perches 		pr_err("reg_w failed %d\n", ret);
1121c52af799SJean-Francois Moine 		gspca_dev->usb_err = ret;
1122c52af799SJean-Francois Moine 	}
1123c52af799SJean-Francois Moine }
1124c52af799SJean-Francois Moine 
1125c52af799SJean-Francois Moine static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
1126c52af799SJean-Francois Moine {
112737d5efb0SJoe Perches 	gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x\n", reg, val);
1128c52af799SJean-Francois Moine 	reg_w_i(gspca_dev, reg, val);
1129c52af799SJean-Francois Moine }
1130c52af799SJean-Francois Moine 
1131c52af799SJean-Francois Moine static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
1132c52af799SJean-Francois Moine {
1133c52af799SJean-Francois Moine 	struct usb_device *udev = gspca_dev->dev;
1134c52af799SJean-Francois Moine 	int ret;
1135c52af799SJean-Francois Moine 
1136c52af799SJean-Francois Moine 	if (gspca_dev->usb_err < 0)
1137c52af799SJean-Francois Moine 		return 0;
1138c52af799SJean-Francois Moine 	ret = usb_control_msg(udev,
1139c52af799SJean-Francois Moine 			      usb_rcvctrlpipe(udev, 0),
1140c52af799SJean-Francois Moine 			      0x01,
1141c52af799SJean-Francois Moine 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1142c52af799SJean-Francois Moine 			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
114337d5efb0SJoe Perches 	gspca_dbg(gspca_dev, D_USBI, "reg_r [%04x] -> %02x\n",
114437d5efb0SJoe Perches 		  reg, gspca_dev->usb_buf[0]);
1145c52af799SJean-Francois Moine 	if (ret < 0) {
1146133a9fe9SJoe Perches 		pr_err("reg_r err %d\n", ret);
1147c52af799SJean-Francois Moine 		gspca_dev->usb_err = ret;
1148*4843a543SHans Verkuil 		return 0;
1149c52af799SJean-Francois Moine 	}
1150c52af799SJean-Francois Moine 	return gspca_dev->usb_buf[0];
1151c52af799SJean-Francois Moine }
1152c52af799SJean-Francois Moine 
1153c52af799SJean-Francois Moine static int sccb_check_status(struct gspca_dev *gspca_dev)
1154c52af799SJean-Francois Moine {
1155c52af799SJean-Francois Moine 	u8 data;
1156c52af799SJean-Francois Moine 	int i;
1157c52af799SJean-Francois Moine 
1158c52af799SJean-Francois Moine 	for (i = 0; i < 5; i++) {
115915807765SVladik Aranov 		msleep(20);
1160c52af799SJean-Francois Moine 		data = reg_r(gspca_dev, OV534_REG_STATUS);
1161c52af799SJean-Francois Moine 
1162c52af799SJean-Francois Moine 		switch (data) {
1163c52af799SJean-Francois Moine 		case 0x00:
1164c52af799SJean-Francois Moine 			return 1;
1165c52af799SJean-Francois Moine 		case 0x04:
1166c52af799SJean-Francois Moine 			return 0;
1167c52af799SJean-Francois Moine 		case 0x03:
1168c52af799SJean-Francois Moine 			break;
1169c52af799SJean-Francois Moine 		default:
117037d5efb0SJoe Perches 			gspca_dbg(gspca_dev, D_USBI|D_USBO,
117137d5efb0SJoe Perches 				  "sccb status 0x%02x, attempt %d/5\n",
1172c52af799SJean-Francois Moine 				  data, i + 1);
1173c52af799SJean-Francois Moine 		}
1174c52af799SJean-Francois Moine 	}
1175c52af799SJean-Francois Moine 	return 0;
1176c52af799SJean-Francois Moine }
1177c52af799SJean-Francois Moine 
1178c52af799SJean-Francois Moine static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
1179c52af799SJean-Francois Moine {
118037d5efb0SJoe Perches 	gspca_dbg(gspca_dev, D_USBO, "sccb_write [%02x] = %02x\n", reg, val);
1181c52af799SJean-Francois Moine 	reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
1182c52af799SJean-Francois Moine 	reg_w_i(gspca_dev, OV534_REG_WRITE, val);
1183c52af799SJean-Francois Moine 	reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
1184c52af799SJean-Francois Moine 
1185c52af799SJean-Francois Moine 	if (!sccb_check_status(gspca_dev))
1186133a9fe9SJoe Perches 		pr_err("sccb_write failed\n");
1187c52af799SJean-Francois Moine }
1188c52af799SJean-Francois Moine 
1189c52af799SJean-Francois Moine static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
1190c52af799SJean-Francois Moine {
1191c52af799SJean-Francois Moine 	reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
1192c52af799SJean-Francois Moine 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
1193c52af799SJean-Francois Moine 	if (!sccb_check_status(gspca_dev))
1194133a9fe9SJoe Perches 		pr_err("sccb_read failed 1\n");
1195c52af799SJean-Francois Moine 
1196c52af799SJean-Francois Moine 	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
1197c52af799SJean-Francois Moine 	if (!sccb_check_status(gspca_dev))
1198133a9fe9SJoe Perches 		pr_err("sccb_read failed 2\n");
1199c52af799SJean-Francois Moine 
1200c52af799SJean-Francois Moine 	return reg_r(gspca_dev, OV534_REG_READ);
1201c52af799SJean-Francois Moine }
1202c52af799SJean-Francois Moine 
1203c52af799SJean-Francois Moine /* output a bridge sequence (reg - val) */
1204c52af799SJean-Francois Moine static void reg_w_array(struct gspca_dev *gspca_dev,
1205c52af799SJean-Francois Moine 			const u8 (*data)[2], int len)
1206c52af799SJean-Francois Moine {
1207c52af799SJean-Francois Moine 	while (--len >= 0) {
1208c52af799SJean-Francois Moine 		reg_w(gspca_dev, (*data)[0], (*data)[1]);
1209c52af799SJean-Francois Moine 		data++;
1210c52af799SJean-Francois Moine 	}
1211c52af799SJean-Francois Moine }
1212c52af799SJean-Francois Moine 
1213c52af799SJean-Francois Moine /* output a sensor sequence (reg - val) */
1214c52af799SJean-Francois Moine static void sccb_w_array(struct gspca_dev *gspca_dev,
1215c52af799SJean-Francois Moine 			const u8 (*data)[2], int len)
1216c52af799SJean-Francois Moine {
1217c52af799SJean-Francois Moine 	while (--len >= 0) {
1218c52af799SJean-Francois Moine 		if ((*data)[0] != 0xff) {
1219c52af799SJean-Francois Moine 			sccb_write(gspca_dev, (*data)[0], (*data)[1]);
1220c52af799SJean-Francois Moine 		} else {
1221c52af799SJean-Francois Moine 			sccb_read(gspca_dev, (*data)[1]);
1222c52af799SJean-Francois Moine 			sccb_write(gspca_dev, 0xff, 0x00);
1223c52af799SJean-Francois Moine 		}
1224c52af799SJean-Francois Moine 		data++;
1225c52af799SJean-Francois Moine 	}
1226c52af799SJean-Francois Moine }
1227c52af799SJean-Francois Moine 
1228c52af799SJean-Francois Moine /* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
1229c52af799SJean-Francois Moine  * (direction and output)? */
1230c52af799SJean-Francois Moine static void set_led(struct gspca_dev *gspca_dev, int status)
1231c52af799SJean-Francois Moine {
1232c52af799SJean-Francois Moine 	u8 data;
1233c52af799SJean-Francois Moine 
123437d5efb0SJoe Perches 	gspca_dbg(gspca_dev, D_CONF, "led status: %d\n", status);
1235c52af799SJean-Francois Moine 
1236c52af799SJean-Francois Moine 	data = reg_r(gspca_dev, 0x21);
1237c52af799SJean-Francois Moine 	data |= 0x80;
1238c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0x21, data);
1239c52af799SJean-Francois Moine 
1240c52af799SJean-Francois Moine 	data = reg_r(gspca_dev, 0x23);
1241c52af799SJean-Francois Moine 	if (status)
1242c52af799SJean-Francois Moine 		data |= 0x80;
1243c52af799SJean-Francois Moine 	else
1244c52af799SJean-Francois Moine 		data &= ~0x80;
1245c52af799SJean-Francois Moine 
1246c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0x23, data);
1247c52af799SJean-Francois Moine 
1248c52af799SJean-Francois Moine 	if (!status) {
1249c52af799SJean-Francois Moine 		data = reg_r(gspca_dev, 0x21);
1250c52af799SJean-Francois Moine 		data &= ~0x80;
1251c52af799SJean-Francois Moine 		reg_w(gspca_dev, 0x21, data);
1252c52af799SJean-Francois Moine 	}
1253c52af799SJean-Francois Moine }
1254c52af799SJean-Francois Moine 
1255f3920f0fSHans Verkuil static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
1256c52af799SJean-Francois Moine {
1257c52af799SJean-Francois Moine 	struct sd *sd = (struct sd *) gspca_dev;
1258c52af799SJean-Francois Moine 	u8 val;
1259d9ef28a9SJose Alberto Reguero 	s8 sval;
1260c52af799SJean-Francois Moine 
1261d9ef28a9SJose Alberto Reguero 	if (sd->sensor == SENSOR_OV562x) {
1262f3920f0fSHans Verkuil 		sval = brightness;
1263d9ef28a9SJose Alberto Reguero 		val = 0x76;
1264d9ef28a9SJose Alberto Reguero 		val += sval;
1265d9ef28a9SJose Alberto Reguero 		sccb_write(gspca_dev, 0x24, val);
1266d9ef28a9SJose Alberto Reguero 		val = 0x6a;
1267d9ef28a9SJose Alberto Reguero 		val += sval;
1268d9ef28a9SJose Alberto Reguero 		sccb_write(gspca_dev, 0x25, val);
1269d9ef28a9SJose Alberto Reguero 		if (sval < -40)
1270d9ef28a9SJose Alberto Reguero 			val = 0x71;
1271d9ef28a9SJose Alberto Reguero 		else if (sval < 20)
1272d9ef28a9SJose Alberto Reguero 			val = 0x94;
1273d9ef28a9SJose Alberto Reguero 		else
1274d9ef28a9SJose Alberto Reguero 			val = 0xe6;
1275d9ef28a9SJose Alberto Reguero 		sccb_write(gspca_dev, 0x26, val);
1276d9ef28a9SJose Alberto Reguero 	} else {
1277f3920f0fSHans Verkuil 		val = brightness;
1278c52af799SJean-Francois Moine 		if (val < 8)
1279c52af799SJean-Francois Moine 			val = 15 - val;		/* f .. 8 */
1280c52af799SJean-Francois Moine 		else
1281c52af799SJean-Francois Moine 			val = val - 8;		/* 0 .. 7 */
1282c52af799SJean-Francois Moine 		sccb_write(gspca_dev, 0x55,	/* brtn - brightness adjustment */
1283c52af799SJean-Francois Moine 				0x0f | (val << 4));
1284c52af799SJean-Francois Moine 	}
1285d9ef28a9SJose Alberto Reguero }
1286c52af799SJean-Francois Moine 
1287f3920f0fSHans Verkuil static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
1288c52af799SJean-Francois Moine {
1289c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x56,	/* cnst1 - contrast 1 ctrl coeff */
1290f3920f0fSHans Verkuil 			val << 4);
1291c52af799SJean-Francois Moine }
1292c52af799SJean-Francois Moine 
1293f3920f0fSHans Verkuil static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
1294c52af799SJean-Francois Moine {
1295c52af799SJean-Francois Moine 	u8 val;
1296c52af799SJean-Francois Moine 
1297c52af799SJean-Francois Moine /*fixme: should adjust agc/awb/aec by different controls */
1298c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
1299c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1300f3920f0fSHans Verkuil 	if (autogain)
1301c52af799SJean-Francois Moine 		val |= 0x05;		/* agc & aec */
1302c52af799SJean-Francois Moine 	else
1303c52af799SJean-Francois Moine 		val &= 0xfa;
1304c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x13, val);
1305c52af799SJean-Francois Moine }
1306c52af799SJean-Francois Moine 
1307f3920f0fSHans Verkuil static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
1308c52af799SJean-Francois Moine {
1309c52af799SJean-Francois Moine 	static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
1310f3920f0fSHans Verkuil 	u8 val;
1311c52af799SJean-Francois Moine 
1312f3920f0fSHans Verkuil 	sccb_write(gspca_dev, 0x10, expo[exposure]);	/* aec[9:2] */
1313c52af799SJean-Francois Moine 
1314c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
1315c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1316c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x13, val);
1317c52af799SJean-Francois Moine 
1318c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0xa1);		/* aech */
1319c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1320c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xa1, val & 0xe0);	/* aec[15:10] = 0 */
1321c52af799SJean-Francois Moine }
1322c52af799SJean-Francois Moine 
1323f3920f0fSHans Verkuil static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
1324c52af799SJean-Francois Moine {
1325c52af799SJean-Francois Moine 	if (val < 0) {				/* auto */
1326c52af799SJean-Francois Moine 		val = sccb_read(gspca_dev, 0x42);	/* com17 */
1327c52af799SJean-Francois Moine 		sccb_write(gspca_dev, 0xff, 0x00);
1328c52af799SJean-Francois Moine 		sccb_write(gspca_dev, 0x42, val | 0x40);
1329c52af799SJean-Francois Moine 				/* Edge enhancement strength auto adjust */
1330c52af799SJean-Francois Moine 		return;
1331c52af799SJean-Francois Moine 	}
1332c52af799SJean-Francois Moine 	if (val != 0)
1333c52af799SJean-Francois Moine 		val = 1 << (val - 1);
1334c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x3f,	/* edge - edge enhance. factor */
1335c52af799SJean-Francois Moine 			val);
1336c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0x42);		/* com17 */
1337c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1338c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x42, val & 0xbf);
1339c52af799SJean-Francois Moine }
1340c52af799SJean-Francois Moine 
1341f3920f0fSHans Verkuil static void setsatur(struct gspca_dev *gspca_dev, s32 val)
1342c52af799SJean-Francois Moine {
1343c52af799SJean-Francois Moine 	u8 val1, val2, val3;
1344c52af799SJean-Francois Moine 	static const u8 matrix[5][2] = {
1345c52af799SJean-Francois Moine 		{0x14, 0x38},
1346c52af799SJean-Francois Moine 		{0x1e, 0x54},
1347c52af799SJean-Francois Moine 		{0x28, 0x70},
1348c52af799SJean-Francois Moine 		{0x32, 0x8c},
1349c52af799SJean-Francois Moine 		{0x48, 0x90}
1350c52af799SJean-Francois Moine 	};
1351c52af799SJean-Francois Moine 
1352f3920f0fSHans Verkuil 	val1 = matrix[val][0];
1353f3920f0fSHans Verkuil 	val2 = matrix[val][1];
1354c52af799SJean-Francois Moine 	val3 = val1 + val2;
1355c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x4f, val3);	/* matrix coeff */
1356c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x50, val3);
1357c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x51, 0x00);
1358c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x52, val1);
1359c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x53, val2);
1360c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x54, val3);
1361c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x58, 0x1a);	/* mtxs - coeff signs */
1362c52af799SJean-Francois Moine 
1363c52af799SJean-Francois Moine 	val1 = sccb_read(gspca_dev, 0x41);	/* com16 */
1364c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1365c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x41, val1);
1366c52af799SJean-Francois Moine }
1367c52af799SJean-Francois Moine 
1368f3920f0fSHans Verkuil static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
1369c52af799SJean-Francois Moine {
1370c52af799SJean-Francois Moine 	u8 val;
1371c52af799SJean-Francois Moine 
1372c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0x13);		/* com8 */
1373c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1374f3920f0fSHans Verkuil 	if (freq == 0) {
1375c52af799SJean-Francois Moine 		sccb_write(gspca_dev, 0x13, val & 0xdf);
1376c52af799SJean-Francois Moine 		return;
1377c52af799SJean-Francois Moine 	}
1378c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x13, val | 0x20);
1379c52af799SJean-Francois Moine 
1380c52af799SJean-Francois Moine 	val = sccb_read(gspca_dev, 0x42);		/* com17 */
1381c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0xff, 0x00);
1382f3920f0fSHans Verkuil 	if (freq == 1)
1383c52af799SJean-Francois Moine 		val |= 0x01;
1384c52af799SJean-Francois Moine 	else
1385c52af799SJean-Francois Moine 		val &= 0xfe;
1386c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x42, val);
1387c52af799SJean-Francois Moine }
1388c52af799SJean-Francois Moine 
1389c52af799SJean-Francois Moine /* this function is called at probe time */
1390c52af799SJean-Francois Moine static int sd_config(struct gspca_dev *gspca_dev,
1391c52af799SJean-Francois Moine 		     const struct usb_device_id *id)
1392c52af799SJean-Francois Moine {
1393c52af799SJean-Francois Moine 	return 0;
1394c52af799SJean-Francois Moine }
1395c52af799SJean-Francois Moine 
1396c52af799SJean-Francois Moine /* this function is called at probe and resume time */
1397c52af799SJean-Francois Moine static int sd_init(struct gspca_dev *gspca_dev)
1398c52af799SJean-Francois Moine {
13998d64d4f6SJean-François Moine 	struct sd *sd = (struct sd *) gspca_dev;
1400c52af799SJean-Francois Moine 	u16 sensor_id;
1401c52af799SJean-Francois Moine 
1402c52af799SJean-Francois Moine 	/* reset bridge */
1403c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe7, 0x3a);
1404c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe0, 0x08);
1405c52af799SJean-Francois Moine 	msleep(100);
1406c52af799SJean-Francois Moine 
1407c52af799SJean-Francois Moine 	/* initialize the sensor address */
1408c52af799SJean-Francois Moine 	reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
1409c52af799SJean-Francois Moine 
1410c52af799SJean-Francois Moine 	/* reset sensor */
1411c52af799SJean-Francois Moine 	sccb_write(gspca_dev, 0x12, 0x80);
1412c52af799SJean-Francois Moine 	msleep(10);
1413c52af799SJean-Francois Moine 
1414c52af799SJean-Francois Moine 	/* probe the sensor */
1415c52af799SJean-Francois Moine 	sccb_read(gspca_dev, 0x0a);
1416c52af799SJean-Francois Moine 	sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
1417c52af799SJean-Francois Moine 	sccb_read(gspca_dev, 0x0b);
1418c52af799SJean-Francois Moine 	sensor_id |= sccb_read(gspca_dev, 0x0b);
141937d5efb0SJoe Perches 	gspca_dbg(gspca_dev, D_PROBE, "Sensor ID: %04x\n", sensor_id);
1420c52af799SJean-Francois Moine 
1421c52af799SJean-Francois Moine 	/* initialize */
14228d64d4f6SJean-François Moine 	if ((sensor_id & 0xfff0) == 0x9650) {
14238d64d4f6SJean-François Moine 		sd->sensor = SENSOR_OV965x;
14248d64d4f6SJean-François Moine 
14257592e037SJean-François Moine 		gspca_dev->cam.cam_mode = ov965x_mode;
14267592e037SJean-François Moine 		gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
14277592e037SJean-François Moine 
1428c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_init,
1429c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_init));
14308d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_init,
14318d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_init));
1432c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_init_2,
1433c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_init_2));
14348d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_init_2,
14358d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_init_2));
1436c52af799SJean-Francois Moine 		reg_w(gspca_dev, 0xe0, 0x00);
1437c52af799SJean-Francois Moine 		reg_w(gspca_dev, 0xe0, 0x01);
1438c52af799SJean-Francois Moine 		set_led(gspca_dev, 0);
1439c52af799SJean-Francois Moine 		reg_w(gspca_dev, 0xe0, 0x00);
14408d64d4f6SJean-François Moine 	} else if ((sensor_id & 0xfff0) == 0x9710) {
14418d64d4f6SJean-François Moine 		const char *p;
14428d64d4f6SJean-François Moine 		int l;
14438d64d4f6SJean-François Moine 
14448d64d4f6SJean-François Moine 		sd->sensor = SENSOR_OV971x;
14458d64d4f6SJean-François Moine 
14468d64d4f6SJean-François Moine 		gspca_dev->cam.cam_mode = ov971x_mode;
14478d64d4f6SJean-François Moine 		gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
14488d64d4f6SJean-François Moine 
14498d64d4f6SJean-François Moine 		gspca_dev->cam.bulk = 1;
14508d64d4f6SJean-François Moine 		gspca_dev->cam.bulk_size = 16384;
14518d64d4f6SJean-François Moine 		gspca_dev->cam.bulk_nurbs = 2;
14528d64d4f6SJean-François Moine 
14538d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov971x_init,
14548d64d4f6SJean-François Moine 				ARRAY_SIZE(ov971x_init));
14558d64d4f6SJean-François Moine 
14568d64d4f6SJean-François Moine 		/* set video format on bridge processor */
14578d64d4f6SJean-François Moine 		/* access bridge processor's video format registers at: 0x00 */
14588d64d4f6SJean-François Moine 		reg_w(gspca_dev, 0x1c, 0x00);
14598d64d4f6SJean-François Moine 		/*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
14608d64d4f6SJean-François Moine 		reg_w(gspca_dev, 0x1d, 0x00);
14618d64d4f6SJean-François Moine 
14628d64d4f6SJean-François Moine 		/* Will W. specific stuff
14638d64d4f6SJean-François Moine 		 * set VSYNC to
14648d64d4f6SJean-François Moine 		 *	output (0x1f) if first webcam
14658d64d4f6SJean-François Moine 		 *	input (0x17) if 2nd or 3rd webcam */
14668d64d4f6SJean-François Moine 		p = video_device_node_name(&gspca_dev->vdev);
14678d64d4f6SJean-François Moine 		l = strlen(p) - 1;
14688d64d4f6SJean-François Moine 		if (p[l] == '0')
14698d64d4f6SJean-François Moine 			reg_w(gspca_dev, 0x56, 0x1f);
14708d64d4f6SJean-François Moine 		else
14718d64d4f6SJean-François Moine 			reg_w(gspca_dev, 0x56, 0x17);
1472965b37a4SJose Alberto Reguero 	} else if ((sensor_id & 0xfff0) == 0x5620) {
1473965b37a4SJose Alberto Reguero 		sd->sensor = SENSOR_OV562x;
1474965b37a4SJose Alberto Reguero 		gspca_dev->cam.cam_mode = ov562x_mode;
1475965b37a4SJose Alberto Reguero 		gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
1476965b37a4SJose Alberto Reguero 
1477965b37a4SJose Alberto Reguero 		reg_w_array(gspca_dev, ov562x_init,
1478965b37a4SJose Alberto Reguero 				ARRAY_SIZE(ov562x_init));
1479965b37a4SJose Alberto Reguero 		sccb_w_array(gspca_dev, ov562x_init_2,
1480965b37a4SJose Alberto Reguero 				ARRAY_SIZE(ov562x_init_2));
1481965b37a4SJose Alberto Reguero 		reg_w(gspca_dev, 0xe0, 0x00);
148215807765SVladik Aranov 	} else if ((sensor_id & 0xfff0) == 0x3610) {
148315807765SVladik Aranov 		sd->sensor = SENSOR_OV361x;
148415807765SVladik Aranov 		gspca_dev->cam.cam_mode = ov361x_mode;
148515807765SVladik Aranov 		gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode);
148615807765SVladik Aranov 		reg_w(gspca_dev, 0xe7, 0x3a);
148715807765SVladik Aranov 		reg_w(gspca_dev, 0xf1, 0x60);
148815807765SVladik Aranov 		sccb_write(gspca_dev, 0x12, 0x80);
14898d64d4f6SJean-François Moine 	} else {
1490a581c72aSGreg Kroah-Hartman 		pr_err("Unknown sensor %04x", sensor_id);
14918d64d4f6SJean-François Moine 		return -EINVAL;
14928d64d4f6SJean-François Moine 	}
1493c52af799SJean-Francois Moine 
14944b27d074SJean-Francois Moine 	return gspca_dev->usb_err;
1495c52af799SJean-Francois Moine }
1496c52af799SJean-Francois Moine 
149715807765SVladik Aranov static int sd_start_ov361x(struct gspca_dev *gspca_dev)
149815807765SVladik Aranov {
149915807765SVladik Aranov 	sccb_write(gspca_dev, 0x12, 0x80);
150015807765SVladik Aranov 	msleep(20);
150115807765SVladik Aranov 	switch (gspca_dev->curr_mode % (ov361x_last)) {
150215807765SVladik Aranov 	case ov361x_2048:
150315807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_2048,
150415807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_2048));
150515807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_2048,
150615807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_2048));
150715807765SVladik Aranov 		break;
150815807765SVladik Aranov 	case ov361x_1600:
150915807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_1600,
151015807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_1600));
151115807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_1600,
151215807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_1600));
151315807765SVladik Aranov 		break;
151415807765SVladik Aranov 	case ov361x_1024:
151515807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_1024,
151615807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_1024));
151715807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_1024,
151815807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_1024));
151915807765SVladik Aranov 		break;
152015807765SVladik Aranov 	case ov361x_640:
152115807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_640,
152215807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_640));
152315807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_640,
152415807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_640));
152515807765SVladik Aranov 		break;
152615807765SVladik Aranov 	case ov361x_320:
152715807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_320,
152815807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_320));
152915807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_320,
153015807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_320));
153115807765SVladik Aranov 		break;
153215807765SVladik Aranov 	case ov361x_160:
153315807765SVladik Aranov 		reg_w_array(gspca_dev, ov361x_bridge_start_160,
153415807765SVladik Aranov 			    ARRAY_SIZE(ov361x_bridge_start_160));
153515807765SVladik Aranov 		sccb_w_array(gspca_dev, ov361x_start_160,
153615807765SVladik Aranov 			     ARRAY_SIZE(ov361x_start_160));
153715807765SVladik Aranov 		break;
153815807765SVladik Aranov 	}
153915807765SVladik Aranov 	reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */
154015807765SVladik Aranov 
154115807765SVladik Aranov 	return gspca_dev->usb_err;
154215807765SVladik Aranov }
154315807765SVladik Aranov 
1544c52af799SJean-Francois Moine static int sd_start(struct gspca_dev *gspca_dev)
1545c52af799SJean-Francois Moine {
15468d64d4f6SJean-François Moine 	struct sd *sd = (struct sd *) gspca_dev;
15478d64d4f6SJean-François Moine 
1548d9ef28a9SJose Alberto Reguero 	if (sd->sensor == SENSOR_OV971x)
15498d64d4f6SJean-François Moine 		return gspca_dev->usb_err;
155082b343b2SHans Verkuil 	if (sd->sensor == SENSOR_OV562x)
1551d9ef28a9SJose Alberto Reguero 		return gspca_dev->usb_err;
155215807765SVladik Aranov 	if (sd->sensor == SENSOR_OV361x)
155315807765SVladik Aranov 		return sd_start_ov361x(gspca_dev);
155482b343b2SHans Verkuil 
1555c52af799SJean-Francois Moine 	switch (gspca_dev->curr_mode) {
1556c52af799SJean-Francois Moine 	case QVGA_MODE:			/* 320x240 */
15578d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_1_vga,
15588d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_1_vga));
1559c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_start_qvga,
1560c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_start_qvga));
15618d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_2_qvga,
15628d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_2_qvga));
1563c52af799SJean-Francois Moine 		break;
1564c52af799SJean-Francois Moine 	case VGA_MODE:			/* 640x480 */
15658d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_1_vga,
15668d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_1_vga));
1567c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_start_vga,
1568c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_start_vga));
15698d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_2_vga,
15708d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_2_vga));
1571c52af799SJean-Francois Moine 		break;
1572c52af799SJean-Francois Moine 	case SVGA_MODE:			/* 800x600 */
15738d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_1_svga,
15748d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_1_svga));
1575c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_start_svga,
1576c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_start_svga));
15778d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_2_svga,
15788d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_2_svga));
1579c52af799SJean-Francois Moine 		break;
1580c52af799SJean-Francois Moine 	case XGA_MODE:			/* 1024x768 */
15818d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_1_xga,
15828d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_1_xga));
1583c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_start_xga,
1584c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_start_xga));
15858d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_2_svga,
15868d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_2_svga));
1587c52af799SJean-Francois Moine 		break;
1588c52af799SJean-Francois Moine 	default:
1589c52af799SJean-Francois Moine /*	case SXGA_MODE:			 * 1280x1024 */
15908d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_1_sxga,
15918d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_1_sxga));
1592c52af799SJean-Francois Moine 		reg_w_array(gspca_dev, bridge_start_sxga,
1593c52af799SJean-Francois Moine 				ARRAY_SIZE(bridge_start_sxga));
15948d64d4f6SJean-François Moine 		sccb_w_array(gspca_dev, ov965x_start_2_sxga,
15958d64d4f6SJean-François Moine 				ARRAY_SIZE(ov965x_start_2_sxga));
1596c52af799SJean-Francois Moine 		break;
1597c52af799SJean-Francois Moine 	}
1598c52af799SJean-Francois Moine 
1599c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe0, 0x00);
1600c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe0, 0x00);
1601c52af799SJean-Francois Moine 	set_led(gspca_dev, 1);
16024b27d074SJean-Francois Moine 	return gspca_dev->usb_err;
1603c52af799SJean-Francois Moine }
1604c52af799SJean-Francois Moine 
1605c52af799SJean-Francois Moine static void sd_stopN(struct gspca_dev *gspca_dev)
1606c52af799SJean-Francois Moine {
160715807765SVladik Aranov 	if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) {
160815807765SVladik Aranov 		reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */
160915807765SVladik Aranov 		/* reg_w(gspca_dev, 0x31, 0x09); */
161015807765SVladik Aranov 		return;
161115807765SVladik Aranov 	}
1612c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe0, 0x01);
1613c52af799SJean-Francois Moine 	set_led(gspca_dev, 0);
1614c52af799SJean-Francois Moine 	reg_w(gspca_dev, 0xe0, 0x00);
1615c52af799SJean-Francois Moine }
1616c52af799SJean-Francois Moine 
1617c52af799SJean-Francois Moine /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1618c52af799SJean-Francois Moine #define UVC_STREAM_EOH	(1 << 7)
1619c52af799SJean-Francois Moine #define UVC_STREAM_ERR	(1 << 6)
1620c52af799SJean-Francois Moine #define UVC_STREAM_STI	(1 << 5)
1621c52af799SJean-Francois Moine #define UVC_STREAM_RES	(1 << 4)
1622c52af799SJean-Francois Moine #define UVC_STREAM_SCR	(1 << 3)
1623c52af799SJean-Francois Moine #define UVC_STREAM_PTS	(1 << 2)
1624c52af799SJean-Francois Moine #define UVC_STREAM_EOF	(1 << 1)
1625c52af799SJean-Francois Moine #define UVC_STREAM_FID	(1 << 0)
1626c52af799SJean-Francois Moine 
1627c52af799SJean-Francois Moine static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1628c52af799SJean-Francois Moine 			u8 *data, int len)
1629c52af799SJean-Francois Moine {
1630c52af799SJean-Francois Moine 	struct sd *sd = (struct sd *) gspca_dev;
1631c52af799SJean-Francois Moine 	__u32 this_pts;
1632c52af799SJean-Francois Moine 	u8 this_fid;
1633c52af799SJean-Francois Moine 	int remaining_len = len;
16348d64d4f6SJean-François Moine 	int payload_len;
1635c52af799SJean-Francois Moine 
16368d64d4f6SJean-François Moine 	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1637c52af799SJean-Francois Moine 	do {
16388d64d4f6SJean-François Moine 		len = min(remaining_len, payload_len);
1639c52af799SJean-Francois Moine 
1640c52af799SJean-Francois Moine 		/* Payloads are prefixed with a UVC-style header.  We
1641c52af799SJean-Francois Moine 		   consider a frame to start when the FID toggles, or the PTS
1642c52af799SJean-Francois Moine 		   changes.  A frame ends when EOF is set, and we've received
1643c52af799SJean-Francois Moine 		   the correct number of bytes. */
1644c52af799SJean-Francois Moine 
1645c52af799SJean-Francois Moine 		/* Verify UVC header.  Header length is always 12 */
1646c52af799SJean-Francois Moine 		if (data[0] != 12 || len < 12) {
164737d5efb0SJoe Perches 			gspca_dbg(gspca_dev, D_PACK, "bad header\n");
1648c52af799SJean-Francois Moine 			goto discard;
1649c52af799SJean-Francois Moine 		}
1650c52af799SJean-Francois Moine 
1651c52af799SJean-Francois Moine 		/* Check errors */
1652c52af799SJean-Francois Moine 		if (data[1] & UVC_STREAM_ERR) {
165337d5efb0SJoe Perches 			gspca_dbg(gspca_dev, D_PACK, "payload error\n");
1654c52af799SJean-Francois Moine 			goto discard;
1655c52af799SJean-Francois Moine 		}
1656c52af799SJean-Francois Moine 
1657c52af799SJean-Francois Moine 		/* Extract PTS and FID */
1658c52af799SJean-Francois Moine 		if (!(data[1] & UVC_STREAM_PTS)) {
165937d5efb0SJoe Perches 			gspca_dbg(gspca_dev, D_PACK, "PTS not present\n");
1660c52af799SJean-Francois Moine 			goto discard;
1661c52af799SJean-Francois Moine 		}
1662c52af799SJean-Francois Moine 		this_pts = (data[5] << 24) | (data[4] << 16)
1663c52af799SJean-Francois Moine 						| (data[3] << 8) | data[2];
1664c52af799SJean-Francois Moine 		this_fid = data[1] & UVC_STREAM_FID;
1665c52af799SJean-Francois Moine 
1666c52af799SJean-Francois Moine 		/* If PTS or FID has changed, start a new frame. */
1667c52af799SJean-Francois Moine 		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1668c52af799SJean-Francois Moine 			if (gspca_dev->last_packet_type == INTER_PACKET)
1669c52af799SJean-Francois Moine 				gspca_frame_add(gspca_dev, LAST_PACKET,
1670c52af799SJean-Francois Moine 						NULL, 0);
1671c52af799SJean-Francois Moine 			sd->last_pts = this_pts;
1672c52af799SJean-Francois Moine 			sd->last_fid = this_fid;
1673c52af799SJean-Francois Moine 			gspca_frame_add(gspca_dev, FIRST_PACKET,
1674c52af799SJean-Francois Moine 					data + 12, len - 12);
1675c52af799SJean-Francois Moine 		/* If this packet is marked as EOF, end the frame */
1676c52af799SJean-Francois Moine 		} else if (data[1] & UVC_STREAM_EOF) {
1677c52af799SJean-Francois Moine 			sd->last_pts = 0;
1678c52af799SJean-Francois Moine 			gspca_frame_add(gspca_dev, LAST_PACKET,
1679c52af799SJean-Francois Moine 					data + 12, len - 12);
1680c52af799SJean-Francois Moine 		} else {
1681c52af799SJean-Francois Moine 
1682c52af799SJean-Francois Moine 			/* Add the data from this payload */
1683c52af799SJean-Francois Moine 			gspca_frame_add(gspca_dev, INTER_PACKET,
1684c52af799SJean-Francois Moine 					data + 12, len - 12);
1685c52af799SJean-Francois Moine 		}
1686c52af799SJean-Francois Moine 
1687c52af799SJean-Francois Moine 		/* Done this payload */
1688c52af799SJean-Francois Moine 		goto scan_next;
1689c52af799SJean-Francois Moine 
1690c52af799SJean-Francois Moine discard:
1691c52af799SJean-Francois Moine 		/* Discard data until a new frame starts. */
1692c52af799SJean-Francois Moine 		gspca_dev->last_packet_type = DISCARD_PACKET;
1693c52af799SJean-Francois Moine 
1694c52af799SJean-Francois Moine scan_next:
1695c52af799SJean-Francois Moine 		remaining_len -= len;
1696c52af799SJean-Francois Moine 		data += len;
1697c52af799SJean-Francois Moine 	} while (remaining_len > 0);
1698c52af799SJean-Francois Moine }
1699c52af799SJean-Francois Moine 
1700f3920f0fSHans Verkuil static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
1701c52af799SJean-Francois Moine {
1702f3920f0fSHans Verkuil 	struct gspca_dev *gspca_dev =
1703f3920f0fSHans Verkuil 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
1704f3920f0fSHans Verkuil 
1705f3920f0fSHans Verkuil 	gspca_dev->usb_err = 0;
1706f3920f0fSHans Verkuil 
1707f3920f0fSHans Verkuil 	if (!gspca_dev->streaming)
1708f3920f0fSHans Verkuil 		return 0;
1709f3920f0fSHans Verkuil 
1710f3920f0fSHans Verkuil 	switch (ctrl->id) {
1711f3920f0fSHans Verkuil 	case V4L2_CID_BRIGHTNESS:
1712f3920f0fSHans Verkuil 		setbrightness(gspca_dev, ctrl->val);
1713f3920f0fSHans Verkuil 		break;
1714f3920f0fSHans Verkuil 	case V4L2_CID_CONTRAST:
1715f3920f0fSHans Verkuil 		setcontrast(gspca_dev, ctrl->val);
1716f3920f0fSHans Verkuil 		break;
1717f3920f0fSHans Verkuil 	case V4L2_CID_SATURATION:
1718f3920f0fSHans Verkuil 		setsatur(gspca_dev, ctrl->val);
1719f3920f0fSHans Verkuil 		break;
1720c52af799SJean-Francois Moine 	case V4L2_CID_POWER_LINE_FREQUENCY:
1721f3920f0fSHans Verkuil 		setlightfreq(gspca_dev, ctrl->val);
1722f3920f0fSHans Verkuil 		break;
1723f3920f0fSHans Verkuil 	case V4L2_CID_SHARPNESS:
1724f3920f0fSHans Verkuil 		setsharpness(gspca_dev, ctrl->val);
1725f3920f0fSHans Verkuil 		break;
1726f3920f0fSHans Verkuil 	case V4L2_CID_AUTOGAIN:
1727f3920f0fSHans Verkuil 		if (ctrl->is_new)
1728f3920f0fSHans Verkuil 			setautogain(gspca_dev, ctrl->val);
1729f3920f0fSHans Verkuil 		if (!ctrl->val && gspca_dev->exposure->is_new)
1730f3920f0fSHans Verkuil 			setexposure(gspca_dev, gspca_dev->exposure->val);
1731c52af799SJean-Francois Moine 		break;
1732c52af799SJean-Francois Moine 	}
1733f3920f0fSHans Verkuil 	return gspca_dev->usb_err;
1734f3920f0fSHans Verkuil }
1735f3920f0fSHans Verkuil 
1736f3920f0fSHans Verkuil static const struct v4l2_ctrl_ops sd_ctrl_ops = {
1737f3920f0fSHans Verkuil 	.s_ctrl = sd_s_ctrl,
1738f3920f0fSHans Verkuil };
1739f3920f0fSHans Verkuil 
1740f3920f0fSHans Verkuil static int sd_init_controls(struct gspca_dev *gspca_dev)
1741f3920f0fSHans Verkuil {
1742f3920f0fSHans Verkuil 	struct sd *sd = (struct sd *)gspca_dev;
1743f3920f0fSHans Verkuil 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
1744f3920f0fSHans Verkuil 
1745f3920f0fSHans Verkuil 	if (sd->sensor == SENSOR_OV971x)
1746f3920f0fSHans Verkuil 		return 0;
174715807765SVladik Aranov 	if (sd->sensor == SENSOR_OV361x)
174815807765SVladik Aranov 		return 0;
1749f3920f0fSHans Verkuil 	gspca_dev->vdev.ctrl_handler = hdl;
1750f3920f0fSHans Verkuil 	v4l2_ctrl_handler_init(hdl, 7);
1751f3920f0fSHans Verkuil 	if (sd->sensor == SENSOR_OV562x) {
1752f3920f0fSHans Verkuil 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1753f3920f0fSHans Verkuil 			V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
1754f3920f0fSHans Verkuil 	} else {
1755f3920f0fSHans Verkuil 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1756f3920f0fSHans Verkuil 			V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
1757f3920f0fSHans Verkuil 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1758f3920f0fSHans Verkuil 			V4L2_CID_CONTRAST, 0, 15, 1, 3);
1759f3920f0fSHans Verkuil 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1760f3920f0fSHans Verkuil 			V4L2_CID_SATURATION, 0, 4, 1, 2);
1761f3920f0fSHans Verkuil 		/* -1 = auto */
1762f3920f0fSHans Verkuil 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1763f3920f0fSHans Verkuil 			V4L2_CID_SHARPNESS, -1, 4, 1, -1);
1764f3920f0fSHans Verkuil 		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1765f3920f0fSHans Verkuil 			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
1766f3920f0fSHans Verkuil 		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
1767f3920f0fSHans Verkuil 			V4L2_CID_EXPOSURE, 0, 3, 1, 0);
1768f3920f0fSHans Verkuil 		v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
1769f3920f0fSHans Verkuil 			V4L2_CID_POWER_LINE_FREQUENCY,
1770f3920f0fSHans Verkuil 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
1771f3920f0fSHans Verkuil 		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
1772f3920f0fSHans Verkuil 	}
1773f3920f0fSHans Verkuil 
1774f3920f0fSHans Verkuil 	if (hdl->error) {
1775f3920f0fSHans Verkuil 		pr_err("Could not initialize controls\n");
1776f3920f0fSHans Verkuil 		return hdl->error;
1777f3920f0fSHans Verkuil 	}
1778f3920f0fSHans Verkuil 	return 0;
1779c52af799SJean-Francois Moine }
1780c52af799SJean-Francois Moine 
1781c52af799SJean-Francois Moine /* sub-driver description */
1782c52af799SJean-Francois Moine static const struct sd_desc sd_desc = {
1783c52af799SJean-Francois Moine 	.name     = MODULE_NAME,
1784c52af799SJean-Francois Moine 	.config   = sd_config,
1785c52af799SJean-Francois Moine 	.init     = sd_init,
1786f3920f0fSHans Verkuil 	.init_controls = sd_init_controls,
1787c52af799SJean-Francois Moine 	.start    = sd_start,
1788c52af799SJean-Francois Moine 	.stopN    = sd_stopN,
1789c52af799SJean-Francois Moine 	.pkt_scan = sd_pkt_scan,
1790c52af799SJean-Francois Moine };
1791c52af799SJean-Francois Moine 
1792c52af799SJean-Francois Moine /* -- module initialisation -- */
179395c967c1SJean-François Moine static const struct usb_device_id device_table[] = {
17948d64d4f6SJean-François Moine 	{USB_DEVICE(0x05a9, 0x8065)},
1795c52af799SJean-Francois Moine 	{USB_DEVICE(0x06f8, 0x3003)},
1796965b37a4SJose Alberto Reguero 	{USB_DEVICE(0x05a9, 0x1550)},
1797c52af799SJean-Francois Moine 	{}
1798c52af799SJean-Francois Moine };
1799c52af799SJean-Francois Moine 
1800c52af799SJean-Francois Moine MODULE_DEVICE_TABLE(usb, device_table);
1801c52af799SJean-Francois Moine 
1802c52af799SJean-Francois Moine /* -- device connect -- */
1803c52af799SJean-Francois Moine static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1804c52af799SJean-Francois Moine {
1805c52af799SJean-Francois Moine 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1806c52af799SJean-Francois Moine 				THIS_MODULE);
1807c52af799SJean-Francois Moine }
1808c52af799SJean-Francois Moine 
1809c52af799SJean-Francois Moine static struct usb_driver sd_driver = {
1810c52af799SJean-Francois Moine 	.name       = MODULE_NAME,
1811c52af799SJean-Francois Moine 	.id_table   = device_table,
1812c52af799SJean-Francois Moine 	.probe      = sd_probe,
1813c52af799SJean-Francois Moine 	.disconnect = gspca_disconnect,
1814c52af799SJean-Francois Moine #ifdef CONFIG_PM
1815c52af799SJean-Francois Moine 	.suspend    = gspca_suspend,
1816c52af799SJean-Francois Moine 	.resume     = gspca_resume,
18178bb58964SHans de Goede 	.reset_resume = gspca_resume,
1818c52af799SJean-Francois Moine #endif
1819c52af799SJean-Francois Moine };
1820c52af799SJean-Francois Moine 
1821ecb3b2b3SGreg Kroah-Hartman module_usb_driver(sd_driver);
1822