162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
662306a36Sopenharmony_ci * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define MODULE_NAME "sonixj"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/input.h>
1462306a36Sopenharmony_ci#include "gspca.h"
1562306a36Sopenharmony_ci#include "jpeg.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ciMODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
1862306a36Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
1962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* specific webcam descriptor */
2262306a36Sopenharmony_cistruct sd {
2362306a36Sopenharmony_ci	struct gspca_dev gspca_dev;	/* !! must be the first item */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	atomic_t avg_lum;
2662306a36Sopenharmony_ci	struct v4l2_ctrl *brightness;
2762306a36Sopenharmony_ci	struct v4l2_ctrl *contrast;
2862306a36Sopenharmony_ci	struct v4l2_ctrl *saturation;
2962306a36Sopenharmony_ci	struct { /* red/blue balance control cluster */
3062306a36Sopenharmony_ci		struct v4l2_ctrl *red_bal;
3162306a36Sopenharmony_ci		struct v4l2_ctrl *blue_bal;
3262306a36Sopenharmony_ci	};
3362306a36Sopenharmony_ci	struct { /* hflip/vflip control cluster */
3462306a36Sopenharmony_ci		struct v4l2_ctrl *vflip;
3562306a36Sopenharmony_ci		struct v4l2_ctrl *hflip;
3662306a36Sopenharmony_ci	};
3762306a36Sopenharmony_ci	struct v4l2_ctrl *gamma;
3862306a36Sopenharmony_ci	struct v4l2_ctrl *illum;
3962306a36Sopenharmony_ci	struct v4l2_ctrl *sharpness;
4062306a36Sopenharmony_ci	struct v4l2_ctrl *freq;
4162306a36Sopenharmony_ci	u32 exposure;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	struct work_struct work;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	u32 pktsz;			/* (used by pkt_scan) */
4662306a36Sopenharmony_ci	u16 npkt;
4762306a36Sopenharmony_ci	s8 nchg;
4862306a36Sopenharmony_ci	s8 short_mark;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	u8 quality;			/* image quality */
5162306a36Sopenharmony_ci#define QUALITY_MIN 25
5262306a36Sopenharmony_ci#define QUALITY_MAX 90
5362306a36Sopenharmony_ci#define QUALITY_DEF 70
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	u8 reg01;
5662306a36Sopenharmony_ci	u8 reg17;
5762306a36Sopenharmony_ci	u8 reg18;
5862306a36Sopenharmony_ci	u8 flags;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	s8 ag_cnt;
6162306a36Sopenharmony_ci#define AG_CNT_START 13
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	u8 bridge;
6462306a36Sopenharmony_ci#define BRIDGE_SN9C102P 0
6562306a36Sopenharmony_ci#define BRIDGE_SN9C105 1
6662306a36Sopenharmony_ci#define BRIDGE_SN9C110 2
6762306a36Sopenharmony_ci#define BRIDGE_SN9C120 3
6862306a36Sopenharmony_ci	u8 sensor;			/* Type of image sensor chip */
6962306a36Sopenharmony_ci	u8 i2c_addr;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	u8 jpeg_hdr[JPEG_HDR_SZ];
7262306a36Sopenharmony_ci};
7362306a36Sopenharmony_cienum sensors {
7462306a36Sopenharmony_ci	SENSOR_ADCM1700,
7562306a36Sopenharmony_ci	SENSOR_GC0307,
7662306a36Sopenharmony_ci	SENSOR_HV7131R,
7762306a36Sopenharmony_ci	SENSOR_MI0360,
7862306a36Sopenharmony_ci	SENSOR_MI0360B,
7962306a36Sopenharmony_ci	SENSOR_MO4000,
8062306a36Sopenharmony_ci	SENSOR_MT9V111,
8162306a36Sopenharmony_ci	SENSOR_OM6802,
8262306a36Sopenharmony_ci	SENSOR_OV7630,
8362306a36Sopenharmony_ci	SENSOR_OV7648,
8462306a36Sopenharmony_ci	SENSOR_OV7660,
8562306a36Sopenharmony_ci	SENSOR_PO1030,
8662306a36Sopenharmony_ci	SENSOR_PO2030N,
8762306a36Sopenharmony_ci	SENSOR_SOI768,
8862306a36Sopenharmony_ci	SENSOR_SP80708,
8962306a36Sopenharmony_ci};
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic void qual_upd(struct work_struct *work);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/* device flags */
9462306a36Sopenharmony_ci#define F_PDN_INV	0x01	/* inverse pin S_PWR_DN / sn_xxx tables */
9562306a36Sopenharmony_ci#define F_ILLUM		0x02	/* presence of illuminator */
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/* sn9c1xx definitions */
9862306a36Sopenharmony_ci/* register 0x01 */
9962306a36Sopenharmony_ci#define S_PWR_DN	0x01	/* sensor power down */
10062306a36Sopenharmony_ci#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */
10162306a36Sopenharmony_ci#define V_TX_EN		0x04	/* video transfer enable */
10262306a36Sopenharmony_ci#define LED		0x08	/* output to pin LED */
10362306a36Sopenharmony_ci#define SCL_SEL_OD	0x20	/* open-drain mode */
10462306a36Sopenharmony_ci#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */
10562306a36Sopenharmony_ci/* register 0x17 */
10662306a36Sopenharmony_ci#define MCK_SIZE_MASK	0x1f	/* sensor master clock */
10762306a36Sopenharmony_ci#define SEN_CLK_EN	0x20	/* enable sensor clock */
10862306a36Sopenharmony_ci#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic const struct v4l2_pix_format cif_mode[] = {
11162306a36Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
11262306a36Sopenharmony_ci		.bytesperline = 352,
11362306a36Sopenharmony_ci		.sizeimage = 352 * 288 * 4 / 8 + 590,
11462306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
11562306a36Sopenharmony_ci		.priv = 0},
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
11862306a36Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
11962306a36Sopenharmony_ci		.bytesperline = 160,
12062306a36Sopenharmony_ci		.sizeimage = 160 * 120 * 4 / 8 + 590,
12162306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
12262306a36Sopenharmony_ci		.priv = 2},
12362306a36Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
12462306a36Sopenharmony_ci		.bytesperline = 320,
12562306a36Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
12662306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
12762306a36Sopenharmony_ci		.priv = 1},
12862306a36Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
12962306a36Sopenharmony_ci		.bytesperline = 640,
13062306a36Sopenharmony_ci		/* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
13162306a36Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 4 + 590,
13262306a36Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
13362306a36Sopenharmony_ci		.priv = 0},
13462306a36Sopenharmony_ci};
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic const u8 sn_adcm1700[0x1c] = {
13762306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
13862306a36Sopenharmony_ci	0x00,	0x43,	0x60,	0x00,	0x1a,	0x00,	0x00,	0x00,
13962306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
14062306a36Sopenharmony_ci	0x80,	0x51,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
14162306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
14262306a36Sopenharmony_ci	0x03,	0x00,	0x05,	0x01,	0x05,	0x16,	0x12,	0x42,
14362306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
14462306a36Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
14562306a36Sopenharmony_ci};
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic const u8 sn_gc0307[0x1c] = {
14862306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
14962306a36Sopenharmony_ci	0x00,	0x61,	0x62,	0x00,	0x1a,	0x00,	0x00,	0x00,
15062306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
15162306a36Sopenharmony_ci	0x80,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
15262306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
15362306a36Sopenharmony_ci	0x03,	0x00,	0x03,	0x01,	0x08,	0x28,	0x1e,	0x02,
15462306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
15562306a36Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
15662306a36Sopenharmony_ci};
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic const u8 sn_hv7131[0x1c] = {
15962306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
16062306a36Sopenharmony_ci	0x00,	0x03,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
16162306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
16262306a36Sopenharmony_ci	0x81,	0x11,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
16362306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
16462306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x03,	0x28,	0x1e,	0x41,
16562306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
16662306a36Sopenharmony_ci	0x0a,	0x00,	0x00,	0x00
16762306a36Sopenharmony_ci};
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cistatic const u8 sn_mi0360[0x1c] = {
17062306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
17162306a36Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
17262306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
17362306a36Sopenharmony_ci	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
17462306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
17562306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x61,
17662306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
17762306a36Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic const u8 sn_mi0360b[0x1c] = {
18162306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
18262306a36Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
18362306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
18462306a36Sopenharmony_ci	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
18562306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
18662306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x40,
18762306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
18862306a36Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic const u8 sn_mo4000[0x1c] = {
19262306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
19362306a36Sopenharmony_ci	0x00,	0x23,	0x60,	0x00,	0x1a,	0x00,	0x20,	0x18,
19462306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
19562306a36Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
19662306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
19762306a36Sopenharmony_ci	0x03,	 0x00,	0x0b,	0x0f,	0x14,	0x28,	0x1e,	0x40,
19862306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
19962306a36Sopenharmony_ci	0x08,	0x00,	0x00,	0x00
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cistatic const u8 sn_mt9v111[0x1c] = {
20362306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
20462306a36Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
20562306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
20662306a36Sopenharmony_ci	0x81,	0x5c,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
20762306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
20862306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x1c,	0x28,	0x1e,	0x40,
20962306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
21062306a36Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
21162306a36Sopenharmony_ci};
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic const u8 sn_om6802[0x1c] = {
21462306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
21562306a36Sopenharmony_ci	0x00,	0x23,	0x72,	0x00,	0x1a,	0x20,	0x20,	0x19,
21662306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
21762306a36Sopenharmony_ci	0x80,	0x34,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
21862306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
21962306a36Sopenharmony_ci	0x03,	0x00,	0x51,	0x01,	0x00,	0x28,	0x1e,	0x40,
22062306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
22162306a36Sopenharmony_ci	0x05,	0x00,	0x00,	0x00
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic const u8 sn_ov7630[0x1c] = {
22562306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
22662306a36Sopenharmony_ci	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
22762306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
22862306a36Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
22962306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
23062306a36Sopenharmony_ci	0x03,	0x00,	0x04,	0x01,	0x0a,	0x28,	0x1e,	0xc2,
23162306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
23262306a36Sopenharmony_ci	0x0b,	0x00,	0x00,	0x00
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic const u8 sn_ov7648[0x1c] = {
23662306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
23762306a36Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
23862306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
23962306a36Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
24062306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
24162306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x00,	0x28,	0x1e,	0x00,
24262306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
24362306a36Sopenharmony_ci	0x0b,	0x00,	0x00,	0x00
24462306a36Sopenharmony_ci};
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic const u8 sn_ov7660[0x1c] = {
24762306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
24862306a36Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
24962306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
25062306a36Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
25162306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
25262306a36Sopenharmony_ci	0x03,	0x00,	0x01,	0x01,	0x08,	0x28,	0x1e,	0x20,
25362306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
25462306a36Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic const u8 sn_po1030[0x1c] = {
25862306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
25962306a36Sopenharmony_ci	0x00,	0x21,	0x62,	0x00,	0x1a,	0x20,	0x20,	0x20,
26062306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
26162306a36Sopenharmony_ci	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
26262306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
26362306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x06,	0x06,	0x28,	0x1e,	0x00,
26462306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
26562306a36Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
26662306a36Sopenharmony_ci};
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic const u8 sn_po2030n[0x1c] = {
26962306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
27062306a36Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
27162306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
27262306a36Sopenharmony_ci	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
27362306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
27462306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x14,	0x28,	0x1e,	0x00,
27562306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
27662306a36Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
27762306a36Sopenharmony_ci};
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic const u8 sn_soi768[0x1c] = {
28062306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
28162306a36Sopenharmony_ci	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
28262306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
28362306a36Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
28462306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
28562306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x08,	0x28,	0x1e,	0x00,
28662306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
28762306a36Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
28862306a36Sopenharmony_ci};
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic const u8 sn_sp80708[0x1c] = {
29162306a36Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
29262306a36Sopenharmony_ci	0x00,	0x63,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
29362306a36Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
29462306a36Sopenharmony_ci	0x81,	0x18,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
29562306a36Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
29662306a36Sopenharmony_ci	0x03,	0x00,	0x00,	0x03,	0x04,	0x28,	0x1e,	0x00,
29762306a36Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
29862306a36Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
29962306a36Sopenharmony_ci};
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci/* sequence specific to the sensors - !! index = SENSOR_xxx */
30262306a36Sopenharmony_cistatic const u8 *sn_tb[] = {
30362306a36Sopenharmony_ci[SENSOR_ADCM1700] =	sn_adcm1700,
30462306a36Sopenharmony_ci[SENSOR_GC0307] =	sn_gc0307,
30562306a36Sopenharmony_ci[SENSOR_HV7131R] =	sn_hv7131,
30662306a36Sopenharmony_ci[SENSOR_MI0360] =	sn_mi0360,
30762306a36Sopenharmony_ci[SENSOR_MI0360B] =	sn_mi0360b,
30862306a36Sopenharmony_ci[SENSOR_MO4000] =	sn_mo4000,
30962306a36Sopenharmony_ci[SENSOR_MT9V111] =	sn_mt9v111,
31062306a36Sopenharmony_ci[SENSOR_OM6802] =	sn_om6802,
31162306a36Sopenharmony_ci[SENSOR_OV7630] =	sn_ov7630,
31262306a36Sopenharmony_ci[SENSOR_OV7648] =	sn_ov7648,
31362306a36Sopenharmony_ci[SENSOR_OV7660] =	sn_ov7660,
31462306a36Sopenharmony_ci[SENSOR_PO1030] =	sn_po1030,
31562306a36Sopenharmony_ci[SENSOR_PO2030N] =	sn_po2030n,
31662306a36Sopenharmony_ci[SENSOR_SOI768] =	sn_soi768,
31762306a36Sopenharmony_ci[SENSOR_SP80708] =	sn_sp80708,
31862306a36Sopenharmony_ci};
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci/* default gamma table */
32162306a36Sopenharmony_cistatic const u8 gamma_def[17] = {
32262306a36Sopenharmony_ci	0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
32362306a36Sopenharmony_ci	0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci/* gamma for sensor ADCM1700 */
32662306a36Sopenharmony_cistatic const u8 gamma_spec_0[17] = {
32762306a36Sopenharmony_ci	0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
32862306a36Sopenharmony_ci	0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
32962306a36Sopenharmony_ci};
33062306a36Sopenharmony_ci/* gamma for sensors HV7131R and MT9V111 */
33162306a36Sopenharmony_cistatic const u8 gamma_spec_1[17] = {
33262306a36Sopenharmony_ci	0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
33362306a36Sopenharmony_ci	0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci/* gamma for sensor GC0307 */
33662306a36Sopenharmony_cistatic const u8 gamma_spec_2[17] = {
33762306a36Sopenharmony_ci	0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
33862306a36Sopenharmony_ci	0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
33962306a36Sopenharmony_ci};
34062306a36Sopenharmony_ci/* gamma for sensor SP80708 */
34162306a36Sopenharmony_cistatic const u8 gamma_spec_3[17] = {
34262306a36Sopenharmony_ci	0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
34362306a36Sopenharmony_ci	0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
34462306a36Sopenharmony_ci};
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci/* color matrix and offsets */
34762306a36Sopenharmony_cistatic const u8 reg84[] = {
34862306a36Sopenharmony_ci	0x14, 0x00, 0x27, 0x00, 0x07, 0x00,	/* YR YG YB gains */
34962306a36Sopenharmony_ci	0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,	/* UR UG UB */
35062306a36Sopenharmony_ci	0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,	/* VR VG VB */
35162306a36Sopenharmony_ci	0x00, 0x00, 0x00			/* YUV offsets */
35262306a36Sopenharmony_ci};
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci#define DELAY	0xdd
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cistatic const u8 adcm1700_sensor_init[][8] = {
35762306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
35862306a36Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},	/* reset */
35962306a36Sopenharmony_ci	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
36062306a36Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
36162306a36Sopenharmony_ci	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
36262306a36Sopenharmony_ci	{0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
36362306a36Sopenharmony_ci	{0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
36462306a36Sopenharmony_ci	{0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
36562306a36Sopenharmony_ci	{0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
36662306a36Sopenharmony_ci	{0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
36762306a36Sopenharmony_ci	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
36862306a36Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
36962306a36Sopenharmony_ci	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
37062306a36Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
37162306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
37262306a36Sopenharmony_ci	{0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
37362306a36Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
37462306a36Sopenharmony_ci	{}
37562306a36Sopenharmony_ci};
37662306a36Sopenharmony_cistatic const u8 adcm1700_sensor_param1[][8] = {
37762306a36Sopenharmony_ci	{0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},	/* exposure? */
37862306a36Sopenharmony_ci	{0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
38162306a36Sopenharmony_ci	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
38262306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
38362306a36Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
38462306a36Sopenharmony_ci	{0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10},	/* exposure? */
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
38762306a36Sopenharmony_ci	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
38862306a36Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
38962306a36Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
39062306a36Sopenharmony_ci	{}
39162306a36Sopenharmony_ci};
39262306a36Sopenharmony_cistatic const u8 gc0307_sensor_init[][8] = {
39362306a36Sopenharmony_ci	{0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
39462306a36Sopenharmony_ci	{0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
39562306a36Sopenharmony_ci	{0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
39662306a36Sopenharmony_ci	{0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
39762306a36Sopenharmony_ci	{0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
39862306a36Sopenharmony_ci	{0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
39962306a36Sopenharmony_ci	{0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
40062306a36Sopenharmony_ci	{0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
40162306a36Sopenharmony_ci	{0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
40262306a36Sopenharmony_ci	{0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
40362306a36Sopenharmony_ci	{0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
40462306a36Sopenharmony_ci	{0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
40562306a36Sopenharmony_ci	{0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
40662306a36Sopenharmony_ci	{0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
40762306a36Sopenharmony_ci	{0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
40862306a36Sopenharmony_ci	{0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
40962306a36Sopenharmony_ci	{0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
41062306a36Sopenharmony_ci	{0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
41162306a36Sopenharmony_ci	{0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
41262306a36Sopenharmony_ci	{0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
41362306a36Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
41462306a36Sopenharmony_ci	{0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
41562306a36Sopenharmony_ci	{0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
41662306a36Sopenharmony_ci	{0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
41762306a36Sopenharmony_ci	{0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
41862306a36Sopenharmony_ci	{0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
41962306a36Sopenharmony_ci	{0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
42062306a36Sopenharmony_ci	{0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
42162306a36Sopenharmony_ci	{0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
42262306a36Sopenharmony_ci	{0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
42362306a36Sopenharmony_ci	{0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
42462306a36Sopenharmony_ci	{0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
42562306a36Sopenharmony_ci	{0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
42662306a36Sopenharmony_ci	{0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
42762306a36Sopenharmony_ci	{0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
42862306a36Sopenharmony_ci	{0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
42962306a36Sopenharmony_ci	{0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
43062306a36Sopenharmony_ci	{0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
43162306a36Sopenharmony_ci	{}
43262306a36Sopenharmony_ci};
43362306a36Sopenharmony_cistatic const u8 gc0307_sensor_param1[][8] = {
43462306a36Sopenharmony_ci	{0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
43562306a36Sopenharmony_ci	{0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
43662306a36Sopenharmony_ci	{0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
43762306a36Sopenharmony_ci	{0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
43862306a36Sopenharmony_ci/*param3*/
43962306a36Sopenharmony_ci	{0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
44062306a36Sopenharmony_ci	{0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
44162306a36Sopenharmony_ci	{}
44262306a36Sopenharmony_ci};
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic const u8 hv7131r_sensor_init[][8] = {
44562306a36Sopenharmony_ci	{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
44662306a36Sopenharmony_ci	{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
44762306a36Sopenharmony_ci	{0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
44862306a36Sopenharmony_ci/*	{0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
44962306a36Sopenharmony_ci	{0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
45062306a36Sopenharmony_ci	{0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
45162306a36Sopenharmony_ci/*	{0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
45462306a36Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
45562306a36Sopenharmony_ci	{0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
45662306a36Sopenharmony_ci	{0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
45762306a36Sopenharmony_ci	{0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
45862306a36Sopenharmony_ci	{0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
45962306a36Sopenharmony_ci	{0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
46062306a36Sopenharmony_ci	{0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
46362306a36Sopenharmony_ci	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
46462306a36Sopenharmony_ci	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
46562306a36Sopenharmony_ci	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
46662306a36Sopenharmony_ci	{0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
46962306a36Sopenharmony_ci	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
47062306a36Sopenharmony_ci	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
47162306a36Sopenharmony_ci	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
47262306a36Sopenharmony_ci	{0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
47362306a36Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
47462306a36Sopenharmony_ci							/* set sensor clock */
47562306a36Sopenharmony_ci	{}
47662306a36Sopenharmony_ci};
47762306a36Sopenharmony_cistatic const u8 mi0360_sensor_init[][8] = {
47862306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
47962306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
48062306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
48162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
48262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
48362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
48462306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
48562306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
48662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
48762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
48862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
48962306a36Sopenharmony_ci	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
49062306a36Sopenharmony_ci	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
49162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
49262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
49362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
49462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
49562306a36Sopenharmony_ci	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
49662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
49762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
49862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
49962306a36Sopenharmony_ci	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
50062306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
50162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
50262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
50362306a36Sopenharmony_ci	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
50462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
50562306a36Sopenharmony_ci	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
50662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
50762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
50862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
50962306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
51062306a36Sopenharmony_ci	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
51362306a36Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
51462306a36Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
51562306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
51662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
51962306a36Sopenharmony_ci	{0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
52062306a36Sopenharmony_ci	{0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
52162306a36Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
52462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
52562306a36Sopenharmony_ci/*	{0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
52662306a36Sopenharmony_ci/*	{0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
52762306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
52862306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
52962306a36Sopenharmony_ci	{}
53062306a36Sopenharmony_ci};
53162306a36Sopenharmony_cistatic const u8 mi0360b_sensor_init[][8] = {
53262306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
53362306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
53462306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
53562306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
53662306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
53762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
53862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
53962306a36Sopenharmony_ci	{0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
54062306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
54162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
54262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
54362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
54462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
54562306a36Sopenharmony_ci	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
54662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
54762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
54862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
54962306a36Sopenharmony_ci	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
55062306a36Sopenharmony_ci	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
55162306a36Sopenharmony_ci	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
55262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
55362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
55462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
55562306a36Sopenharmony_ci	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
55662306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
55762306a36Sopenharmony_ci	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
55862306a36Sopenharmony_ci	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
55962306a36Sopenharmony_ci	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
56062306a36Sopenharmony_ci	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
56162306a36Sopenharmony_ci	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
56262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
56362306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
56462306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
56562306a36Sopenharmony_ci	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
56662306a36Sopenharmony_ci	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
56962306a36Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
57062306a36Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
57162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
57262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
57362306a36Sopenharmony_ci	{}
57462306a36Sopenharmony_ci};
57562306a36Sopenharmony_cistatic const u8 mi0360b_sensor_param1[][8] = {
57662306a36Sopenharmony_ci	{0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
57762306a36Sopenharmony_ci	{0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
57862306a36Sopenharmony_ci	{0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
57962306a36Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
58262306a36Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
58362306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
58462306a36Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
58562306a36Sopenharmony_ci	{}
58662306a36Sopenharmony_ci};
58762306a36Sopenharmony_cistatic const u8 mo4000_sensor_init[][8] = {
58862306a36Sopenharmony_ci	{0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
58962306a36Sopenharmony_ci	{0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
59062306a36Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
59162306a36Sopenharmony_ci	{0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
59262306a36Sopenharmony_ci	{0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
59362306a36Sopenharmony_ci	{0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
59462306a36Sopenharmony_ci	{0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
59562306a36Sopenharmony_ci	{0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
59662306a36Sopenharmony_ci	{0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
59762306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
59862306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
59962306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
60062306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
60162306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
60262306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
60362306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
60462306a36Sopenharmony_ci	{0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
60562306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
60662306a36Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
60762306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
60862306a36Sopenharmony_ci	{}
60962306a36Sopenharmony_ci};
61062306a36Sopenharmony_cistatic const u8 mt9v111_sensor_init[][8] = {
61162306a36Sopenharmony_ci	{0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
61262306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
61362306a36Sopenharmony_ci	{0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
61462306a36Sopenharmony_ci	{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
61562306a36Sopenharmony_ci	{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
61662306a36Sopenharmony_ci	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
61762306a36Sopenharmony_ci	{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
61862306a36Sopenharmony_ci	{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
61962306a36Sopenharmony_ci	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
62062306a36Sopenharmony_ci	{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
62162306a36Sopenharmony_ci	{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
62262306a36Sopenharmony_ci	{0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
62362306a36Sopenharmony_ci	{0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
62462306a36Sopenharmony_ci	{0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
62562306a36Sopenharmony_ci	{0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
62662306a36Sopenharmony_ci	{0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
62762306a36Sopenharmony_ci	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
62862306a36Sopenharmony_ci	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
62962306a36Sopenharmony_ci	{}
63062306a36Sopenharmony_ci};
63162306a36Sopenharmony_cistatic const u8 mt9v111_sensor_param1[][8] = {
63262306a36Sopenharmony_ci	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
63362306a36Sopenharmony_ci	{0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
63462306a36Sopenharmony_ci	{0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
63562306a36Sopenharmony_ci	{0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
63662306a36Sopenharmony_ci	{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
63762306a36Sopenharmony_ci	{}
63862306a36Sopenharmony_ci};
63962306a36Sopenharmony_cistatic const u8 om6802_init0[2][8] = {
64062306a36Sopenharmony_ci/*fixme: variable*/
64162306a36Sopenharmony_ci	{0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
64262306a36Sopenharmony_ci	{0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
64362306a36Sopenharmony_ci};
64462306a36Sopenharmony_cistatic const u8 om6802_sensor_init[][8] = {
64562306a36Sopenharmony_ci	{0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
64662306a36Sopenharmony_ci						/* factory mode */
64762306a36Sopenharmony_ci	{0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
64862306a36Sopenharmony_ci						/* output raw RGB */
64962306a36Sopenharmony_ci	{0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
65062306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
65162306a36Sopenharmony_ci	{0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
65262306a36Sopenharmony_ci		/* auto-exposure speed (0) / white balance mode (auto RGB) */
65362306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
65462306a36Sopenharmony_ci							 * set color mode */
65562306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
65662306a36Sopenharmony_ci						 * max AGC value in AE */
65762306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
65862306a36Sopenharmony_ci							 * preset AGC */
65962306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
66062306a36Sopenharmony_ci						 * preset brightness */
66162306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
66262306a36Sopenharmony_ci							 * preset contrast */
66362306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
66462306a36Sopenharmony_ci							 * preset gamma */
66562306a36Sopenharmony_ci	{0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
66662306a36Sopenharmony_ci				/* luminance mode (0x4f -> AutoExpo on) */
66762306a36Sopenharmony_ci	{0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
66862306a36Sopenharmony_ci							/* preset shutter */
66962306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
67062306a36Sopenharmony_ci							 * auto frame rate */
67162306a36Sopenharmony_ci/*	{0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
67262306a36Sopenharmony_ci	{0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
67362306a36Sopenharmony_ci	{}
67462306a36Sopenharmony_ci};
67562306a36Sopenharmony_cistatic const u8 om6802_sensor_param1[][8] = {
67662306a36Sopenharmony_ci	{0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
67762306a36Sopenharmony_ci	{0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
67862306a36Sopenharmony_ci	{0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
67962306a36Sopenharmony_ci	{0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
68062306a36Sopenharmony_ci	{}
68162306a36Sopenharmony_ci};
68262306a36Sopenharmony_cistatic const u8 ov7630_sensor_init[][8] = {
68362306a36Sopenharmony_ci	{0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
68462306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
68562306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
68662306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
68762306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
68862306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
68962306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
69062306a36Sopenharmony_ci/* win: i2c_r from 00 to 80 */
69162306a36Sopenharmony_ci	{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
69262306a36Sopenharmony_ci	{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
69362306a36Sopenharmony_ci/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
69462306a36Sopenharmony_ci	0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
69562306a36Sopenharmony_ci	{0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
69662306a36Sopenharmony_ci	{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
69762306a36Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
69862306a36Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
69962306a36Sopenharmony_ci	{0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
70062306a36Sopenharmony_ci	{0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
70162306a36Sopenharmony_ci	{0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
70262306a36Sopenharmony_ci	{0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
70362306a36Sopenharmony_ci	{0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
70462306a36Sopenharmony_ci	{0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
70562306a36Sopenharmony_ci	{0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
70662306a36Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
70762306a36Sopenharmony_ci	{0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
70862306a36Sopenharmony_ci	{0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
70962306a36Sopenharmony_ci	{0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
71062306a36Sopenharmony_ci	{0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
71162306a36Sopenharmony_ci	{0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
71262306a36Sopenharmony_ci	{0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
71362306a36Sopenharmony_ci	{0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
71462306a36Sopenharmony_ci	{0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
71562306a36Sopenharmony_ci	{0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
71662306a36Sopenharmony_ci	{0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
71762306a36Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
71862306a36Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
71962306a36Sopenharmony_ci	{}
72062306a36Sopenharmony_ci};
72162306a36Sopenharmony_cistatic const u8 ov7630_sensor_param1[][8] = {
72262306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
72362306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
72462306a36Sopenharmony_ci/*fixme: + 0x12, 0x04*/
72562306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
72662306a36Sopenharmony_ci							 * set by setvflip */
72762306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
72862306a36Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
72962306a36Sopenharmony_ci	{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
73062306a36Sopenharmony_ci/* */
73162306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
73262306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
73362306a36Sopenharmony_ci/* */
73462306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
73562306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
73662306a36Sopenharmony_ci	{}
73762306a36Sopenharmony_ci};
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cistatic const u8 ov7648_sensor_init[][8] = {
74062306a36Sopenharmony_ci	{0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
74162306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},	/* reset */
74262306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
74362306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
74462306a36Sopenharmony_ci	{0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
74562306a36Sopenharmony_ci	{0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
74662306a36Sopenharmony_ci	{0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
74762306a36Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
74862306a36Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
74962306a36Sopenharmony_ci	{0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
75062306a36Sopenharmony_ci	{0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
75162306a36Sopenharmony_ci	{0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
75262306a36Sopenharmony_ci	{0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
75362306a36Sopenharmony_ci	{0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
75462306a36Sopenharmony_ci	{0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
75562306a36Sopenharmony_ci	{0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
75662306a36Sopenharmony_ci	{0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
75762306a36Sopenharmony_ci	{0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
75862306a36Sopenharmony_ci	{0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
75962306a36Sopenharmony_ci	{0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
76062306a36Sopenharmony_ci	{0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
76162306a36Sopenharmony_ci	{0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
76462306a36Sopenharmony_ci/*	{0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
76562306a36Sopenharmony_ci/*	{0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
76662306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
76762306a36Sopenharmony_ci	{}
76862306a36Sopenharmony_ci};
76962306a36Sopenharmony_cistatic const u8 ov7648_sensor_param1[][8] = {
77062306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
77162306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
77262306a36Sopenharmony_ci							 * set by setvflip */
77362306a36Sopenharmony_ci	{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
77462306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
77562306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
77662306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
77762306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
77862306a36Sopenharmony_ci/*...*/
77962306a36Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
78062306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
78162306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
78262306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
78362306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
78462306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	{}
78762306a36Sopenharmony_ci};
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistatic const u8 ov7660_sensor_init[][8] = {
79062306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
79162306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
79262306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
79362306a36Sopenharmony_ci						/* Outformat = rawRGB */
79462306a36Sopenharmony_ci	{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
79562306a36Sopenharmony_ci	{0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
79662306a36Sopenharmony_ci						/* GAIN BLUE RED VREF */
79762306a36Sopenharmony_ci	{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
79862306a36Sopenharmony_ci						/* COM 1 BAVE GEAVE AECHH */
79962306a36Sopenharmony_ci	{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
80062306a36Sopenharmony_ci	{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
80162306a36Sopenharmony_ci	{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
80262306a36Sopenharmony_ci						/* AECH CLKRC COM7 COM8 */
80362306a36Sopenharmony_ci	{0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
80462306a36Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
80562306a36Sopenharmony_ci						/* HSTART HSTOP VSTRT VSTOP */
80662306a36Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
80762306a36Sopenharmony_ci	{0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
80862306a36Sopenharmony_ci	{0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
80962306a36Sopenharmony_ci					/* BOS GBOS GROS ROS (BGGR offset) */
81062306a36Sopenharmony_ci/*	{0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
81162306a36Sopenharmony_ci	{0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
81262306a36Sopenharmony_ci						/* AEW AEB VPT BBIAS */
81362306a36Sopenharmony_ci	{0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
81462306a36Sopenharmony_ci						/* GbBIAS RSVD EXHCH EXHCL */
81562306a36Sopenharmony_ci	{0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
81662306a36Sopenharmony_ci						/* RBIAS ADVFL ASDVFH YAVE */
81762306a36Sopenharmony_ci	{0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
81862306a36Sopenharmony_ci						/* HSYST HSYEN HREF */
81962306a36Sopenharmony_ci	{0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
82062306a36Sopenharmony_ci	{0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
82162306a36Sopenharmony_ci						/* ADC ACOM OFON TSLB */
82262306a36Sopenharmony_ci	{0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
82362306a36Sopenharmony_ci						/* COM11 COM12 COM13 COM14 */
82462306a36Sopenharmony_ci	{0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
82562306a36Sopenharmony_ci						/* EDGE COM15 COM16 COM17 */
82662306a36Sopenharmony_ci	{0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
82762306a36Sopenharmony_ci	{0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
82862306a36Sopenharmony_ci	{0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
82962306a36Sopenharmony_ci	{0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
83062306a36Sopenharmony_ci	{0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
83162306a36Sopenharmony_ci	{0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
83262306a36Sopenharmony_ci	{0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
83362306a36Sopenharmony_ci	{0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
83462306a36Sopenharmony_ci	{0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
83562306a36Sopenharmony_ci	{0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
83662306a36Sopenharmony_ci						/* LCC1 LCC2 LCC3 LCC4 */
83762306a36Sopenharmony_ci	{0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
83862306a36Sopenharmony_ci	{0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
83962306a36Sopenharmony_ci	{0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
84062306a36Sopenharmony_ci					/* band gap reference [0:3] DBLV */
84162306a36Sopenharmony_ci	{0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
84262306a36Sopenharmony_ci	{0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
84362306a36Sopenharmony_ci	{0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
84462306a36Sopenharmony_ci	{0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
84562306a36Sopenharmony_ci	{0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
84662306a36Sopenharmony_ci	{0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
84762306a36Sopenharmony_ci	{0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
84862306a36Sopenharmony_ci	{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
84962306a36Sopenharmony_ci	{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
85062306a36Sopenharmony_ci	{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
85162306a36Sopenharmony_ci/* not in all ms-win traces*/
85262306a36Sopenharmony_ci	{0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
85362306a36Sopenharmony_ci	{}
85462306a36Sopenharmony_ci};
85562306a36Sopenharmony_cistatic const u8 ov7660_sensor_param1[][8] = {
85662306a36Sopenharmony_ci	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
85762306a36Sopenharmony_ci						/* bits[3..0]reserved */
85862306a36Sopenharmony_ci	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
85962306a36Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
86062306a36Sopenharmony_ci						/* VREF vertical frame ctrl */
86162306a36Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
86262306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
86362306a36Sopenharmony_ci	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
86462306a36Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
86562306a36Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
86662306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
86762306a36Sopenharmony_ci/****** (some exchanges in the win trace) ******/
86862306a36Sopenharmony_ci/*fixme:param2*/
86962306a36Sopenharmony_ci	{0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
87062306a36Sopenharmony_ci	{0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
87162306a36Sopenharmony_ci	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
87262306a36Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
87362306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
87462306a36Sopenharmony_ci/****** (some exchanges in the win trace) ******/
87562306a36Sopenharmony_ci/******!! startsensor KO if changed !!****/
87662306a36Sopenharmony_ci/*fixme: param3*/
87762306a36Sopenharmony_ci	{0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
87862306a36Sopenharmony_ci	{0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
87962306a36Sopenharmony_ci	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
88062306a36Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
88162306a36Sopenharmony_ci	{}
88262306a36Sopenharmony_ci};
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_cistatic const u8 po1030_sensor_init[][8] = {
88562306a36Sopenharmony_ci/* the sensor registers are described in m5602/m5602_po1030.h */
88662306a36Sopenharmony_ci	{0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
88762306a36Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
88862306a36Sopenharmony_ci	{0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
88962306a36Sopenharmony_ci	{0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
89062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
89162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
89262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
89362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
89462306a36Sopenharmony_ci	{0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
89562306a36Sopenharmony_ci	{0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
89662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
89762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
89862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
89962306a36Sopenharmony_ci	{0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
90062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
90162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
90262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
90362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
90462306a36Sopenharmony_ci	{0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
90562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
90662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
90762306a36Sopenharmony_ci	{0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
90862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
90962306a36Sopenharmony_ci	{0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
91062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
91162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
91262306a36Sopenharmony_ci	{0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
91362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
91662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
91762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
91862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
91962306a36Sopenharmony_ci	{0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
92062306a36Sopenharmony_ci	{}
92162306a36Sopenharmony_ci};
92262306a36Sopenharmony_cistatic const u8 po1030_sensor_param1[][8] = {
92362306a36Sopenharmony_ci/* from ms-win traces - these values change with auto gain/expo/wb.. */
92462306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
92562306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
92662306a36Sopenharmony_ci/* mean values */
92762306a36Sopenharmony_ci	{0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
92862306a36Sopenharmony_ci	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
92962306a36Sopenharmony_ci	{0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
93262306a36Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
93362306a36Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
93462306a36Sopenharmony_ci/*	{0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
93562306a36Sopenharmony_ci	{}
93662306a36Sopenharmony_ci};
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_cistatic const u8 po2030n_sensor_init[][8] = {
93962306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
94062306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
94162306a36Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
94262306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
94362306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
94462306a36Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
94562306a36Sopenharmony_ci	{0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
94662306a36Sopenharmony_ci	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
94762306a36Sopenharmony_ci	{0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
94862306a36Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
94962306a36Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
95062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
95162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
95262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
95362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
95462306a36Sopenharmony_ci	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
95562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
95662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
95762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
95862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
95962306a36Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
96062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
96162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
96262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
96362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
96462306a36Sopenharmony_ci	{0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
96562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
96662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
96762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
96862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
96962306a36Sopenharmony_ci	{0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
97062306a36Sopenharmony_ci	{0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
97162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
97262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
97362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
97462306a36Sopenharmony_ci	{0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
97562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
97662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
97762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
97862306a36Sopenharmony_ci	{0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
97962306a36Sopenharmony_ci	{0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
98062306a36Sopenharmony_ci	{0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
98162306a36Sopenharmony_ci	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
98262306a36Sopenharmony_ci	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
98362306a36Sopenharmony_ci	{0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
98462306a36Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
98562306a36Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
98662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
98762306a36Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
98862306a36Sopenharmony_ci	{0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
98962306a36Sopenharmony_ci	{}
99062306a36Sopenharmony_ci};
99162306a36Sopenharmony_cistatic const u8 po2030n_sensor_param1[][8] = {
99262306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
99362306a36Sopenharmony_ci	{DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
99462306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
99562306a36Sopenharmony_ci	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
99662306a36Sopenharmony_ci	{0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
99762306a36Sopenharmony_ci/*param2*/
99862306a36Sopenharmony_ci	{0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
99962306a36Sopenharmony_ci	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
100062306a36Sopenharmony_ci	{0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
100162306a36Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
100262306a36Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
100362306a36Sopenharmony_ci	{}
100462306a36Sopenharmony_ci};
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_cistatic const u8 soi768_sensor_init[][8] = {
100762306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
100862306a36Sopenharmony_ci	{DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
100962306a36Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
101062306a36Sopenharmony_ci	{0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
101162306a36Sopenharmony_ci	{0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
101262306a36Sopenharmony_ci	{0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
101362306a36Sopenharmony_ci	{}
101462306a36Sopenharmony_ci};
101562306a36Sopenharmony_cistatic const u8 soi768_sensor_param1[][8] = {
101662306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
101762306a36Sopenharmony_ci	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
101862306a36Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
101962306a36Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
102062306a36Sopenharmony_ci	{0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
102162306a36Sopenharmony_ci/* */
102262306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
102362306a36Sopenharmony_ci/*	{0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
102462306a36Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
102562306a36Sopenharmony_ci/*	{0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
102662306a36Sopenharmony_ci	{0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
102762306a36Sopenharmony_ci/* the next sequence should be used for auto gain */
102862306a36Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
102962306a36Sopenharmony_ci			/* global gain ? : 07 - change with 0x15 at the end */
103062306a36Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
103162306a36Sopenharmony_ci	{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
103262306a36Sopenharmony_ci	{0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
103362306a36Sopenharmony_ci			/* exposure ? : 0200 - change with 0x1e at the end */
103462306a36Sopenharmony_ci	{}
103562306a36Sopenharmony_ci};
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistatic const u8 sp80708_sensor_init[][8] = {
103862306a36Sopenharmony_ci	{0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
103962306a36Sopenharmony_ci	{0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
104062306a36Sopenharmony_ci	{0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
104162306a36Sopenharmony_ci	{0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
104262306a36Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
104362306a36Sopenharmony_ci	{0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
104462306a36Sopenharmony_ci	{0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
104562306a36Sopenharmony_ci	{0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
104662306a36Sopenharmony_ci	{0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
104762306a36Sopenharmony_ci	{0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
104862306a36Sopenharmony_ci	{0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
104962306a36Sopenharmony_ci	{0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
105062306a36Sopenharmony_ci	{0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
105162306a36Sopenharmony_ci	{0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
105262306a36Sopenharmony_ci	{0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
105362306a36Sopenharmony_ci	{0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
105462306a36Sopenharmony_ci	{0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
105562306a36Sopenharmony_ci	{0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
105662306a36Sopenharmony_ci	{0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
105762306a36Sopenharmony_ci	{0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
105862306a36Sopenharmony_ci	{0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
105962306a36Sopenharmony_ci	{0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
106062306a36Sopenharmony_ci	{0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
106162306a36Sopenharmony_ci	{0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
106262306a36Sopenharmony_ci	{0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
106362306a36Sopenharmony_ci	{0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
106462306a36Sopenharmony_ci	{0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
106562306a36Sopenharmony_ci	{0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
106662306a36Sopenharmony_ci	{0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
106762306a36Sopenharmony_ci	{0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
106862306a36Sopenharmony_ci	{0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
106962306a36Sopenharmony_ci	{0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
107062306a36Sopenharmony_ci	{0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
107162306a36Sopenharmony_ci	{0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
107262306a36Sopenharmony_ci	{0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
107362306a36Sopenharmony_ci	{0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
107462306a36Sopenharmony_ci	{0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
107562306a36Sopenharmony_ci	{0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
107662306a36Sopenharmony_ci	{0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
107762306a36Sopenharmony_ci	{0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
107862306a36Sopenharmony_ci	{0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
107962306a36Sopenharmony_ci	{0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
108062306a36Sopenharmony_ci	{0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
108162306a36Sopenharmony_ci	{0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
108262306a36Sopenharmony_ci	{0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
108362306a36Sopenharmony_ci	{0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
108462306a36Sopenharmony_ci	{0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
108562306a36Sopenharmony_ci	{0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
108662306a36Sopenharmony_ci	{0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
108762306a36Sopenharmony_ci	{0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
108862306a36Sopenharmony_ci	{0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
108962306a36Sopenharmony_ci	{0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
109062306a36Sopenharmony_ci	{0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
109162306a36Sopenharmony_ci	{0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
109262306a36Sopenharmony_ci	{0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
109362306a36Sopenharmony_ci	{0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
109462306a36Sopenharmony_ci	{0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
109562306a36Sopenharmony_ci	{0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
109662306a36Sopenharmony_ci	{0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
109762306a36Sopenharmony_ci	{0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
109862306a36Sopenharmony_ci	{0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
109962306a36Sopenharmony_ci	{0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
110062306a36Sopenharmony_ci	{0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
110162306a36Sopenharmony_ci	{0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
110262306a36Sopenharmony_ci	{0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
110362306a36Sopenharmony_ci	{0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
110462306a36Sopenharmony_ci	{0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
110562306a36Sopenharmony_ci	{0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
110662306a36Sopenharmony_ci	{0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
110762306a36Sopenharmony_ci	{0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
110862306a36Sopenharmony_ci	{0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
110962306a36Sopenharmony_ci	{}
111062306a36Sopenharmony_ci};
111162306a36Sopenharmony_cistatic const u8 sp80708_sensor_param1[][8] = {
111262306a36Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
111362306a36Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
111462306a36Sopenharmony_ci	{0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
111562306a36Sopenharmony_ci	{0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
111662306a36Sopenharmony_ci	{0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
111762306a36Sopenharmony_ci	{0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
111862306a36Sopenharmony_ci	{0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
111962306a36Sopenharmony_ci	{}
112062306a36Sopenharmony_ci};
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_cistatic const u8 (*sensor_init[])[8] = {
112362306a36Sopenharmony_ci[SENSOR_ADCM1700] =	adcm1700_sensor_init,
112462306a36Sopenharmony_ci[SENSOR_GC0307] =	gc0307_sensor_init,
112562306a36Sopenharmony_ci[SENSOR_HV7131R] =	hv7131r_sensor_init,
112662306a36Sopenharmony_ci[SENSOR_MI0360] =	mi0360_sensor_init,
112762306a36Sopenharmony_ci[SENSOR_MI0360B] =	mi0360b_sensor_init,
112862306a36Sopenharmony_ci[SENSOR_MO4000] =	mo4000_sensor_init,
112962306a36Sopenharmony_ci[SENSOR_MT9V111] =	mt9v111_sensor_init,
113062306a36Sopenharmony_ci[SENSOR_OM6802] =	om6802_sensor_init,
113162306a36Sopenharmony_ci[SENSOR_OV7630] =	ov7630_sensor_init,
113262306a36Sopenharmony_ci[SENSOR_OV7648] =	ov7648_sensor_init,
113362306a36Sopenharmony_ci[SENSOR_OV7660] =	ov7660_sensor_init,
113462306a36Sopenharmony_ci[SENSOR_PO1030] =	po1030_sensor_init,
113562306a36Sopenharmony_ci[SENSOR_PO2030N] =	po2030n_sensor_init,
113662306a36Sopenharmony_ci[SENSOR_SOI768] =	soi768_sensor_init,
113762306a36Sopenharmony_ci[SENSOR_SP80708] =	sp80708_sensor_init,
113862306a36Sopenharmony_ci};
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci/* read <len> bytes to gspca_dev->usb_buf */
114162306a36Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev,
114262306a36Sopenharmony_ci		  u16 value, int len)
114362306a36Sopenharmony_ci{
114462306a36Sopenharmony_ci	int ret;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
114762306a36Sopenharmony_ci		return;
114862306a36Sopenharmony_ci	if (len > USB_BUF_SZ) {
114962306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_r: buffer overflow\n");
115062306a36Sopenharmony_ci		return;
115162306a36Sopenharmony_ci	}
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
115462306a36Sopenharmony_ci			usb_rcvctrlpipe(gspca_dev->dev, 0),
115562306a36Sopenharmony_ci			0,
115662306a36Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
115762306a36Sopenharmony_ci			value, 0,
115862306a36Sopenharmony_ci			gspca_dev->usb_buf, len,
115962306a36Sopenharmony_ci			500);
116062306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBI, "reg_r [%02x] -> %02x\n",
116162306a36Sopenharmony_ci		  value, gspca_dev->usb_buf[0]);
116262306a36Sopenharmony_ci	if (ret < 0) {
116362306a36Sopenharmony_ci		pr_err("reg_r err %d\n", ret);
116462306a36Sopenharmony_ci		gspca_dev->usb_err = ret;
116562306a36Sopenharmony_ci		/*
116662306a36Sopenharmony_ci		 * Make sure the buffer is zeroed to avoid uninitialized
116762306a36Sopenharmony_ci		 * values.
116862306a36Sopenharmony_ci		 */
116962306a36Sopenharmony_ci		memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
117062306a36Sopenharmony_ci	}
117162306a36Sopenharmony_ci}
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_cistatic void reg_w1(struct gspca_dev *gspca_dev,
117462306a36Sopenharmony_ci		   u16 value,
117562306a36Sopenharmony_ci		   u8 data)
117662306a36Sopenharmony_ci{
117762306a36Sopenharmony_ci	int ret;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
118062306a36Sopenharmony_ci		return;
118162306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg_w1 [%04x] = %02x\n", value, data);
118262306a36Sopenharmony_ci	gspca_dev->usb_buf[0] = data;
118362306a36Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
118462306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
118562306a36Sopenharmony_ci			0x08,
118662306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
118762306a36Sopenharmony_ci			value,
118862306a36Sopenharmony_ci			0,
118962306a36Sopenharmony_ci			gspca_dev->usb_buf, 1,
119062306a36Sopenharmony_ci			500);
119162306a36Sopenharmony_ci	if (ret < 0) {
119262306a36Sopenharmony_ci		pr_err("reg_w1 err %d\n", ret);
119362306a36Sopenharmony_ci		gspca_dev->usb_err = ret;
119462306a36Sopenharmony_ci	}
119562306a36Sopenharmony_ci}
119662306a36Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev,
119762306a36Sopenharmony_ci			  u16 value,
119862306a36Sopenharmony_ci			  const u8 *buffer,
119962306a36Sopenharmony_ci			  int len)
120062306a36Sopenharmony_ci{
120162306a36Sopenharmony_ci	int ret;
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
120462306a36Sopenharmony_ci		return;
120562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x %02x ..\n",
120662306a36Sopenharmony_ci		  value, buffer[0], buffer[1]);
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	if (len > USB_BUF_SZ) {
120962306a36Sopenharmony_ci		gspca_err(gspca_dev, "reg_w: buffer overflow\n");
121062306a36Sopenharmony_ci		return;
121162306a36Sopenharmony_ci	}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, len);
121462306a36Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
121562306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
121662306a36Sopenharmony_ci			0x08,
121762306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
121862306a36Sopenharmony_ci			value, 0,
121962306a36Sopenharmony_ci			gspca_dev->usb_buf, len,
122062306a36Sopenharmony_ci			500);
122162306a36Sopenharmony_ci	if (ret < 0) {
122262306a36Sopenharmony_ci		pr_err("reg_w err %d\n", ret);
122362306a36Sopenharmony_ci		gspca_dev->usb_err = ret;
122462306a36Sopenharmony_ci	}
122562306a36Sopenharmony_ci}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci/* I2C write 1 byte */
122862306a36Sopenharmony_cistatic void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
123162306a36Sopenharmony_ci	int ret;
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
123462306a36Sopenharmony_ci		return;
123562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "i2c_w1 [%02x] = %02x\n", reg, val);
123662306a36Sopenharmony_ci	switch (sd->sensor) {
123762306a36Sopenharmony_ci	case SENSOR_ADCM1700:
123862306a36Sopenharmony_ci	case SENSOR_OM6802:
123962306a36Sopenharmony_ci	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
124062306a36Sopenharmony_ci		gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
124162306a36Sopenharmony_ci		break;
124262306a36Sopenharmony_ci	default:			/* i2c command = a1 (400 kHz) */
124362306a36Sopenharmony_ci		gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
124462306a36Sopenharmony_ci		break;
124562306a36Sopenharmony_ci	}
124662306a36Sopenharmony_ci	gspca_dev->usb_buf[1] = sd->i2c_addr;
124762306a36Sopenharmony_ci	gspca_dev->usb_buf[2] = reg;
124862306a36Sopenharmony_ci	gspca_dev->usb_buf[3] = val;
124962306a36Sopenharmony_ci	gspca_dev->usb_buf[4] = 0;
125062306a36Sopenharmony_ci	gspca_dev->usb_buf[5] = 0;
125162306a36Sopenharmony_ci	gspca_dev->usb_buf[6] = 0;
125262306a36Sopenharmony_ci	gspca_dev->usb_buf[7] = 0x10;
125362306a36Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
125462306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
125562306a36Sopenharmony_ci			0x08,
125662306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
125762306a36Sopenharmony_ci			0x08,			/* value = i2c */
125862306a36Sopenharmony_ci			0,
125962306a36Sopenharmony_ci			gspca_dev->usb_buf, 8,
126062306a36Sopenharmony_ci			500);
126162306a36Sopenharmony_ci	msleep(2);
126262306a36Sopenharmony_ci	if (ret < 0) {
126362306a36Sopenharmony_ci		pr_err("i2c_w1 err %d\n", ret);
126462306a36Sopenharmony_ci		gspca_dev->usb_err = ret;
126562306a36Sopenharmony_ci	}
126662306a36Sopenharmony_ci}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci/* I2C write 8 bytes */
126962306a36Sopenharmony_cistatic void i2c_w8(struct gspca_dev *gspca_dev,
127062306a36Sopenharmony_ci		   const u8 *buffer)
127162306a36Sopenharmony_ci{
127262306a36Sopenharmony_ci	int ret;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
127562306a36Sopenharmony_ci		return;
127662306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "i2c_w8 [%02x] = %02x ..\n",
127762306a36Sopenharmony_ci		  buffer[2], buffer[3]);
127862306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, 8);
127962306a36Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
128062306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
128162306a36Sopenharmony_ci			0x08,
128262306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
128362306a36Sopenharmony_ci			0x08, 0,		/* value, index */
128462306a36Sopenharmony_ci			gspca_dev->usb_buf, 8,
128562306a36Sopenharmony_ci			500);
128662306a36Sopenharmony_ci	msleep(2);
128762306a36Sopenharmony_ci	if (ret < 0) {
128862306a36Sopenharmony_ci		pr_err("i2c_w8 err %d\n", ret);
128962306a36Sopenharmony_ci		gspca_dev->usb_err = ret;
129062306a36Sopenharmony_ci	}
129162306a36Sopenharmony_ci}
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
129462306a36Sopenharmony_cistatic void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
129562306a36Sopenharmony_ci{
129662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
129762306a36Sopenharmony_ci	u8 mode[8];
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	switch (sd->sensor) {
130062306a36Sopenharmony_ci	case SENSOR_ADCM1700:
130162306a36Sopenharmony_ci	case SENSOR_OM6802:
130262306a36Sopenharmony_ci	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
130362306a36Sopenharmony_ci		mode[0] = 0x80 | 0x10;
130462306a36Sopenharmony_ci		break;
130562306a36Sopenharmony_ci	default:			/* i2c command = 91 (400 kHz) */
130662306a36Sopenharmony_ci		mode[0] = 0x81 | 0x10;
130762306a36Sopenharmony_ci		break;
130862306a36Sopenharmony_ci	}
130962306a36Sopenharmony_ci	mode[1] = sd->i2c_addr;
131062306a36Sopenharmony_ci	mode[2] = reg;
131162306a36Sopenharmony_ci	mode[3] = 0;
131262306a36Sopenharmony_ci	mode[4] = 0;
131362306a36Sopenharmony_ci	mode[5] = 0;
131462306a36Sopenharmony_ci	mode[6] = 0;
131562306a36Sopenharmony_ci	mode[7] = 0x10;
131662306a36Sopenharmony_ci	i2c_w8(gspca_dev, mode);
131762306a36Sopenharmony_ci	msleep(2);
131862306a36Sopenharmony_ci	mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
131962306a36Sopenharmony_ci	mode[2] = 0;
132062306a36Sopenharmony_ci	i2c_w8(gspca_dev, mode);
132162306a36Sopenharmony_ci	msleep(2);
132262306a36Sopenharmony_ci	reg_r(gspca_dev, 0x0a, 5);
132362306a36Sopenharmony_ci}
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_cistatic void i2c_w_seq(struct gspca_dev *gspca_dev,
132662306a36Sopenharmony_ci			const u8 (*data)[8])
132762306a36Sopenharmony_ci{
132862306a36Sopenharmony_ci	while ((*data)[0] != 0) {
132962306a36Sopenharmony_ci		if ((*data)[0] != DELAY)
133062306a36Sopenharmony_ci			i2c_w8(gspca_dev, *data);
133162306a36Sopenharmony_ci		else
133262306a36Sopenharmony_ci			msleep((*data)[1]);
133362306a36Sopenharmony_ci		data++;
133462306a36Sopenharmony_ci	}
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci/* check the ID of the hv7131 sensor */
133862306a36Sopenharmony_ci/* this sequence is needed because it activates the sensor */
133962306a36Sopenharmony_cistatic void hv7131r_probe(struct gspca_dev *gspca_dev)
134062306a36Sopenharmony_ci{
134162306a36Sopenharmony_ci	i2c_w1(gspca_dev, 0x02, 0);		/* sensor wakeup */
134262306a36Sopenharmony_ci	msleep(10);
134362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x02, 0x66);		/* Gpio on */
134462306a36Sopenharmony_ci	msleep(10);
134562306a36Sopenharmony_ci	i2c_r(gspca_dev, 0, 5);			/* read sensor id */
134662306a36Sopenharmony_ci	if (gspca_dev->usb_buf[0] == 0x02	/* chip ID (02 is R) */
134762306a36Sopenharmony_ci	    && gspca_dev->usb_buf[1] == 0x09
134862306a36Sopenharmony_ci	    && gspca_dev->usb_buf[2] == 0x01) {
134962306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor HV7131R found\n");
135062306a36Sopenharmony_ci		return;
135162306a36Sopenharmony_ci	}
135262306a36Sopenharmony_ci	pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
135362306a36Sopenharmony_ci		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
135462306a36Sopenharmony_ci		gspca_dev->usb_buf[2]);
135562306a36Sopenharmony_ci}
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_cistatic void mi0360_probe(struct gspca_dev *gspca_dev)
135862306a36Sopenharmony_ci{
135962306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
136062306a36Sopenharmony_ci	int i, j;
136162306a36Sopenharmony_ci	u16 val = 0;
136262306a36Sopenharmony_ci	static const u8 probe_tb[][4][8] = {
136362306a36Sopenharmony_ci	    {					/* mi0360 */
136462306a36Sopenharmony_ci		{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
136562306a36Sopenharmony_ci		{0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
136662306a36Sopenharmony_ci		{0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
136762306a36Sopenharmony_ci		{0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
136862306a36Sopenharmony_ci	    },
136962306a36Sopenharmony_ci	    {					/* mt9v111 */
137062306a36Sopenharmony_ci		{0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
137162306a36Sopenharmony_ci		{0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
137262306a36Sopenharmony_ci		{0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
137362306a36Sopenharmony_ci		{}
137462306a36Sopenharmony_ci	    },
137562306a36Sopenharmony_ci	};
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
137862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x17, 0x62);
137962306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x08);
138062306a36Sopenharmony_ci		for (j = 0; j < 3; j++)
138162306a36Sopenharmony_ci			i2c_w8(gspca_dev, probe_tb[i][j]);
138262306a36Sopenharmony_ci		msleep(2);
138362306a36Sopenharmony_ci		reg_r(gspca_dev, 0x0a, 5);
138462306a36Sopenharmony_ci		val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
138562306a36Sopenharmony_ci		if (probe_tb[i][3][0] != 0)
138662306a36Sopenharmony_ci			i2c_w8(gspca_dev, probe_tb[i][3]);
138762306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x29);
138862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x17, 0x42);
138962306a36Sopenharmony_ci		if (val != 0xffff)
139062306a36Sopenharmony_ci			break;
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
139362306a36Sopenharmony_ci		return;
139462306a36Sopenharmony_ci	switch (val) {
139562306a36Sopenharmony_ci	case 0x8221:
139662306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mi0360b\n");
139762306a36Sopenharmony_ci		sd->sensor = SENSOR_MI0360B;
139862306a36Sopenharmony_ci		break;
139962306a36Sopenharmony_ci	case 0x823a:
140062306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mt9v111\n");
140162306a36Sopenharmony_ci		sd->sensor = SENSOR_MT9V111;
140262306a36Sopenharmony_ci		break;
140362306a36Sopenharmony_ci	case 0x8243:
140462306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mi0360\n");
140562306a36Sopenharmony_ci		break;
140662306a36Sopenharmony_ci	default:
140762306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Unknown sensor %04x - forced to mi0360\n",
140862306a36Sopenharmony_ci			  val);
140962306a36Sopenharmony_ci		break;
141062306a36Sopenharmony_ci	}
141162306a36Sopenharmony_ci}
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_cistatic void ov7630_probe(struct gspca_dev *gspca_dev)
141462306a36Sopenharmony_ci{
141562306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
141662306a36Sopenharmony_ci	u16 val;
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	/* check ov76xx */
141962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
142062306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
142162306a36Sopenharmony_ci	sd->i2c_addr = 0x21;
142262306a36Sopenharmony_ci	i2c_r(gspca_dev, 0x0a, 2);
142362306a36Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
142462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
142562306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
142662306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
142762306a36Sopenharmony_ci		return;
142862306a36Sopenharmony_ci	if (val == 0x7628) {			/* soi768 */
142962306a36Sopenharmony_ci		sd->sensor = SENSOR_SOI768;
143062306a36Sopenharmony_ci/*fixme: only valid for 0c45:613e?*/
143162306a36Sopenharmony_ci		gspca_dev->cam.input_flags =
143262306a36Sopenharmony_ci				V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
143362306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor soi768\n");
143462306a36Sopenharmony_ci		return;
143562306a36Sopenharmony_ci	}
143662306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Sensor ov%04x\n", val);
143762306a36Sopenharmony_ci}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_cistatic void ov7648_probe(struct gspca_dev *gspca_dev)
144062306a36Sopenharmony_ci{
144162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
144262306a36Sopenharmony_ci	u16 val;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	/* check ov76xx */
144562306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
144662306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
144762306a36Sopenharmony_ci	sd->i2c_addr = 0x21;
144862306a36Sopenharmony_ci	i2c_r(gspca_dev, 0x0a, 2);
144962306a36Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
145062306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
145162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
145262306a36Sopenharmony_ci	if ((val & 0xff00) == 0x7600) {		/* ov76xx */
145362306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor ov%04x\n", val);
145462306a36Sopenharmony_ci		return;
145562306a36Sopenharmony_ci	}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	/* check po1030 */
145862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
145962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
146062306a36Sopenharmony_ci	sd->i2c_addr = 0x6e;
146162306a36Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 2);
146262306a36Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
146362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
146462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
146562306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
146662306a36Sopenharmony_ci		return;
146762306a36Sopenharmony_ci	if (val == 0x1030) {			/* po1030 */
146862306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor po1030\n");
146962306a36Sopenharmony_ci		sd->sensor = SENSOR_PO1030;
147062306a36Sopenharmony_ci		return;
147162306a36Sopenharmony_ci	}
147262306a36Sopenharmony_ci	pr_err("Unknown sensor %04x\n", val);
147362306a36Sopenharmony_ci}
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
147662306a36Sopenharmony_cistatic void po2030n_probe(struct gspca_dev *gspca_dev)
147762306a36Sopenharmony_ci{
147862306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
147962306a36Sopenharmony_ci	u16 val;
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	/* check gc0307 */
148262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
148362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
148462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x02, 0x22);
148562306a36Sopenharmony_ci	sd->i2c_addr = 0x21;
148662306a36Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 1);
148762306a36Sopenharmony_ci	val = gspca_dev->usb_buf[4];
148862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);		/* reset */
148962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
149062306a36Sopenharmony_ci	if (val == 0x99) {			/* gc0307 (?) */
149162306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor gc0307\n");
149262306a36Sopenharmony_ci		sd->sensor = SENSOR_GC0307;
149362306a36Sopenharmony_ci		return;
149462306a36Sopenharmony_ci	}
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	/* check po2030n */
149762306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
149862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x0a);
149962306a36Sopenharmony_ci	sd->i2c_addr = 0x6e;
150062306a36Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 2);
150162306a36Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
150262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
150362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
150462306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
150562306a36Sopenharmony_ci		return;
150662306a36Sopenharmony_ci	if (val == 0x2030) {
150762306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor po2030n\n");
150862306a36Sopenharmony_ci/*		sd->sensor = SENSOR_PO2030N; */
150962306a36Sopenharmony_ci	} else {
151062306a36Sopenharmony_ci		pr_err("Unknown sensor ID %04x\n", val);
151162306a36Sopenharmony_ci	}
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci/* this function is called at probe time */
151562306a36Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
151662306a36Sopenharmony_ci			const struct usb_device_id *id)
151762306a36Sopenharmony_ci{
151862306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
151962306a36Sopenharmony_ci	struct cam *cam;
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	sd->bridge = id->driver_info >> 16;
152262306a36Sopenharmony_ci	sd->sensor = id->driver_info >> 8;
152362306a36Sopenharmony_ci	sd->flags = id->driver_info;
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	cam = &gspca_dev->cam;
152662306a36Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
152762306a36Sopenharmony_ci		cam->cam_mode = cif_mode;
152862306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(cif_mode);
152962306a36Sopenharmony_ci	} else {
153062306a36Sopenharmony_ci		cam->cam_mode = vga_mode;
153162306a36Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(vga_mode);
153262306a36Sopenharmony_ci	}
153362306a36Sopenharmony_ci	cam->npkt = 24;			/* 24 packets per ISOC message */
153462306a36Sopenharmony_ci
153562306a36Sopenharmony_ci	sd->ag_cnt = -1;
153662306a36Sopenharmony_ci	sd->quality = QUALITY_DEF;
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	INIT_WORK(&sd->work, qual_upd);
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	return 0;
154162306a36Sopenharmony_ci}
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci/* this function is called at probe and resume time */
154462306a36Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
154562306a36Sopenharmony_ci{
154662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
154762306a36Sopenharmony_ci	const u8 *sn9c1xx;
154862306a36Sopenharmony_ci	u8 regGpio[] = { 0x29, 0x70 };		/* no audio */
154962306a36Sopenharmony_ci	u8 regF1;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	/* setup a selector by bridge */
155262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x01);
155362306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00, 1);
155462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x00);
155562306a36Sopenharmony_ci	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */
155662306a36Sopenharmony_ci	regF1 = gspca_dev->usb_buf[0];
155762306a36Sopenharmony_ci	if (gspca_dev->usb_err < 0)
155862306a36Sopenharmony_ci		return gspca_dev->usb_err;
155962306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Sonix chip id: %02x\n", regF1);
156062306a36Sopenharmony_ci	if (gspca_dev->audio)
156162306a36Sopenharmony_ci		regGpio[1] |= 0x04;		/* with audio */
156262306a36Sopenharmony_ci	switch (sd->bridge) {
156362306a36Sopenharmony_ci	case BRIDGE_SN9C102P:
156462306a36Sopenharmony_ci	case BRIDGE_SN9C105:
156562306a36Sopenharmony_ci		if (regF1 != 0x11)
156662306a36Sopenharmony_ci			return -ENODEV;
156762306a36Sopenharmony_ci		break;
156862306a36Sopenharmony_ci	default:
156962306a36Sopenharmony_ci/*	case BRIDGE_SN9C110: */
157062306a36Sopenharmony_ci/*	case BRIDGE_SN9C120: */
157162306a36Sopenharmony_ci		if (regF1 != 0x12)
157262306a36Sopenharmony_ci			return -ENODEV;
157362306a36Sopenharmony_ci	}
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci	switch (sd->sensor) {
157662306a36Sopenharmony_ci	case SENSOR_MI0360:
157762306a36Sopenharmony_ci		mi0360_probe(gspca_dev);
157862306a36Sopenharmony_ci		break;
157962306a36Sopenharmony_ci	case SENSOR_OV7630:
158062306a36Sopenharmony_ci		ov7630_probe(gspca_dev);
158162306a36Sopenharmony_ci		break;
158262306a36Sopenharmony_ci	case SENSOR_OV7648:
158362306a36Sopenharmony_ci		ov7648_probe(gspca_dev);
158462306a36Sopenharmony_ci		break;
158562306a36Sopenharmony_ci	case SENSOR_PO2030N:
158662306a36Sopenharmony_ci		po2030n_probe(gspca_dev);
158762306a36Sopenharmony_ci		break;
158862306a36Sopenharmony_ci	}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_ci	switch (sd->bridge) {
159162306a36Sopenharmony_ci	case BRIDGE_SN9C102P:
159262306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02, regGpio[1]);
159362306a36Sopenharmony_ci		break;
159462306a36Sopenharmony_ci	default:
159562306a36Sopenharmony_ci		reg_w(gspca_dev, 0x01, regGpio, 2);
159662306a36Sopenharmony_ci		break;
159762306a36Sopenharmony_ci	}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	/* Note we do not disable the sensor clock here (power saving mode),
160062306a36Sopenharmony_ci	   as that also disables the button on the cam. */
160162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x00);
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	/* set the i2c address */
160462306a36Sopenharmony_ci	sn9c1xx = sn_tb[sd->sensor];
160562306a36Sopenharmony_ci	sd->i2c_addr = sn9c1xx[9];
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	return gspca_dev->usb_err;
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl);
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
161362306a36Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
161462306a36Sopenharmony_ci};
161562306a36Sopenharmony_ci
161662306a36Sopenharmony_ci/* this function is called at probe time */
161762306a36Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
161862306a36Sopenharmony_ci{
161962306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
162062306a36Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
162362306a36Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 14);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
162662306a36Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
162762306a36Sopenharmony_ci#define CONTRAST_MAX 127
162862306a36Sopenharmony_ci	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
162962306a36Sopenharmony_ci			V4L2_CID_CONTRAST, 0, CONTRAST_MAX, 1, 20);
163062306a36Sopenharmony_ci#define COLORS_DEF 25
163162306a36Sopenharmony_ci	sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
163262306a36Sopenharmony_ci			V4L2_CID_SATURATION, 0, 40, 1, COLORS_DEF);
163362306a36Sopenharmony_ci	sd->red_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
163462306a36Sopenharmony_ci			V4L2_CID_RED_BALANCE, 24, 40, 1, 32);
163562306a36Sopenharmony_ci	sd->blue_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
163662306a36Sopenharmony_ci			V4L2_CID_BLUE_BALANCE, 24, 40, 1, 32);
163762306a36Sopenharmony_ci#define GAMMA_DEF 20
163862306a36Sopenharmony_ci	sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
163962306a36Sopenharmony_ci			V4L2_CID_GAMMA, 0, 40, 1, GAMMA_DEF);
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	if (sd->sensor == SENSOR_OM6802)
164262306a36Sopenharmony_ci		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
164362306a36Sopenharmony_ci			V4L2_CID_SHARPNESS, 0, 255, 1, 16);
164462306a36Sopenharmony_ci	else
164562306a36Sopenharmony_ci		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
164662306a36Sopenharmony_ci			V4L2_CID_SHARPNESS, 0, 255, 1, 90);
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	if (sd->flags & F_ILLUM)
164962306a36Sopenharmony_ci		sd->illum = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
165062306a36Sopenharmony_ci			V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
165362306a36Sopenharmony_ci		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
165462306a36Sopenharmony_ci			V4L2_CID_EXPOSURE, 500, 1500, 1, 1024);
165562306a36Sopenharmony_ci		gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
165662306a36Sopenharmony_ci			V4L2_CID_GAIN, 4, 49, 1, 15);
165762306a36Sopenharmony_ci		sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
165862306a36Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
165962306a36Sopenharmony_ci	}
166062306a36Sopenharmony_ci
166162306a36Sopenharmony_ci	if (sd->sensor != SENSOR_ADCM1700 && sd->sensor != SENSOR_OV7660 &&
166262306a36Sopenharmony_ci	    sd->sensor != SENSOR_PO1030 && sd->sensor != SENSOR_SOI768 &&
166362306a36Sopenharmony_ci	    sd->sensor != SENSOR_SP80708)
166462306a36Sopenharmony_ci		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
166562306a36Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci	if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_OV7630 ||
166862306a36Sopenharmony_ci	    sd->sensor == SENSOR_OV7648 || sd->sensor == SENSOR_PO2030N)
166962306a36Sopenharmony_ci		sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
167062306a36Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	if (sd->sensor == SENSOR_OV7630 || sd->sensor == SENSOR_OV7648 ||
167362306a36Sopenharmony_ci	    sd->sensor == SENSOR_OV7660)
167462306a36Sopenharmony_ci		sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
167562306a36Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY,
167662306a36Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
167762306a36Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	if (hdl->error) {
168062306a36Sopenharmony_ci		pr_err("Could not initialize controls\n");
168162306a36Sopenharmony_ci		return hdl->error;
168262306a36Sopenharmony_ci	}
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	v4l2_ctrl_cluster(2, &sd->red_bal);
168562306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
168662306a36Sopenharmony_ci		v4l2_ctrl_cluster(2, &sd->vflip);
168762306a36Sopenharmony_ci		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	return 0;
169162306a36Sopenharmony_ci}
169262306a36Sopenharmony_ci
169362306a36Sopenharmony_cistatic u32 expo_adjust(struct gspca_dev *gspca_dev,
169462306a36Sopenharmony_ci			u32 expo)
169562306a36Sopenharmony_ci{
169662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	switch (sd->sensor) {
169962306a36Sopenharmony_ci	case SENSOR_GC0307: {
170062306a36Sopenharmony_ci		int a, b;
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci		/* expo = 0..255 -> a = 19..43 */
170362306a36Sopenharmony_ci		a = 19 + expo * 25 / 256;
170462306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x68, a);
170562306a36Sopenharmony_ci		a -= 12;
170662306a36Sopenharmony_ci		b = a * a * 4;			/* heuristic */
170762306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x03, b >> 8);
170862306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x04, b);
170962306a36Sopenharmony_ci		break;
171062306a36Sopenharmony_ci	    }
171162306a36Sopenharmony_ci	case SENSOR_HV7131R: {
171262306a36Sopenharmony_ci		u8 Expodoit[] =
171362306a36Sopenharmony_ci			{ 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci		Expodoit[3] = expo >> 16;
171662306a36Sopenharmony_ci		Expodoit[4] = expo >> 8;
171762306a36Sopenharmony_ci		Expodoit[5] = expo;
171862306a36Sopenharmony_ci		i2c_w8(gspca_dev, Expodoit);
171962306a36Sopenharmony_ci		break;
172062306a36Sopenharmony_ci	    }
172162306a36Sopenharmony_ci	case SENSOR_MI0360:
172262306a36Sopenharmony_ci	case SENSOR_MI0360B: {
172362306a36Sopenharmony_ci		u8 expoMi[] =		/* exposure 0x0635 -> 4 fp/s 0x10 */
172462306a36Sopenharmony_ci			{ 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
172562306a36Sopenharmony_ci		static const u8 doit[] =		/* update sensor */
172662306a36Sopenharmony_ci			{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
172762306a36Sopenharmony_ci		static const u8 sensorgo[] =		/* sensor on */
172862306a36Sopenharmony_ci			{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci		if (expo > 0x0635)
173162306a36Sopenharmony_ci			expo = 0x0635;
173262306a36Sopenharmony_ci		else if (expo < 0x0001)
173362306a36Sopenharmony_ci			expo = 0x0001;
173462306a36Sopenharmony_ci		expoMi[3] = expo >> 8;
173562306a36Sopenharmony_ci		expoMi[4] = expo;
173662306a36Sopenharmony_ci		i2c_w8(gspca_dev, expoMi);
173762306a36Sopenharmony_ci		i2c_w8(gspca_dev, doit);
173862306a36Sopenharmony_ci		i2c_w8(gspca_dev, sensorgo);
173962306a36Sopenharmony_ci		break;
174062306a36Sopenharmony_ci	    }
174162306a36Sopenharmony_ci	case SENSOR_MO4000: {
174262306a36Sopenharmony_ci		u8 expoMof[] =
174362306a36Sopenharmony_ci			{ 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
174462306a36Sopenharmony_ci		u8 expoMo10[] =
174562306a36Sopenharmony_ci			{ 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
174662306a36Sopenharmony_ci		static const u8 gainMo[] =
174762306a36Sopenharmony_ci			{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci		if (expo > 0x1fff)
175062306a36Sopenharmony_ci			expo = 0x1fff;
175162306a36Sopenharmony_ci		else if (expo < 0x0001)
175262306a36Sopenharmony_ci			expo = 0x0001;
175362306a36Sopenharmony_ci		expoMof[3] = (expo & 0x03fc) >> 2;
175462306a36Sopenharmony_ci		i2c_w8(gspca_dev, expoMof);
175562306a36Sopenharmony_ci		expoMo10[3] = ((expo & 0x1c00) >> 10)
175662306a36Sopenharmony_ci				| ((expo & 0x0003) << 4);
175762306a36Sopenharmony_ci		i2c_w8(gspca_dev, expoMo10);
175862306a36Sopenharmony_ci		i2c_w8(gspca_dev, gainMo);
175962306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_FRAM, "set exposure %d\n",
176062306a36Sopenharmony_ci			  ((expoMo10[3] & 0x07) << 10)
176162306a36Sopenharmony_ci			  | (expoMof[3] << 2)
176262306a36Sopenharmony_ci			  | ((expoMo10[3] & 0x30) >> 4));
176362306a36Sopenharmony_ci		break;
176462306a36Sopenharmony_ci	    }
176562306a36Sopenharmony_ci	case SENSOR_MT9V111: {
176662306a36Sopenharmony_ci		u8 expo_c1[] =
176762306a36Sopenharmony_ci			{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci		if (expo > 0x0390)
177062306a36Sopenharmony_ci			expo = 0x0390;
177162306a36Sopenharmony_ci		else if (expo < 0x0060)
177262306a36Sopenharmony_ci			expo = 0x0060;
177362306a36Sopenharmony_ci		expo_c1[3] = expo >> 8;
177462306a36Sopenharmony_ci		expo_c1[4] = expo;
177562306a36Sopenharmony_ci		i2c_w8(gspca_dev, expo_c1);
177662306a36Sopenharmony_ci		break;
177762306a36Sopenharmony_ci	    }
177862306a36Sopenharmony_ci	case SENSOR_OM6802: {
177962306a36Sopenharmony_ci		u8 gainOm[] =
178062306a36Sopenharmony_ci			{ 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
178162306a36Sopenharmony_ci				/* preset AGC - works when AutoExpo = off */
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci		if (expo > 0x03ff)
178462306a36Sopenharmony_ci			expo = 0x03ff;
178562306a36Sopenharmony_ci		if (expo < 0x0001)
178662306a36Sopenharmony_ci			expo = 0x0001;
178762306a36Sopenharmony_ci		gainOm[3] = expo >> 2;
178862306a36Sopenharmony_ci		i2c_w8(gspca_dev, gainOm);
178962306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x96, expo >> 5);
179062306a36Sopenharmony_ci		gspca_dbg(gspca_dev, D_FRAM, "set exposure %d\n", gainOm[3]);
179162306a36Sopenharmony_ci		break;
179262306a36Sopenharmony_ci	    }
179362306a36Sopenharmony_ci	}
179462306a36Sopenharmony_ci	return expo;
179562306a36Sopenharmony_ci}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev)
179862306a36Sopenharmony_ci{
179962306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
180062306a36Sopenharmony_ci	unsigned int expo;
180162306a36Sopenharmony_ci	int brightness = sd->brightness->val;
180262306a36Sopenharmony_ci	u8 k2;
180362306a36Sopenharmony_ci
180462306a36Sopenharmony_ci	k2 = (brightness - 0x80) >> 2;
180562306a36Sopenharmony_ci	switch (sd->sensor) {
180662306a36Sopenharmony_ci	case SENSOR_ADCM1700:
180762306a36Sopenharmony_ci		if (k2 > 0x1f)
180862306a36Sopenharmony_ci			k2 = 0;		/* only positive Y offset */
180962306a36Sopenharmony_ci		break;
181062306a36Sopenharmony_ci	case SENSOR_HV7131R:
181162306a36Sopenharmony_ci		expo = brightness << 12;
181262306a36Sopenharmony_ci		if (expo > 0x002dc6c0)
181362306a36Sopenharmony_ci			expo = 0x002dc6c0;
181462306a36Sopenharmony_ci		else if (expo < 0x02a0)
181562306a36Sopenharmony_ci			expo = 0x02a0;
181662306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
181762306a36Sopenharmony_ci		break;
181862306a36Sopenharmony_ci	case SENSOR_MI0360:
181962306a36Sopenharmony_ci	case SENSOR_MO4000:
182062306a36Sopenharmony_ci		expo = brightness << 4;
182162306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
182262306a36Sopenharmony_ci		break;
182362306a36Sopenharmony_ci	case SENSOR_MI0360B:
182462306a36Sopenharmony_ci		expo = brightness << 2;
182562306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
182662306a36Sopenharmony_ci		break;
182762306a36Sopenharmony_ci	case SENSOR_GC0307:
182862306a36Sopenharmony_ci		expo = brightness;
182962306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
183062306a36Sopenharmony_ci		return;			/* don't set the Y offset */
183162306a36Sopenharmony_ci	case SENSOR_MT9V111:
183262306a36Sopenharmony_ci		expo = brightness << 2;
183362306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
183462306a36Sopenharmony_ci		return;			/* don't set the Y offset */
183562306a36Sopenharmony_ci	case SENSOR_OM6802:
183662306a36Sopenharmony_ci		expo = brightness << 2;
183762306a36Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
183862306a36Sopenharmony_ci		return;			/* Y offset already set */
183962306a36Sopenharmony_ci	}
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
184262306a36Sopenharmony_ci}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev)
184562306a36Sopenharmony_ci{
184662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
184762306a36Sopenharmony_ci	u8 k2;
184862306a36Sopenharmony_ci	u8 contrast[6];
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	k2 = sd->contrast->val * 37 / (CONTRAST_MAX + 1)
185162306a36Sopenharmony_ci				+ 37;		/* 37..73 */
185262306a36Sopenharmony_ci	contrast[0] = (k2 + 1) / 2;		/* red */
185362306a36Sopenharmony_ci	contrast[1] = 0;
185462306a36Sopenharmony_ci	contrast[2] = k2;			/* green */
185562306a36Sopenharmony_ci	contrast[3] = 0;
185662306a36Sopenharmony_ci	contrast[4] = k2 / 5;			/* blue */
185762306a36Sopenharmony_ci	contrast[5] = 0;
185862306a36Sopenharmony_ci	reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
185962306a36Sopenharmony_ci}
186062306a36Sopenharmony_ci
186162306a36Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev)
186262306a36Sopenharmony_ci{
186362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
186462306a36Sopenharmony_ci	int i, v, colors;
186562306a36Sopenharmony_ci	const s16 *uv;
186662306a36Sopenharmony_ci	u8 reg8a[12];			/* U & V gains */
186762306a36Sopenharmony_ci	static const s16 uv_com[6] = {	/* same as reg84 in signed decimal */
186862306a36Sopenharmony_ci		-24, -38, 64,		/* UR UG UB */
186962306a36Sopenharmony_ci		 62, -51, -9		/* VR VG VB */
187062306a36Sopenharmony_ci	};
187162306a36Sopenharmony_ci	static const s16 uv_mi0360b[6] = {
187262306a36Sopenharmony_ci		-20, -38, 64,		/* UR UG UB */
187362306a36Sopenharmony_ci		 60, -51, -9		/* VR VG VB */
187462306a36Sopenharmony_ci	};
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci	colors = sd->saturation->val;
187762306a36Sopenharmony_ci	if (sd->sensor == SENSOR_MI0360B)
187862306a36Sopenharmony_ci		uv = uv_mi0360b;
187962306a36Sopenharmony_ci	else
188062306a36Sopenharmony_ci		uv = uv_com;
188162306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
188262306a36Sopenharmony_ci		v = uv[i] * colors / COLORS_DEF;
188362306a36Sopenharmony_ci		reg8a[i * 2] = v;
188462306a36Sopenharmony_ci		reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
188562306a36Sopenharmony_ci	}
188662306a36Sopenharmony_ci	reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
188762306a36Sopenharmony_ci}
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_cistatic void setredblue(struct gspca_dev *gspca_dev)
189062306a36Sopenharmony_ci{
189162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
189262306a36Sopenharmony_ci
189362306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
189462306a36Sopenharmony_ci		u8 rg1b[] =		/* red  green1 blue (no g2) */
189562306a36Sopenharmony_ci			{0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci		/* 0x40 = normal value = gain x 1 */
189862306a36Sopenharmony_ci		rg1b[3] = sd->red_bal->val * 2;
189962306a36Sopenharmony_ci		rg1b[5] = sd->blue_bal->val * 2;
190062306a36Sopenharmony_ci		i2c_w8(gspca_dev, rg1b);
190162306a36Sopenharmony_ci		return;
190262306a36Sopenharmony_ci	}
190362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x05, sd->red_bal->val);
190462306a36Sopenharmony_ci/*	reg_w1(gspca_dev, 0x07, 32); */
190562306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x06, sd->blue_bal->val);
190662306a36Sopenharmony_ci}
190762306a36Sopenharmony_ci
190862306a36Sopenharmony_cistatic void setgamma(struct gspca_dev *gspca_dev)
190962306a36Sopenharmony_ci{
191062306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
191162306a36Sopenharmony_ci	int i, val;
191262306a36Sopenharmony_ci	u8 gamma[17];
191362306a36Sopenharmony_ci	const u8 *gamma_base;
191462306a36Sopenharmony_ci	static const u8 delta[17] = {
191562306a36Sopenharmony_ci		0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
191662306a36Sopenharmony_ci		0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
191762306a36Sopenharmony_ci	};
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	switch (sd->sensor) {
192062306a36Sopenharmony_ci	case SENSOR_ADCM1700:
192162306a36Sopenharmony_ci		gamma_base = gamma_spec_0;
192262306a36Sopenharmony_ci		break;
192362306a36Sopenharmony_ci	case SENSOR_HV7131R:
192462306a36Sopenharmony_ci	case SENSOR_MI0360B:
192562306a36Sopenharmony_ci	case SENSOR_MT9V111:
192662306a36Sopenharmony_ci		gamma_base = gamma_spec_1;
192762306a36Sopenharmony_ci		break;
192862306a36Sopenharmony_ci	case SENSOR_GC0307:
192962306a36Sopenharmony_ci		gamma_base = gamma_spec_2;
193062306a36Sopenharmony_ci		break;
193162306a36Sopenharmony_ci	case SENSOR_SP80708:
193262306a36Sopenharmony_ci		gamma_base = gamma_spec_3;
193362306a36Sopenharmony_ci		break;
193462306a36Sopenharmony_ci	default:
193562306a36Sopenharmony_ci		gamma_base = gamma_def;
193662306a36Sopenharmony_ci		break;
193762306a36Sopenharmony_ci	}
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ci	val = sd->gamma->val;
194062306a36Sopenharmony_ci	for (i = 0; i < sizeof gamma; i++)
194162306a36Sopenharmony_ci		gamma[i] = gamma_base[i]
194262306a36Sopenharmony_ci			+ delta[i] * (val - GAMMA_DEF) / 32;
194362306a36Sopenharmony_ci	reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
194462306a36Sopenharmony_ci}
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_cistatic void setexposure(struct gspca_dev *gspca_dev)
194762306a36Sopenharmony_ci{
194862306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
195162306a36Sopenharmony_ci		u8 rexpo[] =		/* 1a: expo H, 1b: expo M */
195262306a36Sopenharmony_ci			{0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci		rexpo[3] = gspca_dev->exposure->val >> 8;
195562306a36Sopenharmony_ci		i2c_w8(gspca_dev, rexpo);
195662306a36Sopenharmony_ci		msleep(6);
195762306a36Sopenharmony_ci		rexpo[2] = 0x1b;
195862306a36Sopenharmony_ci		rexpo[3] = gspca_dev->exposure->val;
195962306a36Sopenharmony_ci		i2c_w8(gspca_dev, rexpo);
196062306a36Sopenharmony_ci	}
196162306a36Sopenharmony_ci}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev)
196462306a36Sopenharmony_ci{
196562306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	switch (sd->sensor) {
196862306a36Sopenharmony_ci	case SENSOR_OV7630:
196962306a36Sopenharmony_ci	case SENSOR_OV7648: {
197062306a36Sopenharmony_ci		u8 comb;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci		if (sd->sensor == SENSOR_OV7630)
197362306a36Sopenharmony_ci			comb = 0xc0;
197462306a36Sopenharmony_ci		else
197562306a36Sopenharmony_ci			comb = 0xa0;
197662306a36Sopenharmony_ci		if (gspca_dev->autogain->val)
197762306a36Sopenharmony_ci			comb |= 0x03;
197862306a36Sopenharmony_ci		i2c_w1(&sd->gspca_dev, 0x13, comb);
197962306a36Sopenharmony_ci		return;
198062306a36Sopenharmony_ci	    }
198162306a36Sopenharmony_ci	}
198262306a36Sopenharmony_ci	if (gspca_dev->autogain->val)
198362306a36Sopenharmony_ci		sd->ag_cnt = AG_CNT_START;
198462306a36Sopenharmony_ci	else
198562306a36Sopenharmony_ci		sd->ag_cnt = -1;
198662306a36Sopenharmony_ci}
198762306a36Sopenharmony_ci
198862306a36Sopenharmony_cistatic void setgain(struct gspca_dev *gspca_dev)
198962306a36Sopenharmony_ci{
199062306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
199362306a36Sopenharmony_ci		u8 rgain[] =		/* 15: gain */
199462306a36Sopenharmony_ci			{0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci		rgain[3] = gspca_dev->gain->val;
199762306a36Sopenharmony_ci		i2c_w8(gspca_dev, rgain);
199862306a36Sopenharmony_ci	}
199962306a36Sopenharmony_ci}
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_cistatic void sethvflip(struct gspca_dev *gspca_dev)
200262306a36Sopenharmony_ci{
200362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
200462306a36Sopenharmony_ci	u8 comn;
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	switch (sd->sensor) {
200762306a36Sopenharmony_ci	case SENSOR_HV7131R:
200862306a36Sopenharmony_ci		comn = 0x18;			/* clkdiv = 1, ablcen = 1 */
200962306a36Sopenharmony_ci		if (sd->vflip->val)
201062306a36Sopenharmony_ci			comn |= 0x01;
201162306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x01, comn);	/* sctra */
201262306a36Sopenharmony_ci		break;
201362306a36Sopenharmony_ci	case SENSOR_OV7630:
201462306a36Sopenharmony_ci		comn = 0x02;
201562306a36Sopenharmony_ci		if (!sd->vflip->val)
201662306a36Sopenharmony_ci			comn |= 0x80;
201762306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x75, comn);
201862306a36Sopenharmony_ci		break;
201962306a36Sopenharmony_ci	case SENSOR_OV7648:
202062306a36Sopenharmony_ci		comn = 0x06;
202162306a36Sopenharmony_ci		if (sd->vflip->val)
202262306a36Sopenharmony_ci			comn |= 0x80;
202362306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x75, comn);
202462306a36Sopenharmony_ci		break;
202562306a36Sopenharmony_ci	case SENSOR_PO2030N:
202662306a36Sopenharmony_ci		/* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
202762306a36Sopenharmony_ci		 * (reset value: 0x0A)
202862306a36Sopenharmony_ci		 * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
202962306a36Sopenharmony_ci		 * bit6: VM: Vertical Mirror: 0: disable, 1: enable
203062306a36Sopenharmony_ci		 * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
203162306a36Sopenharmony_ci		 * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
203262306a36Sopenharmony_ci		 * bit3-0: X
203362306a36Sopenharmony_ci		 */
203462306a36Sopenharmony_ci		comn = 0x0a;
203562306a36Sopenharmony_ci		if (sd->hflip->val)
203662306a36Sopenharmony_ci			comn |= 0x80;
203762306a36Sopenharmony_ci		if (sd->vflip->val)
203862306a36Sopenharmony_ci			comn |= 0x40;
203962306a36Sopenharmony_ci		i2c_w1(&sd->gspca_dev, 0x1e, comn);
204062306a36Sopenharmony_ci		break;
204162306a36Sopenharmony_ci	}
204262306a36Sopenharmony_ci}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_cistatic void setsharpness(struct gspca_dev *gspca_dev)
204562306a36Sopenharmony_ci{
204662306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x99, sd->sharpness->val);
204962306a36Sopenharmony_ci}
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_cistatic void setillum(struct gspca_dev *gspca_dev)
205262306a36Sopenharmony_ci{
205362306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci	switch (sd->sensor) {
205662306a36Sopenharmony_ci	case SENSOR_ADCM1700:
205762306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02,				/* gpio */
205862306a36Sopenharmony_ci			sd->illum->val ? 0x64 : 0x60);
205962306a36Sopenharmony_ci		break;
206062306a36Sopenharmony_ci	case SENSOR_MT9V111:
206162306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02,
206262306a36Sopenharmony_ci			sd->illum->val ? 0x77 : 0x74);
206362306a36Sopenharmony_ci/* should have been: */
206462306a36Sopenharmony_ci/*						0x55 : 0x54);	* 370i */
206562306a36Sopenharmony_ci/*						0x66 : 0x64);	* Clip */
206662306a36Sopenharmony_ci		break;
206762306a36Sopenharmony_ci	}
206862306a36Sopenharmony_ci}
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_cistatic void setfreq(struct gspca_dev *gspca_dev)
207162306a36Sopenharmony_ci{
207262306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	if (sd->sensor == SENSOR_OV7660) {
207562306a36Sopenharmony_ci		u8 com8;
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci		com8 = 0xdf;		/* auto gain/wb/expo */
207862306a36Sopenharmony_ci		switch (sd->freq->val) {
207962306a36Sopenharmony_ci		case 0: /* Banding filter disabled */
208062306a36Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8 | 0x20);
208162306a36Sopenharmony_ci			break;
208262306a36Sopenharmony_ci		case 1: /* 50 hz */
208362306a36Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8);
208462306a36Sopenharmony_ci			i2c_w1(gspca_dev, 0x3b, 0x0a);
208562306a36Sopenharmony_ci			break;
208662306a36Sopenharmony_ci		case 2: /* 60 hz */
208762306a36Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8);
208862306a36Sopenharmony_ci			i2c_w1(gspca_dev, 0x3b, 0x02);
208962306a36Sopenharmony_ci			break;
209062306a36Sopenharmony_ci		}
209162306a36Sopenharmony_ci	} else {
209262306a36Sopenharmony_ci		u8 reg2a = 0, reg2b = 0, reg2d = 0;
209362306a36Sopenharmony_ci
209462306a36Sopenharmony_ci		/* Get reg2a / reg2d base values */
209562306a36Sopenharmony_ci		switch (sd->sensor) {
209662306a36Sopenharmony_ci		case SENSOR_OV7630:
209762306a36Sopenharmony_ci			reg2a = 0x08;
209862306a36Sopenharmony_ci			reg2d = 0x01;
209962306a36Sopenharmony_ci			break;
210062306a36Sopenharmony_ci		case SENSOR_OV7648:
210162306a36Sopenharmony_ci			reg2a = 0x11;
210262306a36Sopenharmony_ci			reg2d = 0x81;
210362306a36Sopenharmony_ci			break;
210462306a36Sopenharmony_ci		}
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci		switch (sd->freq->val) {
210762306a36Sopenharmony_ci		case 0: /* Banding filter disabled */
210862306a36Sopenharmony_ci			break;
210962306a36Sopenharmony_ci		case 1: /* 50 hz (filter on and framerate adj) */
211062306a36Sopenharmony_ci			reg2a |= 0x80;
211162306a36Sopenharmony_ci			reg2b = 0xac;
211262306a36Sopenharmony_ci			reg2d |= 0x04;
211362306a36Sopenharmony_ci			break;
211462306a36Sopenharmony_ci		case 2: /* 60 hz (filter on, no framerate adj) */
211562306a36Sopenharmony_ci			reg2a |= 0x80;
211662306a36Sopenharmony_ci			reg2d |= 0x04;
211762306a36Sopenharmony_ci			break;
211862306a36Sopenharmony_ci		}
211962306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x2a, reg2a);
212062306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x2b, reg2b);
212162306a36Sopenharmony_ci		i2c_w1(gspca_dev, 0x2d, reg2d);
212262306a36Sopenharmony_ci	}
212362306a36Sopenharmony_ci}
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_cistatic void setjpegqual(struct gspca_dev *gspca_dev)
212662306a36Sopenharmony_ci{
212762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
213062306a36Sopenharmony_ci#if USB_BUF_SZ < 64
213162306a36Sopenharmony_ci#error "No room enough in usb_buf for quantization table"
213262306a36Sopenharmony_ci#endif
213362306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
213462306a36Sopenharmony_ci	usb_control_msg(gspca_dev->dev,
213562306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
213662306a36Sopenharmony_ci			0x08,
213762306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
213862306a36Sopenharmony_ci			0x0100, 0,
213962306a36Sopenharmony_ci			gspca_dev->usb_buf, 64,
214062306a36Sopenharmony_ci			500);
214162306a36Sopenharmony_ci	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
214262306a36Sopenharmony_ci	usb_control_msg(gspca_dev->dev,
214362306a36Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
214462306a36Sopenharmony_ci			0x08,
214562306a36Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
214662306a36Sopenharmony_ci			0x0140, 0,
214762306a36Sopenharmony_ci			gspca_dev->usb_buf, 64,
214862306a36Sopenharmony_ci			500);
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	sd->reg18 ^= 0x40;
215162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sd->reg18);
215262306a36Sopenharmony_ci}
215362306a36Sopenharmony_ci
215462306a36Sopenharmony_ci/* JPEG quality update */
215562306a36Sopenharmony_ci/* This function is executed from a work queue. */
215662306a36Sopenharmony_cistatic void qual_upd(struct work_struct *work)
215762306a36Sopenharmony_ci{
215862306a36Sopenharmony_ci	struct sd *sd = container_of(work, struct sd, work);
215962306a36Sopenharmony_ci	struct gspca_dev *gspca_dev = &sd->gspca_dev;
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci	/* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
216262306a36Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
216362306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "qual_upd %d%%\n", sd->quality);
216462306a36Sopenharmony_ci	gspca_dev->usb_err = 0;
216562306a36Sopenharmony_ci	setjpegqual(gspca_dev);
216662306a36Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
216762306a36Sopenharmony_ci}
216862306a36Sopenharmony_ci
216962306a36Sopenharmony_ci/* -- start the camera -- */
217062306a36Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
217162306a36Sopenharmony_ci{
217262306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
217362306a36Sopenharmony_ci	int i;
217462306a36Sopenharmony_ci	u8 reg01, reg17;
217562306a36Sopenharmony_ci	u8 reg0102[2];
217662306a36Sopenharmony_ci	const u8 *sn9c1xx;
217762306a36Sopenharmony_ci	const u8 (*init)[8];
217862306a36Sopenharmony_ci	const u8 *reg9a;
217962306a36Sopenharmony_ci	int mode;
218062306a36Sopenharmony_ci	static const u8 reg9a_def[] =
218162306a36Sopenharmony_ci		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
218262306a36Sopenharmony_ci	static const u8 reg9a_spec[] =
218362306a36Sopenharmony_ci		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
218462306a36Sopenharmony_ci	static const u8 regd4[] = {0x60, 0x00, 0x00};
218562306a36Sopenharmony_ci	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
218662306a36Sopenharmony_ci	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
218762306a36Sopenharmony_ci	static const u8 CA_adcm1700[] =
218862306a36Sopenharmony_ci				{ 0x14, 0xec, 0x0a, 0xf6 };
218962306a36Sopenharmony_ci	static const u8 CA_po2030n[] =
219062306a36Sopenharmony_ci				{ 0x1e, 0xe2, 0x14, 0xec };
219162306a36Sopenharmony_ci	static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
219262306a36Sopenharmony_ci	static const u8 CE_gc0307[] =
219362306a36Sopenharmony_ci				{ 0x32, 0xce, 0x2d, 0xd3 };
219462306a36Sopenharmony_ci	static const u8 CE_ov76xx[] =
219562306a36Sopenharmony_ci				{ 0x32, 0xdd, 0x32, 0xdd };
219662306a36Sopenharmony_ci	static const u8 CE_po2030n[] =
219762306a36Sopenharmony_ci				{ 0x14, 0xe7, 0x1e, 0xdd };
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci	/* create the JPEG header */
220062306a36Sopenharmony_ci	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
220162306a36Sopenharmony_ci			gspca_dev->pixfmt.width,
220262306a36Sopenharmony_ci			0x21);		/* JPEG 422 */
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	/* initialize the bridge */
220562306a36Sopenharmony_ci	sn9c1xx = sn_tb[sd->sensor];
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	/* sensor clock already enabled in sd_init */
220862306a36Sopenharmony_ci	/* reg_w1(gspca_dev, 0xf1, 0x00); */
220962306a36Sopenharmony_ci	reg01 = sn9c1xx[1];
221062306a36Sopenharmony_ci	if (sd->flags & F_PDN_INV)
221162306a36Sopenharmony_ci		reg01 ^= S_PDN_INV;		/* power down inverted */
221262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	/* configure gpio */
221562306a36Sopenharmony_ci	reg0102[0] = reg01;
221662306a36Sopenharmony_ci	reg0102[1] = sn9c1xx[2];
221762306a36Sopenharmony_ci	if (gspca_dev->audio)
221862306a36Sopenharmony_ci		reg0102[1] |= 0x04;	/* keep the audio connection */
221962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x01, reg0102, 2);
222062306a36Sopenharmony_ci	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
222162306a36Sopenharmony_ci	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
222262306a36Sopenharmony_ci	switch (sd->sensor) {
222362306a36Sopenharmony_ci	case SENSOR_GC0307:
222462306a36Sopenharmony_ci	case SENSOR_OV7660:
222562306a36Sopenharmony_ci	case SENSOR_PO1030:
222662306a36Sopenharmony_ci	case SENSOR_PO2030N:
222762306a36Sopenharmony_ci	case SENSOR_SOI768:
222862306a36Sopenharmony_ci	case SENSOR_SP80708:
222962306a36Sopenharmony_ci		reg9a = reg9a_spec;
223062306a36Sopenharmony_ci		break;
223162306a36Sopenharmony_ci	default:
223262306a36Sopenharmony_ci		reg9a = reg9a_def;
223362306a36Sopenharmony_ci		break;
223462306a36Sopenharmony_ci	}
223562306a36Sopenharmony_ci	reg_w(gspca_dev, 0x9a, reg9a, 6);
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ci	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_ci	reg17 = sn9c1xx[0x17];
224262306a36Sopenharmony_ci	switch (sd->sensor) {
224362306a36Sopenharmony_ci	case SENSOR_GC0307:
224462306a36Sopenharmony_ci		msleep(50);		/*fixme: is it useful? */
224562306a36Sopenharmony_ci		break;
224662306a36Sopenharmony_ci	case SENSOR_OM6802:
224762306a36Sopenharmony_ci		msleep(10);
224862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x73);
224962306a36Sopenharmony_ci		reg17 |= SEN_CLK_EN;
225062306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x17, reg17);
225162306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x22);
225262306a36Sopenharmony_ci		msleep(100);
225362306a36Sopenharmony_ci		reg01 = SCL_SEL_OD | S_PDN_INV;
225462306a36Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
225562306a36Sopenharmony_ci		reg17 |= 0x04;		/* clock / 4 */
225662306a36Sopenharmony_ci		break;
225762306a36Sopenharmony_ci	}
225862306a36Sopenharmony_ci	reg01 |= SYS_SEL_48M;
225962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
226062306a36Sopenharmony_ci	reg17 |= SEN_CLK_EN;
226162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
226262306a36Sopenharmony_ci	reg01 &= ~S_PWR_DN;		/* sensor power on */
226362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
226462306a36Sopenharmony_ci	reg01 &= ~SCL_SEL_OD;		/* remove open-drain mode */
226562306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
226662306a36Sopenharmony_ci
226762306a36Sopenharmony_ci	switch (sd->sensor) {
226862306a36Sopenharmony_ci	case SENSOR_HV7131R:
226962306a36Sopenharmony_ci		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */
227062306a36Sopenharmony_ci		break;
227162306a36Sopenharmony_ci	case SENSOR_OM6802:
227262306a36Sopenharmony_ci		msleep(10);
227362306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
227462306a36Sopenharmony_ci		i2c_w8(gspca_dev, om6802_init0[0]);
227562306a36Sopenharmony_ci		i2c_w8(gspca_dev, om6802_init0[1]);
227662306a36Sopenharmony_ci		msleep(15);
227762306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x71);
227862306a36Sopenharmony_ci		msleep(150);
227962306a36Sopenharmony_ci		break;
228062306a36Sopenharmony_ci	case SENSOR_SP80708:
228162306a36Sopenharmony_ci		msleep(100);
228262306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x62);
228362306a36Sopenharmony_ci		break;
228462306a36Sopenharmony_ci	}
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	/* initialize the sensor */
228762306a36Sopenharmony_ci	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
229062306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
229162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
229262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
229362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
229462306a36Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
229562306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xd2, 0x3a);	/* AE_H_SIZE = 116 */
229662306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xd3, 0x30);	/* AE_V_SIZE = 96 */
229762306a36Sopenharmony_ci	} else {
229862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xd2, 0x6a);	/* AE_H_SIZE = 212 */
229962306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xd3, 0x50);	/* AE_V_SIZE = 160 */
230062306a36Sopenharmony_ci	}
230162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0xc6, 0x00);
230262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0xc7, 0x00);
230362306a36Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
230462306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xc8, 0x2c);	/* AW_H_STOP = 352 */
230562306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xc9, 0x24);	/* AW_V_STOP = 288 */
230662306a36Sopenharmony_ci	} else {
230762306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xc8, 0x50);	/* AW_H_STOP = 640 */
230862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0xc9, 0x3c);	/* AW_V_STOP = 480 */
230962306a36Sopenharmony_ci	}
231062306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
231162306a36Sopenharmony_ci	switch (sd->sensor) {
231262306a36Sopenharmony_ci	case SENSOR_OM6802:
231362306a36Sopenharmony_ci/*	case SENSOR_OV7648:		* fixme: sometimes */
231462306a36Sopenharmony_ci		break;
231562306a36Sopenharmony_ci	default:
231662306a36Sopenharmony_ci		reg17 |= DEF_EN;
231762306a36Sopenharmony_ci		break;
231862306a36Sopenharmony_ci	}
231962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x05, 0x00);		/* red */
232262306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x07, 0x00);		/* green */
232362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x06, 0x00);		/* blue */
232462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
232562306a36Sopenharmony_ci
232662306a36Sopenharmony_ci	setgamma(gspca_dev);
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
232962306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
233062306a36Sopenharmony_ci		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
233162306a36Sopenharmony_ci	switch (sd->sensor) {
233262306a36Sopenharmony_ci	case SENSOR_ADCM1700:
233362306a36Sopenharmony_ci	case SENSOR_OV7660:
233462306a36Sopenharmony_ci	case SENSOR_SP80708:
233562306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x05);
233662306a36Sopenharmony_ci		break;
233762306a36Sopenharmony_ci	case SENSOR_GC0307:
233862306a36Sopenharmony_ci	case SENSOR_MT9V111:
233962306a36Sopenharmony_ci	case SENSOR_MI0360B:
234062306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x07);
234162306a36Sopenharmony_ci		break;
234262306a36Sopenharmony_ci	case SENSOR_OV7630:
234362306a36Sopenharmony_ci	case SENSOR_OV7648:
234462306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x0a);
234562306a36Sopenharmony_ci		break;
234662306a36Sopenharmony_ci	case SENSOR_PO2030N:
234762306a36Sopenharmony_ci	case SENSOR_SOI768:
234862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x06);
234962306a36Sopenharmony_ci		break;
235062306a36Sopenharmony_ci	default:
235162306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x08);
235262306a36Sopenharmony_ci		break;
235362306a36Sopenharmony_ci	}
235462306a36Sopenharmony_ci	setsharpness(gspca_dev);
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci	reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
235762306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x05, 0x20);		/* red */
235862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x07, 0x20);		/* green */
235962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x06, 0x20);		/* blue */
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	init = NULL;
236262306a36Sopenharmony_ci	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
236362306a36Sopenharmony_ci	reg01 |= SYS_SEL_48M | V_TX_EN;
236462306a36Sopenharmony_ci	reg17 &= ~MCK_SIZE_MASK;
236562306a36Sopenharmony_ci	reg17 |= 0x02;			/* clock / 2 */
236662306a36Sopenharmony_ci	switch (sd->sensor) {
236762306a36Sopenharmony_ci	case SENSOR_ADCM1700:
236862306a36Sopenharmony_ci		init = adcm1700_sensor_param1;
236962306a36Sopenharmony_ci		break;
237062306a36Sopenharmony_ci	case SENSOR_GC0307:
237162306a36Sopenharmony_ci		init = gc0307_sensor_param1;
237262306a36Sopenharmony_ci		break;
237362306a36Sopenharmony_ci	case SENSOR_HV7131R:
237462306a36Sopenharmony_ci	case SENSOR_MI0360:
237562306a36Sopenharmony_ci		if (!mode)
237662306a36Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
237762306a36Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
237862306a36Sopenharmony_ci		reg17 |= 0x01;			/* clock / 1 */
237962306a36Sopenharmony_ci		break;
238062306a36Sopenharmony_ci	case SENSOR_MI0360B:
238162306a36Sopenharmony_ci		init = mi0360b_sensor_param1;
238262306a36Sopenharmony_ci		break;
238362306a36Sopenharmony_ci	case SENSOR_MO4000:
238462306a36Sopenharmony_ci		if (mode) {			/* if 320x240 */
238562306a36Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
238662306a36Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
238762306a36Sopenharmony_ci			reg17 |= 0x01;		/* clock / 1 */
238862306a36Sopenharmony_ci		}
238962306a36Sopenharmony_ci		break;
239062306a36Sopenharmony_ci	case SENSOR_MT9V111:
239162306a36Sopenharmony_ci		init = mt9v111_sensor_param1;
239262306a36Sopenharmony_ci		break;
239362306a36Sopenharmony_ci	case SENSOR_OM6802:
239462306a36Sopenharmony_ci		init = om6802_sensor_param1;
239562306a36Sopenharmony_ci		if (!mode) {			/* if 640x480 */
239662306a36Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
239762306a36Sopenharmony_ci			reg17 |= 0x04;		/* clock / 4 */
239862306a36Sopenharmony_ci		} else {
239962306a36Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
240062306a36Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
240162306a36Sopenharmony_ci			reg17 |= 0x02;		/* clock / 2 */
240262306a36Sopenharmony_ci		}
240362306a36Sopenharmony_ci		break;
240462306a36Sopenharmony_ci	case SENSOR_OV7630:
240562306a36Sopenharmony_ci		init = ov7630_sensor_param1;
240662306a36Sopenharmony_ci		break;
240762306a36Sopenharmony_ci	case SENSOR_OV7648:
240862306a36Sopenharmony_ci		init = ov7648_sensor_param1;
240962306a36Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
241062306a36Sopenharmony_ci		reg17 |= 0x01;			/* clock / 1 */
241162306a36Sopenharmony_ci		break;
241262306a36Sopenharmony_ci	case SENSOR_OV7660:
241362306a36Sopenharmony_ci		init = ov7660_sensor_param1;
241462306a36Sopenharmony_ci		break;
241562306a36Sopenharmony_ci	case SENSOR_PO1030:
241662306a36Sopenharmony_ci		init = po1030_sensor_param1;
241762306a36Sopenharmony_ci		break;
241862306a36Sopenharmony_ci	case SENSOR_PO2030N:
241962306a36Sopenharmony_ci		init = po2030n_sensor_param1;
242062306a36Sopenharmony_ci		break;
242162306a36Sopenharmony_ci	case SENSOR_SOI768:
242262306a36Sopenharmony_ci		init = soi768_sensor_param1;
242362306a36Sopenharmony_ci		break;
242462306a36Sopenharmony_ci	case SENSOR_SP80708:
242562306a36Sopenharmony_ci		init = sp80708_sensor_param1;
242662306a36Sopenharmony_ci		break;
242762306a36Sopenharmony_ci	}
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_ci	/* more sensor initialization - param1 */
243062306a36Sopenharmony_ci	if (init != NULL) {
243162306a36Sopenharmony_ci		i2c_w_seq(gspca_dev, init);
243262306a36Sopenharmony_ci/*		init = NULL; */
243362306a36Sopenharmony_ci	}
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci	reg_w(gspca_dev, 0xc0, C0, 6);
243662306a36Sopenharmony_ci	switch (sd->sensor) {
243762306a36Sopenharmony_ci	case SENSOR_ADCM1700:
243862306a36Sopenharmony_ci	case SENSOR_GC0307:
243962306a36Sopenharmony_ci	case SENSOR_SOI768:
244062306a36Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
244162306a36Sopenharmony_ci		break;
244262306a36Sopenharmony_ci	case SENSOR_PO2030N:
244362306a36Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA_po2030n, 4);
244462306a36Sopenharmony_ci		break;
244562306a36Sopenharmony_ci	default:
244662306a36Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA, 4);
244762306a36Sopenharmony_ci		break;
244862306a36Sopenharmony_ci	}
244962306a36Sopenharmony_ci	switch (sd->sensor) {
245062306a36Sopenharmony_ci	case SENSOR_ADCM1700:
245162306a36Sopenharmony_ci	case SENSOR_OV7630:
245262306a36Sopenharmony_ci	case SENSOR_OV7648:
245362306a36Sopenharmony_ci	case SENSOR_OV7660:
245462306a36Sopenharmony_ci	case SENSOR_SOI768:
245562306a36Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
245662306a36Sopenharmony_ci		break;
245762306a36Sopenharmony_ci	case SENSOR_GC0307:
245862306a36Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_gc0307, 4);
245962306a36Sopenharmony_ci		break;
246062306a36Sopenharmony_ci	case SENSOR_PO2030N:
246162306a36Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_po2030n, 4);
246262306a36Sopenharmony_ci		break;
246362306a36Sopenharmony_ci	default:
246462306a36Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE, 4);
246562306a36Sopenharmony_ci					/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
246662306a36Sopenharmony_ci		break;
246762306a36Sopenharmony_ci	}
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_ci	/* here change size mode 0 -> VGA; 1 -> CIF */
247062306a36Sopenharmony_ci	sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
247162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sd->reg18);
247262306a36Sopenharmony_ci	setjpegqual(gspca_dev);
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
247562306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
247662306a36Sopenharmony_ci	sd->reg01 = reg01;
247762306a36Sopenharmony_ci	sd->reg17 = reg17;
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci	sd->pktsz = sd->npkt = 0;
248062306a36Sopenharmony_ci	sd->nchg = sd->short_mark = 0;
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci	return gspca_dev->usb_err;
248362306a36Sopenharmony_ci}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
248662306a36Sopenharmony_ci{
248762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
248862306a36Sopenharmony_ci	static const u8 stophv7131[] =
248962306a36Sopenharmony_ci		{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
249062306a36Sopenharmony_ci	static const u8 stopmi0360[] =
249162306a36Sopenharmony_ci		{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
249262306a36Sopenharmony_ci	static const u8 stopov7648[] =
249362306a36Sopenharmony_ci		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
249462306a36Sopenharmony_ci	static const u8 stopsoi768[] =
249562306a36Sopenharmony_ci		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
249662306a36Sopenharmony_ci	u8 reg01;
249762306a36Sopenharmony_ci	u8 reg17;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	reg01 = sd->reg01;
250062306a36Sopenharmony_ci	reg17 = sd->reg17 & ~SEN_CLK_EN;
250162306a36Sopenharmony_ci	switch (sd->sensor) {
250262306a36Sopenharmony_ci	case SENSOR_ADCM1700:
250362306a36Sopenharmony_ci	case SENSOR_GC0307:
250462306a36Sopenharmony_ci	case SENSOR_PO2030N:
250562306a36Sopenharmony_ci	case SENSOR_SP80708:
250662306a36Sopenharmony_ci		reg01 |= LED;
250762306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
250862306a36Sopenharmony_ci		reg01 &= ~(LED | V_TX_EN);
250962306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
251062306a36Sopenharmony_ci/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */
251162306a36Sopenharmony_ci		break;
251262306a36Sopenharmony_ci	case SENSOR_HV7131R:
251362306a36Sopenharmony_ci		reg01 &= ~V_TX_EN;
251462306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
251562306a36Sopenharmony_ci		i2c_w8(gspca_dev, stophv7131);
251662306a36Sopenharmony_ci		break;
251762306a36Sopenharmony_ci	case SENSOR_MI0360:
251862306a36Sopenharmony_ci	case SENSOR_MI0360B:
251962306a36Sopenharmony_ci		reg01 &= ~V_TX_EN;
252062306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
252162306a36Sopenharmony_ci/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */
252262306a36Sopenharmony_ci		i2c_w8(gspca_dev, stopmi0360);
252362306a36Sopenharmony_ci		break;
252462306a36Sopenharmony_ci	case SENSOR_MT9V111:
252562306a36Sopenharmony_ci	case SENSOR_OM6802:
252662306a36Sopenharmony_ci	case SENSOR_PO1030:
252762306a36Sopenharmony_ci		reg01 &= ~V_TX_EN;
252862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
252962306a36Sopenharmony_ci		break;
253062306a36Sopenharmony_ci	case SENSOR_OV7630:
253162306a36Sopenharmony_ci	case SENSOR_OV7648:
253262306a36Sopenharmony_ci		reg01 &= ~V_TX_EN;
253362306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
253462306a36Sopenharmony_ci		i2c_w8(gspca_dev, stopov7648);
253562306a36Sopenharmony_ci		break;
253662306a36Sopenharmony_ci	case SENSOR_OV7660:
253762306a36Sopenharmony_ci		reg01 &= ~V_TX_EN;
253862306a36Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
253962306a36Sopenharmony_ci		break;
254062306a36Sopenharmony_ci	case SENSOR_SOI768:
254162306a36Sopenharmony_ci		i2c_w8(gspca_dev, stopsoi768);
254262306a36Sopenharmony_ci		break;
254362306a36Sopenharmony_ci	}
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	reg01 |= SCL_SEL_OD;
254662306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
254762306a36Sopenharmony_ci	reg01 |= S_PWR_DN;		/* sensor power down */
254862306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
254962306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
255062306a36Sopenharmony_ci	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */
255162306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
255262306a36Sopenharmony_ci	reg01 |= LED;
255362306a36Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
255462306a36Sopenharmony_ci	/* Don't disable sensor clock as that disables the button on the cam */
255562306a36Sopenharmony_ci	/* reg_w1(gspca_dev, 0xf1, 0x01); */
255662306a36Sopenharmony_ci}
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */
255962306a36Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */
256062306a36Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
256162306a36Sopenharmony_ci{
256262306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
256362306a36Sopenharmony_ci
256462306a36Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
256562306a36Sopenharmony_ci	flush_work(&sd->work);
256662306a36Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
256762306a36Sopenharmony_ci}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev)
257062306a36Sopenharmony_ci{
257162306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
257262306a36Sopenharmony_ci	int delta;
257362306a36Sopenharmony_ci	int expotimes;
257462306a36Sopenharmony_ci	u8 luma_mean = 130;
257562306a36Sopenharmony_ci	u8 luma_delta = 20;
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci	/* Thanks S., without your advice, autobright should not work :) */
257862306a36Sopenharmony_ci	if (sd->ag_cnt < 0)
257962306a36Sopenharmony_ci		return;
258062306a36Sopenharmony_ci	if (--sd->ag_cnt >= 0)
258162306a36Sopenharmony_ci		return;
258262306a36Sopenharmony_ci	sd->ag_cnt = AG_CNT_START;
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_ci	delta = atomic_read(&sd->avg_lum);
258562306a36Sopenharmony_ci	gspca_dbg(gspca_dev, D_FRAM, "mean lum %d\n", delta);
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
258862306a36Sopenharmony_ci		gspca_expo_autogain(gspca_dev, delta, luma_mean, luma_delta,
258962306a36Sopenharmony_ci					15, 1024);
259062306a36Sopenharmony_ci		return;
259162306a36Sopenharmony_ci	}
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	if (delta < luma_mean - luma_delta ||
259462306a36Sopenharmony_ci	    delta > luma_mean + luma_delta) {
259562306a36Sopenharmony_ci		switch (sd->sensor) {
259662306a36Sopenharmony_ci		case SENSOR_GC0307:
259762306a36Sopenharmony_ci			expotimes = sd->exposure;
259862306a36Sopenharmony_ci			expotimes += (luma_mean - delta) >> 6;
259962306a36Sopenharmony_ci			if (expotimes < 0)
260062306a36Sopenharmony_ci				expotimes = 0;
260162306a36Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
260262306a36Sopenharmony_ci						   (unsigned int) expotimes);
260362306a36Sopenharmony_ci			break;
260462306a36Sopenharmony_ci		case SENSOR_HV7131R:
260562306a36Sopenharmony_ci			expotimes = sd->exposure >> 8;
260662306a36Sopenharmony_ci			expotimes += (luma_mean - delta) >> 4;
260762306a36Sopenharmony_ci			if (expotimes < 0)
260862306a36Sopenharmony_ci				expotimes = 0;
260962306a36Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
261062306a36Sopenharmony_ci					(unsigned int) (expotimes << 8));
261162306a36Sopenharmony_ci			break;
261262306a36Sopenharmony_ci		case SENSOR_OM6802:
261362306a36Sopenharmony_ci		case SENSOR_MT9V111:
261462306a36Sopenharmony_ci			expotimes = sd->exposure;
261562306a36Sopenharmony_ci			expotimes += (luma_mean - delta) >> 2;
261662306a36Sopenharmony_ci			if (expotimes < 0)
261762306a36Sopenharmony_ci				expotimes = 0;
261862306a36Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
261962306a36Sopenharmony_ci						   (unsigned int) expotimes);
262062306a36Sopenharmony_ci			setredblue(gspca_dev);
262162306a36Sopenharmony_ci			break;
262262306a36Sopenharmony_ci		default:
262362306a36Sopenharmony_ci/*		case SENSOR_MO4000: */
262462306a36Sopenharmony_ci/*		case SENSOR_MI0360: */
262562306a36Sopenharmony_ci/*		case SENSOR_MI0360B: */
262662306a36Sopenharmony_ci			expotimes = sd->exposure;
262762306a36Sopenharmony_ci			expotimes += (luma_mean - delta) >> 6;
262862306a36Sopenharmony_ci			if (expotimes < 0)
262962306a36Sopenharmony_ci				expotimes = 0;
263062306a36Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
263162306a36Sopenharmony_ci						   (unsigned int) expotimes);
263262306a36Sopenharmony_ci			setredblue(gspca_dev);
263362306a36Sopenharmony_ci			break;
263462306a36Sopenharmony_ci		}
263562306a36Sopenharmony_ci	}
263662306a36Sopenharmony_ci}
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci/* set the average luminosity from an isoc marker */
263962306a36Sopenharmony_cistatic void set_lum(struct sd *sd,
264062306a36Sopenharmony_ci		    u8 *data)
264162306a36Sopenharmony_ci{
264262306a36Sopenharmony_ci	int avg_lum;
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci	/*	w0 w1 w2
264562306a36Sopenharmony_ci	 *	w3 w4 w5
264662306a36Sopenharmony_ci	 *	w6 w7 w8
264762306a36Sopenharmony_ci	 */
264862306a36Sopenharmony_ci	avg_lum = (data[27] << 8) + data[28]		/* w3 */
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_ci		+ (data[31] << 8) + data[32]		/* w5 */
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci		+ (data[23] << 8) + data[24]		/* w1 */
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci		+ (data[35] << 8) + data[36]		/* w7 */
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci		+ (data[29] << 10) + (data[30] << 2);	/* w4 * 4 */
265762306a36Sopenharmony_ci	avg_lum >>= 10;
265862306a36Sopenharmony_ci	atomic_set(&sd->avg_lum, avg_lum);
265962306a36Sopenharmony_ci}
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci/* scan the URB packets */
266262306a36Sopenharmony_ci/* This function is run at interrupt level. */
266362306a36Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
266462306a36Sopenharmony_ci			u8 *data,			/* isoc packet */
266562306a36Sopenharmony_ci			int len)			/* iso packet length */
266662306a36Sopenharmony_ci{
266762306a36Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
266862306a36Sopenharmony_ci	int i, new_qual;
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci	/*
267162306a36Sopenharmony_ci	 * A frame ends on the marker
267262306a36Sopenharmony_ci	 *		ff ff 00 c4 c4 96 ..
267362306a36Sopenharmony_ci	 * which is 62 bytes long and is followed by various information
267462306a36Sopenharmony_ci	 * including statuses and luminosity.
267562306a36Sopenharmony_ci	 *
267662306a36Sopenharmony_ci	 * A marker may be split on two packets.
267762306a36Sopenharmony_ci	 *
267862306a36Sopenharmony_ci	 * The 6th byte of a marker contains the bits:
267962306a36Sopenharmony_ci	 *	0x08: USB full
268062306a36Sopenharmony_ci	 *	0xc0: frame sequence
268162306a36Sopenharmony_ci	 * When the bit 'USB full' is set, the frame must be discarded;
268262306a36Sopenharmony_ci	 * this is also the case when the 2 bytes before the marker are
268362306a36Sopenharmony_ci	 * not the JPEG end of frame ('ff d9').
268462306a36Sopenharmony_ci	 */
268562306a36Sopenharmony_ci
268662306a36Sopenharmony_ci	/* count the packets and their size */
268762306a36Sopenharmony_ci	sd->npkt++;
268862306a36Sopenharmony_ci	sd->pktsz += len;
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci/*fixme: assumption about the following code:
269162306a36Sopenharmony_ci *	- there can be only one marker in a packet
269262306a36Sopenharmony_ci */
269362306a36Sopenharmony_ci
269462306a36Sopenharmony_ci	/* skip the remaining bytes of a short marker */
269562306a36Sopenharmony_ci	i = sd->short_mark;
269662306a36Sopenharmony_ci	if (i != 0) {
269762306a36Sopenharmony_ci		sd->short_mark = 0;
269862306a36Sopenharmony_ci		if (i < 0	/* if 'ff' at end of previous packet */
269962306a36Sopenharmony_ci		 && data[0] == 0xff
270062306a36Sopenharmony_ci		 && data[1] == 0x00)
270162306a36Sopenharmony_ci			goto marker_found;
270262306a36Sopenharmony_ci		if (data[0] == 0xff && data[1] == 0xff) {
270362306a36Sopenharmony_ci			i = 0;
270462306a36Sopenharmony_ci			goto marker_found;
270562306a36Sopenharmony_ci		}
270662306a36Sopenharmony_ci		len -= i;
270762306a36Sopenharmony_ci		if (len <= 0)
270862306a36Sopenharmony_ci			return;
270962306a36Sopenharmony_ci		data += i;
271062306a36Sopenharmony_ci	}
271162306a36Sopenharmony_ci
271262306a36Sopenharmony_ci	/* search backwards if there is a marker in the packet */
271362306a36Sopenharmony_ci	for (i = len - 1; --i >= 0; ) {
271462306a36Sopenharmony_ci		if (data[i] != 0xff) {
271562306a36Sopenharmony_ci			i--;
271662306a36Sopenharmony_ci			continue;
271762306a36Sopenharmony_ci		}
271862306a36Sopenharmony_ci		if (data[i + 1] == 0xff) {
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci			/* (there may be 'ff ff' inside a marker) */
272162306a36Sopenharmony_ci			if (i + 2 >= len || data[i + 2] == 0x00)
272262306a36Sopenharmony_ci				goto marker_found;
272362306a36Sopenharmony_ci		}
272462306a36Sopenharmony_ci	}
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	/* no marker found */
272762306a36Sopenharmony_ci	/* add the JPEG header if first fragment */
272862306a36Sopenharmony_ci	if (data[len - 1] == 0xff)
272962306a36Sopenharmony_ci		sd->short_mark = -1;
273062306a36Sopenharmony_ci	if (gspca_dev->last_packet_type == LAST_PACKET)
273162306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET,
273262306a36Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
273362306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
273462306a36Sopenharmony_ci	return;
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	/* marker found */
273762306a36Sopenharmony_ci	/* if some error, discard the frame and decrease the quality */
273862306a36Sopenharmony_cimarker_found:
273962306a36Sopenharmony_ci	new_qual = 0;
274062306a36Sopenharmony_ci	if (i > 2) {
274162306a36Sopenharmony_ci		if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
274262306a36Sopenharmony_ci			gspca_dev->last_packet_type = DISCARD_PACKET;
274362306a36Sopenharmony_ci			new_qual = -3;
274462306a36Sopenharmony_ci		}
274562306a36Sopenharmony_ci	} else if (i + 6 < len) {
274662306a36Sopenharmony_ci		if (data[i + 6] & 0x08) {
274762306a36Sopenharmony_ci			gspca_dev->last_packet_type = DISCARD_PACKET;
274862306a36Sopenharmony_ci			new_qual = -5;
274962306a36Sopenharmony_ci		}
275062306a36Sopenharmony_ci	}
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci	gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci	/* compute the filling rate and a new JPEG quality */
275562306a36Sopenharmony_ci	if (new_qual == 0) {
275662306a36Sopenharmony_ci		int r;
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci		r = (sd->pktsz * 100) /
275962306a36Sopenharmony_ci			(sd->npkt *
276062306a36Sopenharmony_ci				gspca_dev->urb[0]->iso_frame_desc[0].length);
276162306a36Sopenharmony_ci		if (r >= 85)
276262306a36Sopenharmony_ci			new_qual = -3;
276362306a36Sopenharmony_ci		else if (r < 75)
276462306a36Sopenharmony_ci			new_qual = 2;
276562306a36Sopenharmony_ci	}
276662306a36Sopenharmony_ci	if (new_qual != 0) {
276762306a36Sopenharmony_ci		sd->nchg += new_qual;
276862306a36Sopenharmony_ci		if (sd->nchg < -6 || sd->nchg >= 12) {
276962306a36Sopenharmony_ci			sd->nchg = 0;
277062306a36Sopenharmony_ci			new_qual += sd->quality;
277162306a36Sopenharmony_ci			if (new_qual < QUALITY_MIN)
277262306a36Sopenharmony_ci				new_qual = QUALITY_MIN;
277362306a36Sopenharmony_ci			else if (new_qual > QUALITY_MAX)
277462306a36Sopenharmony_ci				new_qual = QUALITY_MAX;
277562306a36Sopenharmony_ci			if (new_qual != sd->quality) {
277662306a36Sopenharmony_ci				sd->quality = new_qual;
277762306a36Sopenharmony_ci				schedule_work(&sd->work);
277862306a36Sopenharmony_ci			}
277962306a36Sopenharmony_ci		}
278062306a36Sopenharmony_ci	} else {
278162306a36Sopenharmony_ci		sd->nchg = 0;
278262306a36Sopenharmony_ci	}
278362306a36Sopenharmony_ci	sd->pktsz = sd->npkt = 0;
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	/* if the marker is smaller than 62 bytes,
278662306a36Sopenharmony_ci	 * memorize the number of bytes to skip in the next packet */
278762306a36Sopenharmony_ci	if (i + 62 > len) {			/* no more usable data */
278862306a36Sopenharmony_ci		sd->short_mark = i + 62 - len;
278962306a36Sopenharmony_ci		return;
279062306a36Sopenharmony_ci	}
279162306a36Sopenharmony_ci	if (sd->ag_cnt >= 0)
279262306a36Sopenharmony_ci		set_lum(sd, data + i);
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci	/* if more data, start a new frame */
279562306a36Sopenharmony_ci	i += 62;
279662306a36Sopenharmony_ci	if (i < len) {
279762306a36Sopenharmony_ci		data += i;
279862306a36Sopenharmony_ci		len -= i;
279962306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET,
280062306a36Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
280162306a36Sopenharmony_ci		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
280262306a36Sopenharmony_ci	}
280362306a36Sopenharmony_ci}
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
280662306a36Sopenharmony_ci{
280762306a36Sopenharmony_ci	struct gspca_dev *gspca_dev =
280862306a36Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	gspca_dev->usb_err = 0;
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	if (!gspca_dev->streaming)
281362306a36Sopenharmony_ci		return 0;
281462306a36Sopenharmony_ci
281562306a36Sopenharmony_ci	switch (ctrl->id) {
281662306a36Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
281762306a36Sopenharmony_ci		setbrightness(gspca_dev);
281862306a36Sopenharmony_ci		break;
281962306a36Sopenharmony_ci	case V4L2_CID_CONTRAST:
282062306a36Sopenharmony_ci		setcontrast(gspca_dev);
282162306a36Sopenharmony_ci		break;
282262306a36Sopenharmony_ci	case V4L2_CID_SATURATION:
282362306a36Sopenharmony_ci		setcolors(gspca_dev);
282462306a36Sopenharmony_ci		break;
282562306a36Sopenharmony_ci	case V4L2_CID_RED_BALANCE:
282662306a36Sopenharmony_ci		setredblue(gspca_dev);
282762306a36Sopenharmony_ci		break;
282862306a36Sopenharmony_ci	case V4L2_CID_GAMMA:
282962306a36Sopenharmony_ci		setgamma(gspca_dev);
283062306a36Sopenharmony_ci		break;
283162306a36Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
283262306a36Sopenharmony_ci		setautogain(gspca_dev);
283362306a36Sopenharmony_ci		setexposure(gspca_dev);
283462306a36Sopenharmony_ci		setgain(gspca_dev);
283562306a36Sopenharmony_ci		break;
283662306a36Sopenharmony_ci	case V4L2_CID_VFLIP:
283762306a36Sopenharmony_ci		sethvflip(gspca_dev);
283862306a36Sopenharmony_ci		break;
283962306a36Sopenharmony_ci	case V4L2_CID_SHARPNESS:
284062306a36Sopenharmony_ci		setsharpness(gspca_dev);
284162306a36Sopenharmony_ci		break;
284262306a36Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_1:
284362306a36Sopenharmony_ci		setillum(gspca_dev);
284462306a36Sopenharmony_ci		break;
284562306a36Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:
284662306a36Sopenharmony_ci		setfreq(gspca_dev);
284762306a36Sopenharmony_ci		break;
284862306a36Sopenharmony_ci	default:
284962306a36Sopenharmony_ci		return -EINVAL;
285062306a36Sopenharmony_ci	}
285162306a36Sopenharmony_ci	return gspca_dev->usb_err;
285262306a36Sopenharmony_ci}
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
285562306a36Sopenharmony_cistatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
285662306a36Sopenharmony_ci			u8 *data,		/* interrupt packet data */
285762306a36Sopenharmony_ci			int len)		/* interrupt packet length */
285862306a36Sopenharmony_ci{
285962306a36Sopenharmony_ci	int ret = -EINVAL;
286062306a36Sopenharmony_ci
286162306a36Sopenharmony_ci	if (len == 1 && data[0] == 1) {
286262306a36Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
286362306a36Sopenharmony_ci		input_sync(gspca_dev->input_dev);
286462306a36Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
286562306a36Sopenharmony_ci		input_sync(gspca_dev->input_dev);
286662306a36Sopenharmony_ci		ret = 0;
286762306a36Sopenharmony_ci	}
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci	return ret;
287062306a36Sopenharmony_ci}
287162306a36Sopenharmony_ci#endif
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_ci/* sub-driver description */
287462306a36Sopenharmony_cistatic const struct sd_desc sd_desc = {
287562306a36Sopenharmony_ci	.name = MODULE_NAME,
287662306a36Sopenharmony_ci	.config = sd_config,
287762306a36Sopenharmony_ci	.init = sd_init,
287862306a36Sopenharmony_ci	.init_controls = sd_init_controls,
287962306a36Sopenharmony_ci	.start = sd_start,
288062306a36Sopenharmony_ci	.stopN = sd_stopN,
288162306a36Sopenharmony_ci	.stop0 = sd_stop0,
288262306a36Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
288362306a36Sopenharmony_ci	.dq_callback = do_autogain,
288462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
288562306a36Sopenharmony_ci	.int_pkt_scan = sd_int_pkt_scan,
288662306a36Sopenharmony_ci#endif
288762306a36Sopenharmony_ci};
288862306a36Sopenharmony_ci
288962306a36Sopenharmony_ci/* -- module initialisation -- */
289062306a36Sopenharmony_ci#define BS(bridge, sensor) \
289162306a36Sopenharmony_ci	.driver_info = (BRIDGE_ ## bridge << 16) \
289262306a36Sopenharmony_ci			| (SENSOR_ ## sensor << 8)
289362306a36Sopenharmony_ci#define BSF(bridge, sensor, flags) \
289462306a36Sopenharmony_ci	.driver_info = (BRIDGE_ ## bridge << 16) \
289562306a36Sopenharmony_ci			| (SENSOR_ ## sensor << 8) \
289662306a36Sopenharmony_ci			| (flags)
289762306a36Sopenharmony_cistatic const struct usb_device_id device_table[] = {
289862306a36Sopenharmony_ci	{USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)},
289962306a36Sopenharmony_ci	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
290062306a36Sopenharmony_ci	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
290162306a36Sopenharmony_ci	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
290262306a36Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
290362306a36Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
290462306a36Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
290562306a36Sopenharmony_ci	{USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
290662306a36Sopenharmony_ci	{USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
290762306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
290862306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
290962306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
291062306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
291162306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
291262306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
291362306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
291462306a36Sopenharmony_ci						/* or MT9V111 */
291562306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
291662306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
291762306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
291862306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
291962306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
292062306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
292162306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
292262306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
292362306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
292462306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
292562306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
292662306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},	/*sn9c128*/
292762306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},	/* /GC0305*/
292862306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
292962306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},	/*sn9c128*/
293062306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},	/*sn9c128*/
293162306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)},	/*sn9c128*/
293262306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)},	/*sn9c128*/
293362306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
293462306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
293562306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
293662306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)},	/*sn9c325?*/
293762306a36Sopenharmony_ci/*bw600.inf:*/
293862306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)},	/*sn9c325?*/
293962306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
294062306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
294162306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
294262306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
294362306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
294462306a36Sopenharmony_ci						/* or MT9V111 / MI0360B */
294562306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
294662306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
294762306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
294862306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
294962306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
295062306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
295162306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},	/*sn9c120b*/
295262306a36Sopenharmony_ci						/* or GC0305 / GC0307 */
295362306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},	/*sn9c120b*/
295462306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},	/*sn9c120b*/
295562306a36Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
295662306a36Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */	/*sn9c120b*/
295762306a36Sopenharmony_ci	{}
295862306a36Sopenharmony_ci};
295962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_ci/* -- device connect -- */
296262306a36Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
296362306a36Sopenharmony_ci		    const struct usb_device_id *id)
296462306a36Sopenharmony_ci{
296562306a36Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
296662306a36Sopenharmony_ci				THIS_MODULE);
296762306a36Sopenharmony_ci}
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_cistatic struct usb_driver sd_driver = {
297062306a36Sopenharmony_ci	.name = MODULE_NAME,
297162306a36Sopenharmony_ci	.id_table = device_table,
297262306a36Sopenharmony_ci	.probe = sd_probe,
297362306a36Sopenharmony_ci	.disconnect = gspca_disconnect,
297462306a36Sopenharmony_ci#ifdef CONFIG_PM
297562306a36Sopenharmony_ci	.suspend = gspca_suspend,
297662306a36Sopenharmony_ci	.resume = gspca_resume,
297762306a36Sopenharmony_ci	.reset_resume = gspca_resume,
297862306a36Sopenharmony_ci#endif
297962306a36Sopenharmony_ci};
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_cimodule_usb_driver(sd_driver);
2982