18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
68c2ecf20Sopenharmony_ci * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define MODULE_NAME "sonixj"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/input.h>
148c2ecf20Sopenharmony_ci#include "gspca.h"
158c2ecf20Sopenharmony_ci#include "jpeg.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
188c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
198c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/* specific webcam descriptor */
228c2ecf20Sopenharmony_cistruct sd {
238c2ecf20Sopenharmony_ci	struct gspca_dev gspca_dev;	/* !! must be the first item */
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	atomic_t avg_lum;
268c2ecf20Sopenharmony_ci	struct v4l2_ctrl *brightness;
278c2ecf20Sopenharmony_ci	struct v4l2_ctrl *contrast;
288c2ecf20Sopenharmony_ci	struct v4l2_ctrl *saturation;
298c2ecf20Sopenharmony_ci	struct { /* red/blue balance control cluster */
308c2ecf20Sopenharmony_ci		struct v4l2_ctrl *red_bal;
318c2ecf20Sopenharmony_ci		struct v4l2_ctrl *blue_bal;
328c2ecf20Sopenharmony_ci	};
338c2ecf20Sopenharmony_ci	struct { /* hflip/vflip control cluster */
348c2ecf20Sopenharmony_ci		struct v4l2_ctrl *vflip;
358c2ecf20Sopenharmony_ci		struct v4l2_ctrl *hflip;
368c2ecf20Sopenharmony_ci	};
378c2ecf20Sopenharmony_ci	struct v4l2_ctrl *gamma;
388c2ecf20Sopenharmony_ci	struct v4l2_ctrl *illum;
398c2ecf20Sopenharmony_ci	struct v4l2_ctrl *sharpness;
408c2ecf20Sopenharmony_ci	struct v4l2_ctrl *freq;
418c2ecf20Sopenharmony_ci	u32 exposure;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	struct work_struct work;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci	u32 pktsz;			/* (used by pkt_scan) */
468c2ecf20Sopenharmony_ci	u16 npkt;
478c2ecf20Sopenharmony_ci	s8 nchg;
488c2ecf20Sopenharmony_ci	s8 short_mark;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	u8 quality;			/* image quality */
518c2ecf20Sopenharmony_ci#define QUALITY_MIN 25
528c2ecf20Sopenharmony_ci#define QUALITY_MAX 90
538c2ecf20Sopenharmony_ci#define QUALITY_DEF 70
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	u8 reg01;
568c2ecf20Sopenharmony_ci	u8 reg17;
578c2ecf20Sopenharmony_ci	u8 reg18;
588c2ecf20Sopenharmony_ci	u8 flags;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	s8 ag_cnt;
618c2ecf20Sopenharmony_ci#define AG_CNT_START 13
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	u8 bridge;
648c2ecf20Sopenharmony_ci#define BRIDGE_SN9C102P 0
658c2ecf20Sopenharmony_ci#define BRIDGE_SN9C105 1
668c2ecf20Sopenharmony_ci#define BRIDGE_SN9C110 2
678c2ecf20Sopenharmony_ci#define BRIDGE_SN9C120 3
688c2ecf20Sopenharmony_ci	u8 sensor;			/* Type of image sensor chip */
698c2ecf20Sopenharmony_ci	u8 i2c_addr;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	u8 jpeg_hdr[JPEG_HDR_SZ];
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_cienum sensors {
748c2ecf20Sopenharmony_ci	SENSOR_ADCM1700,
758c2ecf20Sopenharmony_ci	SENSOR_GC0307,
768c2ecf20Sopenharmony_ci	SENSOR_HV7131R,
778c2ecf20Sopenharmony_ci	SENSOR_MI0360,
788c2ecf20Sopenharmony_ci	SENSOR_MI0360B,
798c2ecf20Sopenharmony_ci	SENSOR_MO4000,
808c2ecf20Sopenharmony_ci	SENSOR_MT9V111,
818c2ecf20Sopenharmony_ci	SENSOR_OM6802,
828c2ecf20Sopenharmony_ci	SENSOR_OV7630,
838c2ecf20Sopenharmony_ci	SENSOR_OV7648,
848c2ecf20Sopenharmony_ci	SENSOR_OV7660,
858c2ecf20Sopenharmony_ci	SENSOR_PO1030,
868c2ecf20Sopenharmony_ci	SENSOR_PO2030N,
878c2ecf20Sopenharmony_ci	SENSOR_SOI768,
888c2ecf20Sopenharmony_ci	SENSOR_SP80708,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic void qual_upd(struct work_struct *work);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* device flags */
948c2ecf20Sopenharmony_ci#define F_PDN_INV	0x01	/* inverse pin S_PWR_DN / sn_xxx tables */
958c2ecf20Sopenharmony_ci#define F_ILLUM		0x02	/* presence of illuminator */
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/* sn9c1xx definitions */
988c2ecf20Sopenharmony_ci/* register 0x01 */
998c2ecf20Sopenharmony_ci#define S_PWR_DN	0x01	/* sensor power down */
1008c2ecf20Sopenharmony_ci#define S_PDN_INV	0x02	/* inverse pin S_PWR_DN */
1018c2ecf20Sopenharmony_ci#define V_TX_EN		0x04	/* video transfer enable */
1028c2ecf20Sopenharmony_ci#define LED		0x08	/* output to pin LED */
1038c2ecf20Sopenharmony_ci#define SCL_SEL_OD	0x20	/* open-drain mode */
1048c2ecf20Sopenharmony_ci#define SYS_SEL_48M	0x40	/* system clock 0: 24MHz, 1: 48MHz */
1058c2ecf20Sopenharmony_ci/* register 0x17 */
1068c2ecf20Sopenharmony_ci#define MCK_SIZE_MASK	0x1f	/* sensor master clock */
1078c2ecf20Sopenharmony_ci#define SEN_CLK_EN	0x20	/* enable sensor clock */
1088c2ecf20Sopenharmony_ci#define DEF_EN		0x80	/* defect pixel by 0: soft, 1: hard */
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format cif_mode[] = {
1118c2ecf20Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1128c2ecf20Sopenharmony_ci		.bytesperline = 352,
1138c2ecf20Sopenharmony_ci		.sizeimage = 352 * 288 * 4 / 8 + 590,
1148c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1158c2ecf20Sopenharmony_ci		.priv = 0},
1168c2ecf20Sopenharmony_ci};
1178c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
1188c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1198c2ecf20Sopenharmony_ci		.bytesperline = 160,
1208c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120 * 4 / 8 + 590,
1218c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1228c2ecf20Sopenharmony_ci		.priv = 2},
1238c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1248c2ecf20Sopenharmony_ci		.bytesperline = 320,
1258c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 8 + 590,
1268c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1278c2ecf20Sopenharmony_ci		.priv = 1},
1288c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1298c2ecf20Sopenharmony_ci		.bytesperline = 640,
1308c2ecf20Sopenharmony_ci		/* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
1318c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 4 + 590,
1328c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1338c2ecf20Sopenharmony_ci		.priv = 0},
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic const u8 sn_adcm1700[0x1c] = {
1378c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1388c2ecf20Sopenharmony_ci	0x00,	0x43,	0x60,	0x00,	0x1a,	0x00,	0x00,	0x00,
1398c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1408c2ecf20Sopenharmony_ci	0x80,	0x51,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1418c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1428c2ecf20Sopenharmony_ci	0x03,	0x00,	0x05,	0x01,	0x05,	0x16,	0x12,	0x42,
1438c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1448c2ecf20Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
1458c2ecf20Sopenharmony_ci};
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic const u8 sn_gc0307[0x1c] = {
1488c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1498c2ecf20Sopenharmony_ci	0x00,	0x61,	0x62,	0x00,	0x1a,	0x00,	0x00,	0x00,
1508c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1518c2ecf20Sopenharmony_ci	0x80,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1528c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1538c2ecf20Sopenharmony_ci	0x03,	0x00,	0x03,	0x01,	0x08,	0x28,	0x1e,	0x02,
1548c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1558c2ecf20Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
1568c2ecf20Sopenharmony_ci};
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistatic const u8 sn_hv7131[0x1c] = {
1598c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1608c2ecf20Sopenharmony_ci	0x00,	0x03,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
1618c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1628c2ecf20Sopenharmony_ci	0x81,	0x11,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1638c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1648c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x03,	0x28,	0x1e,	0x41,
1658c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1668c2ecf20Sopenharmony_ci	0x0a,	0x00,	0x00,	0x00
1678c2ecf20Sopenharmony_ci};
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic const u8 sn_mi0360[0x1c] = {
1708c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1718c2ecf20Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
1728c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1738c2ecf20Sopenharmony_ci	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1748c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1758c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x61,
1768c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1778c2ecf20Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic const u8 sn_mi0360b[0x1c] = {
1818c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1828c2ecf20Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
1838c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1848c2ecf20Sopenharmony_ci	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1858c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1868c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x0a,	0x28,	0x1e,	0x40,
1878c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1888c2ecf20Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
1898c2ecf20Sopenharmony_ci};
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic const u8 sn_mo4000[0x1c] = {
1928c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
1938c2ecf20Sopenharmony_ci	0x00,	0x23,	0x60,	0x00,	0x1a,	0x00,	0x20,	0x18,
1948c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
1958c2ecf20Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
1968c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
1978c2ecf20Sopenharmony_ci	0x03,	 0x00,	0x0b,	0x0f,	0x14,	0x28,	0x1e,	0x40,
1988c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
1998c2ecf20Sopenharmony_ci	0x08,	0x00,	0x00,	0x00
2008c2ecf20Sopenharmony_ci};
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic const u8 sn_mt9v111[0x1c] = {
2038c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2048c2ecf20Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
2058c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2068c2ecf20Sopenharmony_ci	0x81,	0x5c,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2078c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2088c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x02,	0x1c,	0x28,	0x1e,	0x40,
2098c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2108c2ecf20Sopenharmony_ci	0x06,	0x00,	0x00,	0x00
2118c2ecf20Sopenharmony_ci};
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic const u8 sn_om6802[0x1c] = {
2148c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2158c2ecf20Sopenharmony_ci	0x00,	0x23,	0x72,	0x00,	0x1a,	0x20,	0x20,	0x19,
2168c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2178c2ecf20Sopenharmony_ci	0x80,	0x34,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2188c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2198c2ecf20Sopenharmony_ci	0x03,	0x00,	0x51,	0x01,	0x00,	0x28,	0x1e,	0x40,
2208c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2218c2ecf20Sopenharmony_ci	0x05,	0x00,	0x00,	0x00
2228c2ecf20Sopenharmony_ci};
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic const u8 sn_ov7630[0x1c] = {
2258c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2268c2ecf20Sopenharmony_ci	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
2278c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2288c2ecf20Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2298c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2308c2ecf20Sopenharmony_ci	0x03,	0x00,	0x04,	0x01,	0x0a,	0x28,	0x1e,	0xc2,
2318c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2328c2ecf20Sopenharmony_ci	0x0b,	0x00,	0x00,	0x00
2338c2ecf20Sopenharmony_ci};
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic const u8 sn_ov7648[0x1c] = {
2368c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2378c2ecf20Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
2388c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2398c2ecf20Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2408c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2418c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x00,	0x28,	0x1e,	0x00,
2428c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2438c2ecf20Sopenharmony_ci	0x0b,	0x00,	0x00,	0x00
2448c2ecf20Sopenharmony_ci};
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic const u8 sn_ov7660[0x1c] = {
2478c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2488c2ecf20Sopenharmony_ci	0x00,	0x61,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
2498c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2508c2ecf20Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2518c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2528c2ecf20Sopenharmony_ci	0x03,	0x00,	0x01,	0x01,	0x08,	0x28,	0x1e,	0x20,
2538c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2548c2ecf20Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
2558c2ecf20Sopenharmony_ci};
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cistatic const u8 sn_po1030[0x1c] = {
2588c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2598c2ecf20Sopenharmony_ci	0x00,	0x21,	0x62,	0x00,	0x1a,	0x20,	0x20,	0x20,
2608c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2618c2ecf20Sopenharmony_ci	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2628c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2638c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x06,	0x06,	0x28,	0x1e,	0x00,
2648c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2658c2ecf20Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
2668c2ecf20Sopenharmony_ci};
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic const u8 sn_po2030n[0x1c] = {
2698c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2708c2ecf20Sopenharmony_ci	0x00,	0x63,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
2718c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2728c2ecf20Sopenharmony_ci	0x81,	0x6e,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2738c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2748c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x14,	0x28,	0x1e,	0x00,
2758c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2768c2ecf20Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
2778c2ecf20Sopenharmony_ci};
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_cistatic const u8 sn_soi768[0x1c] = {
2808c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2818c2ecf20Sopenharmony_ci	0x00,	0x21,	0x40,	0x00,	0x1a,	0x00,	0x00,	0x00,
2828c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2838c2ecf20Sopenharmony_ci	0x81,	0x21,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2848c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2858c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x01,	0x08,	0x28,	0x1e,	0x00,
2868c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2878c2ecf20Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistatic const u8 sn_sp80708[0x1c] = {
2918c2ecf20Sopenharmony_ci/*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
2928c2ecf20Sopenharmony_ci	0x00,	0x63,	0x60,	0x00,	0x1a,	0x20,	0x20,	0x20,
2938c2ecf20Sopenharmony_ci/*	reg8	reg9	rega	regb	regc	regd	rege	regf */
2948c2ecf20Sopenharmony_ci	0x81,	0x18,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
2958c2ecf20Sopenharmony_ci/*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
2968c2ecf20Sopenharmony_ci	0x03,	0x00,	0x00,	0x03,	0x04,	0x28,	0x1e,	0x00,
2978c2ecf20Sopenharmony_ci/*	reg18	reg19	reg1a	reg1b */
2988c2ecf20Sopenharmony_ci	0x07,	0x00,	0x00,	0x00
2998c2ecf20Sopenharmony_ci};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci/* sequence specific to the sensors - !! index = SENSOR_xxx */
3028c2ecf20Sopenharmony_cistatic const u8 *sn_tb[] = {
3038c2ecf20Sopenharmony_ci[SENSOR_ADCM1700] =	sn_adcm1700,
3048c2ecf20Sopenharmony_ci[SENSOR_GC0307] =	sn_gc0307,
3058c2ecf20Sopenharmony_ci[SENSOR_HV7131R] =	sn_hv7131,
3068c2ecf20Sopenharmony_ci[SENSOR_MI0360] =	sn_mi0360,
3078c2ecf20Sopenharmony_ci[SENSOR_MI0360B] =	sn_mi0360b,
3088c2ecf20Sopenharmony_ci[SENSOR_MO4000] =	sn_mo4000,
3098c2ecf20Sopenharmony_ci[SENSOR_MT9V111] =	sn_mt9v111,
3108c2ecf20Sopenharmony_ci[SENSOR_OM6802] =	sn_om6802,
3118c2ecf20Sopenharmony_ci[SENSOR_OV7630] =	sn_ov7630,
3128c2ecf20Sopenharmony_ci[SENSOR_OV7648] =	sn_ov7648,
3138c2ecf20Sopenharmony_ci[SENSOR_OV7660] =	sn_ov7660,
3148c2ecf20Sopenharmony_ci[SENSOR_PO1030] =	sn_po1030,
3158c2ecf20Sopenharmony_ci[SENSOR_PO2030N] =	sn_po2030n,
3168c2ecf20Sopenharmony_ci[SENSOR_SOI768] =	sn_soi768,
3178c2ecf20Sopenharmony_ci[SENSOR_SP80708] =	sn_sp80708,
3188c2ecf20Sopenharmony_ci};
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci/* default gamma table */
3218c2ecf20Sopenharmony_cistatic const u8 gamma_def[17] = {
3228c2ecf20Sopenharmony_ci	0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
3238c2ecf20Sopenharmony_ci	0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci/* gamma for sensor ADCM1700 */
3268c2ecf20Sopenharmony_cistatic const u8 gamma_spec_0[17] = {
3278c2ecf20Sopenharmony_ci	0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
3288c2ecf20Sopenharmony_ci	0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
3298c2ecf20Sopenharmony_ci};
3308c2ecf20Sopenharmony_ci/* gamma for sensors HV7131R and MT9V111 */
3318c2ecf20Sopenharmony_cistatic const u8 gamma_spec_1[17] = {
3328c2ecf20Sopenharmony_ci	0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
3338c2ecf20Sopenharmony_ci	0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
3348c2ecf20Sopenharmony_ci};
3358c2ecf20Sopenharmony_ci/* gamma for sensor GC0307 */
3368c2ecf20Sopenharmony_cistatic const u8 gamma_spec_2[17] = {
3378c2ecf20Sopenharmony_ci	0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
3388c2ecf20Sopenharmony_ci	0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
3398c2ecf20Sopenharmony_ci};
3408c2ecf20Sopenharmony_ci/* gamma for sensor SP80708 */
3418c2ecf20Sopenharmony_cistatic const u8 gamma_spec_3[17] = {
3428c2ecf20Sopenharmony_ci	0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
3438c2ecf20Sopenharmony_ci	0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
3448c2ecf20Sopenharmony_ci};
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci/* color matrix and offsets */
3478c2ecf20Sopenharmony_cistatic const u8 reg84[] = {
3488c2ecf20Sopenharmony_ci	0x14, 0x00, 0x27, 0x00, 0x07, 0x00,	/* YR YG YB gains */
3498c2ecf20Sopenharmony_ci	0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,	/* UR UG UB */
3508c2ecf20Sopenharmony_ci	0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,	/* VR VG VB */
3518c2ecf20Sopenharmony_ci	0x00, 0x00, 0x00			/* YUV offsets */
3528c2ecf20Sopenharmony_ci};
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci#define DELAY	0xdd
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_cistatic const u8 adcm1700_sensor_init[][8] = {
3578c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
3588c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},	/* reset */
3598c2ecf20Sopenharmony_ci	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3608c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
3618c2ecf20Sopenharmony_ci	{DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3628c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
3638c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
3648c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
3658c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
3668c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
3678c2ecf20Sopenharmony_ci	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3688c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
3698c2ecf20Sopenharmony_ci	{DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
3708c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
3718c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
3728c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
3738c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
3748c2ecf20Sopenharmony_ci	{}
3758c2ecf20Sopenharmony_ci};
3768c2ecf20Sopenharmony_cistatic const u8 adcm1700_sensor_param1[][8] = {
3778c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},	/* exposure? */
3788c2ecf20Sopenharmony_ci	{0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
3818c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
3828c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
3838c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
3848c2ecf20Sopenharmony_ci	{0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10},	/* exposure? */
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
3878c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
3888c2ecf20Sopenharmony_ci	{0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
3898c2ecf20Sopenharmony_ci	{0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
3908c2ecf20Sopenharmony_ci	{}
3918c2ecf20Sopenharmony_ci};
3928c2ecf20Sopenharmony_cistatic const u8 gc0307_sensor_init[][8] = {
3938c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
3948c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
3958c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
3968c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
3978c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
3988c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
3998c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
4008c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
4018c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
4028c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
4038c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
4048c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
4058c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
4068c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
4078c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
4088c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
4098c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
4108c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
4118c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
4128c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
4138c2ecf20Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
4148c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
4158c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
4168c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
4178c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
4188c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
4198c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
4208c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
4218c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
4228c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
4238c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
4248c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
4258c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
4268c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
4278c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
4288c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
4298c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
4308c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
4318c2ecf20Sopenharmony_ci	{}
4328c2ecf20Sopenharmony_ci};
4338c2ecf20Sopenharmony_cistatic const u8 gc0307_sensor_param1[][8] = {
4348c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
4358c2ecf20Sopenharmony_ci	{0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
4368c2ecf20Sopenharmony_ci	{0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
4378c2ecf20Sopenharmony_ci	{0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
4388c2ecf20Sopenharmony_ci/*param3*/
4398c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
4408c2ecf20Sopenharmony_ci	{0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
4418c2ecf20Sopenharmony_ci	{}
4428c2ecf20Sopenharmony_ci};
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_cistatic const u8 hv7131r_sensor_init[][8] = {
4458c2ecf20Sopenharmony_ci	{0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
4468c2ecf20Sopenharmony_ci	{0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
4478c2ecf20Sopenharmony_ci	{0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
4488c2ecf20Sopenharmony_ci/*	{0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
4498c2ecf20Sopenharmony_ci	{0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
4508c2ecf20Sopenharmony_ci	{0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
4518c2ecf20Sopenharmony_ci/*	{0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
4548c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
4558c2ecf20Sopenharmony_ci	{0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
4568c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
4578c2ecf20Sopenharmony_ci	{0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
4588c2ecf20Sopenharmony_ci	{0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
4598c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
4608c2ecf20Sopenharmony_ci	{0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
4638c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
4648c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
4658c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
4668c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
4698c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
4708c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
4718c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
4728c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
4738c2ecf20Sopenharmony_ci	{0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
4748c2ecf20Sopenharmony_ci							/* set sensor clock */
4758c2ecf20Sopenharmony_ci	{}
4768c2ecf20Sopenharmony_ci};
4778c2ecf20Sopenharmony_cistatic const u8 mi0360_sensor_init[][8] = {
4788c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
4798c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
4808c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
4818c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
4828c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
4838c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
4848c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
4858c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
4868c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
4878c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
4888c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
4898c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
4908c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
4918c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
4928c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
4938c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
4948c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
4958c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
4968c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
4978c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
4988c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
4998c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
5008c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
5018c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
5028c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
5038c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
5048c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
5058c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
5068c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
5078c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
5088c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
5098c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
5108c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
5138c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
5148c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
5158c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
5168c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
5198c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
5208c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
5218c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
5248c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
5258c2ecf20Sopenharmony_ci/*	{0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
5268c2ecf20Sopenharmony_ci/*	{0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
5278c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
5288c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
5298c2ecf20Sopenharmony_ci	{}
5308c2ecf20Sopenharmony_ci};
5318c2ecf20Sopenharmony_cistatic const u8 mi0360b_sensor_init[][8] = {
5328c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
5338c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
5348c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
5358c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
5368c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
5378c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
5388c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
5398c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
5408c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
5418c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
5428c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
5438c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
5448c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
5458c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
5468c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
5478c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
5488c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
5498c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
5508c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
5518c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
5528c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
5538c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
5548c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
5558c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
5568c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
5578c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
5588c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
5598c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
5608c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
5618c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
5628c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
5638c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
5648c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
5658c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
5668c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
5698c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
5708c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
5718c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
5728c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
5738c2ecf20Sopenharmony_ci	{}
5748c2ecf20Sopenharmony_ci};
5758c2ecf20Sopenharmony_cistatic const u8 mi0360b_sensor_param1[][8] = {
5768c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
5778c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
5788c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
5798c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
5828c2ecf20Sopenharmony_ci	{0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
5838c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
5848c2ecf20Sopenharmony_ci	{0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
5858c2ecf20Sopenharmony_ci	{}
5868c2ecf20Sopenharmony_ci};
5878c2ecf20Sopenharmony_cistatic const u8 mo4000_sensor_init[][8] = {
5888c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
5898c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
5908c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
5918c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
5928c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
5938c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
5948c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
5958c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
5968c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
5978c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
5988c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
5998c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
6008c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
6018c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
6028c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
6038c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
6048c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
6058c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
6068c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
6078c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
6088c2ecf20Sopenharmony_ci	{}
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_cistatic const u8 mt9v111_sensor_init[][8] = {
6118c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
6128c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
6138c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
6148c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
6158c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
6168c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
6178c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
6188c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
6198c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
6208c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
6218c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
6228c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
6238c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
6248c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
6258c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
6268c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
6278c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
6288c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
6298c2ecf20Sopenharmony_ci	{}
6308c2ecf20Sopenharmony_ci};
6318c2ecf20Sopenharmony_cistatic const u8 mt9v111_sensor_param1[][8] = {
6328c2ecf20Sopenharmony_ci	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
6338c2ecf20Sopenharmony_ci	{0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
6348c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
6358c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
6368c2ecf20Sopenharmony_ci	{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
6378c2ecf20Sopenharmony_ci	{}
6388c2ecf20Sopenharmony_ci};
6398c2ecf20Sopenharmony_cistatic const u8 om6802_init0[2][8] = {
6408c2ecf20Sopenharmony_ci/*fixme: variable*/
6418c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
6428c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
6438c2ecf20Sopenharmony_ci};
6448c2ecf20Sopenharmony_cistatic const u8 om6802_sensor_init[][8] = {
6458c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
6468c2ecf20Sopenharmony_ci						/* factory mode */
6478c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
6488c2ecf20Sopenharmony_ci						/* output raw RGB */
6498c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
6508c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
6518c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
6528c2ecf20Sopenharmony_ci		/* auto-exposure speed (0) / white balance mode (auto RGB) */
6538c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
6548c2ecf20Sopenharmony_ci							 * set color mode */
6558c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
6568c2ecf20Sopenharmony_ci						 * max AGC value in AE */
6578c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
6588c2ecf20Sopenharmony_ci							 * preset AGC */
6598c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
6608c2ecf20Sopenharmony_ci						 * preset brightness */
6618c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
6628c2ecf20Sopenharmony_ci							 * preset contrast */
6638c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
6648c2ecf20Sopenharmony_ci							 * preset gamma */
6658c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
6668c2ecf20Sopenharmony_ci				/* luminance mode (0x4f -> AutoExpo on) */
6678c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
6688c2ecf20Sopenharmony_ci							/* preset shutter */
6698c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
6708c2ecf20Sopenharmony_ci							 * auto frame rate */
6718c2ecf20Sopenharmony_ci/*	{0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
6728c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
6738c2ecf20Sopenharmony_ci	{}
6748c2ecf20Sopenharmony_ci};
6758c2ecf20Sopenharmony_cistatic const u8 om6802_sensor_param1[][8] = {
6768c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
6778c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
6788c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
6798c2ecf20Sopenharmony_ci	{0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
6808c2ecf20Sopenharmony_ci	{}
6818c2ecf20Sopenharmony_ci};
6828c2ecf20Sopenharmony_cistatic const u8 ov7630_sensor_init[][8] = {
6838c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
6848c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
6858c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
6868c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
6878c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
6888c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
6898c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
6908c2ecf20Sopenharmony_ci/* win: i2c_r from 00 to 80 */
6918c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
6928c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
6938c2ecf20Sopenharmony_ci/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
6948c2ecf20Sopenharmony_ci	0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
6958c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
6968c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
6978c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
6988c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
6998c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
7008c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
7018c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
7028c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
7038c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
7048c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
7058c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
7068c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
7078c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
7088c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
7098c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
7108c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
7118c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
7128c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
7138c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
7148c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
7158c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
7168c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
7178c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
7188c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
7198c2ecf20Sopenharmony_ci	{}
7208c2ecf20Sopenharmony_ci};
7218c2ecf20Sopenharmony_cistatic const u8 ov7630_sensor_param1[][8] = {
7228c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
7238c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
7248c2ecf20Sopenharmony_ci/*fixme: + 0x12, 0x04*/
7258c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
7268c2ecf20Sopenharmony_ci							 * set by setvflip */
7278c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
7288c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
7298c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
7308c2ecf20Sopenharmony_ci/* */
7318c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
7328c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
7338c2ecf20Sopenharmony_ci/* */
7348c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
7358c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
7368c2ecf20Sopenharmony_ci	{}
7378c2ecf20Sopenharmony_ci};
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_cistatic const u8 ov7648_sensor_init[][8] = {
7408c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
7418c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},	/* reset */
7428c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
7438c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
7448c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
7458c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
7468c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
7478c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
7488c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
7498c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
7508c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
7518c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
7528c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
7538c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
7548c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
7558c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
7568c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
7578c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
7588c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
7598c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
7608c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
7618c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
7648c2ecf20Sopenharmony_ci/*	{0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
7658c2ecf20Sopenharmony_ci/*	{0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
7668c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
7678c2ecf20Sopenharmony_ci	{}
7688c2ecf20Sopenharmony_ci};
7698c2ecf20Sopenharmony_cistatic const u8 ov7648_sensor_param1[][8] = {
7708c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
7718c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
7728c2ecf20Sopenharmony_ci							 * set by setvflip */
7738c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
7748c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
7758c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
7768c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
7778c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
7788c2ecf20Sopenharmony_ci/*...*/
7798c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
7808c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
7818c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
7828c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
7838c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
7848c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	{}
7878c2ecf20Sopenharmony_ci};
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_cistatic const u8 ov7660_sensor_init[][8] = {
7908c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
7918c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
7928c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
7938c2ecf20Sopenharmony_ci						/* Outformat = rawRGB */
7948c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
7958c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
7968c2ecf20Sopenharmony_ci						/* GAIN BLUE RED VREF */
7978c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
7988c2ecf20Sopenharmony_ci						/* COM 1 BAVE GEAVE AECHH */
7998c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
8008c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
8018c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
8028c2ecf20Sopenharmony_ci						/* AECH CLKRC COM7 COM8 */
8038c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
8048c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
8058c2ecf20Sopenharmony_ci						/* HSTART HSTOP VSTRT VSTOP */
8068c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
8078c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
8088c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
8098c2ecf20Sopenharmony_ci					/* BOS GBOS GROS ROS (BGGR offset) */
8108c2ecf20Sopenharmony_ci/*	{0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
8118c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
8128c2ecf20Sopenharmony_ci						/* AEW AEB VPT BBIAS */
8138c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
8148c2ecf20Sopenharmony_ci						/* GbBIAS RSVD EXHCH EXHCL */
8158c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
8168c2ecf20Sopenharmony_ci						/* RBIAS ADVFL ASDVFH YAVE */
8178c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
8188c2ecf20Sopenharmony_ci						/* HSYST HSYEN HREF */
8198c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
8208c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
8218c2ecf20Sopenharmony_ci						/* ADC ACOM OFON TSLB */
8228c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
8238c2ecf20Sopenharmony_ci						/* COM11 COM12 COM13 COM14 */
8248c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
8258c2ecf20Sopenharmony_ci						/* EDGE COM15 COM16 COM17 */
8268c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
8278c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
8288c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
8298c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
8308c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
8318c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
8328c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
8338c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
8348c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
8358c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
8368c2ecf20Sopenharmony_ci						/* LCC1 LCC2 LCC3 LCC4 */
8378c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
8388c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
8398c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
8408c2ecf20Sopenharmony_ci					/* band gap reference [0:3] DBLV */
8418c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
8428c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
8438c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
8448c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
8458c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
8468c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
8478c2ecf20Sopenharmony_ci	{0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
8488c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
8498c2ecf20Sopenharmony_ci	{0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
8508c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
8518c2ecf20Sopenharmony_ci/* not in all ms-win traces*/
8528c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
8538c2ecf20Sopenharmony_ci	{}
8548c2ecf20Sopenharmony_ci};
8558c2ecf20Sopenharmony_cistatic const u8 ov7660_sensor_param1[][8] = {
8568c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
8578c2ecf20Sopenharmony_ci						/* bits[3..0]reserved */
8588c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
8598c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
8608c2ecf20Sopenharmony_ci						/* VREF vertical frame ctrl */
8618c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
8628c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
8638c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
8648c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
8658c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
8668c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
8678c2ecf20Sopenharmony_ci/****** (some exchanges in the win trace) ******/
8688c2ecf20Sopenharmony_ci/*fixme:param2*/
8698c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
8708c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
8718c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
8728c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
8738c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
8748c2ecf20Sopenharmony_ci/****** (some exchanges in the win trace) ******/
8758c2ecf20Sopenharmony_ci/******!! startsensor KO if changed !!****/
8768c2ecf20Sopenharmony_ci/*fixme: param3*/
8778c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
8788c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
8798c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
8808c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
8818c2ecf20Sopenharmony_ci	{}
8828c2ecf20Sopenharmony_ci};
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_cistatic const u8 po1030_sensor_init[][8] = {
8858c2ecf20Sopenharmony_ci/* the sensor registers are described in m5602/m5602_po1030.h */
8868c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
8878c2ecf20Sopenharmony_ci	{DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
8888c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
8898c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
8908c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
8918c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
8928c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
8938c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
8948c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
8958c2ecf20Sopenharmony_ci	{0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
8968c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
8978c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
8988c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
8998c2ecf20Sopenharmony_ci	{0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
9008c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
9018c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
9028c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
9038c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
9048c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
9058c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
9068c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
9078c2ecf20Sopenharmony_ci	{0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
9088c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
9098c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
9108c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
9118c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
9128c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
9138c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
9168c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
9178c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
9188c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
9198c2ecf20Sopenharmony_ci	{0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
9208c2ecf20Sopenharmony_ci	{}
9218c2ecf20Sopenharmony_ci};
9228c2ecf20Sopenharmony_cistatic const u8 po1030_sensor_param1[][8] = {
9238c2ecf20Sopenharmony_ci/* from ms-win traces - these values change with auto gain/expo/wb.. */
9248c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
9258c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
9268c2ecf20Sopenharmony_ci/* mean values */
9278c2ecf20Sopenharmony_ci	{0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
9288c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
9298c2ecf20Sopenharmony_ci	{0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
9328c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
9338c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
9348c2ecf20Sopenharmony_ci/*	{0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
9358c2ecf20Sopenharmony_ci	{}
9368c2ecf20Sopenharmony_ci};
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_cistatic const u8 po2030n_sensor_init[][8] = {
9398c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
9408c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
9418c2ecf20Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
9428c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
9438c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
9448c2ecf20Sopenharmony_ci	{DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
9458c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
9468c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
9478c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
9488c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
9498c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
9508c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
9518c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
9528c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
9538c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
9548c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
9558c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
9568c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
9578c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
9588c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
9598c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
9608c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
9618c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
9628c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
9638c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
9648c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
9658c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
9668c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
9678c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
9688c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
9698c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
9708c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
9718c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
9728c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
9738c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
9748c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
9758c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
9768c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
9778c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
9788c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
9798c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
9808c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
9818c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
9828c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
9838c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
9848c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
9858c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
9868c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
9878c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
9888c2ecf20Sopenharmony_ci	{0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
9898c2ecf20Sopenharmony_ci	{}
9908c2ecf20Sopenharmony_ci};
9918c2ecf20Sopenharmony_cistatic const u8 po2030n_sensor_param1[][8] = {
9928c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
9938c2ecf20Sopenharmony_ci	{DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
9948c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
9958c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
9968c2ecf20Sopenharmony_ci	{0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
9978c2ecf20Sopenharmony_ci/*param2*/
9988c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
9998c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
10008c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
10018c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
10028c2ecf20Sopenharmony_ci	{0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
10038c2ecf20Sopenharmony_ci	{}
10048c2ecf20Sopenharmony_ci};
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_cistatic const u8 soi768_sensor_init[][8] = {
10078c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
10088c2ecf20Sopenharmony_ci	{DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
10098c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
10108c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
10118c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
10128c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
10138c2ecf20Sopenharmony_ci	{}
10148c2ecf20Sopenharmony_ci};
10158c2ecf20Sopenharmony_cistatic const u8 soi768_sensor_param1[][8] = {
10168c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
10178c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
10188c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
10198c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
10208c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
10218c2ecf20Sopenharmony_ci/* */
10228c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
10238c2ecf20Sopenharmony_ci/*	{0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
10248c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
10258c2ecf20Sopenharmony_ci/*	{0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
10268c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
10278c2ecf20Sopenharmony_ci/* the next sequence should be used for auto gain */
10288c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
10298c2ecf20Sopenharmony_ci			/* global gain ? : 07 - change with 0x15 at the end */
10308c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
10318c2ecf20Sopenharmony_ci	{0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
10328c2ecf20Sopenharmony_ci	{0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
10338c2ecf20Sopenharmony_ci			/* exposure ? : 0200 - change with 0x1e at the end */
10348c2ecf20Sopenharmony_ci	{}
10358c2ecf20Sopenharmony_ci};
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic const u8 sp80708_sensor_init[][8] = {
10388c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
10398c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
10408c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
10418c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
10428c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
10438c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
10448c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
10458c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
10468c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
10478c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
10488c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
10498c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
10508c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
10518c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
10528c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
10538c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
10548c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
10558c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
10568c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
10578c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
10588c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
10598c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
10608c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
10618c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
10628c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
10638c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
10648c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
10658c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
10668c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
10678c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
10688c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
10698c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
10708c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
10718c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
10728c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
10738c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
10748c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
10758c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
10768c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
10778c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
10788c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
10798c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
10808c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
10818c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
10828c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
10838c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
10848c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
10858c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
10868c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
10878c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
10888c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
10898c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
10908c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
10918c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
10928c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
10938c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
10948c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
10958c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
10968c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
10978c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
10988c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
10998c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
11008c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
11018c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
11028c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
11038c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
11048c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
11058c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
11068c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
11078c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
11088c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
11098c2ecf20Sopenharmony_ci	{}
11108c2ecf20Sopenharmony_ci};
11118c2ecf20Sopenharmony_cistatic const u8 sp80708_sensor_param1[][8] = {
11128c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
11138c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
11148c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
11158c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
11168c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
11178c2ecf20Sopenharmony_ci	{0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
11188c2ecf20Sopenharmony_ci	{0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
11198c2ecf20Sopenharmony_ci	{}
11208c2ecf20Sopenharmony_ci};
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_cistatic const u8 (*sensor_init[])[8] = {
11238c2ecf20Sopenharmony_ci[SENSOR_ADCM1700] =	adcm1700_sensor_init,
11248c2ecf20Sopenharmony_ci[SENSOR_GC0307] =	gc0307_sensor_init,
11258c2ecf20Sopenharmony_ci[SENSOR_HV7131R] =	hv7131r_sensor_init,
11268c2ecf20Sopenharmony_ci[SENSOR_MI0360] =	mi0360_sensor_init,
11278c2ecf20Sopenharmony_ci[SENSOR_MI0360B] =	mi0360b_sensor_init,
11288c2ecf20Sopenharmony_ci[SENSOR_MO4000] =	mo4000_sensor_init,
11298c2ecf20Sopenharmony_ci[SENSOR_MT9V111] =	mt9v111_sensor_init,
11308c2ecf20Sopenharmony_ci[SENSOR_OM6802] =	om6802_sensor_init,
11318c2ecf20Sopenharmony_ci[SENSOR_OV7630] =	ov7630_sensor_init,
11328c2ecf20Sopenharmony_ci[SENSOR_OV7648] =	ov7648_sensor_init,
11338c2ecf20Sopenharmony_ci[SENSOR_OV7660] =	ov7660_sensor_init,
11348c2ecf20Sopenharmony_ci[SENSOR_PO1030] =	po1030_sensor_init,
11358c2ecf20Sopenharmony_ci[SENSOR_PO2030N] =	po2030n_sensor_init,
11368c2ecf20Sopenharmony_ci[SENSOR_SOI768] =	soi768_sensor_init,
11378c2ecf20Sopenharmony_ci[SENSOR_SP80708] =	sp80708_sensor_init,
11388c2ecf20Sopenharmony_ci};
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci/* read <len> bytes to gspca_dev->usb_buf */
11418c2ecf20Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev,
11428c2ecf20Sopenharmony_ci		  u16 value, int len)
11438c2ecf20Sopenharmony_ci{
11448c2ecf20Sopenharmony_ci	int ret;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11478c2ecf20Sopenharmony_ci		return;
11488c2ecf20Sopenharmony_ci	if (len > USB_BUF_SZ) {
11498c2ecf20Sopenharmony_ci		gspca_err(gspca_dev, "reg_r: buffer overflow\n");
11508c2ecf20Sopenharmony_ci		return;
11518c2ecf20Sopenharmony_ci	}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
11548c2ecf20Sopenharmony_ci			usb_rcvctrlpipe(gspca_dev->dev, 0),
11558c2ecf20Sopenharmony_ci			0,
11568c2ecf20Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
11578c2ecf20Sopenharmony_ci			value, 0,
11588c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, len,
11598c2ecf20Sopenharmony_ci			500);
11608c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBI, "reg_r [%02x] -> %02x\n",
11618c2ecf20Sopenharmony_ci		  value, gspca_dev->usb_buf[0]);
11628c2ecf20Sopenharmony_ci	if (ret < 0) {
11638c2ecf20Sopenharmony_ci		pr_err("reg_r err %d\n", ret);
11648c2ecf20Sopenharmony_ci		gspca_dev->usb_err = ret;
11658c2ecf20Sopenharmony_ci		/*
11668c2ecf20Sopenharmony_ci		 * Make sure the buffer is zeroed to avoid uninitialized
11678c2ecf20Sopenharmony_ci		 * values.
11688c2ecf20Sopenharmony_ci		 */
11698c2ecf20Sopenharmony_ci		memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
11708c2ecf20Sopenharmony_ci	}
11718c2ecf20Sopenharmony_ci}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_cistatic void reg_w1(struct gspca_dev *gspca_dev,
11748c2ecf20Sopenharmony_ci		   u16 value,
11758c2ecf20Sopenharmony_ci		   u8 data)
11768c2ecf20Sopenharmony_ci{
11778c2ecf20Sopenharmony_ci	int ret;
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11808c2ecf20Sopenharmony_ci		return;
11818c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg_w1 [%04x] = %02x\n", value, data);
11828c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[0] = data;
11838c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
11848c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
11858c2ecf20Sopenharmony_ci			0x08,
11868c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
11878c2ecf20Sopenharmony_ci			value,
11888c2ecf20Sopenharmony_ci			0,
11898c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 1,
11908c2ecf20Sopenharmony_ci			500);
11918c2ecf20Sopenharmony_ci	if (ret < 0) {
11928c2ecf20Sopenharmony_ci		pr_err("reg_w1 err %d\n", ret);
11938c2ecf20Sopenharmony_ci		gspca_dev->usb_err = ret;
11948c2ecf20Sopenharmony_ci	}
11958c2ecf20Sopenharmony_ci}
11968c2ecf20Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev,
11978c2ecf20Sopenharmony_ci			  u16 value,
11988c2ecf20Sopenharmony_ci			  const u8 *buffer,
11998c2ecf20Sopenharmony_ci			  int len)
12008c2ecf20Sopenharmony_ci{
12018c2ecf20Sopenharmony_ci	int ret;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12048c2ecf20Sopenharmony_ci		return;
12058c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x %02x ..\n",
12068c2ecf20Sopenharmony_ci		  value, buffer[0], buffer[1]);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	if (len > USB_BUF_SZ) {
12098c2ecf20Sopenharmony_ci		gspca_err(gspca_dev, "reg_w: buffer overflow\n");
12108c2ecf20Sopenharmony_ci		return;
12118c2ecf20Sopenharmony_ci	}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, len);
12148c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
12158c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
12168c2ecf20Sopenharmony_ci			0x08,
12178c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
12188c2ecf20Sopenharmony_ci			value, 0,
12198c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, len,
12208c2ecf20Sopenharmony_ci			500);
12218c2ecf20Sopenharmony_ci	if (ret < 0) {
12228c2ecf20Sopenharmony_ci		pr_err("reg_w err %d\n", ret);
12238c2ecf20Sopenharmony_ci		gspca_dev->usb_err = ret;
12248c2ecf20Sopenharmony_ci	}
12258c2ecf20Sopenharmony_ci}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci/* I2C write 1 byte */
12288c2ecf20Sopenharmony_cistatic void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
12298c2ecf20Sopenharmony_ci{
12308c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12318c2ecf20Sopenharmony_ci	int ret;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12348c2ecf20Sopenharmony_ci		return;
12358c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "i2c_w1 [%02x] = %02x\n", reg, val);
12368c2ecf20Sopenharmony_ci	switch (sd->sensor) {
12378c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
12388c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
12398c2ecf20Sopenharmony_ci	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
12408c2ecf20Sopenharmony_ci		gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
12418c2ecf20Sopenharmony_ci		break;
12428c2ecf20Sopenharmony_ci	default:			/* i2c command = a1 (400 kHz) */
12438c2ecf20Sopenharmony_ci		gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
12448c2ecf20Sopenharmony_ci		break;
12458c2ecf20Sopenharmony_ci	}
12468c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[1] = sd->i2c_addr;
12478c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[2] = reg;
12488c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[3] = val;
12498c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[4] = 0;
12508c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[5] = 0;
12518c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[6] = 0;
12528c2ecf20Sopenharmony_ci	gspca_dev->usb_buf[7] = 0x10;
12538c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
12548c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
12558c2ecf20Sopenharmony_ci			0x08,
12568c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
12578c2ecf20Sopenharmony_ci			0x08,			/* value = i2c */
12588c2ecf20Sopenharmony_ci			0,
12598c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 8,
12608c2ecf20Sopenharmony_ci			500);
12618c2ecf20Sopenharmony_ci	msleep(2);
12628c2ecf20Sopenharmony_ci	if (ret < 0) {
12638c2ecf20Sopenharmony_ci		pr_err("i2c_w1 err %d\n", ret);
12648c2ecf20Sopenharmony_ci		gspca_dev->usb_err = ret;
12658c2ecf20Sopenharmony_ci	}
12668c2ecf20Sopenharmony_ci}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci/* I2C write 8 bytes */
12698c2ecf20Sopenharmony_cistatic void i2c_w8(struct gspca_dev *gspca_dev,
12708c2ecf20Sopenharmony_ci		   const u8 *buffer)
12718c2ecf20Sopenharmony_ci{
12728c2ecf20Sopenharmony_ci	int ret;
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12758c2ecf20Sopenharmony_ci		return;
12768c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "i2c_w8 [%02x] = %02x ..\n",
12778c2ecf20Sopenharmony_ci		  buffer[2], buffer[3]);
12788c2ecf20Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, 8);
12798c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
12808c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
12818c2ecf20Sopenharmony_ci			0x08,
12828c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
12838c2ecf20Sopenharmony_ci			0x08, 0,		/* value, index */
12848c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 8,
12858c2ecf20Sopenharmony_ci			500);
12868c2ecf20Sopenharmony_ci	msleep(2);
12878c2ecf20Sopenharmony_ci	if (ret < 0) {
12888c2ecf20Sopenharmony_ci		pr_err("i2c_w8 err %d\n", ret);
12898c2ecf20Sopenharmony_ci		gspca_dev->usb_err = ret;
12908c2ecf20Sopenharmony_ci	}
12918c2ecf20Sopenharmony_ci}
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
12948c2ecf20Sopenharmony_cistatic void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
12958c2ecf20Sopenharmony_ci{
12968c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12978c2ecf20Sopenharmony_ci	u8 mode[8];
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	switch (sd->sensor) {
13008c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
13018c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
13028c2ecf20Sopenharmony_ci	case SENSOR_GC0307:		/* i2c command = a0 (100 kHz) */
13038c2ecf20Sopenharmony_ci		mode[0] = 0x80 | 0x10;
13048c2ecf20Sopenharmony_ci		break;
13058c2ecf20Sopenharmony_ci	default:			/* i2c command = 91 (400 kHz) */
13068c2ecf20Sopenharmony_ci		mode[0] = 0x81 | 0x10;
13078c2ecf20Sopenharmony_ci		break;
13088c2ecf20Sopenharmony_ci	}
13098c2ecf20Sopenharmony_ci	mode[1] = sd->i2c_addr;
13108c2ecf20Sopenharmony_ci	mode[2] = reg;
13118c2ecf20Sopenharmony_ci	mode[3] = 0;
13128c2ecf20Sopenharmony_ci	mode[4] = 0;
13138c2ecf20Sopenharmony_ci	mode[5] = 0;
13148c2ecf20Sopenharmony_ci	mode[6] = 0;
13158c2ecf20Sopenharmony_ci	mode[7] = 0x10;
13168c2ecf20Sopenharmony_ci	i2c_w8(gspca_dev, mode);
13178c2ecf20Sopenharmony_ci	msleep(2);
13188c2ecf20Sopenharmony_ci	mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
13198c2ecf20Sopenharmony_ci	mode[2] = 0;
13208c2ecf20Sopenharmony_ci	i2c_w8(gspca_dev, mode);
13218c2ecf20Sopenharmony_ci	msleep(2);
13228c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x0a, 5);
13238c2ecf20Sopenharmony_ci}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_cistatic void i2c_w_seq(struct gspca_dev *gspca_dev,
13268c2ecf20Sopenharmony_ci			const u8 (*data)[8])
13278c2ecf20Sopenharmony_ci{
13288c2ecf20Sopenharmony_ci	while ((*data)[0] != 0) {
13298c2ecf20Sopenharmony_ci		if ((*data)[0] != DELAY)
13308c2ecf20Sopenharmony_ci			i2c_w8(gspca_dev, *data);
13318c2ecf20Sopenharmony_ci		else
13328c2ecf20Sopenharmony_ci			msleep((*data)[1]);
13338c2ecf20Sopenharmony_ci		data++;
13348c2ecf20Sopenharmony_ci	}
13358c2ecf20Sopenharmony_ci}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci/* check the ID of the hv7131 sensor */
13388c2ecf20Sopenharmony_ci/* this sequence is needed because it activates the sensor */
13398c2ecf20Sopenharmony_cistatic void hv7131r_probe(struct gspca_dev *gspca_dev)
13408c2ecf20Sopenharmony_ci{
13418c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x02, 0);		/* sensor wakeup */
13428c2ecf20Sopenharmony_ci	msleep(10);
13438c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x02, 0x66);		/* Gpio on */
13448c2ecf20Sopenharmony_ci	msleep(10);
13458c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0, 5);			/* read sensor id */
13468c2ecf20Sopenharmony_ci	if (gspca_dev->usb_buf[0] == 0x02	/* chip ID (02 is R) */
13478c2ecf20Sopenharmony_ci	    && gspca_dev->usb_buf[1] == 0x09
13488c2ecf20Sopenharmony_ci	    && gspca_dev->usb_buf[2] == 0x01) {
13498c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor HV7131R found\n");
13508c2ecf20Sopenharmony_ci		return;
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci	pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
13538c2ecf20Sopenharmony_ci		gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
13548c2ecf20Sopenharmony_ci		gspca_dev->usb_buf[2]);
13558c2ecf20Sopenharmony_ci}
13568c2ecf20Sopenharmony_ci
13578c2ecf20Sopenharmony_cistatic void mi0360_probe(struct gspca_dev *gspca_dev)
13588c2ecf20Sopenharmony_ci{
13598c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
13608c2ecf20Sopenharmony_ci	int i, j;
13618c2ecf20Sopenharmony_ci	u16 val = 0;
13628c2ecf20Sopenharmony_ci	static const u8 probe_tb[][4][8] = {
13638c2ecf20Sopenharmony_ci	    {					/* mi0360 */
13648c2ecf20Sopenharmony_ci		{0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
13658c2ecf20Sopenharmony_ci		{0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
13668c2ecf20Sopenharmony_ci		{0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
13678c2ecf20Sopenharmony_ci		{0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
13688c2ecf20Sopenharmony_ci	    },
13698c2ecf20Sopenharmony_ci	    {					/* mt9v111 */
13708c2ecf20Sopenharmony_ci		{0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
13718c2ecf20Sopenharmony_ci		{0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
13728c2ecf20Sopenharmony_ci		{0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
13738c2ecf20Sopenharmony_ci		{}
13748c2ecf20Sopenharmony_ci	    },
13758c2ecf20Sopenharmony_ci	};
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
13788c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x17, 0x62);
13798c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x08);
13808c2ecf20Sopenharmony_ci		for (j = 0; j < 3; j++)
13818c2ecf20Sopenharmony_ci			i2c_w8(gspca_dev, probe_tb[i][j]);
13828c2ecf20Sopenharmony_ci		msleep(2);
13838c2ecf20Sopenharmony_ci		reg_r(gspca_dev, 0x0a, 5);
13848c2ecf20Sopenharmony_ci		val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
13858c2ecf20Sopenharmony_ci		if (probe_tb[i][3][0] != 0)
13868c2ecf20Sopenharmony_ci			i2c_w8(gspca_dev, probe_tb[i][3]);
13878c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x29);
13888c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x17, 0x42);
13898c2ecf20Sopenharmony_ci		if (val != 0xffff)
13908c2ecf20Sopenharmony_ci			break;
13918c2ecf20Sopenharmony_ci	}
13928c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
13938c2ecf20Sopenharmony_ci		return;
13948c2ecf20Sopenharmony_ci	switch (val) {
13958c2ecf20Sopenharmony_ci	case 0x8221:
13968c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mi0360b\n");
13978c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_MI0360B;
13988c2ecf20Sopenharmony_ci		break;
13998c2ecf20Sopenharmony_ci	case 0x823a:
14008c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mt9v111\n");
14018c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_MT9V111;
14028c2ecf20Sopenharmony_ci		break;
14038c2ecf20Sopenharmony_ci	case 0x8243:
14048c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor mi0360\n");
14058c2ecf20Sopenharmony_ci		break;
14068c2ecf20Sopenharmony_ci	default:
14078c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Unknown sensor %04x - forced to mi0360\n",
14088c2ecf20Sopenharmony_ci			  val);
14098c2ecf20Sopenharmony_ci		break;
14108c2ecf20Sopenharmony_ci	}
14118c2ecf20Sopenharmony_ci}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_cistatic void ov7630_probe(struct gspca_dev *gspca_dev)
14148c2ecf20Sopenharmony_ci{
14158c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
14168c2ecf20Sopenharmony_ci	u16 val;
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci	/* check ov76xx */
14198c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
14208c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
14218c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x21;
14228c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0x0a, 2);
14238c2ecf20Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
14248c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
14258c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
14268c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
14278c2ecf20Sopenharmony_ci		return;
14288c2ecf20Sopenharmony_ci	if (val == 0x7628) {			/* soi768 */
14298c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_SOI768;
14308c2ecf20Sopenharmony_ci/*fixme: only valid for 0c45:613e?*/
14318c2ecf20Sopenharmony_ci		gspca_dev->cam.input_flags =
14328c2ecf20Sopenharmony_ci				V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
14338c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor soi768\n");
14348c2ecf20Sopenharmony_ci		return;
14358c2ecf20Sopenharmony_ci	}
14368c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Sensor ov%04x\n", val);
14378c2ecf20Sopenharmony_ci}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_cistatic void ov7648_probe(struct gspca_dev *gspca_dev)
14408c2ecf20Sopenharmony_ci{
14418c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
14428c2ecf20Sopenharmony_ci	u16 val;
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	/* check ov76xx */
14458c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
14468c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
14478c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x21;
14488c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0x0a, 2);
14498c2ecf20Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
14508c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
14518c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
14528c2ecf20Sopenharmony_ci	if ((val & 0xff00) == 0x7600) {		/* ov76xx */
14538c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor ov%04x\n", val);
14548c2ecf20Sopenharmony_ci		return;
14558c2ecf20Sopenharmony_ci	}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_ci	/* check po1030 */
14588c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
14598c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
14608c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x6e;
14618c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 2);
14628c2ecf20Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
14638c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
14648c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
14658c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
14668c2ecf20Sopenharmony_ci		return;
14678c2ecf20Sopenharmony_ci	if (val == 0x1030) {			/* po1030 */
14688c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor po1030\n");
14698c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_PO1030;
14708c2ecf20Sopenharmony_ci		return;
14718c2ecf20Sopenharmony_ci	}
14728c2ecf20Sopenharmony_ci	pr_err("Unknown sensor %04x\n", val);
14738c2ecf20Sopenharmony_ci}
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
14768c2ecf20Sopenharmony_cistatic void po2030n_probe(struct gspca_dev *gspca_dev)
14778c2ecf20Sopenharmony_ci{
14788c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
14798c2ecf20Sopenharmony_ci	u16 val;
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci	/* check gc0307 */
14828c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
14838c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x08);
14848c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x02, 0x22);
14858c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x21;
14868c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 1);
14878c2ecf20Sopenharmony_ci	val = gspca_dev->usb_buf[4];
14888c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);		/* reset */
14898c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
14908c2ecf20Sopenharmony_ci	if (val == 0x99) {			/* gc0307 (?) */
14918c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor gc0307\n");
14928c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_GC0307;
14938c2ecf20Sopenharmony_ci		return;
14948c2ecf20Sopenharmony_ci	}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	/* check po2030n */
14978c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x62);
14988c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x0a);
14998c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x6e;
15008c2ecf20Sopenharmony_ci	i2c_r(gspca_dev, 0x00, 2);
15018c2ecf20Sopenharmony_ci	val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
15028c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, 0x29);
15038c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, 0x42);
15048c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
15058c2ecf20Sopenharmony_ci		return;
15068c2ecf20Sopenharmony_ci	if (val == 0x2030) {
15078c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_PROBE, "Sensor po2030n\n");
15088c2ecf20Sopenharmony_ci/*		sd->sensor = SENSOR_PO2030N; */
15098c2ecf20Sopenharmony_ci	} else {
15108c2ecf20Sopenharmony_ci		pr_err("Unknown sensor ID %04x\n", val);
15118c2ecf20Sopenharmony_ci	}
15128c2ecf20Sopenharmony_ci}
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci/* this function is called at probe time */
15158c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
15168c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
15178c2ecf20Sopenharmony_ci{
15188c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
15198c2ecf20Sopenharmony_ci	struct cam *cam;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	sd->bridge = id->driver_info >> 16;
15228c2ecf20Sopenharmony_ci	sd->sensor = id->driver_info >> 8;
15238c2ecf20Sopenharmony_ci	sd->flags = id->driver_info;
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	cam = &gspca_dev->cam;
15268c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
15278c2ecf20Sopenharmony_ci		cam->cam_mode = cif_mode;
15288c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(cif_mode);
15298c2ecf20Sopenharmony_ci	} else {
15308c2ecf20Sopenharmony_ci		cam->cam_mode = vga_mode;
15318c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(vga_mode);
15328c2ecf20Sopenharmony_ci	}
15338c2ecf20Sopenharmony_ci	cam->npkt = 24;			/* 24 packets per ISOC message */
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci	sd->ag_cnt = -1;
15368c2ecf20Sopenharmony_ci	sd->quality = QUALITY_DEF;
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	INIT_WORK(&sd->work, qual_upd);
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	return 0;
15418c2ecf20Sopenharmony_ci}
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */
15448c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
15458c2ecf20Sopenharmony_ci{
15468c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
15478c2ecf20Sopenharmony_ci	const u8 *sn9c1xx;
15488c2ecf20Sopenharmony_ci	u8 regGpio[] = { 0x29, 0x70 };		/* no audio */
15498c2ecf20Sopenharmony_ci	u8 regF1;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	/* setup a selector by bridge */
15528c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x01);
15538c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x00, 1);
15548c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x00);
15558c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x00, 1);		/* get sonix chip id */
15568c2ecf20Sopenharmony_ci	regF1 = gspca_dev->usb_buf[0];
15578c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
15588c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
15598c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_PROBE, "Sonix chip id: %02x\n", regF1);
15608c2ecf20Sopenharmony_ci	if (gspca_dev->audio)
15618c2ecf20Sopenharmony_ci		regGpio[1] |= 0x04;		/* with audio */
15628c2ecf20Sopenharmony_ci	switch (sd->bridge) {
15638c2ecf20Sopenharmony_ci	case BRIDGE_SN9C102P:
15648c2ecf20Sopenharmony_ci	case BRIDGE_SN9C105:
15658c2ecf20Sopenharmony_ci		if (regF1 != 0x11)
15668c2ecf20Sopenharmony_ci			return -ENODEV;
15678c2ecf20Sopenharmony_ci		break;
15688c2ecf20Sopenharmony_ci	default:
15698c2ecf20Sopenharmony_ci/*	case BRIDGE_SN9C110: */
15708c2ecf20Sopenharmony_ci/*	case BRIDGE_SN9C120: */
15718c2ecf20Sopenharmony_ci		if (regF1 != 0x12)
15728c2ecf20Sopenharmony_ci			return -ENODEV;
15738c2ecf20Sopenharmony_ci	}
15748c2ecf20Sopenharmony_ci
15758c2ecf20Sopenharmony_ci	switch (sd->sensor) {
15768c2ecf20Sopenharmony_ci	case SENSOR_MI0360:
15778c2ecf20Sopenharmony_ci		mi0360_probe(gspca_dev);
15788c2ecf20Sopenharmony_ci		break;
15798c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
15808c2ecf20Sopenharmony_ci		ov7630_probe(gspca_dev);
15818c2ecf20Sopenharmony_ci		break;
15828c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
15838c2ecf20Sopenharmony_ci		ov7648_probe(gspca_dev);
15848c2ecf20Sopenharmony_ci		break;
15858c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
15868c2ecf20Sopenharmony_ci		po2030n_probe(gspca_dev);
15878c2ecf20Sopenharmony_ci		break;
15888c2ecf20Sopenharmony_ci	}
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	switch (sd->bridge) {
15918c2ecf20Sopenharmony_ci	case BRIDGE_SN9C102P:
15928c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02, regGpio[1]);
15938c2ecf20Sopenharmony_ci		break;
15948c2ecf20Sopenharmony_ci	default:
15958c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0x01, regGpio, 2);
15968c2ecf20Sopenharmony_ci		break;
15978c2ecf20Sopenharmony_ci	}
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_ci	/* Note we do not disable the sensor clock here (power saving mode),
16008c2ecf20Sopenharmony_ci	   as that also disables the button on the cam. */
16018c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0xf1, 0x00);
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	/* set the i2c address */
16048c2ecf20Sopenharmony_ci	sn9c1xx = sn_tb[sd->sensor];
16058c2ecf20Sopenharmony_ci	sd->i2c_addr = sn9c1xx[9];
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
16088c2ecf20Sopenharmony_ci}
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl);
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
16138c2ecf20Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
16148c2ecf20Sopenharmony_ci};
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci/* this function is called at probe time */
16178c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
16188c2ecf20Sopenharmony_ci{
16198c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
16208c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
16238c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 14);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16268c2ecf20Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
16278c2ecf20Sopenharmony_ci#define CONTRAST_MAX 127
16288c2ecf20Sopenharmony_ci	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16298c2ecf20Sopenharmony_ci			V4L2_CID_CONTRAST, 0, CONTRAST_MAX, 1, 20);
16308c2ecf20Sopenharmony_ci#define COLORS_DEF 25
16318c2ecf20Sopenharmony_ci	sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16328c2ecf20Sopenharmony_ci			V4L2_CID_SATURATION, 0, 40, 1, COLORS_DEF);
16338c2ecf20Sopenharmony_ci	sd->red_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16348c2ecf20Sopenharmony_ci			V4L2_CID_RED_BALANCE, 24, 40, 1, 32);
16358c2ecf20Sopenharmony_ci	sd->blue_bal = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16368c2ecf20Sopenharmony_ci			V4L2_CID_BLUE_BALANCE, 24, 40, 1, 32);
16378c2ecf20Sopenharmony_ci#define GAMMA_DEF 20
16388c2ecf20Sopenharmony_ci	sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16398c2ecf20Sopenharmony_ci			V4L2_CID_GAMMA, 0, 40, 1, GAMMA_DEF);
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_OM6802)
16428c2ecf20Sopenharmony_ci		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16438c2ecf20Sopenharmony_ci			V4L2_CID_SHARPNESS, 0, 255, 1, 16);
16448c2ecf20Sopenharmony_ci	else
16458c2ecf20Sopenharmony_ci		sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16468c2ecf20Sopenharmony_ci			V4L2_CID_SHARPNESS, 0, 255, 1, 90);
16478c2ecf20Sopenharmony_ci
16488c2ecf20Sopenharmony_ci	if (sd->flags & F_ILLUM)
16498c2ecf20Sopenharmony_ci		sd->illum = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16508c2ecf20Sopenharmony_ci			V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
16538c2ecf20Sopenharmony_ci		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16548c2ecf20Sopenharmony_ci			V4L2_CID_EXPOSURE, 500, 1500, 1, 1024);
16558c2ecf20Sopenharmony_ci		gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16568c2ecf20Sopenharmony_ci			V4L2_CID_GAIN, 4, 49, 1, 15);
16578c2ecf20Sopenharmony_ci		sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16588c2ecf20Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
16598c2ecf20Sopenharmony_ci	}
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	if (sd->sensor != SENSOR_ADCM1700 && sd->sensor != SENSOR_OV7660 &&
16628c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_PO1030 && sd->sensor != SENSOR_SOI768 &&
16638c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_SP80708)
16648c2ecf20Sopenharmony_ci		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16658c2ecf20Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_HV7131R || sd->sensor == SENSOR_OV7630 ||
16688c2ecf20Sopenharmony_ci	    sd->sensor == SENSOR_OV7648 || sd->sensor == SENSOR_PO2030N)
16698c2ecf20Sopenharmony_ci		sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
16708c2ecf20Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_OV7630 || sd->sensor == SENSOR_OV7648 ||
16738c2ecf20Sopenharmony_ci	    sd->sensor == SENSOR_OV7660)
16748c2ecf20Sopenharmony_ci		sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
16758c2ecf20Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY,
16768c2ecf20Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
16778c2ecf20Sopenharmony_ci			V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	if (hdl->error) {
16808c2ecf20Sopenharmony_ci		pr_err("Could not initialize controls\n");
16818c2ecf20Sopenharmony_ci		return hdl->error;
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	v4l2_ctrl_cluster(2, &sd->red_bal);
16858c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
16868c2ecf20Sopenharmony_ci		v4l2_ctrl_cluster(2, &sd->vflip);
16878c2ecf20Sopenharmony_ci		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
16888c2ecf20Sopenharmony_ci	}
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci	return 0;
16918c2ecf20Sopenharmony_ci}
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_cistatic u32 expo_adjust(struct gspca_dev *gspca_dev,
16948c2ecf20Sopenharmony_ci			u32 expo)
16958c2ecf20Sopenharmony_ci{
16968c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
16978c2ecf20Sopenharmony_ci
16988c2ecf20Sopenharmony_ci	switch (sd->sensor) {
16998c2ecf20Sopenharmony_ci	case SENSOR_GC0307: {
17008c2ecf20Sopenharmony_ci		int a, b;
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci		/* expo = 0..255 -> a = 19..43 */
17038c2ecf20Sopenharmony_ci		a = 19 + expo * 25 / 256;
17048c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x68, a);
17058c2ecf20Sopenharmony_ci		a -= 12;
17068c2ecf20Sopenharmony_ci		b = a * a * 4;			/* heuristic */
17078c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x03, b >> 8);
17088c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x04, b);
17098c2ecf20Sopenharmony_ci		break;
17108c2ecf20Sopenharmony_ci	    }
17118c2ecf20Sopenharmony_ci	case SENSOR_HV7131R: {
17128c2ecf20Sopenharmony_ci		u8 Expodoit[] =
17138c2ecf20Sopenharmony_ci			{ 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci		Expodoit[3] = expo >> 16;
17168c2ecf20Sopenharmony_ci		Expodoit[4] = expo >> 8;
17178c2ecf20Sopenharmony_ci		Expodoit[5] = expo;
17188c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, Expodoit);
17198c2ecf20Sopenharmony_ci		break;
17208c2ecf20Sopenharmony_ci	    }
17218c2ecf20Sopenharmony_ci	case SENSOR_MI0360:
17228c2ecf20Sopenharmony_ci	case SENSOR_MI0360B: {
17238c2ecf20Sopenharmony_ci		u8 expoMi[] =		/* exposure 0x0635 -> 4 fp/s 0x10 */
17248c2ecf20Sopenharmony_ci			{ 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
17258c2ecf20Sopenharmony_ci		static const u8 doit[] =		/* update sensor */
17268c2ecf20Sopenharmony_ci			{ 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
17278c2ecf20Sopenharmony_ci		static const u8 sensorgo[] =		/* sensor on */
17288c2ecf20Sopenharmony_ci			{ 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci		if (expo > 0x0635)
17318c2ecf20Sopenharmony_ci			expo = 0x0635;
17328c2ecf20Sopenharmony_ci		else if (expo < 0x0001)
17338c2ecf20Sopenharmony_ci			expo = 0x0001;
17348c2ecf20Sopenharmony_ci		expoMi[3] = expo >> 8;
17358c2ecf20Sopenharmony_ci		expoMi[4] = expo;
17368c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, expoMi);
17378c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, doit);
17388c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, sensorgo);
17398c2ecf20Sopenharmony_ci		break;
17408c2ecf20Sopenharmony_ci	    }
17418c2ecf20Sopenharmony_ci	case SENSOR_MO4000: {
17428c2ecf20Sopenharmony_ci		u8 expoMof[] =
17438c2ecf20Sopenharmony_ci			{ 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
17448c2ecf20Sopenharmony_ci		u8 expoMo10[] =
17458c2ecf20Sopenharmony_ci			{ 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
17468c2ecf20Sopenharmony_ci		static const u8 gainMo[] =
17478c2ecf20Sopenharmony_ci			{ 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
17488c2ecf20Sopenharmony_ci
17498c2ecf20Sopenharmony_ci		if (expo > 0x1fff)
17508c2ecf20Sopenharmony_ci			expo = 0x1fff;
17518c2ecf20Sopenharmony_ci		else if (expo < 0x0001)
17528c2ecf20Sopenharmony_ci			expo = 0x0001;
17538c2ecf20Sopenharmony_ci		expoMof[3] = (expo & 0x03fc) >> 2;
17548c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, expoMof);
17558c2ecf20Sopenharmony_ci		expoMo10[3] = ((expo & 0x1c00) >> 10)
17568c2ecf20Sopenharmony_ci				| ((expo & 0x0003) << 4);
17578c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, expoMo10);
17588c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, gainMo);
17598c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_FRAM, "set exposure %d\n",
17608c2ecf20Sopenharmony_ci			  ((expoMo10[3] & 0x07) << 10)
17618c2ecf20Sopenharmony_ci			  | (expoMof[3] << 2)
17628c2ecf20Sopenharmony_ci			  | ((expoMo10[3] & 0x30) >> 4));
17638c2ecf20Sopenharmony_ci		break;
17648c2ecf20Sopenharmony_ci	    }
17658c2ecf20Sopenharmony_ci	case SENSOR_MT9V111: {
17668c2ecf20Sopenharmony_ci		u8 expo_c1[] =
17678c2ecf20Sopenharmony_ci			{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci		if (expo > 0x0390)
17708c2ecf20Sopenharmony_ci			expo = 0x0390;
17718c2ecf20Sopenharmony_ci		else if (expo < 0x0060)
17728c2ecf20Sopenharmony_ci			expo = 0x0060;
17738c2ecf20Sopenharmony_ci		expo_c1[3] = expo >> 8;
17748c2ecf20Sopenharmony_ci		expo_c1[4] = expo;
17758c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, expo_c1);
17768c2ecf20Sopenharmony_ci		break;
17778c2ecf20Sopenharmony_ci	    }
17788c2ecf20Sopenharmony_ci	case SENSOR_OM6802: {
17798c2ecf20Sopenharmony_ci		u8 gainOm[] =
17808c2ecf20Sopenharmony_ci			{ 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
17818c2ecf20Sopenharmony_ci				/* preset AGC - works when AutoExpo = off */
17828c2ecf20Sopenharmony_ci
17838c2ecf20Sopenharmony_ci		if (expo > 0x03ff)
17848c2ecf20Sopenharmony_ci			expo = 0x03ff;
17858c2ecf20Sopenharmony_ci		if (expo < 0x0001)
17868c2ecf20Sopenharmony_ci			expo = 0x0001;
17878c2ecf20Sopenharmony_ci		gainOm[3] = expo >> 2;
17888c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, gainOm);
17898c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x96, expo >> 5);
17908c2ecf20Sopenharmony_ci		gspca_dbg(gspca_dev, D_FRAM, "set exposure %d\n", gainOm[3]);
17918c2ecf20Sopenharmony_ci		break;
17928c2ecf20Sopenharmony_ci	    }
17938c2ecf20Sopenharmony_ci	}
17948c2ecf20Sopenharmony_ci	return expo;
17958c2ecf20Sopenharmony_ci}
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev)
17988c2ecf20Sopenharmony_ci{
17998c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
18008c2ecf20Sopenharmony_ci	unsigned int expo;
18018c2ecf20Sopenharmony_ci	int brightness = sd->brightness->val;
18028c2ecf20Sopenharmony_ci	u8 k2;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	k2 = (brightness - 0x80) >> 2;
18058c2ecf20Sopenharmony_ci	switch (sd->sensor) {
18068c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
18078c2ecf20Sopenharmony_ci		if (k2 > 0x1f)
18088c2ecf20Sopenharmony_ci			k2 = 0;		/* only positive Y offset */
18098c2ecf20Sopenharmony_ci		break;
18108c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
18118c2ecf20Sopenharmony_ci		expo = brightness << 12;
18128c2ecf20Sopenharmony_ci		if (expo > 0x002dc6c0)
18138c2ecf20Sopenharmony_ci			expo = 0x002dc6c0;
18148c2ecf20Sopenharmony_ci		else if (expo < 0x02a0)
18158c2ecf20Sopenharmony_ci			expo = 0x02a0;
18168c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18178c2ecf20Sopenharmony_ci		break;
18188c2ecf20Sopenharmony_ci	case SENSOR_MI0360:
18198c2ecf20Sopenharmony_ci	case SENSOR_MO4000:
18208c2ecf20Sopenharmony_ci		expo = brightness << 4;
18218c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18228c2ecf20Sopenharmony_ci		break;
18238c2ecf20Sopenharmony_ci	case SENSOR_MI0360B:
18248c2ecf20Sopenharmony_ci		expo = brightness << 2;
18258c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18268c2ecf20Sopenharmony_ci		break;
18278c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
18288c2ecf20Sopenharmony_ci		expo = brightness;
18298c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18308c2ecf20Sopenharmony_ci		return;			/* don't set the Y offset */
18318c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
18328c2ecf20Sopenharmony_ci		expo = brightness << 2;
18338c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18348c2ecf20Sopenharmony_ci		return;			/* don't set the Y offset */
18358c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
18368c2ecf20Sopenharmony_ci		expo = brightness << 2;
18378c2ecf20Sopenharmony_ci		sd->exposure = expo_adjust(gspca_dev, expo);
18388c2ecf20Sopenharmony_ci		return;			/* Y offset already set */
18398c2ecf20Sopenharmony_ci	}
18408c2ecf20Sopenharmony_ci
18418c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x96, k2);	/* color matrix Y offset */
18428c2ecf20Sopenharmony_ci}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_cistatic void setcontrast(struct gspca_dev *gspca_dev)
18458c2ecf20Sopenharmony_ci{
18468c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
18478c2ecf20Sopenharmony_ci	u8 k2;
18488c2ecf20Sopenharmony_ci	u8 contrast[6];
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	k2 = sd->contrast->val * 37 / (CONTRAST_MAX + 1)
18518c2ecf20Sopenharmony_ci				+ 37;		/* 37..73 */
18528c2ecf20Sopenharmony_ci	contrast[0] = (k2 + 1) / 2;		/* red */
18538c2ecf20Sopenharmony_ci	contrast[1] = 0;
18548c2ecf20Sopenharmony_ci	contrast[2] = k2;			/* green */
18558c2ecf20Sopenharmony_ci	contrast[3] = 0;
18568c2ecf20Sopenharmony_ci	contrast[4] = k2 / 5;			/* blue */
18578c2ecf20Sopenharmony_ci	contrast[5] = 0;
18588c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
18598c2ecf20Sopenharmony_ci}
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_cistatic void setcolors(struct gspca_dev *gspca_dev)
18628c2ecf20Sopenharmony_ci{
18638c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
18648c2ecf20Sopenharmony_ci	int i, v, colors;
18658c2ecf20Sopenharmony_ci	const s16 *uv;
18668c2ecf20Sopenharmony_ci	u8 reg8a[12];			/* U & V gains */
18678c2ecf20Sopenharmony_ci	static const s16 uv_com[6] = {	/* same as reg84 in signed decimal */
18688c2ecf20Sopenharmony_ci		-24, -38, 64,		/* UR UG UB */
18698c2ecf20Sopenharmony_ci		 62, -51, -9		/* VR VG VB */
18708c2ecf20Sopenharmony_ci	};
18718c2ecf20Sopenharmony_ci	static const s16 uv_mi0360b[6] = {
18728c2ecf20Sopenharmony_ci		-20, -38, 64,		/* UR UG UB */
18738c2ecf20Sopenharmony_ci		 60, -51, -9		/* VR VG VB */
18748c2ecf20Sopenharmony_ci	};
18758c2ecf20Sopenharmony_ci
18768c2ecf20Sopenharmony_ci	colors = sd->saturation->val;
18778c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_MI0360B)
18788c2ecf20Sopenharmony_ci		uv = uv_mi0360b;
18798c2ecf20Sopenharmony_ci	else
18808c2ecf20Sopenharmony_ci		uv = uv_com;
18818c2ecf20Sopenharmony_ci	for (i = 0; i < 6; i++) {
18828c2ecf20Sopenharmony_ci		v = uv[i] * colors / COLORS_DEF;
18838c2ecf20Sopenharmony_ci		reg8a[i * 2] = v;
18848c2ecf20Sopenharmony_ci		reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
18858c2ecf20Sopenharmony_ci	}
18868c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
18878c2ecf20Sopenharmony_ci}
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_cistatic void setredblue(struct gspca_dev *gspca_dev)
18908c2ecf20Sopenharmony_ci{
18918c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
18948c2ecf20Sopenharmony_ci		u8 rg1b[] =		/* red  green1 blue (no g2) */
18958c2ecf20Sopenharmony_ci			{0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci		/* 0x40 = normal value = gain x 1 */
18988c2ecf20Sopenharmony_ci		rg1b[3] = sd->red_bal->val * 2;
18998c2ecf20Sopenharmony_ci		rg1b[5] = sd->blue_bal->val * 2;
19008c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, rg1b);
19018c2ecf20Sopenharmony_ci		return;
19028c2ecf20Sopenharmony_ci	}
19038c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x05, sd->red_bal->val);
19048c2ecf20Sopenharmony_ci/*	reg_w1(gspca_dev, 0x07, 32); */
19058c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x06, sd->blue_bal->val);
19068c2ecf20Sopenharmony_ci}
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_cistatic void setgamma(struct gspca_dev *gspca_dev)
19098c2ecf20Sopenharmony_ci{
19108c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
19118c2ecf20Sopenharmony_ci	int i, val;
19128c2ecf20Sopenharmony_ci	u8 gamma[17];
19138c2ecf20Sopenharmony_ci	const u8 *gamma_base;
19148c2ecf20Sopenharmony_ci	static const u8 delta[17] = {
19158c2ecf20Sopenharmony_ci		0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
19168c2ecf20Sopenharmony_ci		0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
19178c2ecf20Sopenharmony_ci	};
19188c2ecf20Sopenharmony_ci
19198c2ecf20Sopenharmony_ci	switch (sd->sensor) {
19208c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
19218c2ecf20Sopenharmony_ci		gamma_base = gamma_spec_0;
19228c2ecf20Sopenharmony_ci		break;
19238c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
19248c2ecf20Sopenharmony_ci	case SENSOR_MI0360B:
19258c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
19268c2ecf20Sopenharmony_ci		gamma_base = gamma_spec_1;
19278c2ecf20Sopenharmony_ci		break;
19288c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
19298c2ecf20Sopenharmony_ci		gamma_base = gamma_spec_2;
19308c2ecf20Sopenharmony_ci		break;
19318c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
19328c2ecf20Sopenharmony_ci		gamma_base = gamma_spec_3;
19338c2ecf20Sopenharmony_ci		break;
19348c2ecf20Sopenharmony_ci	default:
19358c2ecf20Sopenharmony_ci		gamma_base = gamma_def;
19368c2ecf20Sopenharmony_ci		break;
19378c2ecf20Sopenharmony_ci	}
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci	val = sd->gamma->val;
19408c2ecf20Sopenharmony_ci	for (i = 0; i < sizeof gamma; i++)
19418c2ecf20Sopenharmony_ci		gamma[i] = gamma_base[i]
19428c2ecf20Sopenharmony_ci			+ delta[i] * (val - GAMMA_DEF) / 32;
19438c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
19448c2ecf20Sopenharmony_ci}
19458c2ecf20Sopenharmony_ci
19468c2ecf20Sopenharmony_cistatic void setexposure(struct gspca_dev *gspca_dev)
19478c2ecf20Sopenharmony_ci{
19488c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
19498c2ecf20Sopenharmony_ci
19508c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
19518c2ecf20Sopenharmony_ci		u8 rexpo[] =		/* 1a: expo H, 1b: expo M */
19528c2ecf20Sopenharmony_ci			{0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci		rexpo[3] = gspca_dev->exposure->val >> 8;
19558c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, rexpo);
19568c2ecf20Sopenharmony_ci		msleep(6);
19578c2ecf20Sopenharmony_ci		rexpo[2] = 0x1b;
19588c2ecf20Sopenharmony_ci		rexpo[3] = gspca_dev->exposure->val;
19598c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, rexpo);
19608c2ecf20Sopenharmony_ci	}
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_cistatic void setautogain(struct gspca_dev *gspca_dev)
19648c2ecf20Sopenharmony_ci{
19658c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	switch (sd->sensor) {
19688c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
19698c2ecf20Sopenharmony_ci	case SENSOR_OV7648: {
19708c2ecf20Sopenharmony_ci		u8 comb;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci		if (sd->sensor == SENSOR_OV7630)
19738c2ecf20Sopenharmony_ci			comb = 0xc0;
19748c2ecf20Sopenharmony_ci		else
19758c2ecf20Sopenharmony_ci			comb = 0xa0;
19768c2ecf20Sopenharmony_ci		if (gspca_dev->autogain->val)
19778c2ecf20Sopenharmony_ci			comb |= 0x03;
19788c2ecf20Sopenharmony_ci		i2c_w1(&sd->gspca_dev, 0x13, comb);
19798c2ecf20Sopenharmony_ci		return;
19808c2ecf20Sopenharmony_ci	    }
19818c2ecf20Sopenharmony_ci	}
19828c2ecf20Sopenharmony_ci	if (gspca_dev->autogain->val)
19838c2ecf20Sopenharmony_ci		sd->ag_cnt = AG_CNT_START;
19848c2ecf20Sopenharmony_ci	else
19858c2ecf20Sopenharmony_ci		sd->ag_cnt = -1;
19868c2ecf20Sopenharmony_ci}
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_cistatic void setgain(struct gspca_dev *gspca_dev)
19898c2ecf20Sopenharmony_ci{
19908c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
19938c2ecf20Sopenharmony_ci		u8 rgain[] =		/* 15: gain */
19948c2ecf20Sopenharmony_ci			{0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci		rgain[3] = gspca_dev->gain->val;
19978c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, rgain);
19988c2ecf20Sopenharmony_ci	}
19998c2ecf20Sopenharmony_ci}
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_cistatic void sethvflip(struct gspca_dev *gspca_dev)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20048c2ecf20Sopenharmony_ci	u8 comn;
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	switch (sd->sensor) {
20078c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
20088c2ecf20Sopenharmony_ci		comn = 0x18;			/* clkdiv = 1, ablcen = 1 */
20098c2ecf20Sopenharmony_ci		if (sd->vflip->val)
20108c2ecf20Sopenharmony_ci			comn |= 0x01;
20118c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x01, comn);	/* sctra */
20128c2ecf20Sopenharmony_ci		break;
20138c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
20148c2ecf20Sopenharmony_ci		comn = 0x02;
20158c2ecf20Sopenharmony_ci		if (!sd->vflip->val)
20168c2ecf20Sopenharmony_ci			comn |= 0x80;
20178c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x75, comn);
20188c2ecf20Sopenharmony_ci		break;
20198c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
20208c2ecf20Sopenharmony_ci		comn = 0x06;
20218c2ecf20Sopenharmony_ci		if (sd->vflip->val)
20228c2ecf20Sopenharmony_ci			comn |= 0x80;
20238c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x75, comn);
20248c2ecf20Sopenharmony_ci		break;
20258c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
20268c2ecf20Sopenharmony_ci		/* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
20278c2ecf20Sopenharmony_ci		 * (reset value: 0x0A)
20288c2ecf20Sopenharmony_ci		 * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
20298c2ecf20Sopenharmony_ci		 * bit6: VM: Vertical Mirror: 0: disable, 1: enable
20308c2ecf20Sopenharmony_ci		 * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
20318c2ecf20Sopenharmony_ci		 * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
20328c2ecf20Sopenharmony_ci		 * bit3-0: X
20338c2ecf20Sopenharmony_ci		 */
20348c2ecf20Sopenharmony_ci		comn = 0x0a;
20358c2ecf20Sopenharmony_ci		if (sd->hflip->val)
20368c2ecf20Sopenharmony_ci			comn |= 0x80;
20378c2ecf20Sopenharmony_ci		if (sd->vflip->val)
20388c2ecf20Sopenharmony_ci			comn |= 0x40;
20398c2ecf20Sopenharmony_ci		i2c_w1(&sd->gspca_dev, 0x1e, comn);
20408c2ecf20Sopenharmony_ci		break;
20418c2ecf20Sopenharmony_ci	}
20428c2ecf20Sopenharmony_ci}
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_cistatic void setsharpness(struct gspca_dev *gspca_dev)
20458c2ecf20Sopenharmony_ci{
20468c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x99, sd->sharpness->val);
20498c2ecf20Sopenharmony_ci}
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_cistatic void setillum(struct gspca_dev *gspca_dev)
20528c2ecf20Sopenharmony_ci{
20538c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	switch (sd->sensor) {
20568c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
20578c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02,				/* gpio */
20588c2ecf20Sopenharmony_ci			sd->illum->val ? 0x64 : 0x60);
20598c2ecf20Sopenharmony_ci		break;
20608c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
20618c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02,
20628c2ecf20Sopenharmony_ci			sd->illum->val ? 0x77 : 0x74);
20638c2ecf20Sopenharmony_ci/* should have been: */
20648c2ecf20Sopenharmony_ci/*						0x55 : 0x54);	* 370i */
20658c2ecf20Sopenharmony_ci/*						0x66 : 0x64);	* Clip */
20668c2ecf20Sopenharmony_ci		break;
20678c2ecf20Sopenharmony_ci	}
20688c2ecf20Sopenharmony_ci}
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_cistatic void setfreq(struct gspca_dev *gspca_dev)
20718c2ecf20Sopenharmony_ci{
20728c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_OV7660) {
20758c2ecf20Sopenharmony_ci		u8 com8;
20768c2ecf20Sopenharmony_ci
20778c2ecf20Sopenharmony_ci		com8 = 0xdf;		/* auto gain/wb/expo */
20788c2ecf20Sopenharmony_ci		switch (sd->freq->val) {
20798c2ecf20Sopenharmony_ci		case 0: /* Banding filter disabled */
20808c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8 | 0x20);
20818c2ecf20Sopenharmony_ci			break;
20828c2ecf20Sopenharmony_ci		case 1: /* 50 hz */
20838c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8);
20848c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x3b, 0x0a);
20858c2ecf20Sopenharmony_ci			break;
20868c2ecf20Sopenharmony_ci		case 2: /* 60 hz */
20878c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x13, com8);
20888c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x3b, 0x02);
20898c2ecf20Sopenharmony_ci			break;
20908c2ecf20Sopenharmony_ci		}
20918c2ecf20Sopenharmony_ci	} else {
20928c2ecf20Sopenharmony_ci		u8 reg2a = 0, reg2b = 0, reg2d = 0;
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci		/* Get reg2a / reg2d base values */
20958c2ecf20Sopenharmony_ci		switch (sd->sensor) {
20968c2ecf20Sopenharmony_ci		case SENSOR_OV7630:
20978c2ecf20Sopenharmony_ci			reg2a = 0x08;
20988c2ecf20Sopenharmony_ci			reg2d = 0x01;
20998c2ecf20Sopenharmony_ci			break;
21008c2ecf20Sopenharmony_ci		case SENSOR_OV7648:
21018c2ecf20Sopenharmony_ci			reg2a = 0x11;
21028c2ecf20Sopenharmony_ci			reg2d = 0x81;
21038c2ecf20Sopenharmony_ci			break;
21048c2ecf20Sopenharmony_ci		}
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci		switch (sd->freq->val) {
21078c2ecf20Sopenharmony_ci		case 0: /* Banding filter disabled */
21088c2ecf20Sopenharmony_ci			break;
21098c2ecf20Sopenharmony_ci		case 1: /* 50 hz (filter on and framerate adj) */
21108c2ecf20Sopenharmony_ci			reg2a |= 0x80;
21118c2ecf20Sopenharmony_ci			reg2b = 0xac;
21128c2ecf20Sopenharmony_ci			reg2d |= 0x04;
21138c2ecf20Sopenharmony_ci			break;
21148c2ecf20Sopenharmony_ci		case 2: /* 60 hz (filter on, no framerate adj) */
21158c2ecf20Sopenharmony_ci			reg2a |= 0x80;
21168c2ecf20Sopenharmony_ci			reg2d |= 0x04;
21178c2ecf20Sopenharmony_ci			break;
21188c2ecf20Sopenharmony_ci		}
21198c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x2a, reg2a);
21208c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x2b, reg2b);
21218c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x2d, reg2d);
21228c2ecf20Sopenharmony_ci	}
21238c2ecf20Sopenharmony_ci}
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_cistatic void setjpegqual(struct gspca_dev *gspca_dev)
21268c2ecf20Sopenharmony_ci{
21278c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
21308c2ecf20Sopenharmony_ci#if USB_BUF_SZ < 64
21318c2ecf20Sopenharmony_ci#error "No room enough in usb_buf for quantization table"
21328c2ecf20Sopenharmony_ci#endif
21338c2ecf20Sopenharmony_ci	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
21348c2ecf20Sopenharmony_ci	usb_control_msg(gspca_dev->dev,
21358c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
21368c2ecf20Sopenharmony_ci			0x08,
21378c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
21388c2ecf20Sopenharmony_ci			0x0100, 0,
21398c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 64,
21408c2ecf20Sopenharmony_ci			500);
21418c2ecf20Sopenharmony_ci	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
21428c2ecf20Sopenharmony_ci	usb_control_msg(gspca_dev->dev,
21438c2ecf20Sopenharmony_ci			usb_sndctrlpipe(gspca_dev->dev, 0),
21448c2ecf20Sopenharmony_ci			0x08,
21458c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
21468c2ecf20Sopenharmony_ci			0x0140, 0,
21478c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 64,
21488c2ecf20Sopenharmony_ci			500);
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	sd->reg18 ^= 0x40;
21518c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sd->reg18);
21528c2ecf20Sopenharmony_ci}
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci/* JPEG quality update */
21558c2ecf20Sopenharmony_ci/* This function is executed from a work queue. */
21568c2ecf20Sopenharmony_cistatic void qual_upd(struct work_struct *work)
21578c2ecf20Sopenharmony_ci{
21588c2ecf20Sopenharmony_ci	struct sd *sd = container_of(work, struct sd, work);
21598c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev = &sd->gspca_dev;
21608c2ecf20Sopenharmony_ci
21618c2ecf20Sopenharmony_ci	/* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
21628c2ecf20Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
21638c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "qual_upd %d%%\n", sd->quality);
21648c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
21658c2ecf20Sopenharmony_ci	setjpegqual(gspca_dev);
21668c2ecf20Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
21678c2ecf20Sopenharmony_ci}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci/* -- start the camera -- */
21708c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
21718c2ecf20Sopenharmony_ci{
21728c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21738c2ecf20Sopenharmony_ci	int i;
21748c2ecf20Sopenharmony_ci	u8 reg01, reg17;
21758c2ecf20Sopenharmony_ci	u8 reg0102[2];
21768c2ecf20Sopenharmony_ci	const u8 *sn9c1xx;
21778c2ecf20Sopenharmony_ci	const u8 (*init)[8];
21788c2ecf20Sopenharmony_ci	const u8 *reg9a;
21798c2ecf20Sopenharmony_ci	int mode;
21808c2ecf20Sopenharmony_ci	static const u8 reg9a_def[] =
21818c2ecf20Sopenharmony_ci		{0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
21828c2ecf20Sopenharmony_ci	static const u8 reg9a_spec[] =
21838c2ecf20Sopenharmony_ci		{0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
21848c2ecf20Sopenharmony_ci	static const u8 regd4[] = {0x60, 0x00, 0x00};
21858c2ecf20Sopenharmony_ci	static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
21868c2ecf20Sopenharmony_ci	static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
21878c2ecf20Sopenharmony_ci	static const u8 CA_adcm1700[] =
21888c2ecf20Sopenharmony_ci				{ 0x14, 0xec, 0x0a, 0xf6 };
21898c2ecf20Sopenharmony_ci	static const u8 CA_po2030n[] =
21908c2ecf20Sopenharmony_ci				{ 0x1e, 0xe2, 0x14, 0xec };
21918c2ecf20Sopenharmony_ci	static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };	/* MI0360 */
21928c2ecf20Sopenharmony_ci	static const u8 CE_gc0307[] =
21938c2ecf20Sopenharmony_ci				{ 0x32, 0xce, 0x2d, 0xd3 };
21948c2ecf20Sopenharmony_ci	static const u8 CE_ov76xx[] =
21958c2ecf20Sopenharmony_ci				{ 0x32, 0xdd, 0x32, 0xdd };
21968c2ecf20Sopenharmony_ci	static const u8 CE_po2030n[] =
21978c2ecf20Sopenharmony_ci				{ 0x14, 0xe7, 0x1e, 0xdd };
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci	/* create the JPEG header */
22008c2ecf20Sopenharmony_ci	jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
22018c2ecf20Sopenharmony_ci			gspca_dev->pixfmt.width,
22028c2ecf20Sopenharmony_ci			0x21);		/* JPEG 422 */
22038c2ecf20Sopenharmony_ci
22048c2ecf20Sopenharmony_ci	/* initialize the bridge */
22058c2ecf20Sopenharmony_ci	sn9c1xx = sn_tb[sd->sensor];
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	/* sensor clock already enabled in sd_init */
22088c2ecf20Sopenharmony_ci	/* reg_w1(gspca_dev, 0xf1, 0x00); */
22098c2ecf20Sopenharmony_ci	reg01 = sn9c1xx[1];
22108c2ecf20Sopenharmony_ci	if (sd->flags & F_PDN_INV)
22118c2ecf20Sopenharmony_ci		reg01 ^= S_PDN_INV;		/* power down inverted */
22128c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
22138c2ecf20Sopenharmony_ci
22148c2ecf20Sopenharmony_ci	/* configure gpio */
22158c2ecf20Sopenharmony_ci	reg0102[0] = reg01;
22168c2ecf20Sopenharmony_ci	reg0102[1] = sn9c1xx[2];
22178c2ecf20Sopenharmony_ci	if (gspca_dev->audio)
22188c2ecf20Sopenharmony_ci		reg0102[1] |= 0x04;	/* keep the audio connection */
22198c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x01, reg0102, 2);
22208c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
22218c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
22228c2ecf20Sopenharmony_ci	switch (sd->sensor) {
22238c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
22248c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
22258c2ecf20Sopenharmony_ci	case SENSOR_PO1030:
22268c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
22278c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
22288c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
22298c2ecf20Sopenharmony_ci		reg9a = reg9a_spec;
22308c2ecf20Sopenharmony_ci		break;
22318c2ecf20Sopenharmony_ci	default:
22328c2ecf20Sopenharmony_ci		reg9a = reg9a_def;
22338c2ecf20Sopenharmony_ci		break;
22348c2ecf20Sopenharmony_ci	}
22358c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x9a, reg9a, 6);
22368c2ecf20Sopenharmony_ci
22378c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	reg17 = sn9c1xx[0x17];
22428c2ecf20Sopenharmony_ci	switch (sd->sensor) {
22438c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
22448c2ecf20Sopenharmony_ci		msleep(50);		/*fixme: is it useful? */
22458c2ecf20Sopenharmony_ci		break;
22468c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
22478c2ecf20Sopenharmony_ci		msleep(10);
22488c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x73);
22498c2ecf20Sopenharmony_ci		reg17 |= SEN_CLK_EN;
22508c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x17, reg17);
22518c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, 0x22);
22528c2ecf20Sopenharmony_ci		msleep(100);
22538c2ecf20Sopenharmony_ci		reg01 = SCL_SEL_OD | S_PDN_INV;
22548c2ecf20Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
22558c2ecf20Sopenharmony_ci		reg17 |= 0x04;		/* clock / 4 */
22568c2ecf20Sopenharmony_ci		break;
22578c2ecf20Sopenharmony_ci	}
22588c2ecf20Sopenharmony_ci	reg01 |= SYS_SEL_48M;
22598c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
22608c2ecf20Sopenharmony_ci	reg17 |= SEN_CLK_EN;
22618c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
22628c2ecf20Sopenharmony_ci	reg01 &= ~S_PWR_DN;		/* sensor power on */
22638c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
22648c2ecf20Sopenharmony_ci	reg01 &= ~SCL_SEL_OD;		/* remove open-drain mode */
22658c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	switch (sd->sensor) {
22688c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
22698c2ecf20Sopenharmony_ci		hv7131r_probe(gspca_dev);	/*fixme: is it useful? */
22708c2ecf20Sopenharmony_ci		break;
22718c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
22728c2ecf20Sopenharmony_ci		msleep(10);
22738c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
22748c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, om6802_init0[0]);
22758c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, om6802_init0[1]);
22768c2ecf20Sopenharmony_ci		msleep(15);
22778c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x71);
22788c2ecf20Sopenharmony_ci		msleep(150);
22798c2ecf20Sopenharmony_ci		break;
22808c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
22818c2ecf20Sopenharmony_ci		msleep(100);
22828c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x02, 0x62);
22838c2ecf20Sopenharmony_ci		break;
22848c2ecf20Sopenharmony_ci	}
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	/* initialize the sensor */
22878c2ecf20Sopenharmony_ci	i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
22888c2ecf20Sopenharmony_ci
22898c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
22908c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
22918c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
22928c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
22938c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
22948c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
22958c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xd2, 0x3a);	/* AE_H_SIZE = 116 */
22968c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xd3, 0x30);	/* AE_V_SIZE = 96 */
22978c2ecf20Sopenharmony_ci	} else {
22988c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xd2, 0x6a);	/* AE_H_SIZE = 212 */
22998c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xd3, 0x50);	/* AE_V_SIZE = 160 */
23008c2ecf20Sopenharmony_ci	}
23018c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0xc6, 0x00);
23028c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0xc7, 0x00);
23038c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_ADCM1700) {
23048c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xc8, 0x2c);	/* AW_H_STOP = 352 */
23058c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xc9, 0x24);	/* AW_V_STOP = 288 */
23068c2ecf20Sopenharmony_ci	} else {
23078c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xc8, 0x50);	/* AW_H_STOP = 640 */
23088c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0xc9, 0x3c);	/* AW_V_STOP = 480 */
23098c2ecf20Sopenharmony_ci	}
23108c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
23118c2ecf20Sopenharmony_ci	switch (sd->sensor) {
23128c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
23138c2ecf20Sopenharmony_ci/*	case SENSOR_OV7648:		* fixme: sometimes */
23148c2ecf20Sopenharmony_ci		break;
23158c2ecf20Sopenharmony_ci	default:
23168c2ecf20Sopenharmony_ci		reg17 |= DEF_EN;
23178c2ecf20Sopenharmony_ci		break;
23188c2ecf20Sopenharmony_ci	}
23198c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x05, 0x00);		/* red */
23228c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x07, 0x00);		/* green */
23238c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x06, 0x00);		/* blue */
23248c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
23258c2ecf20Sopenharmony_ci
23268c2ecf20Sopenharmony_ci	setgamma(gspca_dev);
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
23298c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++)
23308c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
23318c2ecf20Sopenharmony_ci	switch (sd->sensor) {
23328c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
23338c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
23348c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
23358c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x05);
23368c2ecf20Sopenharmony_ci		break;
23378c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
23388c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
23398c2ecf20Sopenharmony_ci	case SENSOR_MI0360B:
23408c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x07);
23418c2ecf20Sopenharmony_ci		break;
23428c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
23438c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
23448c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x0a);
23458c2ecf20Sopenharmony_ci		break;
23468c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
23478c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
23488c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x06);
23498c2ecf20Sopenharmony_ci		break;
23508c2ecf20Sopenharmony_ci	default:
23518c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x9a, 0x08);
23528c2ecf20Sopenharmony_ci		break;
23538c2ecf20Sopenharmony_ci	}
23548c2ecf20Sopenharmony_ci	setsharpness(gspca_dev);
23558c2ecf20Sopenharmony_ci
23568c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
23578c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x05, 0x20);		/* red */
23588c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x07, 0x20);		/* green */
23598c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x06, 0x20);		/* blue */
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci	init = NULL;
23628c2ecf20Sopenharmony_ci	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
23638c2ecf20Sopenharmony_ci	reg01 |= SYS_SEL_48M | V_TX_EN;
23648c2ecf20Sopenharmony_ci	reg17 &= ~MCK_SIZE_MASK;
23658c2ecf20Sopenharmony_ci	reg17 |= 0x02;			/* clock / 2 */
23668c2ecf20Sopenharmony_ci	switch (sd->sensor) {
23678c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
23688c2ecf20Sopenharmony_ci		init = adcm1700_sensor_param1;
23698c2ecf20Sopenharmony_ci		break;
23708c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
23718c2ecf20Sopenharmony_ci		init = gc0307_sensor_param1;
23728c2ecf20Sopenharmony_ci		break;
23738c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
23748c2ecf20Sopenharmony_ci	case SENSOR_MI0360:
23758c2ecf20Sopenharmony_ci		if (!mode)
23768c2ecf20Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* 640x480: clk 24Mhz */
23778c2ecf20Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
23788c2ecf20Sopenharmony_ci		reg17 |= 0x01;			/* clock / 1 */
23798c2ecf20Sopenharmony_ci		break;
23808c2ecf20Sopenharmony_ci	case SENSOR_MI0360B:
23818c2ecf20Sopenharmony_ci		init = mi0360b_sensor_param1;
23828c2ecf20Sopenharmony_ci		break;
23838c2ecf20Sopenharmony_ci	case SENSOR_MO4000:
23848c2ecf20Sopenharmony_ci		if (mode) {			/* if 320x240 */
23858c2ecf20Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
23868c2ecf20Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
23878c2ecf20Sopenharmony_ci			reg17 |= 0x01;		/* clock / 1 */
23888c2ecf20Sopenharmony_ci		}
23898c2ecf20Sopenharmony_ci		break;
23908c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
23918c2ecf20Sopenharmony_ci		init = mt9v111_sensor_param1;
23928c2ecf20Sopenharmony_ci		break;
23938c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
23948c2ecf20Sopenharmony_ci		init = om6802_sensor_param1;
23958c2ecf20Sopenharmony_ci		if (!mode) {			/* if 640x480 */
23968c2ecf20Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
23978c2ecf20Sopenharmony_ci			reg17 |= 0x04;		/* clock / 4 */
23988c2ecf20Sopenharmony_ci		} else {
23998c2ecf20Sopenharmony_ci			reg01 &= ~SYS_SEL_48M;	/* clk 24Mz */
24008c2ecf20Sopenharmony_ci			reg17 &= ~MCK_SIZE_MASK;
24018c2ecf20Sopenharmony_ci			reg17 |= 0x02;		/* clock / 2 */
24028c2ecf20Sopenharmony_ci		}
24038c2ecf20Sopenharmony_ci		break;
24048c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
24058c2ecf20Sopenharmony_ci		init = ov7630_sensor_param1;
24068c2ecf20Sopenharmony_ci		break;
24078c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
24088c2ecf20Sopenharmony_ci		init = ov7648_sensor_param1;
24098c2ecf20Sopenharmony_ci		reg17 &= ~MCK_SIZE_MASK;
24108c2ecf20Sopenharmony_ci		reg17 |= 0x01;			/* clock / 1 */
24118c2ecf20Sopenharmony_ci		break;
24128c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
24138c2ecf20Sopenharmony_ci		init = ov7660_sensor_param1;
24148c2ecf20Sopenharmony_ci		break;
24158c2ecf20Sopenharmony_ci	case SENSOR_PO1030:
24168c2ecf20Sopenharmony_ci		init = po1030_sensor_param1;
24178c2ecf20Sopenharmony_ci		break;
24188c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
24198c2ecf20Sopenharmony_ci		init = po2030n_sensor_param1;
24208c2ecf20Sopenharmony_ci		break;
24218c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
24228c2ecf20Sopenharmony_ci		init = soi768_sensor_param1;
24238c2ecf20Sopenharmony_ci		break;
24248c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
24258c2ecf20Sopenharmony_ci		init = sp80708_sensor_param1;
24268c2ecf20Sopenharmony_ci		break;
24278c2ecf20Sopenharmony_ci	}
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	/* more sensor initialization - param1 */
24308c2ecf20Sopenharmony_ci	if (init != NULL) {
24318c2ecf20Sopenharmony_ci		i2c_w_seq(gspca_dev, init);
24328c2ecf20Sopenharmony_ci/*		init = NULL; */
24338c2ecf20Sopenharmony_ci	}
24348c2ecf20Sopenharmony_ci
24358c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0xc0, C0, 6);
24368c2ecf20Sopenharmony_ci	switch (sd->sensor) {
24378c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
24388c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
24398c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
24408c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
24418c2ecf20Sopenharmony_ci		break;
24428c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
24438c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA_po2030n, 4);
24448c2ecf20Sopenharmony_ci		break;
24458c2ecf20Sopenharmony_ci	default:
24468c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xca, CA, 4);
24478c2ecf20Sopenharmony_ci		break;
24488c2ecf20Sopenharmony_ci	}
24498c2ecf20Sopenharmony_ci	switch (sd->sensor) {
24508c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
24518c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
24528c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
24538c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
24548c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
24558c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
24568c2ecf20Sopenharmony_ci		break;
24578c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
24588c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_gc0307, 4);
24598c2ecf20Sopenharmony_ci		break;
24608c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
24618c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE_po2030n, 4);
24628c2ecf20Sopenharmony_ci		break;
24638c2ecf20Sopenharmony_ci	default:
24648c2ecf20Sopenharmony_ci		reg_w(gspca_dev, 0xce, CE, 4);
24658c2ecf20Sopenharmony_ci					/* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
24668c2ecf20Sopenharmony_ci		break;
24678c2ecf20Sopenharmony_ci	}
24688c2ecf20Sopenharmony_ci
24698c2ecf20Sopenharmony_ci	/* here change size mode 0 -> VGA; 1 -> CIF */
24708c2ecf20Sopenharmony_ci	sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
24718c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x18, sd->reg18);
24728c2ecf20Sopenharmony_ci	setjpegqual(gspca_dev);
24738c2ecf20Sopenharmony_ci
24748c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
24758c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
24768c2ecf20Sopenharmony_ci	sd->reg01 = reg01;
24778c2ecf20Sopenharmony_ci	sd->reg17 = reg17;
24788c2ecf20Sopenharmony_ci
24798c2ecf20Sopenharmony_ci	sd->pktsz = sd->npkt = 0;
24808c2ecf20Sopenharmony_ci	sd->nchg = sd->short_mark = 0;
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
24838c2ecf20Sopenharmony_ci}
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
24868c2ecf20Sopenharmony_ci{
24878c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
24888c2ecf20Sopenharmony_ci	static const u8 stophv7131[] =
24898c2ecf20Sopenharmony_ci		{ 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
24908c2ecf20Sopenharmony_ci	static const u8 stopmi0360[] =
24918c2ecf20Sopenharmony_ci		{ 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
24928c2ecf20Sopenharmony_ci	static const u8 stopov7648[] =
24938c2ecf20Sopenharmony_ci		{ 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
24948c2ecf20Sopenharmony_ci	static const u8 stopsoi768[] =
24958c2ecf20Sopenharmony_ci		{ 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
24968c2ecf20Sopenharmony_ci	u8 reg01;
24978c2ecf20Sopenharmony_ci	u8 reg17;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci	reg01 = sd->reg01;
25008c2ecf20Sopenharmony_ci	reg17 = sd->reg17 & ~SEN_CLK_EN;
25018c2ecf20Sopenharmony_ci	switch (sd->sensor) {
25028c2ecf20Sopenharmony_ci	case SENSOR_ADCM1700:
25038c2ecf20Sopenharmony_ci	case SENSOR_GC0307:
25048c2ecf20Sopenharmony_ci	case SENSOR_PO2030N:
25058c2ecf20Sopenharmony_ci	case SENSOR_SP80708:
25068c2ecf20Sopenharmony_ci		reg01 |= LED;
25078c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25088c2ecf20Sopenharmony_ci		reg01 &= ~(LED | V_TX_EN);
25098c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25108c2ecf20Sopenharmony_ci/*		reg_w1(gspca_dev, 0x02, 0x??);	 * LED off ? */
25118c2ecf20Sopenharmony_ci		break;
25128c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
25138c2ecf20Sopenharmony_ci		reg01 &= ~V_TX_EN;
25148c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25158c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, stophv7131);
25168c2ecf20Sopenharmony_ci		break;
25178c2ecf20Sopenharmony_ci	case SENSOR_MI0360:
25188c2ecf20Sopenharmony_ci	case SENSOR_MI0360B:
25198c2ecf20Sopenharmony_ci		reg01 &= ~V_TX_EN;
25208c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25218c2ecf20Sopenharmony_ci/*		reg_w1(gspca_dev, 0x02, 0x40);	  * LED off ? */
25228c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, stopmi0360);
25238c2ecf20Sopenharmony_ci		break;
25248c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
25258c2ecf20Sopenharmony_ci	case SENSOR_OM6802:
25268c2ecf20Sopenharmony_ci	case SENSOR_PO1030:
25278c2ecf20Sopenharmony_ci		reg01 &= ~V_TX_EN;
25288c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25298c2ecf20Sopenharmony_ci		break;
25308c2ecf20Sopenharmony_ci	case SENSOR_OV7630:
25318c2ecf20Sopenharmony_ci	case SENSOR_OV7648:
25328c2ecf20Sopenharmony_ci		reg01 &= ~V_TX_EN;
25338c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25348c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, stopov7648);
25358c2ecf20Sopenharmony_ci		break;
25368c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
25378c2ecf20Sopenharmony_ci		reg01 &= ~V_TX_EN;
25388c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x01, reg01);
25398c2ecf20Sopenharmony_ci		break;
25408c2ecf20Sopenharmony_ci	case SENSOR_SOI768:
25418c2ecf20Sopenharmony_ci		i2c_w8(gspca_dev, stopsoi768);
25428c2ecf20Sopenharmony_ci		break;
25438c2ecf20Sopenharmony_ci	}
25448c2ecf20Sopenharmony_ci
25458c2ecf20Sopenharmony_ci	reg01 |= SCL_SEL_OD;
25468c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
25478c2ecf20Sopenharmony_ci	reg01 |= S_PWR_DN;		/* sensor power down */
25488c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
25498c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x17, reg17);
25508c2ecf20Sopenharmony_ci	reg01 &= ~SYS_SEL_48M;		/* clock 24MHz */
25518c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
25528c2ecf20Sopenharmony_ci	reg01 |= LED;
25538c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x01, reg01);
25548c2ecf20Sopenharmony_ci	/* Don't disable sensor clock as that disables the button on the cam */
25558c2ecf20Sopenharmony_ci	/* reg_w1(gspca_dev, 0xf1, 0x01); */
25568c2ecf20Sopenharmony_ci}
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */
25598c2ecf20Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */
25608c2ecf20Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
25618c2ecf20Sopenharmony_ci{
25628c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
25658c2ecf20Sopenharmony_ci	flush_work(&sd->work);
25668c2ecf20Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
25678c2ecf20Sopenharmony_ci}
25688c2ecf20Sopenharmony_ci
25698c2ecf20Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev)
25708c2ecf20Sopenharmony_ci{
25718c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
25728c2ecf20Sopenharmony_ci	int delta;
25738c2ecf20Sopenharmony_ci	int expotimes;
25748c2ecf20Sopenharmony_ci	u8 luma_mean = 130;
25758c2ecf20Sopenharmony_ci	u8 luma_delta = 20;
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_ci	/* Thanks S., without your advice, autobright should not work :) */
25788c2ecf20Sopenharmony_ci	if (sd->ag_cnt < 0)
25798c2ecf20Sopenharmony_ci		return;
25808c2ecf20Sopenharmony_ci	if (--sd->ag_cnt >= 0)
25818c2ecf20Sopenharmony_ci		return;
25828c2ecf20Sopenharmony_ci	sd->ag_cnt = AG_CNT_START;
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci	delta = atomic_read(&sd->avg_lum);
25858c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_FRAM, "mean lum %d\n", delta);
25868c2ecf20Sopenharmony_ci
25878c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_PO2030N) {
25888c2ecf20Sopenharmony_ci		gspca_expo_autogain(gspca_dev, delta, luma_mean, luma_delta,
25898c2ecf20Sopenharmony_ci					15, 1024);
25908c2ecf20Sopenharmony_ci		return;
25918c2ecf20Sopenharmony_ci	}
25928c2ecf20Sopenharmony_ci
25938c2ecf20Sopenharmony_ci	if (delta < luma_mean - luma_delta ||
25948c2ecf20Sopenharmony_ci	    delta > luma_mean + luma_delta) {
25958c2ecf20Sopenharmony_ci		switch (sd->sensor) {
25968c2ecf20Sopenharmony_ci		case SENSOR_GC0307:
25978c2ecf20Sopenharmony_ci			expotimes = sd->exposure;
25988c2ecf20Sopenharmony_ci			expotimes += (luma_mean - delta) >> 6;
25998c2ecf20Sopenharmony_ci			if (expotimes < 0)
26008c2ecf20Sopenharmony_ci				expotimes = 0;
26018c2ecf20Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
26028c2ecf20Sopenharmony_ci						   (unsigned int) expotimes);
26038c2ecf20Sopenharmony_ci			break;
26048c2ecf20Sopenharmony_ci		case SENSOR_HV7131R:
26058c2ecf20Sopenharmony_ci			expotimes = sd->exposure >> 8;
26068c2ecf20Sopenharmony_ci			expotimes += (luma_mean - delta) >> 4;
26078c2ecf20Sopenharmony_ci			if (expotimes < 0)
26088c2ecf20Sopenharmony_ci				expotimes = 0;
26098c2ecf20Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
26108c2ecf20Sopenharmony_ci					(unsigned int) (expotimes << 8));
26118c2ecf20Sopenharmony_ci			break;
26128c2ecf20Sopenharmony_ci		case SENSOR_OM6802:
26138c2ecf20Sopenharmony_ci		case SENSOR_MT9V111:
26148c2ecf20Sopenharmony_ci			expotimes = sd->exposure;
26158c2ecf20Sopenharmony_ci			expotimes += (luma_mean - delta) >> 2;
26168c2ecf20Sopenharmony_ci			if (expotimes < 0)
26178c2ecf20Sopenharmony_ci				expotimes = 0;
26188c2ecf20Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
26198c2ecf20Sopenharmony_ci						   (unsigned int) expotimes);
26208c2ecf20Sopenharmony_ci			setredblue(gspca_dev);
26218c2ecf20Sopenharmony_ci			break;
26228c2ecf20Sopenharmony_ci		default:
26238c2ecf20Sopenharmony_ci/*		case SENSOR_MO4000: */
26248c2ecf20Sopenharmony_ci/*		case SENSOR_MI0360: */
26258c2ecf20Sopenharmony_ci/*		case SENSOR_MI0360B: */
26268c2ecf20Sopenharmony_ci			expotimes = sd->exposure;
26278c2ecf20Sopenharmony_ci			expotimes += (luma_mean - delta) >> 6;
26288c2ecf20Sopenharmony_ci			if (expotimes < 0)
26298c2ecf20Sopenharmony_ci				expotimes = 0;
26308c2ecf20Sopenharmony_ci			sd->exposure = expo_adjust(gspca_dev,
26318c2ecf20Sopenharmony_ci						   (unsigned int) expotimes);
26328c2ecf20Sopenharmony_ci			setredblue(gspca_dev);
26338c2ecf20Sopenharmony_ci			break;
26348c2ecf20Sopenharmony_ci		}
26358c2ecf20Sopenharmony_ci	}
26368c2ecf20Sopenharmony_ci}
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci/* set the average luminosity from an isoc marker */
26398c2ecf20Sopenharmony_cistatic void set_lum(struct sd *sd,
26408c2ecf20Sopenharmony_ci		    u8 *data)
26418c2ecf20Sopenharmony_ci{
26428c2ecf20Sopenharmony_ci	int avg_lum;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ci	/*	w0 w1 w2
26458c2ecf20Sopenharmony_ci	 *	w3 w4 w5
26468c2ecf20Sopenharmony_ci	 *	w6 w7 w8
26478c2ecf20Sopenharmony_ci	 */
26488c2ecf20Sopenharmony_ci	avg_lum = (data[27] << 8) + data[28]		/* w3 */
26498c2ecf20Sopenharmony_ci
26508c2ecf20Sopenharmony_ci		+ (data[31] << 8) + data[32]		/* w5 */
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci		+ (data[23] << 8) + data[24]		/* w1 */
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci		+ (data[35] << 8) + data[36]		/* w7 */
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci		+ (data[29] << 10) + (data[30] << 2);	/* w4 * 4 */
26578c2ecf20Sopenharmony_ci	avg_lum >>= 10;
26588c2ecf20Sopenharmony_ci	atomic_set(&sd->avg_lum, avg_lum);
26598c2ecf20Sopenharmony_ci}
26608c2ecf20Sopenharmony_ci
26618c2ecf20Sopenharmony_ci/* scan the URB packets */
26628c2ecf20Sopenharmony_ci/* This function is run at interrupt level. */
26638c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
26648c2ecf20Sopenharmony_ci			u8 *data,			/* isoc packet */
26658c2ecf20Sopenharmony_ci			int len)			/* iso packet length */
26668c2ecf20Sopenharmony_ci{
26678c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
26688c2ecf20Sopenharmony_ci	int i, new_qual;
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	/*
26718c2ecf20Sopenharmony_ci	 * A frame ends on the marker
26728c2ecf20Sopenharmony_ci	 *		ff ff 00 c4 c4 96 ..
26738c2ecf20Sopenharmony_ci	 * which is 62 bytes long and is followed by various information
26748c2ecf20Sopenharmony_ci	 * including statuses and luminosity.
26758c2ecf20Sopenharmony_ci	 *
26768c2ecf20Sopenharmony_ci	 * A marker may be split on two packets.
26778c2ecf20Sopenharmony_ci	 *
26788c2ecf20Sopenharmony_ci	 * The 6th byte of a marker contains the bits:
26798c2ecf20Sopenharmony_ci	 *	0x08: USB full
26808c2ecf20Sopenharmony_ci	 *	0xc0: frame sequence
26818c2ecf20Sopenharmony_ci	 * When the bit 'USB full' is set, the frame must be discarded;
26828c2ecf20Sopenharmony_ci	 * this is also the case when the 2 bytes before the marker are
26838c2ecf20Sopenharmony_ci	 * not the JPEG end of frame ('ff d9').
26848c2ecf20Sopenharmony_ci	 */
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	/* count the packets and their size */
26878c2ecf20Sopenharmony_ci	sd->npkt++;
26888c2ecf20Sopenharmony_ci	sd->pktsz += len;
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci/*fixme: assumption about the following code:
26918c2ecf20Sopenharmony_ci *	- there can be only one marker in a packet
26928c2ecf20Sopenharmony_ci */
26938c2ecf20Sopenharmony_ci
26948c2ecf20Sopenharmony_ci	/* skip the remaining bytes of a short marker */
26958c2ecf20Sopenharmony_ci	i = sd->short_mark;
26968c2ecf20Sopenharmony_ci	if (i != 0) {
26978c2ecf20Sopenharmony_ci		sd->short_mark = 0;
26988c2ecf20Sopenharmony_ci		if (i < 0	/* if 'ff' at end of previous packet */
26998c2ecf20Sopenharmony_ci		 && data[0] == 0xff
27008c2ecf20Sopenharmony_ci		 && data[1] == 0x00)
27018c2ecf20Sopenharmony_ci			goto marker_found;
27028c2ecf20Sopenharmony_ci		if (data[0] == 0xff && data[1] == 0xff) {
27038c2ecf20Sopenharmony_ci			i = 0;
27048c2ecf20Sopenharmony_ci			goto marker_found;
27058c2ecf20Sopenharmony_ci		}
27068c2ecf20Sopenharmony_ci		len -= i;
27078c2ecf20Sopenharmony_ci		if (len <= 0)
27088c2ecf20Sopenharmony_ci			return;
27098c2ecf20Sopenharmony_ci		data += i;
27108c2ecf20Sopenharmony_ci	}
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci	/* search backwards if there is a marker in the packet */
27138c2ecf20Sopenharmony_ci	for (i = len - 1; --i >= 0; ) {
27148c2ecf20Sopenharmony_ci		if (data[i] != 0xff) {
27158c2ecf20Sopenharmony_ci			i--;
27168c2ecf20Sopenharmony_ci			continue;
27178c2ecf20Sopenharmony_ci		}
27188c2ecf20Sopenharmony_ci		if (data[i + 1] == 0xff) {
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_ci			/* (there may be 'ff ff' inside a marker) */
27218c2ecf20Sopenharmony_ci			if (i + 2 >= len || data[i + 2] == 0x00)
27228c2ecf20Sopenharmony_ci				goto marker_found;
27238c2ecf20Sopenharmony_ci		}
27248c2ecf20Sopenharmony_ci	}
27258c2ecf20Sopenharmony_ci
27268c2ecf20Sopenharmony_ci	/* no marker found */
27278c2ecf20Sopenharmony_ci	/* add the JPEG header if first fragment */
27288c2ecf20Sopenharmony_ci	if (data[len - 1] == 0xff)
27298c2ecf20Sopenharmony_ci		sd->short_mark = -1;
27308c2ecf20Sopenharmony_ci	if (gspca_dev->last_packet_type == LAST_PACKET)
27318c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET,
27328c2ecf20Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
27338c2ecf20Sopenharmony_ci	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
27348c2ecf20Sopenharmony_ci	return;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	/* marker found */
27378c2ecf20Sopenharmony_ci	/* if some error, discard the frame and decrease the quality */
27388c2ecf20Sopenharmony_cimarker_found:
27398c2ecf20Sopenharmony_ci	new_qual = 0;
27408c2ecf20Sopenharmony_ci	if (i > 2) {
27418c2ecf20Sopenharmony_ci		if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
27428c2ecf20Sopenharmony_ci			gspca_dev->last_packet_type = DISCARD_PACKET;
27438c2ecf20Sopenharmony_ci			new_qual = -3;
27448c2ecf20Sopenharmony_ci		}
27458c2ecf20Sopenharmony_ci	} else if (i + 6 < len) {
27468c2ecf20Sopenharmony_ci		if (data[i + 6] & 0x08) {
27478c2ecf20Sopenharmony_ci			gspca_dev->last_packet_type = DISCARD_PACKET;
27488c2ecf20Sopenharmony_ci			new_qual = -5;
27498c2ecf20Sopenharmony_ci		}
27508c2ecf20Sopenharmony_ci	}
27518c2ecf20Sopenharmony_ci
27528c2ecf20Sopenharmony_ci	gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	/* compute the filling rate and a new JPEG quality */
27558c2ecf20Sopenharmony_ci	if (new_qual == 0) {
27568c2ecf20Sopenharmony_ci		int r;
27578c2ecf20Sopenharmony_ci
27588c2ecf20Sopenharmony_ci		r = (sd->pktsz * 100) /
27598c2ecf20Sopenharmony_ci			(sd->npkt *
27608c2ecf20Sopenharmony_ci				gspca_dev->urb[0]->iso_frame_desc[0].length);
27618c2ecf20Sopenharmony_ci		if (r >= 85)
27628c2ecf20Sopenharmony_ci			new_qual = -3;
27638c2ecf20Sopenharmony_ci		else if (r < 75)
27648c2ecf20Sopenharmony_ci			new_qual = 2;
27658c2ecf20Sopenharmony_ci	}
27668c2ecf20Sopenharmony_ci	if (new_qual != 0) {
27678c2ecf20Sopenharmony_ci		sd->nchg += new_qual;
27688c2ecf20Sopenharmony_ci		if (sd->nchg < -6 || sd->nchg >= 12) {
27698c2ecf20Sopenharmony_ci			sd->nchg = 0;
27708c2ecf20Sopenharmony_ci			new_qual += sd->quality;
27718c2ecf20Sopenharmony_ci			if (new_qual < QUALITY_MIN)
27728c2ecf20Sopenharmony_ci				new_qual = QUALITY_MIN;
27738c2ecf20Sopenharmony_ci			else if (new_qual > QUALITY_MAX)
27748c2ecf20Sopenharmony_ci				new_qual = QUALITY_MAX;
27758c2ecf20Sopenharmony_ci			if (new_qual != sd->quality) {
27768c2ecf20Sopenharmony_ci				sd->quality = new_qual;
27778c2ecf20Sopenharmony_ci				schedule_work(&sd->work);
27788c2ecf20Sopenharmony_ci			}
27798c2ecf20Sopenharmony_ci		}
27808c2ecf20Sopenharmony_ci	} else {
27818c2ecf20Sopenharmony_ci		sd->nchg = 0;
27828c2ecf20Sopenharmony_ci	}
27838c2ecf20Sopenharmony_ci	sd->pktsz = sd->npkt = 0;
27848c2ecf20Sopenharmony_ci
27858c2ecf20Sopenharmony_ci	/* if the marker is smaller than 62 bytes,
27868c2ecf20Sopenharmony_ci	 * memorize the number of bytes to skip in the next packet */
27878c2ecf20Sopenharmony_ci	if (i + 62 > len) {			/* no more usable data */
27888c2ecf20Sopenharmony_ci		sd->short_mark = i + 62 - len;
27898c2ecf20Sopenharmony_ci		return;
27908c2ecf20Sopenharmony_ci	}
27918c2ecf20Sopenharmony_ci	if (sd->ag_cnt >= 0)
27928c2ecf20Sopenharmony_ci		set_lum(sd, data + i);
27938c2ecf20Sopenharmony_ci
27948c2ecf20Sopenharmony_ci	/* if more data, start a new frame */
27958c2ecf20Sopenharmony_ci	i += 62;
27968c2ecf20Sopenharmony_ci	if (i < len) {
27978c2ecf20Sopenharmony_ci		data += i;
27988c2ecf20Sopenharmony_ci		len -= i;
27998c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET,
28008c2ecf20Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
28018c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
28028c2ecf20Sopenharmony_ci	}
28038c2ecf20Sopenharmony_ci}
28048c2ecf20Sopenharmony_ci
28058c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
28068c2ecf20Sopenharmony_ci{
28078c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev =
28088c2ecf20Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
28098c2ecf20Sopenharmony_ci
28108c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	if (!gspca_dev->streaming)
28138c2ecf20Sopenharmony_ci		return 0;
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci	switch (ctrl->id) {
28168c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
28178c2ecf20Sopenharmony_ci		setbrightness(gspca_dev);
28188c2ecf20Sopenharmony_ci		break;
28198c2ecf20Sopenharmony_ci	case V4L2_CID_CONTRAST:
28208c2ecf20Sopenharmony_ci		setcontrast(gspca_dev);
28218c2ecf20Sopenharmony_ci		break;
28228c2ecf20Sopenharmony_ci	case V4L2_CID_SATURATION:
28238c2ecf20Sopenharmony_ci		setcolors(gspca_dev);
28248c2ecf20Sopenharmony_ci		break;
28258c2ecf20Sopenharmony_ci	case V4L2_CID_RED_BALANCE:
28268c2ecf20Sopenharmony_ci		setredblue(gspca_dev);
28278c2ecf20Sopenharmony_ci		break;
28288c2ecf20Sopenharmony_ci	case V4L2_CID_GAMMA:
28298c2ecf20Sopenharmony_ci		setgamma(gspca_dev);
28308c2ecf20Sopenharmony_ci		break;
28318c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
28328c2ecf20Sopenharmony_ci		setautogain(gspca_dev);
28338c2ecf20Sopenharmony_ci		setexposure(gspca_dev);
28348c2ecf20Sopenharmony_ci		setgain(gspca_dev);
28358c2ecf20Sopenharmony_ci		break;
28368c2ecf20Sopenharmony_ci	case V4L2_CID_VFLIP:
28378c2ecf20Sopenharmony_ci		sethvflip(gspca_dev);
28388c2ecf20Sopenharmony_ci		break;
28398c2ecf20Sopenharmony_ci	case V4L2_CID_SHARPNESS:
28408c2ecf20Sopenharmony_ci		setsharpness(gspca_dev);
28418c2ecf20Sopenharmony_ci		break;
28428c2ecf20Sopenharmony_ci	case V4L2_CID_ILLUMINATORS_1:
28438c2ecf20Sopenharmony_ci		setillum(gspca_dev);
28448c2ecf20Sopenharmony_ci		break;
28458c2ecf20Sopenharmony_ci	case V4L2_CID_POWER_LINE_FREQUENCY:
28468c2ecf20Sopenharmony_ci		setfreq(gspca_dev);
28478c2ecf20Sopenharmony_ci		break;
28488c2ecf20Sopenharmony_ci	default:
28498c2ecf20Sopenharmony_ci		return -EINVAL;
28508c2ecf20Sopenharmony_ci	}
28518c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
28528c2ecf20Sopenharmony_ci}
28538c2ecf20Sopenharmony_ci
28548c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
28558c2ecf20Sopenharmony_cistatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
28568c2ecf20Sopenharmony_ci			u8 *data,		/* interrupt packet data */
28578c2ecf20Sopenharmony_ci			int len)		/* interrupt packet length */
28588c2ecf20Sopenharmony_ci{
28598c2ecf20Sopenharmony_ci	int ret = -EINVAL;
28608c2ecf20Sopenharmony_ci
28618c2ecf20Sopenharmony_ci	if (len == 1 && data[0] == 1) {
28628c2ecf20Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
28638c2ecf20Sopenharmony_ci		input_sync(gspca_dev->input_dev);
28648c2ecf20Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
28658c2ecf20Sopenharmony_ci		input_sync(gspca_dev->input_dev);
28668c2ecf20Sopenharmony_ci		ret = 0;
28678c2ecf20Sopenharmony_ci	}
28688c2ecf20Sopenharmony_ci
28698c2ecf20Sopenharmony_ci	return ret;
28708c2ecf20Sopenharmony_ci}
28718c2ecf20Sopenharmony_ci#endif
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci/* sub-driver description */
28748c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = {
28758c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
28768c2ecf20Sopenharmony_ci	.config = sd_config,
28778c2ecf20Sopenharmony_ci	.init = sd_init,
28788c2ecf20Sopenharmony_ci	.init_controls = sd_init_controls,
28798c2ecf20Sopenharmony_ci	.start = sd_start,
28808c2ecf20Sopenharmony_ci	.stopN = sd_stopN,
28818c2ecf20Sopenharmony_ci	.stop0 = sd_stop0,
28828c2ecf20Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
28838c2ecf20Sopenharmony_ci	.dq_callback = do_autogain,
28848c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
28858c2ecf20Sopenharmony_ci	.int_pkt_scan = sd_int_pkt_scan,
28868c2ecf20Sopenharmony_ci#endif
28878c2ecf20Sopenharmony_ci};
28888c2ecf20Sopenharmony_ci
28898c2ecf20Sopenharmony_ci/* -- module initialisation -- */
28908c2ecf20Sopenharmony_ci#define BS(bridge, sensor) \
28918c2ecf20Sopenharmony_ci	.driver_info = (BRIDGE_ ## bridge << 16) \
28928c2ecf20Sopenharmony_ci			| (SENSOR_ ## sensor << 8)
28938c2ecf20Sopenharmony_ci#define BSF(bridge, sensor, flags) \
28948c2ecf20Sopenharmony_ci	.driver_info = (BRIDGE_ ## bridge << 16) \
28958c2ecf20Sopenharmony_ci			| (SENSOR_ ## sensor << 8) \
28968c2ecf20Sopenharmony_ci			| (flags)
28978c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = {
28988c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)},
28998c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
29008c2ecf20Sopenharmony_ci	{USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
29018c2ecf20Sopenharmony_ci	{USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
29028c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
29038c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
29048c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
29058c2ecf20Sopenharmony_ci	{USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
29068c2ecf20Sopenharmony_ci	{USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
29078c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
29088c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
29098c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
29108c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
29118c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
29128c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
29138c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
29148c2ecf20Sopenharmony_ci						/* or MT9V111 */
29158c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
29168c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
29178c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
29188c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
29198c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
29208c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
29218c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
29228c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
29238c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
29248c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
29258c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
29268c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},	/*sn9c128*/
29278c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},	/* /GC0305*/
29288c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
29298c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},	/*sn9c128*/
29308c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},	/*sn9c128*/
29318c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)},	/*sn9c128*/
29328c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)},	/*sn9c128*/
29338c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
29348c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
29358c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
29368c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)},	/*sn9c325?*/
29378c2ecf20Sopenharmony_ci/*bw600.inf:*/
29388c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)},	/*sn9c325?*/
29398c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
29408c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
29418c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
29428c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
29438c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
29448c2ecf20Sopenharmony_ci						/* or MT9V111 / MI0360B */
29458c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
29468c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
29478c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
29488c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
29498c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
29508c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
29518c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},	/*sn9c120b*/
29528c2ecf20Sopenharmony_ci						/* or GC0305 / GC0307 */
29538c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},	/*sn9c120b*/
29548c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},	/*sn9c120b*/
29558c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
29568c2ecf20Sopenharmony_ci/*	{USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */	/*sn9c120b*/
29578c2ecf20Sopenharmony_ci	{}
29588c2ecf20Sopenharmony_ci};
29598c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci/* -- device connect -- */
29628c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
29638c2ecf20Sopenharmony_ci		    const struct usb_device_id *id)
29648c2ecf20Sopenharmony_ci{
29658c2ecf20Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
29668c2ecf20Sopenharmony_ci				THIS_MODULE);
29678c2ecf20Sopenharmony_ci}
29688c2ecf20Sopenharmony_ci
29698c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = {
29708c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
29718c2ecf20Sopenharmony_ci	.id_table = device_table,
29728c2ecf20Sopenharmony_ci	.probe = sd_probe,
29738c2ecf20Sopenharmony_ci	.disconnect = gspca_disconnect,
29748c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
29758c2ecf20Sopenharmony_ci	.suspend = gspca_suspend,
29768c2ecf20Sopenharmony_ci	.resume = gspca_resume,
29778c2ecf20Sopenharmony_ci	.reset_resume = gspca_resume,
29788c2ecf20Sopenharmony_ci#endif
29798c2ecf20Sopenharmony_ci};
29808c2ecf20Sopenharmony_ci
29818c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver);
2982