18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *	Sonix sn9c201 sn9c202 library
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
68c2ecf20Sopenharmony_ci *	Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
78c2ecf20Sopenharmony_ci *	Copyright (C) 2009 Brian Johnson <brijohn@gmail.com>
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/input.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include "gspca.h"
158c2ecf20Sopenharmony_ci#include "jpeg.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/dmi.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ciMODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, microdia project <microdia@googlegroups.com>");
208c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
218c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/*
248c2ecf20Sopenharmony_ci * Pixel format private data
258c2ecf20Sopenharmony_ci */
268c2ecf20Sopenharmony_ci#define SCALE_MASK	0x0f
278c2ecf20Sopenharmony_ci#define SCALE_160x120	0
288c2ecf20Sopenharmony_ci#define SCALE_320x240	1
298c2ecf20Sopenharmony_ci#define SCALE_640x480	2
308c2ecf20Sopenharmony_ci#define SCALE_1280x1024	3
318c2ecf20Sopenharmony_ci#define MODE_RAW	0x10
328c2ecf20Sopenharmony_ci#define MODE_JPEG	0x20
338c2ecf20Sopenharmony_ci#define MODE_SXGA	0x80
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define SENSOR_OV9650	0
368c2ecf20Sopenharmony_ci#define SENSOR_OV9655	1
378c2ecf20Sopenharmony_ci#define SENSOR_SOI968	2
388c2ecf20Sopenharmony_ci#define SENSOR_OV7660	3
398c2ecf20Sopenharmony_ci#define SENSOR_OV7670	4
408c2ecf20Sopenharmony_ci#define SENSOR_MT9V011	5
418c2ecf20Sopenharmony_ci#define SENSOR_MT9V111	6
428c2ecf20Sopenharmony_ci#define SENSOR_MT9V112	7
438c2ecf20Sopenharmony_ci#define SENSOR_MT9M001	8
448c2ecf20Sopenharmony_ci#define SENSOR_MT9M111	9
458c2ecf20Sopenharmony_ci#define SENSOR_MT9M112  10
468c2ecf20Sopenharmony_ci#define SENSOR_HV7131R	11
478c2ecf20Sopenharmony_ci#define SENSOR_MT9VPRB	12
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* camera flags */
508c2ecf20Sopenharmony_ci#define HAS_NO_BUTTON	0x1
518c2ecf20Sopenharmony_ci#define LED_REVERSE	0x2 /* some cameras unset gpio to turn on leds */
528c2ecf20Sopenharmony_ci#define FLIP_DETECT	0x4
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* specific webcam descriptor */
558c2ecf20Sopenharmony_cistruct sd {
568c2ecf20Sopenharmony_ci	struct gspca_dev gspca_dev;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	struct { /* color control cluster */
598c2ecf20Sopenharmony_ci		struct v4l2_ctrl *brightness;
608c2ecf20Sopenharmony_ci		struct v4l2_ctrl *contrast;
618c2ecf20Sopenharmony_ci		struct v4l2_ctrl *saturation;
628c2ecf20Sopenharmony_ci		struct v4l2_ctrl *hue;
638c2ecf20Sopenharmony_ci	};
648c2ecf20Sopenharmony_ci	struct { /* blue/red balance control cluster */
658c2ecf20Sopenharmony_ci		struct v4l2_ctrl *blue;
668c2ecf20Sopenharmony_ci		struct v4l2_ctrl *red;
678c2ecf20Sopenharmony_ci	};
688c2ecf20Sopenharmony_ci	struct { /* h/vflip control cluster */
698c2ecf20Sopenharmony_ci		struct v4l2_ctrl *hflip;
708c2ecf20Sopenharmony_ci		struct v4l2_ctrl *vflip;
718c2ecf20Sopenharmony_ci	};
728c2ecf20Sopenharmony_ci	struct v4l2_ctrl *gamma;
738c2ecf20Sopenharmony_ci	struct { /* autogain and exposure or gain control cluster */
748c2ecf20Sopenharmony_ci		struct v4l2_ctrl *autogain;
758c2ecf20Sopenharmony_ci		struct v4l2_ctrl *exposure;
768c2ecf20Sopenharmony_ci		struct v4l2_ctrl *gain;
778c2ecf20Sopenharmony_ci	};
788c2ecf20Sopenharmony_ci	struct v4l2_ctrl *jpegqual;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	struct work_struct work;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	u32 pktsz;			/* (used by pkt_scan) */
838c2ecf20Sopenharmony_ci	u16 npkt;
848c2ecf20Sopenharmony_ci	s8 nchg;
858c2ecf20Sopenharmony_ci	u8 fmt;				/* (used for JPEG QTAB update */
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define MIN_AVG_LUM 80
888c2ecf20Sopenharmony_ci#define MAX_AVG_LUM 130
898c2ecf20Sopenharmony_ci	atomic_t avg_lum;
908c2ecf20Sopenharmony_ci	u8 old_step;
918c2ecf20Sopenharmony_ci	u8 older_step;
928c2ecf20Sopenharmony_ci	u8 exposure_step;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	u8 i2c_addr;
958c2ecf20Sopenharmony_ci	u8 i2c_intf;
968c2ecf20Sopenharmony_ci	u8 sensor;
978c2ecf20Sopenharmony_ci	u8 hstart;
988c2ecf20Sopenharmony_ci	u8 vstart;
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci	u8 jpeg_hdr[JPEG_HDR_SZ];
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	u8 flags;
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic void qual_upd(struct work_struct *work);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_cistruct i2c_reg_u8 {
1088c2ecf20Sopenharmony_ci	u8 reg;
1098c2ecf20Sopenharmony_ci	u8 val;
1108c2ecf20Sopenharmony_ci};
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistruct i2c_reg_u16 {
1138c2ecf20Sopenharmony_ci	u8 reg;
1148c2ecf20Sopenharmony_ci	u16 val;
1158c2ecf20Sopenharmony_ci};
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistatic const struct dmi_system_id flip_dmi_table[] = {
1188c2ecf20Sopenharmony_ci	{
1198c2ecf20Sopenharmony_ci		.ident = "MSI MS-1034",
1208c2ecf20Sopenharmony_ci		.matches = {
1218c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
1228c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
1238c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
1248c2ecf20Sopenharmony_ci		}
1258c2ecf20Sopenharmony_ci	},
1268c2ecf20Sopenharmony_ci	{
1278c2ecf20Sopenharmony_ci		.ident = "MSI MS-1039",
1288c2ecf20Sopenharmony_ci		.matches = {
1298c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
1308c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1039"),
1318c2ecf20Sopenharmony_ci		}
1328c2ecf20Sopenharmony_ci	},
1338c2ecf20Sopenharmony_ci	{
1348c2ecf20Sopenharmony_ci		.ident = "MSI MS-1632",
1358c2ecf20Sopenharmony_ci		.matches = {
1368c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
1378c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
1388c2ecf20Sopenharmony_ci		}
1398c2ecf20Sopenharmony_ci	},
1408c2ecf20Sopenharmony_ci	{
1418c2ecf20Sopenharmony_ci		.ident = "MSI MS-1633X",
1428c2ecf20Sopenharmony_ci		.matches = {
1438c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
1448c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
1458c2ecf20Sopenharmony_ci		}
1468c2ecf20Sopenharmony_ci	},
1478c2ecf20Sopenharmony_ci	{
1488c2ecf20Sopenharmony_ci		.ident = "MSI MS-1635X",
1498c2ecf20Sopenharmony_ci		.matches = {
1508c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
1518c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
1528c2ecf20Sopenharmony_ci		}
1538c2ecf20Sopenharmony_ci	},
1548c2ecf20Sopenharmony_ci	{
1558c2ecf20Sopenharmony_ci		.ident = "ASUSTeK W7J",
1568c2ecf20Sopenharmony_ci		.matches = {
1578c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
1588c2ecf20Sopenharmony_ci			DMI_MATCH(DMI_BOARD_NAME, "W7J       ")
1598c2ecf20Sopenharmony_ci		}
1608c2ecf20Sopenharmony_ci	},
1618c2ecf20Sopenharmony_ci	{}
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
1658c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1668c2ecf20Sopenharmony_ci		.bytesperline = 160,
1678c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120 * 4 / 8 + 590,
1688c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1698c2ecf20Sopenharmony_ci		.priv = SCALE_160x120 | MODE_JPEG},
1708c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
1718c2ecf20Sopenharmony_ci		.bytesperline = 160,
1728c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120,
1738c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
1748c2ecf20Sopenharmony_ci		.priv = SCALE_160x120 | MODE_RAW},
1758c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
1768c2ecf20Sopenharmony_ci		.bytesperline = 160,
1778c2ecf20Sopenharmony_ci		.sizeimage = 240 * 120,
1788c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
1798c2ecf20Sopenharmony_ci		.priv = SCALE_160x120},
1808c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1818c2ecf20Sopenharmony_ci		.bytesperline = 320,
1828c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 * 4 / 8 + 590,
1838c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1848c2ecf20Sopenharmony_ci		.priv = SCALE_320x240 | MODE_JPEG},
1858c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
1868c2ecf20Sopenharmony_ci		.bytesperline = 320,
1878c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 ,
1888c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
1898c2ecf20Sopenharmony_ci		.priv = SCALE_320x240 | MODE_RAW},
1908c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
1918c2ecf20Sopenharmony_ci		.bytesperline = 320,
1928c2ecf20Sopenharmony_ci		.sizeimage = 480 * 240 ,
1938c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
1948c2ecf20Sopenharmony_ci		.priv = SCALE_320x240},
1958c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
1968c2ecf20Sopenharmony_ci		.bytesperline = 640,
1978c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480 * 4 / 8 + 590,
1988c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
1998c2ecf20Sopenharmony_ci		.priv = SCALE_640x480 | MODE_JPEG},
2008c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
2018c2ecf20Sopenharmony_ci		.bytesperline = 640,
2028c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480,
2038c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2048c2ecf20Sopenharmony_ci		.priv = SCALE_640x480 | MODE_RAW},
2058c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
2068c2ecf20Sopenharmony_ci		.bytesperline = 640,
2078c2ecf20Sopenharmony_ci		.sizeimage = 960 * 480,
2088c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2098c2ecf20Sopenharmony_ci		.priv = SCALE_640x480},
2108c2ecf20Sopenharmony_ci};
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format sxga_mode[] = {
2138c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
2148c2ecf20Sopenharmony_ci		.bytesperline = 160,
2158c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120 * 4 / 8 + 590,
2168c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
2178c2ecf20Sopenharmony_ci		.priv = SCALE_160x120 | MODE_JPEG},
2188c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
2198c2ecf20Sopenharmony_ci		.bytesperline = 160,
2208c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120,
2218c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2228c2ecf20Sopenharmony_ci		.priv = SCALE_160x120 | MODE_RAW},
2238c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
2248c2ecf20Sopenharmony_ci		.bytesperline = 160,
2258c2ecf20Sopenharmony_ci		.sizeimage = 240 * 120,
2268c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2278c2ecf20Sopenharmony_ci		.priv = SCALE_160x120},
2288c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
2298c2ecf20Sopenharmony_ci		.bytesperline = 320,
2308c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 * 4 / 8 + 590,
2318c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
2328c2ecf20Sopenharmony_ci		.priv = SCALE_320x240 | MODE_JPEG},
2338c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
2348c2ecf20Sopenharmony_ci		.bytesperline = 320,
2358c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 ,
2368c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2378c2ecf20Sopenharmony_ci		.priv = SCALE_320x240 | MODE_RAW},
2388c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
2398c2ecf20Sopenharmony_ci		.bytesperline = 320,
2408c2ecf20Sopenharmony_ci		.sizeimage = 480 * 240 ,
2418c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2428c2ecf20Sopenharmony_ci		.priv = SCALE_320x240},
2438c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
2448c2ecf20Sopenharmony_ci		.bytesperline = 640,
2458c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480 * 4 / 8 + 590,
2468c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_JPEG,
2478c2ecf20Sopenharmony_ci		.priv = SCALE_640x480 | MODE_JPEG},
2488c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
2498c2ecf20Sopenharmony_ci		.bytesperline = 640,
2508c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480,
2518c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2528c2ecf20Sopenharmony_ci		.priv = SCALE_640x480 | MODE_RAW},
2538c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
2548c2ecf20Sopenharmony_ci		.bytesperline = 640,
2558c2ecf20Sopenharmony_ci		.sizeimage = 960 * 480,
2568c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2578c2ecf20Sopenharmony_ci		.priv = SCALE_640x480},
2588c2ecf20Sopenharmony_ci	{1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
2598c2ecf20Sopenharmony_ci		.bytesperline = 1280,
2608c2ecf20Sopenharmony_ci		.sizeimage = 1280 * 1024,
2618c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2628c2ecf20Sopenharmony_ci		.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
2638c2ecf20Sopenharmony_ci};
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format mono_mode[] = {
2668c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
2678c2ecf20Sopenharmony_ci		.bytesperline = 160,
2688c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120,
2698c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2708c2ecf20Sopenharmony_ci		.priv = SCALE_160x120 | MODE_RAW},
2718c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
2728c2ecf20Sopenharmony_ci		.bytesperline = 320,
2738c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 ,
2748c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2758c2ecf20Sopenharmony_ci		.priv = SCALE_320x240 | MODE_RAW},
2768c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
2778c2ecf20Sopenharmony_ci		.bytesperline = 640,
2788c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480,
2798c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2808c2ecf20Sopenharmony_ci		.priv = SCALE_640x480 | MODE_RAW},
2818c2ecf20Sopenharmony_ci	{1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
2828c2ecf20Sopenharmony_ci		.bytesperline = 1280,
2838c2ecf20Sopenharmony_ci		.sizeimage = 1280 * 1024,
2848c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
2858c2ecf20Sopenharmony_ci		.priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
2868c2ecf20Sopenharmony_ci};
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_cistatic const s16 hsv_red_x[] = {
2898c2ecf20Sopenharmony_ci	41,  44,  46,  48,  50,  52,  54,  56,
2908c2ecf20Sopenharmony_ci	58,  60,  62,  64,  66,  68,  70,  72,
2918c2ecf20Sopenharmony_ci	74,  76,  78,  80,  81,  83,  85,  87,
2928c2ecf20Sopenharmony_ci	88,  90,  92,  93,  95,  97,  98, 100,
2938c2ecf20Sopenharmony_ci	101, 102, 104, 105, 107, 108, 109, 110,
2948c2ecf20Sopenharmony_ci	112, 113, 114, 115, 116, 117, 118, 119,
2958c2ecf20Sopenharmony_ci	120, 121, 122, 123, 123, 124, 125, 125,
2968c2ecf20Sopenharmony_ci	126, 127, 127, 128, 128, 129, 129, 129,
2978c2ecf20Sopenharmony_ci	130, 130, 130, 130, 131, 131, 131, 131,
2988c2ecf20Sopenharmony_ci	131, 131, 131, 131, 130, 130, 130, 130,
2998c2ecf20Sopenharmony_ci	129, 129, 129, 128, 128, 127, 127, 126,
3008c2ecf20Sopenharmony_ci	125, 125, 124, 123, 122, 122, 121, 120,
3018c2ecf20Sopenharmony_ci	119, 118, 117, 116, 115, 114, 112, 111,
3028c2ecf20Sopenharmony_ci	110, 109, 107, 106, 105, 103, 102, 101,
3038c2ecf20Sopenharmony_ci	99,  98,  96,  94,  93,  91,  90,  88,
3048c2ecf20Sopenharmony_ci	86,  84,  83,  81,  79,  77,  75,  74,
3058c2ecf20Sopenharmony_ci	72,  70,  68,  66,  64,  62,  60,  58,
3068c2ecf20Sopenharmony_ci	56,  54,  52,  49,  47,  45,  43,  41,
3078c2ecf20Sopenharmony_ci	39,  36,  34,  32,  30,  28,  25,  23,
3088c2ecf20Sopenharmony_ci	21,  19,  16,  14,  12,   9,   7,   5,
3098c2ecf20Sopenharmony_ci	3,   0,  -1,  -3,  -6,  -8, -10, -12,
3108c2ecf20Sopenharmony_ci	-15, -17, -19, -22, -24, -26, -28, -30,
3118c2ecf20Sopenharmony_ci	-33, -35, -37, -39, -41, -44, -46, -48,
3128c2ecf20Sopenharmony_ci	-50, -52, -54, -56, -58, -60, -62, -64,
3138c2ecf20Sopenharmony_ci	-66, -68, -70, -72, -74, -76, -78, -80,
3148c2ecf20Sopenharmony_ci	-81, -83, -85, -87, -88, -90, -92, -93,
3158c2ecf20Sopenharmony_ci	-95, -97, -98, -100, -101, -102, -104, -105,
3168c2ecf20Sopenharmony_ci	-107, -108, -109, -110, -112, -113, -114, -115,
3178c2ecf20Sopenharmony_ci	-116, -117, -118, -119, -120, -121, -122, -123,
3188c2ecf20Sopenharmony_ci	-123, -124, -125, -125, -126, -127, -127, -128,
3198c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3208c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3218c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3228c2ecf20Sopenharmony_ci	-128, -127, -127, -126, -125, -125, -124, -123,
3238c2ecf20Sopenharmony_ci	-122, -122, -121, -120, -119, -118, -117, -116,
3248c2ecf20Sopenharmony_ci	-115, -114, -112, -111, -110, -109, -107, -106,
3258c2ecf20Sopenharmony_ci	-105, -103, -102, -101, -99, -98, -96, -94,
3268c2ecf20Sopenharmony_ci	-93, -91, -90, -88, -86, -84, -83, -81,
3278c2ecf20Sopenharmony_ci	-79, -77, -75, -74, -72, -70, -68, -66,
3288c2ecf20Sopenharmony_ci	-64, -62, -60, -58, -56, -54, -52, -49,
3298c2ecf20Sopenharmony_ci	-47, -45, -43, -41, -39, -36, -34, -32,
3308c2ecf20Sopenharmony_ci	-30, -28, -25, -23, -21, -19, -16, -14,
3318c2ecf20Sopenharmony_ci	-12,  -9,  -7,  -5,  -3,   0,   1,   3,
3328c2ecf20Sopenharmony_ci	6,   8,  10,  12,  15,  17,  19,  22,
3338c2ecf20Sopenharmony_ci	24,  26,  28,  30,  33,  35,  37,  39, 41
3348c2ecf20Sopenharmony_ci};
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic const s16 hsv_red_y[] = {
3378c2ecf20Sopenharmony_ci	82,  80,  78,  76,  74,  73,  71,  69,
3388c2ecf20Sopenharmony_ci	67,  65,  63,  61,  58,  56,  54,  52,
3398c2ecf20Sopenharmony_ci	50,  48,  46,  44,  41,  39,  37,  35,
3408c2ecf20Sopenharmony_ci	32,  30,  28,  26,  23,  21,  19,  16,
3418c2ecf20Sopenharmony_ci	14,  12,  10,   7,   5,   3,   0,  -1,
3428c2ecf20Sopenharmony_ci	-3,  -6,  -8, -10, -13, -15, -17, -19,
3438c2ecf20Sopenharmony_ci	-22, -24, -26, -29, -31, -33, -35, -38,
3448c2ecf20Sopenharmony_ci	-40, -42, -44, -46, -48, -51, -53, -55,
3458c2ecf20Sopenharmony_ci	-57, -59, -61, -63, -65, -67, -69, -71,
3468c2ecf20Sopenharmony_ci	-73, -75, -77, -79, -81, -82, -84, -86,
3478c2ecf20Sopenharmony_ci	-88, -89, -91, -93, -94, -96, -98, -99,
3488c2ecf20Sopenharmony_ci	-101, -102, -104, -105, -106, -108, -109, -110,
3498c2ecf20Sopenharmony_ci	-112, -113, -114, -115, -116, -117, -119, -120,
3508c2ecf20Sopenharmony_ci	-120, -121, -122, -123, -124, -125, -126, -126,
3518c2ecf20Sopenharmony_ci	-127, -128, -128, -128, -128, -128, -128, -128,
3528c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3538c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3548c2ecf20Sopenharmony_ci	-128, -128, -128, -128, -128, -128, -128, -128,
3558c2ecf20Sopenharmony_ci	-127, -127, -126, -125, -125, -124, -123, -122,
3568c2ecf20Sopenharmony_ci	-121, -120, -119, -118, -117, -116, -115, -114,
3578c2ecf20Sopenharmony_ci	-113, -111, -110, -109, -107, -106, -105, -103,
3588c2ecf20Sopenharmony_ci	-102, -100, -99, -97, -96, -94, -92, -91,
3598c2ecf20Sopenharmony_ci	-89, -87, -85, -84, -82, -80, -78, -76,
3608c2ecf20Sopenharmony_ci	-74, -73, -71, -69, -67, -65, -63, -61,
3618c2ecf20Sopenharmony_ci	-58, -56, -54, -52, -50, -48, -46, -44,
3628c2ecf20Sopenharmony_ci	-41, -39, -37, -35, -32, -30, -28, -26,
3638c2ecf20Sopenharmony_ci	-23, -21, -19, -16, -14, -12, -10,  -7,
3648c2ecf20Sopenharmony_ci	-5,  -3,   0,   1,   3,   6,   8,  10,
3658c2ecf20Sopenharmony_ci	13,  15,  17,  19,  22,  24,  26,  29,
3668c2ecf20Sopenharmony_ci	31,  33,  35,  38,  40,  42,  44,  46,
3678c2ecf20Sopenharmony_ci	48,  51,  53,  55,  57,  59,  61,  63,
3688c2ecf20Sopenharmony_ci	65,  67,  69,  71,  73,  75,  77,  79,
3698c2ecf20Sopenharmony_ci	81,  82,  84,  86,  88,  89,  91,  93,
3708c2ecf20Sopenharmony_ci	94,  96,  98,  99, 101, 102, 104, 105,
3718c2ecf20Sopenharmony_ci	106, 108, 109, 110, 112, 113, 114, 115,
3728c2ecf20Sopenharmony_ci	116, 117, 119, 120, 120, 121, 122, 123,
3738c2ecf20Sopenharmony_ci	124, 125, 126, 126, 127, 128, 128, 129,
3748c2ecf20Sopenharmony_ci	129, 130, 130, 131, 131, 131, 131, 132,
3758c2ecf20Sopenharmony_ci	132, 132, 132, 132, 132, 132, 132, 132,
3768c2ecf20Sopenharmony_ci	132, 132, 132, 131, 131, 131, 130, 130,
3778c2ecf20Sopenharmony_ci	130, 129, 129, 128, 127, 127, 126, 125,
3788c2ecf20Sopenharmony_ci	125, 124, 123, 122, 121, 120, 119, 118,
3798c2ecf20Sopenharmony_ci	117, 116, 115, 114, 113, 111, 110, 109,
3808c2ecf20Sopenharmony_ci	107, 106, 105, 103, 102, 100,  99,  97,
3818c2ecf20Sopenharmony_ci	96, 94, 92, 91, 89, 87, 85, 84, 82
3828c2ecf20Sopenharmony_ci};
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic const s16 hsv_green_x[] = {
3858c2ecf20Sopenharmony_ci	-124, -124, -125, -125, -125, -125, -125, -125,
3868c2ecf20Sopenharmony_ci	-125, -126, -126, -125, -125, -125, -125, -125,
3878c2ecf20Sopenharmony_ci	-125, -124, -124, -124, -123, -123, -122, -122,
3888c2ecf20Sopenharmony_ci	-121, -121, -120, -120, -119, -118, -117, -117,
3898c2ecf20Sopenharmony_ci	-116, -115, -114, -113, -112, -111, -110, -109,
3908c2ecf20Sopenharmony_ci	-108, -107, -105, -104, -103, -102, -100, -99,
3918c2ecf20Sopenharmony_ci	-98, -96, -95, -93, -92, -91, -89, -87,
3928c2ecf20Sopenharmony_ci	-86, -84, -83, -81, -79, -77, -76, -74,
3938c2ecf20Sopenharmony_ci	-72, -70, -69, -67, -65, -63, -61, -59,
3948c2ecf20Sopenharmony_ci	-57, -55, -53, -51, -49, -47, -45, -43,
3958c2ecf20Sopenharmony_ci	-41, -39, -37, -35, -33, -30, -28, -26,
3968c2ecf20Sopenharmony_ci	-24, -22, -20, -18, -15, -13, -11,  -9,
3978c2ecf20Sopenharmony_ci	-7,  -4,  -2,   0,   1,   3,   6,   8,
3988c2ecf20Sopenharmony_ci	10,  12,  14,  17,  19,  21,  23,  25,
3998c2ecf20Sopenharmony_ci	27,  29,  32,  34,  36,  38,  40,  42,
4008c2ecf20Sopenharmony_ci	44,  46,  48,  50,  52,  54,  56,  58,
4018c2ecf20Sopenharmony_ci	60,  62,  64,  66,  68,  70,  71,  73,
4028c2ecf20Sopenharmony_ci	75,  77,  78,  80,  82,  83,  85,  87,
4038c2ecf20Sopenharmony_ci	88,  90,  91,  93,  94,  96,  97,  98,
4048c2ecf20Sopenharmony_ci	100, 101, 102, 104, 105, 106, 107, 108,
4058c2ecf20Sopenharmony_ci	109, 111, 112, 113, 113, 114, 115, 116,
4068c2ecf20Sopenharmony_ci	117, 118, 118, 119, 120, 120, 121, 122,
4078c2ecf20Sopenharmony_ci	122, 123, 123, 124, 124, 124, 125, 125,
4088c2ecf20Sopenharmony_ci	125, 125, 125, 125, 125, 126, 126, 125,
4098c2ecf20Sopenharmony_ci	125, 125, 125, 125, 125, 124, 124, 124,
4108c2ecf20Sopenharmony_ci	123, 123, 122, 122, 121, 121, 120, 120,
4118c2ecf20Sopenharmony_ci	119, 118, 117, 117, 116, 115, 114, 113,
4128c2ecf20Sopenharmony_ci	112, 111, 110, 109, 108, 107, 105, 104,
4138c2ecf20Sopenharmony_ci	103, 102, 100,  99,  98,  96,  95,  93,
4148c2ecf20Sopenharmony_ci	92,  91,  89,  87,  86,  84,  83,  81,
4158c2ecf20Sopenharmony_ci	79,  77,  76,  74,  72,  70,  69,  67,
4168c2ecf20Sopenharmony_ci	65,  63,  61,  59,  57,  55,  53,  51,
4178c2ecf20Sopenharmony_ci	49,  47,  45,  43,  41,  39,  37,  35,
4188c2ecf20Sopenharmony_ci	33,  30,  28,  26,  24,  22,  20,  18,
4198c2ecf20Sopenharmony_ci	15,  13,  11,   9,   7,   4,   2,   0,
4208c2ecf20Sopenharmony_ci	-1,  -3,  -6,  -8, -10, -12, -14, -17,
4218c2ecf20Sopenharmony_ci	-19, -21, -23, -25, -27, -29, -32, -34,
4228c2ecf20Sopenharmony_ci	-36, -38, -40, -42, -44, -46, -48, -50,
4238c2ecf20Sopenharmony_ci	-52, -54, -56, -58, -60, -62, -64, -66,
4248c2ecf20Sopenharmony_ci	-68, -70, -71, -73, -75, -77, -78, -80,
4258c2ecf20Sopenharmony_ci	-82, -83, -85, -87, -88, -90, -91, -93,
4268c2ecf20Sopenharmony_ci	-94, -96, -97, -98, -100, -101, -102, -104,
4278c2ecf20Sopenharmony_ci	-105, -106, -107, -108, -109, -111, -112, -113,
4288c2ecf20Sopenharmony_ci	-113, -114, -115, -116, -117, -118, -118, -119,
4298c2ecf20Sopenharmony_ci	-120, -120, -121, -122, -122, -123, -123, -124, -124
4308c2ecf20Sopenharmony_ci};
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic const s16 hsv_green_y[] = {
4338c2ecf20Sopenharmony_ci	-100, -99, -98, -97, -95, -94, -93, -91,
4348c2ecf20Sopenharmony_ci	-90, -89, -87, -86, -84, -83, -81, -80,
4358c2ecf20Sopenharmony_ci	-78, -76, -75, -73, -71, -70, -68, -66,
4368c2ecf20Sopenharmony_ci	-64, -63, -61, -59, -57, -55, -53, -51,
4378c2ecf20Sopenharmony_ci	-49, -48, -46, -44, -42, -40, -38, -36,
4388c2ecf20Sopenharmony_ci	-34, -32, -30, -27, -25, -23, -21, -19,
4398c2ecf20Sopenharmony_ci	-17, -15, -13, -11,  -9,  -7,  -4,  -2,
4408c2ecf20Sopenharmony_ci	0,   1,   3,   5,   7,   9,  11,  14,
4418c2ecf20Sopenharmony_ci	16,  18,  20,  22,  24,  26,  28,  30,
4428c2ecf20Sopenharmony_ci	32,  34,  36,  38,  40,  42,  44,  46,
4438c2ecf20Sopenharmony_ci	48,  50,  52,  54,  56,  58,  59,  61,
4448c2ecf20Sopenharmony_ci	63,  65,  67,  68,  70,  72,  74,  75,
4458c2ecf20Sopenharmony_ci	77,  78,  80,  82,  83,  85,  86,  88,
4468c2ecf20Sopenharmony_ci	89,  90,  92,  93,  95,  96,  97,  98,
4478c2ecf20Sopenharmony_ci	100, 101, 102, 103, 104, 105, 106, 107,
4488c2ecf20Sopenharmony_ci	108, 109, 110, 111, 112, 112, 113, 114,
4498c2ecf20Sopenharmony_ci	115, 115, 116, 116, 117, 117, 118, 118,
4508c2ecf20Sopenharmony_ci	119, 119, 119, 120, 120, 120, 120, 120,
4518c2ecf20Sopenharmony_ci	121, 121, 121, 121, 121, 121, 120, 120,
4528c2ecf20Sopenharmony_ci	120, 120, 120, 119, 119, 119, 118, 118,
4538c2ecf20Sopenharmony_ci	117, 117, 116, 116, 115, 114, 114, 113,
4548c2ecf20Sopenharmony_ci	112, 111, 111, 110, 109, 108, 107, 106,
4558c2ecf20Sopenharmony_ci	105, 104, 103, 102, 100,  99,  98,  97,
4568c2ecf20Sopenharmony_ci	95,  94,  93,  91,  90,  89,  87,  86,
4578c2ecf20Sopenharmony_ci	84,  83,  81,  80,  78,  76,  75,  73,
4588c2ecf20Sopenharmony_ci	71,  70,  68,  66,  64,  63,  61,  59,
4598c2ecf20Sopenharmony_ci	57,  55,  53,  51,  49,  48,  46,  44,
4608c2ecf20Sopenharmony_ci	42,  40,  38,  36,  34,  32,  30,  27,
4618c2ecf20Sopenharmony_ci	25,  23,  21,  19,  17,  15,  13,  11,
4628c2ecf20Sopenharmony_ci	9,   7,   4,   2,   0,  -1,  -3,  -5,
4638c2ecf20Sopenharmony_ci	-7,  -9, -11, -14, -16, -18, -20, -22,
4648c2ecf20Sopenharmony_ci	-24, -26, -28, -30, -32, -34, -36, -38,
4658c2ecf20Sopenharmony_ci	-40, -42, -44, -46, -48, -50, -52, -54,
4668c2ecf20Sopenharmony_ci	-56, -58, -59, -61, -63, -65, -67, -68,
4678c2ecf20Sopenharmony_ci	-70, -72, -74, -75, -77, -78, -80, -82,
4688c2ecf20Sopenharmony_ci	-83, -85, -86, -88, -89, -90, -92, -93,
4698c2ecf20Sopenharmony_ci	-95, -96, -97, -98, -100, -101, -102, -103,
4708c2ecf20Sopenharmony_ci	-104, -105, -106, -107, -108, -109, -110, -111,
4718c2ecf20Sopenharmony_ci	-112, -112, -113, -114, -115, -115, -116, -116,
4728c2ecf20Sopenharmony_ci	-117, -117, -118, -118, -119, -119, -119, -120,
4738c2ecf20Sopenharmony_ci	-120, -120, -120, -120, -121, -121, -121, -121,
4748c2ecf20Sopenharmony_ci	-121, -121, -120, -120, -120, -120, -120, -119,
4758c2ecf20Sopenharmony_ci	-119, -119, -118, -118, -117, -117, -116, -116,
4768c2ecf20Sopenharmony_ci	-115, -114, -114, -113, -112, -111, -111, -110,
4778c2ecf20Sopenharmony_ci	-109, -108, -107, -106, -105, -104, -103, -102, -100
4788c2ecf20Sopenharmony_ci};
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_cistatic const s16 hsv_blue_x[] = {
4818c2ecf20Sopenharmony_ci	112, 113, 114, 114, 115, 116, 117, 117,
4828c2ecf20Sopenharmony_ci	118, 118, 119, 119, 120, 120, 120, 121,
4838c2ecf20Sopenharmony_ci	121, 121, 122, 122, 122, 122, 122, 122,
4848c2ecf20Sopenharmony_ci	122, 122, 122, 122, 122, 122, 121, 121,
4858c2ecf20Sopenharmony_ci	121, 120, 120, 120, 119, 119, 118, 118,
4868c2ecf20Sopenharmony_ci	117, 116, 116, 115, 114, 113, 113, 112,
4878c2ecf20Sopenharmony_ci	111, 110, 109, 108, 107, 106, 105, 104,
4888c2ecf20Sopenharmony_ci	103, 102, 100,  99,  98,  97,  95,  94,
4898c2ecf20Sopenharmony_ci	93,  91,  90,  88,  87,  85,  84,  82,
4908c2ecf20Sopenharmony_ci	80,  79,  77,  76,  74,  72,  70,  69,
4918c2ecf20Sopenharmony_ci	67,  65,  63,  61,  60,  58,  56,  54,
4928c2ecf20Sopenharmony_ci	52,  50,  48,  46,  44,  42,  40,  38,
4938c2ecf20Sopenharmony_ci	36,  34,  32,  30,  28,  26,  24,  22,
4948c2ecf20Sopenharmony_ci	19,  17,  15,  13,  11,   9,   7,   5,
4958c2ecf20Sopenharmony_ci	2,   0,  -1,  -3,  -5,  -7,  -9, -12,
4968c2ecf20Sopenharmony_ci	-14, -16, -18, -20, -22, -24, -26, -28,
4978c2ecf20Sopenharmony_ci	-31, -33, -35, -37, -39, -41, -43, -45,
4988c2ecf20Sopenharmony_ci	-47, -49, -51, -53, -54, -56, -58, -60,
4998c2ecf20Sopenharmony_ci	-62, -64, -66, -67, -69, -71, -73, -74,
5008c2ecf20Sopenharmony_ci	-76, -78, -79, -81, -83, -84, -86, -87,
5018c2ecf20Sopenharmony_ci	-89, -90, -92, -93, -94, -96, -97, -98,
5028c2ecf20Sopenharmony_ci	-99, -101, -102, -103, -104, -105, -106, -107,
5038c2ecf20Sopenharmony_ci	-108, -109, -110, -111, -112, -113, -114, -114,
5048c2ecf20Sopenharmony_ci	-115, -116, -117, -117, -118, -118, -119, -119,
5058c2ecf20Sopenharmony_ci	-120, -120, -120, -121, -121, -121, -122, -122,
5068c2ecf20Sopenharmony_ci	-122, -122, -122, -122, -122, -122, -122, -122,
5078c2ecf20Sopenharmony_ci	-122, -122, -121, -121, -121, -120, -120, -120,
5088c2ecf20Sopenharmony_ci	-119, -119, -118, -118, -117, -116, -116, -115,
5098c2ecf20Sopenharmony_ci	-114, -113, -113, -112, -111, -110, -109, -108,
5108c2ecf20Sopenharmony_ci	-107, -106, -105, -104, -103, -102, -100, -99,
5118c2ecf20Sopenharmony_ci	-98, -97, -95, -94, -93, -91, -90, -88,
5128c2ecf20Sopenharmony_ci	-87, -85, -84, -82, -80, -79, -77, -76,
5138c2ecf20Sopenharmony_ci	-74, -72, -70, -69, -67, -65, -63, -61,
5148c2ecf20Sopenharmony_ci	-60, -58, -56, -54, -52, -50, -48, -46,
5158c2ecf20Sopenharmony_ci	-44, -42, -40, -38, -36, -34, -32, -30,
5168c2ecf20Sopenharmony_ci	-28, -26, -24, -22, -19, -17, -15, -13,
5178c2ecf20Sopenharmony_ci	-11,  -9,  -7,  -5,  -2,   0,   1,   3,
5188c2ecf20Sopenharmony_ci	5,   7,   9,  12,  14,  16,  18,  20,
5198c2ecf20Sopenharmony_ci	22,  24,  26,  28,  31,  33,  35,  37,
5208c2ecf20Sopenharmony_ci	39,  41,  43,  45,  47,  49,  51,  53,
5218c2ecf20Sopenharmony_ci	54,  56,  58,  60,  62,  64,  66,  67,
5228c2ecf20Sopenharmony_ci	69,  71,  73,  74,  76,  78,  79,  81,
5238c2ecf20Sopenharmony_ci	83,  84,  86,  87,  89,  90,  92,  93,
5248c2ecf20Sopenharmony_ci	94,  96,  97,  98,  99, 101, 102, 103,
5258c2ecf20Sopenharmony_ci	104, 105, 106, 107, 108, 109, 110, 111, 112
5268c2ecf20Sopenharmony_ci};
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic const s16 hsv_blue_y[] = {
5298c2ecf20Sopenharmony_ci	-11, -13, -15, -17, -19, -21, -23, -25,
5308c2ecf20Sopenharmony_ci	-27, -29, -31, -33, -35, -37, -39, -41,
5318c2ecf20Sopenharmony_ci	-43, -45, -46, -48, -50, -52, -54, -55,
5328c2ecf20Sopenharmony_ci	-57, -59, -61, -62, -64, -66, -67, -69,
5338c2ecf20Sopenharmony_ci	-71, -72, -74, -75, -77, -78, -80, -81,
5348c2ecf20Sopenharmony_ci	-83, -84, -86, -87, -88, -90, -91, -92,
5358c2ecf20Sopenharmony_ci	-93, -95, -96, -97, -98, -99, -100, -101,
5368c2ecf20Sopenharmony_ci	-102, -103, -104, -105, -106, -106, -107, -108,
5378c2ecf20Sopenharmony_ci	-109, -109, -110, -111, -111, -112, -112, -113,
5388c2ecf20Sopenharmony_ci	-113, -114, -114, -114, -115, -115, -115, -115,
5398c2ecf20Sopenharmony_ci	-116, -116, -116, -116, -116, -116, -116, -116,
5408c2ecf20Sopenharmony_ci	-116, -115, -115, -115, -115, -114, -114, -114,
5418c2ecf20Sopenharmony_ci	-113, -113, -112, -112, -111, -111, -110, -110,
5428c2ecf20Sopenharmony_ci	-109, -108, -108, -107, -106, -105, -104, -103,
5438c2ecf20Sopenharmony_ci	-102, -101, -100, -99, -98, -97, -96, -95,
5448c2ecf20Sopenharmony_ci	-94, -93, -91, -90, -89, -88, -86, -85,
5458c2ecf20Sopenharmony_ci	-84, -82, -81, -79, -78, -76, -75, -73,
5468c2ecf20Sopenharmony_ci	-71, -70, -68, -67, -65, -63, -62, -60,
5478c2ecf20Sopenharmony_ci	-58, -56, -55, -53, -51, -49, -47, -45,
5488c2ecf20Sopenharmony_ci	-44, -42, -40, -38, -36, -34, -32, -30,
5498c2ecf20Sopenharmony_ci	-28, -26, -24, -22, -20, -18, -16, -14,
5508c2ecf20Sopenharmony_ci	-12, -10,  -8,  -6,  -4,  -2,   0,   1,
5518c2ecf20Sopenharmony_ci	3,   5,   7,   9,  11,  13,  15,  17,
5528c2ecf20Sopenharmony_ci	19,  21,  23,  25,  27,  29,  31,  33,
5538c2ecf20Sopenharmony_ci	35,  37,  39,  41,  43,  45,  46,  48,
5548c2ecf20Sopenharmony_ci	50,  52,  54,  55,  57,  59,  61,  62,
5558c2ecf20Sopenharmony_ci	64,  66,  67,  69,  71,  72,  74,  75,
5568c2ecf20Sopenharmony_ci	77,  78,  80,  81,  83,  84,  86,  87,
5578c2ecf20Sopenharmony_ci	88,  90,  91,  92,  93,  95,  96,  97,
5588c2ecf20Sopenharmony_ci	98,  99, 100, 101, 102, 103, 104, 105,
5598c2ecf20Sopenharmony_ci	106, 106, 107, 108, 109, 109, 110, 111,
5608c2ecf20Sopenharmony_ci	111, 112, 112, 113, 113, 114, 114, 114,
5618c2ecf20Sopenharmony_ci	115, 115, 115, 115, 116, 116, 116, 116,
5628c2ecf20Sopenharmony_ci	116, 116, 116, 116, 116, 115, 115, 115,
5638c2ecf20Sopenharmony_ci	115, 114, 114, 114, 113, 113, 112, 112,
5648c2ecf20Sopenharmony_ci	111, 111, 110, 110, 109, 108, 108, 107,
5658c2ecf20Sopenharmony_ci	106, 105, 104, 103, 102, 101, 100,  99,
5668c2ecf20Sopenharmony_ci	98,  97,  96,  95,  94,  93,  91,  90,
5678c2ecf20Sopenharmony_ci	89,  88,  86,  85,  84,  82,  81,  79,
5688c2ecf20Sopenharmony_ci	78,  76,  75,  73,  71,  70,  68,  67,
5698c2ecf20Sopenharmony_ci	65,  63,  62,  60,  58,  56,  55,  53,
5708c2ecf20Sopenharmony_ci	51,  49,  47,  45,  44,  42,  40,  38,
5718c2ecf20Sopenharmony_ci	36,  34,  32,  30,  28,  26,  24,  22,
5728c2ecf20Sopenharmony_ci	20,  18,  16,  14,  12,  10,   8,   6,
5738c2ecf20Sopenharmony_ci	4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11
5748c2ecf20Sopenharmony_ci};
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_cistatic const u16 bridge_init[][2] = {
5778c2ecf20Sopenharmony_ci	{0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
5788c2ecf20Sopenharmony_ci	{0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
5798c2ecf20Sopenharmony_ci	{0x1068, 0x30}, {0x1069, 0x20},	{0x106a, 0x10},
5808c2ecf20Sopenharmony_ci	{0x106b, 0x08},	{0x1188, 0x87},	{0x11a1, 0x00},
5818c2ecf20Sopenharmony_ci	{0x11a2, 0x00},	{0x11a3, 0x6a},	{0x11a4, 0x50},
5828c2ecf20Sopenharmony_ci	{0x11ab, 0x00},	{0x11ac, 0x00},	{0x11ad, 0x50},
5838c2ecf20Sopenharmony_ci	{0x11ae, 0x3c},	{0x118a, 0x04},	{0x0395, 0x04},
5848c2ecf20Sopenharmony_ci	{0x11b8, 0x3a},	{0x118b, 0x0e},	{0x10f7, 0x05},
5858c2ecf20Sopenharmony_ci	{0x10f8, 0x14},	{0x10fa, 0xff},	{0x10f9, 0x00},
5868c2ecf20Sopenharmony_ci	{0x11ba, 0x0a},	{0x11a5, 0x2d},	{0x11a6, 0x2d},
5878c2ecf20Sopenharmony_ci	{0x11a7, 0x3a},	{0x11a8, 0x05},	{0x11a9, 0x04},
5888c2ecf20Sopenharmony_ci	{0x11aa, 0x3f},	{0x11af, 0x28},	{0x11b0, 0xd8},
5898c2ecf20Sopenharmony_ci	{0x11b1, 0x14},	{0x11b2, 0xec},	{0x11b3, 0x32},
5908c2ecf20Sopenharmony_ci	{0x11b4, 0xdd},	{0x11b5, 0x32},	{0x11b6, 0xdd},
5918c2ecf20Sopenharmony_ci	{0x10e0, 0x2c},	{0x11bc, 0x40},	{0x11bd, 0x01},
5928c2ecf20Sopenharmony_ci	{0x11be, 0xf0},	{0x11bf, 0x00},	{0x118c, 0x1f},
5938c2ecf20Sopenharmony_ci	{0x118d, 0x1f},	{0x118e, 0x1f},	{0x118f, 0x1f},
5948c2ecf20Sopenharmony_ci	{0x1180, 0x01},	{0x1181, 0x00},	{0x1182, 0x01},
5958c2ecf20Sopenharmony_ci	{0x1183, 0x00},	{0x1184, 0x50},	{0x1185, 0x80},
5968c2ecf20Sopenharmony_ci	{0x1007, 0x00}
5978c2ecf20Sopenharmony_ci};
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
6008c2ecf20Sopenharmony_cistatic const u8 ov_gain[] = {
6018c2ecf20Sopenharmony_ci	0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
6028c2ecf20Sopenharmony_ci	0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
6038c2ecf20Sopenharmony_ci	0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
6048c2ecf20Sopenharmony_ci	0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
6058c2ecf20Sopenharmony_ci	0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
6068c2ecf20Sopenharmony_ci	0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
6078c2ecf20Sopenharmony_ci	0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
6088c2ecf20Sopenharmony_ci	0x70 /* 8x */
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
6128c2ecf20Sopenharmony_cistatic const u16 micron1_gain[] = {
6138c2ecf20Sopenharmony_ci	/* 1x   1.25x   1.5x    1.75x */
6148c2ecf20Sopenharmony_ci	0x0020, 0x0028, 0x0030, 0x0038,
6158c2ecf20Sopenharmony_ci	/* 2x   2.25x   2.5x    2.75x */
6168c2ecf20Sopenharmony_ci	0x00a0, 0x00a4, 0x00a8, 0x00ac,
6178c2ecf20Sopenharmony_ci	/* 3x   3.25x   3.5x    3.75x */
6188c2ecf20Sopenharmony_ci	0x00b0, 0x00b4, 0x00b8, 0x00bc,
6198c2ecf20Sopenharmony_ci	/* 4x   4.25x   4.5x    4.75x */
6208c2ecf20Sopenharmony_ci	0x00c0, 0x00c4, 0x00c8, 0x00cc,
6218c2ecf20Sopenharmony_ci	/* 5x   5.25x   5.5x    5.75x */
6228c2ecf20Sopenharmony_ci	0x00d0, 0x00d4, 0x00d8, 0x00dc,
6238c2ecf20Sopenharmony_ci	/* 6x   6.25x   6.5x    6.75x */
6248c2ecf20Sopenharmony_ci	0x00e0, 0x00e4, 0x00e8, 0x00ec,
6258c2ecf20Sopenharmony_ci	/* 7x   7.25x   7.5x    7.75x */
6268c2ecf20Sopenharmony_ci	0x00f0, 0x00f4, 0x00f8, 0x00fc,
6278c2ecf20Sopenharmony_ci	/* 8x */
6288c2ecf20Sopenharmony_ci	0x01c0
6298c2ecf20Sopenharmony_ci};
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci/* mt9m001 sensor uses a different gain formula then other micron sensors */
6328c2ecf20Sopenharmony_ci/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
6338c2ecf20Sopenharmony_cistatic const u16 micron2_gain[] = {
6348c2ecf20Sopenharmony_ci	/* 1x   1.25x   1.5x    1.75x */
6358c2ecf20Sopenharmony_ci	0x0008, 0x000a, 0x000c, 0x000e,
6368c2ecf20Sopenharmony_ci	/* 2x   2.25x   2.5x    2.75x */
6378c2ecf20Sopenharmony_ci	0x0010, 0x0012, 0x0014, 0x0016,
6388c2ecf20Sopenharmony_ci	/* 3x   3.25x   3.5x    3.75x */
6398c2ecf20Sopenharmony_ci	0x0018, 0x001a, 0x001c, 0x001e,
6408c2ecf20Sopenharmony_ci	/* 4x   4.25x   4.5x    4.75x */
6418c2ecf20Sopenharmony_ci	0x0020, 0x0051, 0x0052, 0x0053,
6428c2ecf20Sopenharmony_ci	/* 5x   5.25x   5.5x    5.75x */
6438c2ecf20Sopenharmony_ci	0x0054, 0x0055, 0x0056, 0x0057,
6448c2ecf20Sopenharmony_ci	/* 6x   6.25x   6.5x    6.75x */
6458c2ecf20Sopenharmony_ci	0x0058, 0x0059, 0x005a, 0x005b,
6468c2ecf20Sopenharmony_ci	/* 7x   7.25x   7.5x    7.75x */
6478c2ecf20Sopenharmony_ci	0x005c, 0x005d, 0x005e, 0x005f,
6488c2ecf20Sopenharmony_ci	/* 8x */
6498c2ecf20Sopenharmony_ci	0x0060
6508c2ecf20Sopenharmony_ci};
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci/* Gain = .5 + bit[7:0] / 16 */
6538c2ecf20Sopenharmony_cistatic const u8 hv7131r_gain[] = {
6548c2ecf20Sopenharmony_ci	0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
6558c2ecf20Sopenharmony_ci	0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
6568c2ecf20Sopenharmony_ci	0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
6578c2ecf20Sopenharmony_ci	0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
6588c2ecf20Sopenharmony_ci	0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
6598c2ecf20Sopenharmony_ci	0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
6608c2ecf20Sopenharmony_ci	0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
6618c2ecf20Sopenharmony_ci	0x78 /* 8x */
6628c2ecf20Sopenharmony_ci};
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 soi968_init[] = {
6658c2ecf20Sopenharmony_ci	{0x0c, 0x00}, {0x0f, 0x1f},
6668c2ecf20Sopenharmony_ci	{0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
6678c2ecf20Sopenharmony_ci	{0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
6688c2ecf20Sopenharmony_ci	{0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
6698c2ecf20Sopenharmony_ci	{0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
6708c2ecf20Sopenharmony_ci	{0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
6718c2ecf20Sopenharmony_ci	{0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
6728c2ecf20Sopenharmony_ci	{0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
6738c2ecf20Sopenharmony_ci	{0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
6748c2ecf20Sopenharmony_ci	{0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
6758c2ecf20Sopenharmony_ci	{0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
6768c2ecf20Sopenharmony_ci};
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 ov7660_init[] = {
6798c2ecf20Sopenharmony_ci	{0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
6808c2ecf20Sopenharmony_ci	{0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
6818c2ecf20Sopenharmony_ci	{0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
6828c2ecf20Sopenharmony_ci	/* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
6838c2ecf20Sopenharmony_ci	   0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
6848c2ecf20Sopenharmony_ci	{0x17, 0x10}, {0x18, 0x61},
6858c2ecf20Sopenharmony_ci	{0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
6868c2ecf20Sopenharmony_ci	{0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
6878c2ecf20Sopenharmony_ci	{0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
6888c2ecf20Sopenharmony_ci};
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 ov7670_init[] = {
6918c2ecf20Sopenharmony_ci	{0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
6928c2ecf20Sopenharmony_ci	{0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
6938c2ecf20Sopenharmony_ci	{0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
6948c2ecf20Sopenharmony_ci	{0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
6958c2ecf20Sopenharmony_ci	{0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
6968c2ecf20Sopenharmony_ci	{0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
6978c2ecf20Sopenharmony_ci	{0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
6988c2ecf20Sopenharmony_ci	{0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
6998c2ecf20Sopenharmony_ci	{0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
7008c2ecf20Sopenharmony_ci	{0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
7018c2ecf20Sopenharmony_ci	{0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
7028c2ecf20Sopenharmony_ci	{0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
7038c2ecf20Sopenharmony_ci	{0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
7048c2ecf20Sopenharmony_ci	{0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
7058c2ecf20Sopenharmony_ci	{0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
7068c2ecf20Sopenharmony_ci	{0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
7078c2ecf20Sopenharmony_ci	{0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
7088c2ecf20Sopenharmony_ci	{0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
7098c2ecf20Sopenharmony_ci	{0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
7108c2ecf20Sopenharmony_ci	{0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
7118c2ecf20Sopenharmony_ci	{0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
7128c2ecf20Sopenharmony_ci	{0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
7138c2ecf20Sopenharmony_ci	{0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
7148c2ecf20Sopenharmony_ci	{0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
7158c2ecf20Sopenharmony_ci	{0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
7168c2ecf20Sopenharmony_ci	{0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
7178c2ecf20Sopenharmony_ci	{0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
7188c2ecf20Sopenharmony_ci	{0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
7198c2ecf20Sopenharmony_ci	{0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
7208c2ecf20Sopenharmony_ci	{0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
7218c2ecf20Sopenharmony_ci	{0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
7228c2ecf20Sopenharmony_ci	{0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
7238c2ecf20Sopenharmony_ci	{0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
7248c2ecf20Sopenharmony_ci	{0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
7258c2ecf20Sopenharmony_ci	{0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
7268c2ecf20Sopenharmony_ci	{0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
7278c2ecf20Sopenharmony_ci	{0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
7288c2ecf20Sopenharmony_ci	{0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
7298c2ecf20Sopenharmony_ci	{0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
7308c2ecf20Sopenharmony_ci	{0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
7318c2ecf20Sopenharmony_ci	{0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
7328c2ecf20Sopenharmony_ci	{0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
7338c2ecf20Sopenharmony_ci	{0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
7348c2ecf20Sopenharmony_ci	{0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
7358c2ecf20Sopenharmony_ci	{0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
7368c2ecf20Sopenharmony_ci	{0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
7378c2ecf20Sopenharmony_ci	{0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
7388c2ecf20Sopenharmony_ci	{0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
7398c2ecf20Sopenharmony_ci	{0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
7408c2ecf20Sopenharmony_ci	{0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
7418c2ecf20Sopenharmony_ci	{0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
7428c2ecf20Sopenharmony_ci	{0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
7438c2ecf20Sopenharmony_ci	{0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
7448c2ecf20Sopenharmony_ci	{0x93, 0x00},
7458c2ecf20Sopenharmony_ci};
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 ov9650_init[] = {
7488c2ecf20Sopenharmony_ci	{0x00, 0x00}, {0x01, 0x78},
7498c2ecf20Sopenharmony_ci	{0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
7508c2ecf20Sopenharmony_ci	{0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
7518c2ecf20Sopenharmony_ci	{0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
7528c2ecf20Sopenharmony_ci	{0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
7538c2ecf20Sopenharmony_ci	{0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
7548c2ecf20Sopenharmony_ci	{0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
7558c2ecf20Sopenharmony_ci	{0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
7568c2ecf20Sopenharmony_ci	{0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
7578c2ecf20Sopenharmony_ci	{0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
7588c2ecf20Sopenharmony_ci	{0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
7598c2ecf20Sopenharmony_ci	{0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
7608c2ecf20Sopenharmony_ci	{0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
7618c2ecf20Sopenharmony_ci	{0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
7628c2ecf20Sopenharmony_ci	{0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
7638c2ecf20Sopenharmony_ci	{0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
7648c2ecf20Sopenharmony_ci	{0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
7658c2ecf20Sopenharmony_ci	{0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
7668c2ecf20Sopenharmony_ci	{0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
7678c2ecf20Sopenharmony_ci	{0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
7688c2ecf20Sopenharmony_ci	{0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
7698c2ecf20Sopenharmony_ci	{0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
7708c2ecf20Sopenharmony_ci	{0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
7718c2ecf20Sopenharmony_ci	{0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
7728c2ecf20Sopenharmony_ci	{0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
7738c2ecf20Sopenharmony_ci	{0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
7748c2ecf20Sopenharmony_ci	{0xaa, 0x92}, {0xab, 0x0a},
7758c2ecf20Sopenharmony_ci};
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 ov9655_init[] = {
7788c2ecf20Sopenharmony_ci	{0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
7798c2ecf20Sopenharmony_ci	{0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
7808c2ecf20Sopenharmony_ci	{0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
7818c2ecf20Sopenharmony_ci	{0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
7828c2ecf20Sopenharmony_ci	{0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
7838c2ecf20Sopenharmony_ci	{0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
7848c2ecf20Sopenharmony_ci	{0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
7858c2ecf20Sopenharmony_ci	{0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
7868c2ecf20Sopenharmony_ci	{0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
7878c2ecf20Sopenharmony_ci	{0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
7888c2ecf20Sopenharmony_ci	{0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
7898c2ecf20Sopenharmony_ci	{0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
7908c2ecf20Sopenharmony_ci	{0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
7918c2ecf20Sopenharmony_ci	{0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
7928c2ecf20Sopenharmony_ci	{0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
7938c2ecf20Sopenharmony_ci	{0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
7948c2ecf20Sopenharmony_ci	{0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
7958c2ecf20Sopenharmony_ci	{0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
7968c2ecf20Sopenharmony_ci	{0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
7978c2ecf20Sopenharmony_ci	{0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
7988c2ecf20Sopenharmony_ci	{0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
7998c2ecf20Sopenharmony_ci	{0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
8008c2ecf20Sopenharmony_ci	{0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
8018c2ecf20Sopenharmony_ci	{0x04, 0x03}, {0x00, 0x13},
8028c2ecf20Sopenharmony_ci};
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9v112_init[] = {
8058c2ecf20Sopenharmony_ci	{0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
8068c2ecf20Sopenharmony_ci	{0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
8078c2ecf20Sopenharmony_ci	{0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
8088c2ecf20Sopenharmony_ci	{0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
8098c2ecf20Sopenharmony_ci	{0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
8108c2ecf20Sopenharmony_ci	{0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
8118c2ecf20Sopenharmony_ci	{0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
8128c2ecf20Sopenharmony_ci	{0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
8138c2ecf20Sopenharmony_ci	{0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
8148c2ecf20Sopenharmony_ci	{0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
8158c2ecf20Sopenharmony_ci	{0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
8168c2ecf20Sopenharmony_ci	{0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
8178c2ecf20Sopenharmony_ci	{0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
8188c2ecf20Sopenharmony_ci	{0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
8198c2ecf20Sopenharmony_ci	{0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
8208c2ecf20Sopenharmony_ci	{0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
8218c2ecf20Sopenharmony_ci};
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9v111_init[] = {
8248c2ecf20Sopenharmony_ci	{0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
8258c2ecf20Sopenharmony_ci	{0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
8268c2ecf20Sopenharmony_ci	{0x2e, 0x0c64},	{0x2f, 0x0064}, {0x06, 0x600e},
8278c2ecf20Sopenharmony_ci	{0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
8288c2ecf20Sopenharmony_ci	{0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
8298c2ecf20Sopenharmony_ci	{0x06, 0x002d},	{0x07, 0x3002}, {0x08, 0x0008},
8308c2ecf20Sopenharmony_ci	{0x0e, 0x0008}, {0x20, 0x0000}
8318c2ecf20Sopenharmony_ci};
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9v011_init[] = {
8348c2ecf20Sopenharmony_ci	{0x07, 0x0002},	{0x0d, 0x0001},	{0x0d, 0x0000},
8358c2ecf20Sopenharmony_ci	{0x01, 0x0008},	{0x02, 0x0016},	{0x03, 0x01e1},
8368c2ecf20Sopenharmony_ci	{0x04, 0x0281},	{0x05, 0x0083},	{0x06, 0x0006},
8378c2ecf20Sopenharmony_ci	{0x0d, 0x0002}, {0x0a, 0x0000},	{0x0b, 0x0000},
8388c2ecf20Sopenharmony_ci	{0x0c, 0x0000},	{0x0d, 0x0000},	{0x0e, 0x0000},
8398c2ecf20Sopenharmony_ci	{0x0f, 0x0000},	{0x10, 0x0000},	{0x11, 0x0000},
8408c2ecf20Sopenharmony_ci	{0x12, 0x0000},	{0x13, 0x0000},	{0x14, 0x0000},
8418c2ecf20Sopenharmony_ci	{0x15, 0x0000},	{0x16, 0x0000},	{0x17, 0x0000},
8428c2ecf20Sopenharmony_ci	{0x18, 0x0000},	{0x19, 0x0000},	{0x1a, 0x0000},
8438c2ecf20Sopenharmony_ci	{0x1b, 0x0000},	{0x1c, 0x0000},	{0x1d, 0x0000},
8448c2ecf20Sopenharmony_ci	{0x32, 0x0000},	{0x20, 0x1101},	{0x21, 0x0000},
8458c2ecf20Sopenharmony_ci	{0x22, 0x0000},	{0x23, 0x0000},	{0x24, 0x0000},
8468c2ecf20Sopenharmony_ci	{0x25, 0x0000},	{0x26, 0x0000},	{0x27, 0x0024},
8478c2ecf20Sopenharmony_ci	{0x2f, 0xf7b0},	{0x30, 0x0005},	{0x31, 0x0000},
8488c2ecf20Sopenharmony_ci	{0x32, 0x0000},	{0x33, 0x0000},	{0x34, 0x0100},
8498c2ecf20Sopenharmony_ci	{0x3d, 0x068f},	{0x40, 0x01e0},	{0x41, 0x00d1},
8508c2ecf20Sopenharmony_ci	{0x44, 0x0082},	{0x5a, 0x0000},	{0x5b, 0x0000},
8518c2ecf20Sopenharmony_ci	{0x5c, 0x0000},	{0x5d, 0x0000},	{0x5e, 0x0000},
8528c2ecf20Sopenharmony_ci	{0x5f, 0xa31d},	{0x62, 0x0611},	{0x0a, 0x0000},
8538c2ecf20Sopenharmony_ci	{0x06, 0x0029},	{0x05, 0x0009},	{0x20, 0x1101},
8548c2ecf20Sopenharmony_ci	{0x20, 0x1101},	{0x09, 0x0064},	{0x07, 0x0003},
8558c2ecf20Sopenharmony_ci	{0x2b, 0x0033},	{0x2c, 0x00a0},	{0x2d, 0x00a0},
8568c2ecf20Sopenharmony_ci	{0x2e, 0x0033},	{0x07, 0x0002},	{0x06, 0x0000},
8578c2ecf20Sopenharmony_ci	{0x06, 0x0029},	{0x05, 0x0009},
8588c2ecf20Sopenharmony_ci};
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9m001_init[] = {
8618c2ecf20Sopenharmony_ci	{0x0d, 0x0001},
8628c2ecf20Sopenharmony_ci	{0x0d, 0x0000},
8638c2ecf20Sopenharmony_ci	{0x04, 0x0500},		/* hres = 1280 */
8648c2ecf20Sopenharmony_ci	{0x03, 0x0400},		/* vres = 1024 */
8658c2ecf20Sopenharmony_ci	{0x20, 0x1100},
8668c2ecf20Sopenharmony_ci	{0x06, 0x0010},
8678c2ecf20Sopenharmony_ci	{0x2b, 0x0024},
8688c2ecf20Sopenharmony_ci	{0x2e, 0x0024},
8698c2ecf20Sopenharmony_ci	{0x35, 0x0024},
8708c2ecf20Sopenharmony_ci	{0x2d, 0x0020},
8718c2ecf20Sopenharmony_ci	{0x2c, 0x0020},
8728c2ecf20Sopenharmony_ci	{0x09, 0x0ad4},
8738c2ecf20Sopenharmony_ci	{0x35, 0x0057},
8748c2ecf20Sopenharmony_ci};
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9m111_init[] = {
8778c2ecf20Sopenharmony_ci	{0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
8788c2ecf20Sopenharmony_ci	{0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
8798c2ecf20Sopenharmony_ci	{0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
8808c2ecf20Sopenharmony_ci	{0xf0, 0x0000},
8818c2ecf20Sopenharmony_ci};
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_cistatic const struct i2c_reg_u16 mt9m112_init[] = {
8848c2ecf20Sopenharmony_ci	{0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
8858c2ecf20Sopenharmony_ci	{0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
8868c2ecf20Sopenharmony_ci	{0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
8878c2ecf20Sopenharmony_ci	{0xf0, 0x0000},
8888c2ecf20Sopenharmony_ci};
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_cistatic const struct i2c_reg_u8 hv7131r_init[] = {
8918c2ecf20Sopenharmony_ci	{0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
8928c2ecf20Sopenharmony_ci	{0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
8938c2ecf20Sopenharmony_ci	{0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
8948c2ecf20Sopenharmony_ci	{0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
8958c2ecf20Sopenharmony_ci	{0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
8968c2ecf20Sopenharmony_ci	{0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
8978c2ecf20Sopenharmony_ci	{0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
8988c2ecf20Sopenharmony_ci	{0x23, 0x09}, {0x01, 0x08},
8998c2ecf20Sopenharmony_ci};
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistatic void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
9048c2ecf20Sopenharmony_ci	int result;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
9078c2ecf20Sopenharmony_ci		return;
9088c2ecf20Sopenharmony_ci	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
9098c2ecf20Sopenharmony_ci			0x00,
9108c2ecf20Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
9118c2ecf20Sopenharmony_ci			reg,
9128c2ecf20Sopenharmony_ci			0x00,
9138c2ecf20Sopenharmony_ci			gspca_dev->usb_buf,
9148c2ecf20Sopenharmony_ci			length,
9158c2ecf20Sopenharmony_ci			500);
9168c2ecf20Sopenharmony_ci	if (unlikely(result < 0 || result != length)) {
9178c2ecf20Sopenharmony_ci		pr_err("Read register %02x failed %d\n", reg, result);
9188c2ecf20Sopenharmony_ci		gspca_dev->usb_err = result;
9198c2ecf20Sopenharmony_ci		/*
9208c2ecf20Sopenharmony_ci		 * Make sure the buffer is zeroed to avoid uninitialized
9218c2ecf20Sopenharmony_ci		 * values.
9228c2ecf20Sopenharmony_ci		 */
9238c2ecf20Sopenharmony_ci		memset(gspca_dev->usb_buf, 0, USB_BUF_SZ);
9248c2ecf20Sopenharmony_ci	}
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic void reg_w(struct gspca_dev *gspca_dev, u16 reg,
9288c2ecf20Sopenharmony_ci		 const u8 *buffer, int length)
9298c2ecf20Sopenharmony_ci{
9308c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
9318c2ecf20Sopenharmony_ci	int result;
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
9348c2ecf20Sopenharmony_ci		return;
9358c2ecf20Sopenharmony_ci	memcpy(gspca_dev->usb_buf, buffer, length);
9368c2ecf20Sopenharmony_ci	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
9378c2ecf20Sopenharmony_ci			0x08,
9388c2ecf20Sopenharmony_ci			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
9398c2ecf20Sopenharmony_ci			reg,
9408c2ecf20Sopenharmony_ci			0x00,
9418c2ecf20Sopenharmony_ci			gspca_dev->usb_buf,
9428c2ecf20Sopenharmony_ci			length,
9438c2ecf20Sopenharmony_ci			500);
9448c2ecf20Sopenharmony_ci	if (unlikely(result < 0 || result != length)) {
9458c2ecf20Sopenharmony_ci		pr_err("Write register %02x failed %d\n", reg, result);
9468c2ecf20Sopenharmony_ci		gspca_dev->usb_err = result;
9478c2ecf20Sopenharmony_ci	}
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cistatic void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
9518c2ecf20Sopenharmony_ci{
9528c2ecf20Sopenharmony_ci	reg_w(gspca_dev, reg, &value, 1);
9538c2ecf20Sopenharmony_ci}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_cistatic void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
9568c2ecf20Sopenharmony_ci{
9578c2ecf20Sopenharmony_ci	int i;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x10c0, buffer, 8);
9608c2ecf20Sopenharmony_ci	for (i = 0; i < 5; i++) {
9618c2ecf20Sopenharmony_ci		reg_r(gspca_dev, 0x10c0, 1);
9628c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
9638c2ecf20Sopenharmony_ci			return;
9648c2ecf20Sopenharmony_ci		if (gspca_dev->usb_buf[0] & 0x04) {
9658c2ecf20Sopenharmony_ci			if (gspca_dev->usb_buf[0] & 0x08) {
9668c2ecf20Sopenharmony_ci				pr_err("i2c_w error\n");
9678c2ecf20Sopenharmony_ci				gspca_dev->usb_err = -EIO;
9688c2ecf20Sopenharmony_ci			}
9698c2ecf20Sopenharmony_ci			return;
9708c2ecf20Sopenharmony_ci		}
9718c2ecf20Sopenharmony_ci		msleep(10);
9728c2ecf20Sopenharmony_ci	}
9738c2ecf20Sopenharmony_ci	pr_err("i2c_w reg %02x no response\n", buffer[2]);
9748c2ecf20Sopenharmony_ci/*	gspca_dev->usb_err = -EIO;	fixme: may occur */
9758c2ecf20Sopenharmony_ci}
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_cistatic void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
9788c2ecf20Sopenharmony_ci{
9798c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
9808c2ecf20Sopenharmony_ci	u8 row[8];
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	/*
9838c2ecf20Sopenharmony_ci	 * from the point of view of the bridge, the length
9848c2ecf20Sopenharmony_ci	 * includes the address
9858c2ecf20Sopenharmony_ci	 */
9868c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (2 << 4);
9878c2ecf20Sopenharmony_ci	row[1] = sd->i2c_addr;
9888c2ecf20Sopenharmony_ci	row[2] = reg;
9898c2ecf20Sopenharmony_ci	row[3] = val;
9908c2ecf20Sopenharmony_ci	row[4] = 0x00;
9918c2ecf20Sopenharmony_ci	row[5] = 0x00;
9928c2ecf20Sopenharmony_ci	row[6] = 0x00;
9938c2ecf20Sopenharmony_ci	row[7] = 0x10;
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
9968c2ecf20Sopenharmony_ci}
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_cistatic void i2c_w1_buf(struct gspca_dev *gspca_dev,
9998c2ecf20Sopenharmony_ci			const struct i2c_reg_u8 *buf, int sz)
10008c2ecf20Sopenharmony_ci{
10018c2ecf20Sopenharmony_ci	while (--sz >= 0) {
10028c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, buf->reg, buf->val);
10038c2ecf20Sopenharmony_ci		buf++;
10048c2ecf20Sopenharmony_ci	}
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_cistatic void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
10108c2ecf20Sopenharmony_ci	u8 row[8];
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	/*
10138c2ecf20Sopenharmony_ci	 * from the point of view of the bridge, the length
10148c2ecf20Sopenharmony_ci	 * includes the address
10158c2ecf20Sopenharmony_ci	 */
10168c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (3 << 4);
10178c2ecf20Sopenharmony_ci	row[1] = sd->i2c_addr;
10188c2ecf20Sopenharmony_ci	row[2] = reg;
10198c2ecf20Sopenharmony_ci	row[3] = val >> 8;
10208c2ecf20Sopenharmony_ci	row[4] = val;
10218c2ecf20Sopenharmony_ci	row[5] = 0x00;
10228c2ecf20Sopenharmony_ci	row[6] = 0x00;
10238c2ecf20Sopenharmony_ci	row[7] = 0x10;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
10268c2ecf20Sopenharmony_ci}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_cistatic void i2c_w2_buf(struct gspca_dev *gspca_dev,
10298c2ecf20Sopenharmony_ci			const struct i2c_reg_u16 *buf, int sz)
10308c2ecf20Sopenharmony_ci{
10318c2ecf20Sopenharmony_ci	while (--sz >= 0) {
10328c2ecf20Sopenharmony_ci		i2c_w2(gspca_dev, buf->reg, buf->val);
10338c2ecf20Sopenharmony_ci		buf++;
10348c2ecf20Sopenharmony_ci	}
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
10408c2ecf20Sopenharmony_ci	u8 row[8];
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (1 << 4);
10438c2ecf20Sopenharmony_ci	row[1] = sd->i2c_addr;
10448c2ecf20Sopenharmony_ci	row[2] = reg;
10458c2ecf20Sopenharmony_ci	row[3] = 0;
10468c2ecf20Sopenharmony_ci	row[4] = 0;
10478c2ecf20Sopenharmony_ci	row[5] = 0;
10488c2ecf20Sopenharmony_ci	row[6] = 0;
10498c2ecf20Sopenharmony_ci	row[7] = 0x10;
10508c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
10518c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (1 << 4) | 0x02;
10528c2ecf20Sopenharmony_ci	row[2] = 0;
10538c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
10548c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x10c2, 5);
10558c2ecf20Sopenharmony_ci	*val = gspca_dev->usb_buf[4];
10568c2ecf20Sopenharmony_ci}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_cistatic void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
10598c2ecf20Sopenharmony_ci{
10608c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
10618c2ecf20Sopenharmony_ci	u8 row[8];
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (1 << 4);
10648c2ecf20Sopenharmony_ci	row[1] = sd->i2c_addr;
10658c2ecf20Sopenharmony_ci	row[2] = reg;
10668c2ecf20Sopenharmony_ci	row[3] = 0;
10678c2ecf20Sopenharmony_ci	row[4] = 0;
10688c2ecf20Sopenharmony_ci	row[5] = 0;
10698c2ecf20Sopenharmony_ci	row[6] = 0;
10708c2ecf20Sopenharmony_ci	row[7] = 0x10;
10718c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
10728c2ecf20Sopenharmony_ci	row[0] = sd->i2c_intf | (2 << 4) | 0x02;
10738c2ecf20Sopenharmony_ci	row[2] = 0;
10748c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, row);
10758c2ecf20Sopenharmony_ci	reg_r(gspca_dev, 0x10c2, 5);
10768c2ecf20Sopenharmony_ci	*val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
10778c2ecf20Sopenharmony_ci}
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic void ov9650_init_sensor(struct gspca_dev *gspca_dev)
10808c2ecf20Sopenharmony_ci{
10818c2ecf20Sopenharmony_ci	u16 id;
10828c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	i2c_r2(gspca_dev, 0x1c, &id);
10858c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
10868c2ecf20Sopenharmony_ci		return;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	if (id != 0x7fa2) {
10898c2ecf20Sopenharmony_ci		pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
10908c2ecf20Sopenharmony_ci		gspca_dev->usb_err = -ENODEV;
10918c2ecf20Sopenharmony_ci		return;
10928c2ecf20Sopenharmony_ci	}
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x12, 0x80);		/* sensor reset */
10958c2ecf20Sopenharmony_ci	msleep(200);
10968c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
10978c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
10988c2ecf20Sopenharmony_ci		pr_err("OV9650 sensor initialization failed\n");
10998c2ecf20Sopenharmony_ci	sd->hstart = 1;
11008c2ecf20Sopenharmony_ci	sd->vstart = 7;
11018c2ecf20Sopenharmony_ci}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_cistatic void ov9655_init_sensor(struct gspca_dev *gspca_dev)
11048c2ecf20Sopenharmony_ci{
11058c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x12, 0x80);		/* sensor reset */
11088c2ecf20Sopenharmony_ci	msleep(200);
11098c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
11108c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11118c2ecf20Sopenharmony_ci		pr_err("OV9655 sensor initialization failed\n");
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	sd->hstart = 1;
11148c2ecf20Sopenharmony_ci	sd->vstart = 2;
11158c2ecf20Sopenharmony_ci}
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_cistatic void soi968_init_sensor(struct gspca_dev *gspca_dev)
11188c2ecf20Sopenharmony_ci{
11198c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x12, 0x80);		/* sensor reset */
11228c2ecf20Sopenharmony_ci	msleep(200);
11238c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
11248c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11258c2ecf20Sopenharmony_ci		pr_err("SOI968 sensor initialization failed\n");
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	sd->hstart = 60;
11288c2ecf20Sopenharmony_ci	sd->vstart = 11;
11298c2ecf20Sopenharmony_ci}
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_cistatic void ov7660_init_sensor(struct gspca_dev *gspca_dev)
11328c2ecf20Sopenharmony_ci{
11338c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
11348c2ecf20Sopenharmony_ci
11358c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x12, 0x80);		/* sensor reset */
11368c2ecf20Sopenharmony_ci	msleep(200);
11378c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
11388c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11398c2ecf20Sopenharmony_ci		pr_err("OV7660 sensor initialization failed\n");
11408c2ecf20Sopenharmony_ci	sd->hstart = 3;
11418c2ecf20Sopenharmony_ci	sd->vstart = 3;
11428c2ecf20Sopenharmony_ci}
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_cistatic void ov7670_init_sensor(struct gspca_dev *gspca_dev)
11458c2ecf20Sopenharmony_ci{
11468c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	i2c_w1(gspca_dev, 0x12, 0x80);		/* sensor reset */
11498c2ecf20Sopenharmony_ci	msleep(200);
11508c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
11518c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
11528c2ecf20Sopenharmony_ci		pr_err("OV7670 sensor initialization failed\n");
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	sd->hstart = 0;
11558c2ecf20Sopenharmony_ci	sd->vstart = 1;
11568c2ecf20Sopenharmony_ci}
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_cistatic void mt9v_init_sensor(struct gspca_dev *gspca_dev)
11598c2ecf20Sopenharmony_ci{
11608c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
11618c2ecf20Sopenharmony_ci	u16 value;
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x5d;
11648c2ecf20Sopenharmony_ci	i2c_r2(gspca_dev, 0xff, &value);
11658c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err >= 0
11668c2ecf20Sopenharmony_ci	 && value == 0x8243) {
11678c2ecf20Sopenharmony_ci		i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
11688c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0) {
11698c2ecf20Sopenharmony_ci			pr_err("MT9V011 sensor initialization failed\n");
11708c2ecf20Sopenharmony_ci			return;
11718c2ecf20Sopenharmony_ci		}
11728c2ecf20Sopenharmony_ci		sd->hstart = 2;
11738c2ecf20Sopenharmony_ci		sd->vstart = 2;
11748c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_MT9V011;
11758c2ecf20Sopenharmony_ci		pr_info("MT9V011 sensor detected\n");
11768c2ecf20Sopenharmony_ci		return;
11778c2ecf20Sopenharmony_ci	}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
11808c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x5c;
11818c2ecf20Sopenharmony_ci	i2c_w2(gspca_dev, 0x01, 0x0004);
11828c2ecf20Sopenharmony_ci	i2c_r2(gspca_dev, 0xff, &value);
11838c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err >= 0
11848c2ecf20Sopenharmony_ci	 && value == 0x823a) {
11858c2ecf20Sopenharmony_ci		i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
11868c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0) {
11878c2ecf20Sopenharmony_ci			pr_err("MT9V111 sensor initialization failed\n");
11888c2ecf20Sopenharmony_ci			return;
11898c2ecf20Sopenharmony_ci		}
11908c2ecf20Sopenharmony_ci		sd->hstart = 2;
11918c2ecf20Sopenharmony_ci		sd->vstart = 2;
11928c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_MT9V111;
11938c2ecf20Sopenharmony_ci		pr_info("MT9V111 sensor detected\n");
11948c2ecf20Sopenharmony_ci		return;
11958c2ecf20Sopenharmony_ci	}
11968c2ecf20Sopenharmony_ci
11978c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
11988c2ecf20Sopenharmony_ci	sd->i2c_addr = 0x5d;
11998c2ecf20Sopenharmony_ci	i2c_w2(gspca_dev, 0xf0, 0x0000);
12008c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0) {
12018c2ecf20Sopenharmony_ci		gspca_dev->usb_err = 0;
12028c2ecf20Sopenharmony_ci		sd->i2c_addr = 0x48;
12038c2ecf20Sopenharmony_ci		i2c_w2(gspca_dev, 0xf0, 0x0000);
12048c2ecf20Sopenharmony_ci	}
12058c2ecf20Sopenharmony_ci	i2c_r2(gspca_dev, 0x00, &value);
12068c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err >= 0
12078c2ecf20Sopenharmony_ci	 && value == 0x1229) {
12088c2ecf20Sopenharmony_ci		i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
12098c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0) {
12108c2ecf20Sopenharmony_ci			pr_err("MT9V112 sensor initialization failed\n");
12118c2ecf20Sopenharmony_ci			return;
12128c2ecf20Sopenharmony_ci		}
12138c2ecf20Sopenharmony_ci		sd->hstart = 6;
12148c2ecf20Sopenharmony_ci		sd->vstart = 2;
12158c2ecf20Sopenharmony_ci		sd->sensor = SENSOR_MT9V112;
12168c2ecf20Sopenharmony_ci		pr_info("MT9V112 sensor detected\n");
12178c2ecf20Sopenharmony_ci		return;
12188c2ecf20Sopenharmony_ci	}
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	gspca_dev->usb_err = -ENODEV;
12218c2ecf20Sopenharmony_ci}
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_cistatic void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
12248c2ecf20Sopenharmony_ci{
12258c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
12288c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12298c2ecf20Sopenharmony_ci		pr_err("MT9M112 sensor initialization failed\n");
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	sd->hstart = 0;
12328c2ecf20Sopenharmony_ci	sd->vstart = 2;
12338c2ecf20Sopenharmony_ci}
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_cistatic void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
12368c2ecf20Sopenharmony_ci{
12378c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
12408c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12418c2ecf20Sopenharmony_ci		pr_err("MT9M111 sensor initialization failed\n");
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	sd->hstart = 0;
12448c2ecf20Sopenharmony_ci	sd->vstart = 2;
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_cistatic void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12508c2ecf20Sopenharmony_ci	u16 id;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	i2c_r2(gspca_dev, 0x00, &id);
12538c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12548c2ecf20Sopenharmony_ci		return;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
12578c2ecf20Sopenharmony_ci	switch (id) {
12588c2ecf20Sopenharmony_ci	case 0x8411:
12598c2ecf20Sopenharmony_ci	case 0x8421:
12608c2ecf20Sopenharmony_ci		pr_info("MT9M001 color sensor detected\n");
12618c2ecf20Sopenharmony_ci		break;
12628c2ecf20Sopenharmony_ci	case 0x8431:
12638c2ecf20Sopenharmony_ci		pr_info("MT9M001 mono sensor detected\n");
12648c2ecf20Sopenharmony_ci		break;
12658c2ecf20Sopenharmony_ci	default:
12668c2ecf20Sopenharmony_ci		pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
12678c2ecf20Sopenharmony_ci		gspca_dev->usb_err = -ENODEV;
12688c2ecf20Sopenharmony_ci		return;
12698c2ecf20Sopenharmony_ci	}
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_ci	i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
12728c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12738c2ecf20Sopenharmony_ci		pr_err("MT9M001 sensor initialization failed\n");
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_ci	sd->hstart = 1;
12768c2ecf20Sopenharmony_ci	sd->vstart = 1;
12778c2ecf20Sopenharmony_ci}
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_cistatic void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
12808c2ecf20Sopenharmony_ci{
12818c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
12848c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0)
12858c2ecf20Sopenharmony_ci		pr_err("HV7131R Sensor initialization failed\n");
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	sd->hstart = 0;
12888c2ecf20Sopenharmony_ci	sd->vstart = 1;
12898c2ecf20Sopenharmony_ci}
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_cistatic void set_cmatrix(struct gspca_dev *gspca_dev,
12928c2ecf20Sopenharmony_ci		s32 brightness, s32 contrast, s32 satur, s32 hue)
12938c2ecf20Sopenharmony_ci{
12948c2ecf20Sopenharmony_ci	s32 hue_coord, hue_index = 180 + hue;
12958c2ecf20Sopenharmony_ci	u8 cmatrix[21];
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	memset(cmatrix, 0, sizeof(cmatrix));
12988c2ecf20Sopenharmony_ci	cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
12998c2ecf20Sopenharmony_ci	cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
13008c2ecf20Sopenharmony_ci	cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
13018c2ecf20Sopenharmony_ci	cmatrix[18] = brightness - 0x80;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
13048c2ecf20Sopenharmony_ci	cmatrix[6] = hue_coord;
13058c2ecf20Sopenharmony_ci	cmatrix[7] = (hue_coord >> 8) & 0x0f;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
13088c2ecf20Sopenharmony_ci	cmatrix[8] = hue_coord;
13098c2ecf20Sopenharmony_ci	cmatrix[9] = (hue_coord >> 8) & 0x0f;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
13128c2ecf20Sopenharmony_ci	cmatrix[10] = hue_coord;
13138c2ecf20Sopenharmony_ci	cmatrix[11] = (hue_coord >> 8) & 0x0f;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
13168c2ecf20Sopenharmony_ci	cmatrix[12] = hue_coord;
13178c2ecf20Sopenharmony_ci	cmatrix[13] = (hue_coord >> 8) & 0x0f;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
13208c2ecf20Sopenharmony_ci	cmatrix[14] = hue_coord;
13218c2ecf20Sopenharmony_ci	cmatrix[15] = (hue_coord >> 8) & 0x0f;
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
13248c2ecf20Sopenharmony_ci	cmatrix[16] = hue_coord;
13258c2ecf20Sopenharmony_ci	cmatrix[17] = (hue_coord >> 8) & 0x0f;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x10e1, cmatrix, 21);
13288c2ecf20Sopenharmony_ci}
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_cistatic void set_gamma(struct gspca_dev *gspca_dev, s32 val)
13318c2ecf20Sopenharmony_ci{
13328c2ecf20Sopenharmony_ci	u8 gamma[17];
13338c2ecf20Sopenharmony_ci	u8 gval = val * 0xb8 / 0x100;
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	gamma[0] = 0x0a;
13368c2ecf20Sopenharmony_ci	gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
13378c2ecf20Sopenharmony_ci	gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
13388c2ecf20Sopenharmony_ci	gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
13398c2ecf20Sopenharmony_ci	gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
13408c2ecf20Sopenharmony_ci	gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
13418c2ecf20Sopenharmony_ci	gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
13428c2ecf20Sopenharmony_ci	gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
13438c2ecf20Sopenharmony_ci	gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
13448c2ecf20Sopenharmony_ci	gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
13458c2ecf20Sopenharmony_ci	gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
13468c2ecf20Sopenharmony_ci	gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
13478c2ecf20Sopenharmony_ci	gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
13488c2ecf20Sopenharmony_ci	gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
13498c2ecf20Sopenharmony_ci	gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
13508c2ecf20Sopenharmony_ci	gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
13518c2ecf20Sopenharmony_ci	gamma[16] = 0xf5;
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1190, gamma, 17);
13548c2ecf20Sopenharmony_ci}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_cistatic void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
13578c2ecf20Sopenharmony_ci{
13588c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x118c, red);
13598c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x118f, blue);
13608c2ecf20Sopenharmony_ci}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_cistatic void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
13638c2ecf20Sopenharmony_ci{
13648c2ecf20Sopenharmony_ci	u8 value, tslb;
13658c2ecf20Sopenharmony_ci	u16 value2;
13668c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci	if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
13698c2ecf20Sopenharmony_ci		hflip = !hflip;
13708c2ecf20Sopenharmony_ci		vflip = !vflip;
13718c2ecf20Sopenharmony_ci	}
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	switch (sd->sensor) {
13748c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
13758c2ecf20Sopenharmony_ci		value = 0x01;
13768c2ecf20Sopenharmony_ci		if (hflip)
13778c2ecf20Sopenharmony_ci			value |= 0x20;
13788c2ecf20Sopenharmony_ci		if (vflip) {
13798c2ecf20Sopenharmony_ci			value |= 0x10;
13808c2ecf20Sopenharmony_ci			sd->vstart = 2;
13818c2ecf20Sopenharmony_ci		} else {
13828c2ecf20Sopenharmony_ci			sd->vstart = 3;
13838c2ecf20Sopenharmony_ci		}
13848c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x1182, sd->vstart);
13858c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x1e, value);
13868c2ecf20Sopenharmony_ci		break;
13878c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
13888c2ecf20Sopenharmony_ci		i2c_r1(gspca_dev, 0x1e, &value);
13898c2ecf20Sopenharmony_ci		value &= ~0x30;
13908c2ecf20Sopenharmony_ci		tslb = 0x01;
13918c2ecf20Sopenharmony_ci		if (hflip)
13928c2ecf20Sopenharmony_ci			value |= 0x20;
13938c2ecf20Sopenharmony_ci		if (vflip) {
13948c2ecf20Sopenharmony_ci			value |= 0x10;
13958c2ecf20Sopenharmony_ci			tslb = 0x49;
13968c2ecf20Sopenharmony_ci		}
13978c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x1e, value);
13988c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x3a, tslb);
13998c2ecf20Sopenharmony_ci		break;
14008c2ecf20Sopenharmony_ci	case SENSOR_MT9V111:
14018c2ecf20Sopenharmony_ci	case SENSOR_MT9V011:
14028c2ecf20Sopenharmony_ci		i2c_r2(gspca_dev, 0x20, &value2);
14038c2ecf20Sopenharmony_ci		value2 &= ~0xc0a0;
14048c2ecf20Sopenharmony_ci		if (hflip)
14058c2ecf20Sopenharmony_ci			value2 |= 0x8080;
14068c2ecf20Sopenharmony_ci		if (vflip)
14078c2ecf20Sopenharmony_ci			value2 |= 0x4020;
14088c2ecf20Sopenharmony_ci		i2c_w2(gspca_dev, 0x20, value2);
14098c2ecf20Sopenharmony_ci		break;
14108c2ecf20Sopenharmony_ci	case SENSOR_MT9M112:
14118c2ecf20Sopenharmony_ci	case SENSOR_MT9M111:
14128c2ecf20Sopenharmony_ci	case SENSOR_MT9V112:
14138c2ecf20Sopenharmony_ci		i2c_r2(gspca_dev, 0x20, &value2);
14148c2ecf20Sopenharmony_ci		value2 &= ~0x0003;
14158c2ecf20Sopenharmony_ci		if (hflip)
14168c2ecf20Sopenharmony_ci			value2 |= 0x0002;
14178c2ecf20Sopenharmony_ci		if (vflip)
14188c2ecf20Sopenharmony_ci			value2 |= 0x0001;
14198c2ecf20Sopenharmony_ci		i2c_w2(gspca_dev, 0x20, value2);
14208c2ecf20Sopenharmony_ci		break;
14218c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
14228c2ecf20Sopenharmony_ci		i2c_r1(gspca_dev, 0x01, &value);
14238c2ecf20Sopenharmony_ci		value &= ~0x03;
14248c2ecf20Sopenharmony_ci		if (vflip)
14258c2ecf20Sopenharmony_ci			value |= 0x01;
14268c2ecf20Sopenharmony_ci		if (hflip)
14278c2ecf20Sopenharmony_ci			value |= 0x02;
14288c2ecf20Sopenharmony_ci		i2c_w1(gspca_dev, 0x01, value);
14298c2ecf20Sopenharmony_ci		break;
14308c2ecf20Sopenharmony_ci	}
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_cistatic void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
14348c2ecf20Sopenharmony_ci{
14358c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
14368c2ecf20Sopenharmony_ci	u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
14378c2ecf20Sopenharmony_ci				0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
14388c2ecf20Sopenharmony_ci	int expo2;
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	if (gspca_dev->streaming)
14418c2ecf20Sopenharmony_ci		exp[7] = 0x1e;
14428c2ecf20Sopenharmony_ci
14438c2ecf20Sopenharmony_ci	switch (sd->sensor) {
14448c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
14458c2ecf20Sopenharmony_ci	case SENSOR_OV7670:
14468c2ecf20Sopenharmony_ci	case SENSOR_OV9655:
14478c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
14488c2ecf20Sopenharmony_ci		if (expo > 547)
14498c2ecf20Sopenharmony_ci			expo2 = 547;
14508c2ecf20Sopenharmony_ci		else
14518c2ecf20Sopenharmony_ci			expo2 = expo;
14528c2ecf20Sopenharmony_ci		exp[0] |= (2 << 4);
14538c2ecf20Sopenharmony_ci		exp[2] = 0x10;			/* AECH */
14548c2ecf20Sopenharmony_ci		exp[3] = expo2 >> 2;
14558c2ecf20Sopenharmony_ci		exp[7] = 0x10;
14568c2ecf20Sopenharmony_ci		i2c_w(gspca_dev, exp);
14578c2ecf20Sopenharmony_ci		exp[2] = 0x04;			/* COM1 */
14588c2ecf20Sopenharmony_ci		exp[3] = expo2 & 0x0003;
14598c2ecf20Sopenharmony_ci		exp[7] = 0x10;
14608c2ecf20Sopenharmony_ci		i2c_w(gspca_dev, exp);
14618c2ecf20Sopenharmony_ci		expo -= expo2;
14628c2ecf20Sopenharmony_ci		exp[7] = 0x1e;
14638c2ecf20Sopenharmony_ci		exp[0] |= (3 << 4);
14648c2ecf20Sopenharmony_ci		exp[2] = 0x2d;			/* ADVFL & ADVFH */
14658c2ecf20Sopenharmony_ci		exp[3] = expo;
14668c2ecf20Sopenharmony_ci		exp[4] = expo >> 8;
14678c2ecf20Sopenharmony_ci		break;
14688c2ecf20Sopenharmony_ci	case SENSOR_MT9M001:
14698c2ecf20Sopenharmony_ci	case SENSOR_MT9V112:
14708c2ecf20Sopenharmony_ci	case SENSOR_MT9V011:
14718c2ecf20Sopenharmony_ci		exp[0] |= (3 << 4);
14728c2ecf20Sopenharmony_ci		exp[2] = 0x09;
14738c2ecf20Sopenharmony_ci		exp[3] = expo >> 8;
14748c2ecf20Sopenharmony_ci		exp[4] = expo;
14758c2ecf20Sopenharmony_ci		break;
14768c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
14778c2ecf20Sopenharmony_ci		exp[0] |= (4 << 4);
14788c2ecf20Sopenharmony_ci		exp[2] = 0x25;
14798c2ecf20Sopenharmony_ci		exp[3] = expo >> 5;
14808c2ecf20Sopenharmony_ci		exp[4] = expo << 3;
14818c2ecf20Sopenharmony_ci		exp[5] = 0;
14828c2ecf20Sopenharmony_ci		break;
14838c2ecf20Sopenharmony_ci	default:
14848c2ecf20Sopenharmony_ci		return;
14858c2ecf20Sopenharmony_ci	}
14868c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, exp);
14878c2ecf20Sopenharmony_ci}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_cistatic void set_gain(struct gspca_dev *gspca_dev, s32 g)
14908c2ecf20Sopenharmony_ci{
14918c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
14928c2ecf20Sopenharmony_ci	u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
14938c2ecf20Sopenharmony_ci				0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	if (gspca_dev->streaming)
14968c2ecf20Sopenharmony_ci		gain[7] = 0x15;		/* or 1d ? */
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	switch (sd->sensor) {
14998c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
15008c2ecf20Sopenharmony_ci	case SENSOR_OV7670:
15018c2ecf20Sopenharmony_ci	case SENSOR_SOI968:
15028c2ecf20Sopenharmony_ci	case SENSOR_OV9655:
15038c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
15048c2ecf20Sopenharmony_ci		gain[0] |= (2 << 4);
15058c2ecf20Sopenharmony_ci		gain[3] = ov_gain[g];
15068c2ecf20Sopenharmony_ci		break;
15078c2ecf20Sopenharmony_ci	case SENSOR_MT9V011:
15088c2ecf20Sopenharmony_ci		gain[0] |= (3 << 4);
15098c2ecf20Sopenharmony_ci		gain[2] = 0x35;
15108c2ecf20Sopenharmony_ci		gain[3] = micron1_gain[g] >> 8;
15118c2ecf20Sopenharmony_ci		gain[4] = micron1_gain[g];
15128c2ecf20Sopenharmony_ci		break;
15138c2ecf20Sopenharmony_ci	case SENSOR_MT9V112:
15148c2ecf20Sopenharmony_ci		gain[0] |= (3 << 4);
15158c2ecf20Sopenharmony_ci		gain[2] = 0x2f;
15168c2ecf20Sopenharmony_ci		gain[3] = micron1_gain[g] >> 8;
15178c2ecf20Sopenharmony_ci		gain[4] = micron1_gain[g];
15188c2ecf20Sopenharmony_ci		break;
15198c2ecf20Sopenharmony_ci	case SENSOR_MT9M001:
15208c2ecf20Sopenharmony_ci		gain[0] |= (3 << 4);
15218c2ecf20Sopenharmony_ci		gain[2] = 0x2f;
15228c2ecf20Sopenharmony_ci		gain[3] = micron2_gain[g] >> 8;
15238c2ecf20Sopenharmony_ci		gain[4] = micron2_gain[g];
15248c2ecf20Sopenharmony_ci		break;
15258c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
15268c2ecf20Sopenharmony_ci		gain[0] |= (2 << 4);
15278c2ecf20Sopenharmony_ci		gain[2] = 0x30;
15288c2ecf20Sopenharmony_ci		gain[3] = hv7131r_gain[g];
15298c2ecf20Sopenharmony_ci		break;
15308c2ecf20Sopenharmony_ci	default:
15318c2ecf20Sopenharmony_ci		return;
15328c2ecf20Sopenharmony_ci	}
15338c2ecf20Sopenharmony_ci	i2c_w(gspca_dev, gain);
15348c2ecf20Sopenharmony_ci}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_cistatic void set_quality(struct gspca_dev *gspca_dev, s32 val)
15378c2ecf20Sopenharmony_ci{
15388c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	jpeg_set_qual(sd->jpeg_hdr, val);
15418c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1061, 0x01);	/* stop transfer */
15428c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
15438c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
15448c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
15458c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1061, 0x03);	/* restart transfer */
15468c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x10e0, sd->fmt);
15478c2ecf20Sopenharmony_ci	sd->fmt ^= 0x0c;			/* invert QTAB use + write */
15488c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x10e0, sd->fmt);
15498c2ecf20Sopenharmony_ci}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG
15528c2ecf20Sopenharmony_cistatic int sd_dbg_g_register(struct gspca_dev *gspca_dev,
15538c2ecf20Sopenharmony_ci			struct v4l2_dbg_register *reg)
15548c2ecf20Sopenharmony_ci{
15558c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci	reg->size = 1;
15588c2ecf20Sopenharmony_ci	switch (reg->match.addr) {
15598c2ecf20Sopenharmony_ci	case 0:
15608c2ecf20Sopenharmony_ci		if (reg->reg < 0x1000 || reg->reg > 0x11ff)
15618c2ecf20Sopenharmony_ci			return -EINVAL;
15628c2ecf20Sopenharmony_ci		reg_r(gspca_dev, reg->reg, 1);
15638c2ecf20Sopenharmony_ci		reg->val = gspca_dev->usb_buf[0];
15648c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
15658c2ecf20Sopenharmony_ci	case 1:
15668c2ecf20Sopenharmony_ci		if (sd->sensor >= SENSOR_MT9V011 &&
15678c2ecf20Sopenharmony_ci		    sd->sensor <= SENSOR_MT9M112) {
15688c2ecf20Sopenharmony_ci			i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
15698c2ecf20Sopenharmony_ci			reg->size = 2;
15708c2ecf20Sopenharmony_ci		} else {
15718c2ecf20Sopenharmony_ci			i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
15728c2ecf20Sopenharmony_ci		}
15738c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
15748c2ecf20Sopenharmony_ci	}
15758c2ecf20Sopenharmony_ci	return -EINVAL;
15768c2ecf20Sopenharmony_ci}
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_cistatic int sd_dbg_s_register(struct gspca_dev *gspca_dev,
15798c2ecf20Sopenharmony_ci			const struct v4l2_dbg_register *reg)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	switch (reg->match.addr) {
15848c2ecf20Sopenharmony_ci	case 0:
15858c2ecf20Sopenharmony_ci		if (reg->reg < 0x1000 || reg->reg > 0x11ff)
15868c2ecf20Sopenharmony_ci			return -EINVAL;
15878c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, reg->reg, reg->val);
15888c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
15898c2ecf20Sopenharmony_ci	case 1:
15908c2ecf20Sopenharmony_ci		if (sd->sensor >= SENSOR_MT9V011 &&
15918c2ecf20Sopenharmony_ci		    sd->sensor <= SENSOR_MT9M112) {
15928c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, reg->reg, reg->val);
15938c2ecf20Sopenharmony_ci		} else {
15948c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, reg->reg, reg->val);
15958c2ecf20Sopenharmony_ci		}
15968c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
15978c2ecf20Sopenharmony_ci	}
15988c2ecf20Sopenharmony_ci	return -EINVAL;
15998c2ecf20Sopenharmony_ci}
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_cistatic int sd_chip_info(struct gspca_dev *gspca_dev,
16028c2ecf20Sopenharmony_ci			struct v4l2_dbg_chip_info *chip)
16038c2ecf20Sopenharmony_ci{
16048c2ecf20Sopenharmony_ci	if (chip->match.addr > 1)
16058c2ecf20Sopenharmony_ci		return -EINVAL;
16068c2ecf20Sopenharmony_ci	if (chip->match.addr == 1)
16078c2ecf20Sopenharmony_ci		strscpy(chip->name, "sensor", sizeof(chip->name));
16088c2ecf20Sopenharmony_ci	return 0;
16098c2ecf20Sopenharmony_ci}
16108c2ecf20Sopenharmony_ci#endif
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
16138c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
16148c2ecf20Sopenharmony_ci{
16158c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
16168c2ecf20Sopenharmony_ci	struct cam *cam;
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	cam = &gspca_dev->cam;
16198c2ecf20Sopenharmony_ci	cam->needs_full_bandwidth = 1;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	sd->sensor = id->driver_info >> 8;
16228c2ecf20Sopenharmony_ci	sd->i2c_addr = id->driver_info;
16238c2ecf20Sopenharmony_ci	sd->flags = id->driver_info >> 16;
16248c2ecf20Sopenharmony_ci	sd->i2c_intf = 0x80;			/* i2c 100 Kb/s */
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	switch (sd->sensor) {
16278c2ecf20Sopenharmony_ci	case SENSOR_MT9M112:
16288c2ecf20Sopenharmony_ci	case SENSOR_MT9M111:
16298c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
16308c2ecf20Sopenharmony_ci	case SENSOR_SOI968:
16318c2ecf20Sopenharmony_ci		cam->cam_mode = sxga_mode;
16328c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(sxga_mode);
16338c2ecf20Sopenharmony_ci		break;
16348c2ecf20Sopenharmony_ci	case SENSOR_MT9M001:
16358c2ecf20Sopenharmony_ci		cam->cam_mode = mono_mode;
16368c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(mono_mode);
16378c2ecf20Sopenharmony_ci		break;
16388c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
16398c2ecf20Sopenharmony_ci		sd->i2c_intf = 0x81;			/* i2c 400 Kb/s */
16408c2ecf20Sopenharmony_ci		fallthrough;
16418c2ecf20Sopenharmony_ci	default:
16428c2ecf20Sopenharmony_ci		cam->cam_mode = vga_mode;
16438c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(vga_mode);
16448c2ecf20Sopenharmony_ci		break;
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	sd->old_step = 0;
16488c2ecf20Sopenharmony_ci	sd->older_step = 0;
16498c2ecf20Sopenharmony_ci	sd->exposure_step = 16;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	INIT_WORK(&sd->work, qual_upd);
16528c2ecf20Sopenharmony_ci
16538c2ecf20Sopenharmony_ci	return 0;
16548c2ecf20Sopenharmony_ci}
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
16578c2ecf20Sopenharmony_ci{
16588c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev =
16598c2ecf20Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
16608c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *)gspca_dev;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	if (!gspca_dev->streaming)
16658c2ecf20Sopenharmony_ci		return 0;
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_ci	switch (ctrl->id) {
16688c2ecf20Sopenharmony_ci	/* color control cluster */
16698c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
16708c2ecf20Sopenharmony_ci		set_cmatrix(gspca_dev, sd->brightness->val,
16718c2ecf20Sopenharmony_ci			sd->contrast->val, sd->saturation->val, sd->hue->val);
16728c2ecf20Sopenharmony_ci		break;
16738c2ecf20Sopenharmony_ci	case V4L2_CID_GAMMA:
16748c2ecf20Sopenharmony_ci		set_gamma(gspca_dev, ctrl->val);
16758c2ecf20Sopenharmony_ci		break;
16768c2ecf20Sopenharmony_ci	/* blue/red balance cluster */
16778c2ecf20Sopenharmony_ci	case V4L2_CID_BLUE_BALANCE:
16788c2ecf20Sopenharmony_ci		set_redblue(gspca_dev, sd->blue->val, sd->red->val);
16798c2ecf20Sopenharmony_ci		break;
16808c2ecf20Sopenharmony_ci	/* h/vflip cluster */
16818c2ecf20Sopenharmony_ci	case V4L2_CID_HFLIP:
16828c2ecf20Sopenharmony_ci		set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
16838c2ecf20Sopenharmony_ci		break;
16848c2ecf20Sopenharmony_ci	/* standalone exposure control */
16858c2ecf20Sopenharmony_ci	case V4L2_CID_EXPOSURE:
16868c2ecf20Sopenharmony_ci		set_exposure(gspca_dev, ctrl->val);
16878c2ecf20Sopenharmony_ci		break;
16888c2ecf20Sopenharmony_ci	/* standalone gain control */
16898c2ecf20Sopenharmony_ci	case V4L2_CID_GAIN:
16908c2ecf20Sopenharmony_ci		set_gain(gspca_dev, ctrl->val);
16918c2ecf20Sopenharmony_ci		break;
16928c2ecf20Sopenharmony_ci	/* autogain + exposure or gain control cluster */
16938c2ecf20Sopenharmony_ci	case V4L2_CID_AUTOGAIN:
16948c2ecf20Sopenharmony_ci		if (sd->sensor == SENSOR_SOI968)
16958c2ecf20Sopenharmony_ci			set_gain(gspca_dev, sd->gain->val);
16968c2ecf20Sopenharmony_ci		else
16978c2ecf20Sopenharmony_ci			set_exposure(gspca_dev, sd->exposure->val);
16988c2ecf20Sopenharmony_ci		break;
16998c2ecf20Sopenharmony_ci	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
17008c2ecf20Sopenharmony_ci		set_quality(gspca_dev, ctrl->val);
17018c2ecf20Sopenharmony_ci		break;
17028c2ecf20Sopenharmony_ci	}
17038c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
17048c2ecf20Sopenharmony_ci}
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
17078c2ecf20Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
17088c2ecf20Sopenharmony_ci};
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
17118c2ecf20Sopenharmony_ci{
17128c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
17138c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
17168c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 13);
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17198c2ecf20Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
17208c2ecf20Sopenharmony_ci	sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17218c2ecf20Sopenharmony_ci			V4L2_CID_CONTRAST, 0, 255, 1, 127);
17228c2ecf20Sopenharmony_ci	sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17238c2ecf20Sopenharmony_ci			V4L2_CID_SATURATION, 0, 255, 1, 127);
17248c2ecf20Sopenharmony_ci	sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17258c2ecf20Sopenharmony_ci			V4L2_CID_HUE, -180, 180, 1, 0);
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17288c2ecf20Sopenharmony_ci			V4L2_CID_GAMMA, 0, 255, 1, 0x10);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17318c2ecf20Sopenharmony_ci			V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
17328c2ecf20Sopenharmony_ci	sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17338c2ecf20Sopenharmony_ci			V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
17368c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
17378c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_MT9VPRB) {
17388c2ecf20Sopenharmony_ci		sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17398c2ecf20Sopenharmony_ci			V4L2_CID_HFLIP, 0, 1, 1, 0);
17408c2ecf20Sopenharmony_ci		sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17418c2ecf20Sopenharmony_ci			V4L2_CID_VFLIP, 0, 1, 1, 0);
17428c2ecf20Sopenharmony_ci	}
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
17458c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
17468c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_MT9V111)
17478c2ecf20Sopenharmony_ci		sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17488c2ecf20Sopenharmony_ci			V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci	if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
17518c2ecf20Sopenharmony_ci	    sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
17528c2ecf20Sopenharmony_ci		sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17538c2ecf20Sopenharmony_ci			V4L2_CID_GAIN, 0, 28, 1, 0);
17548c2ecf20Sopenharmony_ci		sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17558c2ecf20Sopenharmony_ci			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
17568c2ecf20Sopenharmony_ci	}
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci	sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
17598c2ecf20Sopenharmony_ci			V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
17608c2ecf20Sopenharmony_ci	if (hdl->error) {
17618c2ecf20Sopenharmony_ci		pr_err("Could not initialize controls\n");
17628c2ecf20Sopenharmony_ci		return hdl->error;
17638c2ecf20Sopenharmony_ci	}
17648c2ecf20Sopenharmony_ci
17658c2ecf20Sopenharmony_ci	v4l2_ctrl_cluster(4, &sd->brightness);
17668c2ecf20Sopenharmony_ci	v4l2_ctrl_cluster(2, &sd->blue);
17678c2ecf20Sopenharmony_ci	if (sd->hflip)
17688c2ecf20Sopenharmony_ci		v4l2_ctrl_cluster(2, &sd->hflip);
17698c2ecf20Sopenharmony_ci	if (sd->autogain) {
17708c2ecf20Sopenharmony_ci		if (sd->sensor == SENSOR_SOI968)
17718c2ecf20Sopenharmony_ci			/* this sensor doesn't have the exposure control and
17728c2ecf20Sopenharmony_ci			   autogain is clustered with gain instead. This works
17738c2ecf20Sopenharmony_ci			   because sd->exposure == NULL. */
17748c2ecf20Sopenharmony_ci			v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
17758c2ecf20Sopenharmony_ci		else
17768c2ecf20Sopenharmony_ci			/* Otherwise autogain is clustered with exposure. */
17778c2ecf20Sopenharmony_ci			v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
17788c2ecf20Sopenharmony_ci	}
17798c2ecf20Sopenharmony_ci	return 0;
17808c2ecf20Sopenharmony_ci}
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
17838c2ecf20Sopenharmony_ci{
17848c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
17858c2ecf20Sopenharmony_ci	int i;
17868c2ecf20Sopenharmony_ci	u8 value;
17878c2ecf20Sopenharmony_ci	u8 i2c_init[9] = {
17888c2ecf20Sopenharmony_ci		0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
17898c2ecf20Sopenharmony_ci	};
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
17928c2ecf20Sopenharmony_ci		value = bridge_init[i][1];
17938c2ecf20Sopenharmony_ci		reg_w(gspca_dev, bridge_init[i][0], &value, 1);
17948c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0) {
17958c2ecf20Sopenharmony_ci			pr_err("Device initialization failed\n");
17968c2ecf20Sopenharmony_ci			return gspca_dev->usb_err;
17978c2ecf20Sopenharmony_ci		}
17988c2ecf20Sopenharmony_ci	}
17998c2ecf20Sopenharmony_ci
18008c2ecf20Sopenharmony_ci	if (sd->flags & LED_REVERSE)
18018c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x1006, 0x00);
18028c2ecf20Sopenharmony_ci	else
18038c2ecf20Sopenharmony_ci		reg_w1(gspca_dev, 0x1006, 0x20);
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x10c0, i2c_init, 9);
18068c2ecf20Sopenharmony_ci	if (gspca_dev->usb_err < 0) {
18078c2ecf20Sopenharmony_ci		pr_err("Device initialization failed\n");
18088c2ecf20Sopenharmony_ci		return gspca_dev->usb_err;
18098c2ecf20Sopenharmony_ci	}
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	switch (sd->sensor) {
18128c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
18138c2ecf20Sopenharmony_ci		ov9650_init_sensor(gspca_dev);
18148c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18158c2ecf20Sopenharmony_ci			break;
18168c2ecf20Sopenharmony_ci		pr_info("OV9650 sensor detected\n");
18178c2ecf20Sopenharmony_ci		break;
18188c2ecf20Sopenharmony_ci	case SENSOR_OV9655:
18198c2ecf20Sopenharmony_ci		ov9655_init_sensor(gspca_dev);
18208c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18218c2ecf20Sopenharmony_ci			break;
18228c2ecf20Sopenharmony_ci		pr_info("OV9655 sensor detected\n");
18238c2ecf20Sopenharmony_ci		break;
18248c2ecf20Sopenharmony_ci	case SENSOR_SOI968:
18258c2ecf20Sopenharmony_ci		soi968_init_sensor(gspca_dev);
18268c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18278c2ecf20Sopenharmony_ci			break;
18288c2ecf20Sopenharmony_ci		pr_info("SOI968 sensor detected\n");
18298c2ecf20Sopenharmony_ci		break;
18308c2ecf20Sopenharmony_ci	case SENSOR_OV7660:
18318c2ecf20Sopenharmony_ci		ov7660_init_sensor(gspca_dev);
18328c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18338c2ecf20Sopenharmony_ci			break;
18348c2ecf20Sopenharmony_ci		pr_info("OV7660 sensor detected\n");
18358c2ecf20Sopenharmony_ci		break;
18368c2ecf20Sopenharmony_ci	case SENSOR_OV7670:
18378c2ecf20Sopenharmony_ci		ov7670_init_sensor(gspca_dev);
18388c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18398c2ecf20Sopenharmony_ci			break;
18408c2ecf20Sopenharmony_ci		pr_info("OV7670 sensor detected\n");
18418c2ecf20Sopenharmony_ci		break;
18428c2ecf20Sopenharmony_ci	case SENSOR_MT9VPRB:
18438c2ecf20Sopenharmony_ci		mt9v_init_sensor(gspca_dev);
18448c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18458c2ecf20Sopenharmony_ci			break;
18468c2ecf20Sopenharmony_ci		pr_info("MT9VPRB sensor detected\n");
18478c2ecf20Sopenharmony_ci		break;
18488c2ecf20Sopenharmony_ci	case SENSOR_MT9M111:
18498c2ecf20Sopenharmony_ci		mt9m111_init_sensor(gspca_dev);
18508c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18518c2ecf20Sopenharmony_ci			break;
18528c2ecf20Sopenharmony_ci		pr_info("MT9M111 sensor detected\n");
18538c2ecf20Sopenharmony_ci		break;
18548c2ecf20Sopenharmony_ci	case SENSOR_MT9M112:
18558c2ecf20Sopenharmony_ci		mt9m112_init_sensor(gspca_dev);
18568c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18578c2ecf20Sopenharmony_ci			break;
18588c2ecf20Sopenharmony_ci		pr_info("MT9M112 sensor detected\n");
18598c2ecf20Sopenharmony_ci		break;
18608c2ecf20Sopenharmony_ci	case SENSOR_MT9M001:
18618c2ecf20Sopenharmony_ci		mt9m001_init_sensor(gspca_dev);
18628c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18638c2ecf20Sopenharmony_ci			break;
18648c2ecf20Sopenharmony_ci		break;
18658c2ecf20Sopenharmony_ci	case SENSOR_HV7131R:
18668c2ecf20Sopenharmony_ci		hv7131r_init_sensor(gspca_dev);
18678c2ecf20Sopenharmony_ci		if (gspca_dev->usb_err < 0)
18688c2ecf20Sopenharmony_ci			break;
18698c2ecf20Sopenharmony_ci		pr_info("HV7131R sensor detected\n");
18708c2ecf20Sopenharmony_ci		break;
18718c2ecf20Sopenharmony_ci	default:
18728c2ecf20Sopenharmony_ci		pr_err("Unsupported sensor\n");
18738c2ecf20Sopenharmony_ci		gspca_dev->usb_err = -ENODEV;
18748c2ecf20Sopenharmony_ci	}
18758c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
18768c2ecf20Sopenharmony_ci}
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_cistatic void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
18798c2ecf20Sopenharmony_ci{
18808c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
18818c2ecf20Sopenharmony_ci	u8 value;
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	switch (sd->sensor) {
18848c2ecf20Sopenharmony_ci	case SENSOR_SOI968:
18858c2ecf20Sopenharmony_ci		if (mode & MODE_SXGA) {
18868c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x17, 0x1d);
18878c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x18, 0xbd);
18888c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x19, 0x01);
18898c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x1a, 0x81);
18908c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x12, 0x00);
18918c2ecf20Sopenharmony_ci			sd->hstart = 140;
18928c2ecf20Sopenharmony_ci			sd->vstart = 19;
18938c2ecf20Sopenharmony_ci		} else {
18948c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x17, 0x13);
18958c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x18, 0x63);
18968c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x19, 0x01);
18978c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x1a, 0x79);
18988c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x12, 0x40);
18998c2ecf20Sopenharmony_ci			sd->hstart = 60;
19008c2ecf20Sopenharmony_ci			sd->vstart = 11;
19018c2ecf20Sopenharmony_ci		}
19028c2ecf20Sopenharmony_ci		break;
19038c2ecf20Sopenharmony_ci	case SENSOR_OV9650:
19048c2ecf20Sopenharmony_ci		if (mode & MODE_SXGA) {
19058c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x17, 0x1b);
19068c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x18, 0xbc);
19078c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x19, 0x01);
19088c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x1a, 0x82);
19098c2ecf20Sopenharmony_ci			i2c_r1(gspca_dev, 0x12, &value);
19108c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x12, value & 0x07);
19118c2ecf20Sopenharmony_ci		} else {
19128c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x17, 0x24);
19138c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x18, 0xc5);
19148c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x19, 0x00);
19158c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x1a, 0x3c);
19168c2ecf20Sopenharmony_ci			i2c_r1(gspca_dev, 0x12, &value);
19178c2ecf20Sopenharmony_ci			i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
19188c2ecf20Sopenharmony_ci		}
19198c2ecf20Sopenharmony_ci		break;
19208c2ecf20Sopenharmony_ci	case SENSOR_MT9M112:
19218c2ecf20Sopenharmony_ci	case SENSOR_MT9M111:
19228c2ecf20Sopenharmony_ci		if (mode & MODE_SXGA) {
19238c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xf0, 0x0002);
19248c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xc8, 0x970b);
19258c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xf0, 0x0000);
19268c2ecf20Sopenharmony_ci		} else {
19278c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xf0, 0x0002);
19288c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xc8, 0x8000);
19298c2ecf20Sopenharmony_ci			i2c_w2(gspca_dev, 0xf0, 0x0000);
19308c2ecf20Sopenharmony_ci		}
19318c2ecf20Sopenharmony_ci		break;
19328c2ecf20Sopenharmony_ci	}
19338c2ecf20Sopenharmony_ci}
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_cistatic int sd_isoc_init(struct gspca_dev *gspca_dev)
19368c2ecf20Sopenharmony_ci{
19378c2ecf20Sopenharmony_ci	struct usb_interface *intf;
19388c2ecf20Sopenharmony_ci	u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
19398c2ecf20Sopenharmony_ci
19408c2ecf20Sopenharmony_ci	/*
19418c2ecf20Sopenharmony_ci	 * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
19428c2ecf20Sopenharmony_ci	 * than our regular bandwidth calculations reserve, so we force the
19438c2ecf20Sopenharmony_ci	 * use of a specific altsetting when using the SN9C20X_I420 fmt.
19448c2ecf20Sopenharmony_ci	 */
19458c2ecf20Sopenharmony_ci	if (!(flags & (MODE_RAW | MODE_JPEG))) {
19468c2ecf20Sopenharmony_ci		intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci		if (intf->num_altsetting != 9) {
19498c2ecf20Sopenharmony_ci			pr_warn("sn9c20x camera with unknown number of alt settings (%d), please report!\n",
19508c2ecf20Sopenharmony_ci				intf->num_altsetting);
19518c2ecf20Sopenharmony_ci			gspca_dev->alt = intf->num_altsetting;
19528c2ecf20Sopenharmony_ci			return 0;
19538c2ecf20Sopenharmony_ci		}
19548c2ecf20Sopenharmony_ci
19558c2ecf20Sopenharmony_ci		switch (gspca_dev->pixfmt.width) {
19568c2ecf20Sopenharmony_ci		case 160: /* 160x120 */
19578c2ecf20Sopenharmony_ci			gspca_dev->alt = 2;
19588c2ecf20Sopenharmony_ci			break;
19598c2ecf20Sopenharmony_ci		case 320: /* 320x240 */
19608c2ecf20Sopenharmony_ci			gspca_dev->alt = 6;
19618c2ecf20Sopenharmony_ci			break;
19628c2ecf20Sopenharmony_ci		default:  /* >= 640x480 */
19638c2ecf20Sopenharmony_ci			gspca_dev->alt = 9;
19648c2ecf20Sopenharmony_ci			break;
19658c2ecf20Sopenharmony_ci		}
19668c2ecf20Sopenharmony_ci	}
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	return 0;
19698c2ecf20Sopenharmony_ci}
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci#define HW_WIN(mode, hstart, vstart) \
19728c2ecf20Sopenharmony_ci((const u8 []){hstart, 0, vstart, 0, \
19738c2ecf20Sopenharmony_ci(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
19748c2ecf20Sopenharmony_ci(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci#define CLR_WIN(width, height) \
19778c2ecf20Sopenharmony_ci((const u8 [])\
19788c2ecf20Sopenharmony_ci{0, width >> 2, 0, height >> 1,\
19798c2ecf20Sopenharmony_ci((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
19828c2ecf20Sopenharmony_ci{
19838c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
19848c2ecf20Sopenharmony_ci	int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
19858c2ecf20Sopenharmony_ci	int width = gspca_dev->pixfmt.width;
19868c2ecf20Sopenharmony_ci	int height = gspca_dev->pixfmt.height;
19878c2ecf20Sopenharmony_ci	u8 fmt, scale = 0;
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	jpeg_define(sd->jpeg_hdr, height, width,
19908c2ecf20Sopenharmony_ci			0x21);
19918c2ecf20Sopenharmony_ci	jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	if (mode & MODE_RAW)
19948c2ecf20Sopenharmony_ci		fmt = 0x2d;
19958c2ecf20Sopenharmony_ci	else if (mode & MODE_JPEG)
19968c2ecf20Sopenharmony_ci		fmt = 0x24;
19978c2ecf20Sopenharmony_ci	else
19988c2ecf20Sopenharmony_ci		fmt = 0x2f;	/* YUV 420 */
19998c2ecf20Sopenharmony_ci	sd->fmt = fmt;
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci	switch (mode & SCALE_MASK) {
20028c2ecf20Sopenharmony_ci	case SCALE_1280x1024:
20038c2ecf20Sopenharmony_ci		scale = 0xc0;
20048c2ecf20Sopenharmony_ci		pr_info("Set 1280x1024\n");
20058c2ecf20Sopenharmony_ci		break;
20068c2ecf20Sopenharmony_ci	case SCALE_640x480:
20078c2ecf20Sopenharmony_ci		scale = 0x80;
20088c2ecf20Sopenharmony_ci		pr_info("Set 640x480\n");
20098c2ecf20Sopenharmony_ci		break;
20108c2ecf20Sopenharmony_ci	case SCALE_320x240:
20118c2ecf20Sopenharmony_ci		scale = 0x90;
20128c2ecf20Sopenharmony_ci		pr_info("Set 320x240\n");
20138c2ecf20Sopenharmony_ci		break;
20148c2ecf20Sopenharmony_ci	case SCALE_160x120:
20158c2ecf20Sopenharmony_ci		scale = 0xa0;
20168c2ecf20Sopenharmony_ci		pr_info("Set 160x120\n");
20178c2ecf20Sopenharmony_ci		break;
20188c2ecf20Sopenharmony_ci	}
20198c2ecf20Sopenharmony_ci
20208c2ecf20Sopenharmony_ci	configure_sensor_output(gspca_dev, mode);
20218c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
20228c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
20238c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
20248c2ecf20Sopenharmony_ci	reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
20258c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1189, scale);
20268c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x10e0, fmt);
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
20298c2ecf20Sopenharmony_ci			v4l2_ctrl_g_ctrl(sd->contrast),
20308c2ecf20Sopenharmony_ci			v4l2_ctrl_g_ctrl(sd->saturation),
20318c2ecf20Sopenharmony_ci			v4l2_ctrl_g_ctrl(sd->hue));
20328c2ecf20Sopenharmony_ci	set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
20338c2ecf20Sopenharmony_ci	set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
20348c2ecf20Sopenharmony_ci			v4l2_ctrl_g_ctrl(sd->red));
20358c2ecf20Sopenharmony_ci	if (sd->gain)
20368c2ecf20Sopenharmony_ci		set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
20378c2ecf20Sopenharmony_ci	if (sd->exposure)
20388c2ecf20Sopenharmony_ci		set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
20398c2ecf20Sopenharmony_ci	if (sd->hflip)
20408c2ecf20Sopenharmony_ci		set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
20418c2ecf20Sopenharmony_ci				v4l2_ctrl_g_ctrl(sd->vflip));
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1007, 0x20);
20448c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1061, 0x03);
20458c2ecf20Sopenharmony_ci
20468c2ecf20Sopenharmony_ci	/* if JPEG, prepare the compression quality update */
20478c2ecf20Sopenharmony_ci	if (mode & MODE_JPEG) {
20488c2ecf20Sopenharmony_ci		sd->pktsz = sd->npkt = 0;
20498c2ecf20Sopenharmony_ci		sd->nchg = 0;
20508c2ecf20Sopenharmony_ci	}
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
20538c2ecf20Sopenharmony_ci}
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
20568c2ecf20Sopenharmony_ci{
20578c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1007, 0x00);
20588c2ecf20Sopenharmony_ci	reg_w1(gspca_dev, 0x1061, 0x01);
20598c2ecf20Sopenharmony_ci}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci/* called on streamoff with alt==0 and on disconnect */
20628c2ecf20Sopenharmony_ci/* the usb_lock is held at entry - restore on exit */
20638c2ecf20Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
20648c2ecf20Sopenharmony_ci{
20658c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
20688c2ecf20Sopenharmony_ci	flush_work(&sd->work);
20698c2ecf20Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
20708c2ecf20Sopenharmony_ci}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_cistatic void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
20738c2ecf20Sopenharmony_ci{
20748c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
20758c2ecf20Sopenharmony_ci	s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
20768c2ecf20Sopenharmony_ci	s32 max = sd->exposure->maximum - sd->exposure_step;
20778c2ecf20Sopenharmony_ci	s32 min = sd->exposure->minimum + sd->exposure_step;
20788c2ecf20Sopenharmony_ci	s16 new_exp;
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	/*
20818c2ecf20Sopenharmony_ci	 * some hardcoded values are present
20828c2ecf20Sopenharmony_ci	 * like those for maximal/minimal exposure
20838c2ecf20Sopenharmony_ci	 * and exposure steps
20848c2ecf20Sopenharmony_ci	 */
20858c2ecf20Sopenharmony_ci	if (avg_lum < MIN_AVG_LUM) {
20868c2ecf20Sopenharmony_ci		if (cur_exp > max)
20878c2ecf20Sopenharmony_ci			return;
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci		new_exp = cur_exp + sd->exposure_step;
20908c2ecf20Sopenharmony_ci		if (new_exp > max)
20918c2ecf20Sopenharmony_ci			new_exp = max;
20928c2ecf20Sopenharmony_ci		if (new_exp < min)
20938c2ecf20Sopenharmony_ci			new_exp = min;
20948c2ecf20Sopenharmony_ci		v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci		sd->older_step = sd->old_step;
20978c2ecf20Sopenharmony_ci		sd->old_step = 1;
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci		if (sd->old_step ^ sd->older_step)
21008c2ecf20Sopenharmony_ci			sd->exposure_step /= 2;
21018c2ecf20Sopenharmony_ci		else
21028c2ecf20Sopenharmony_ci			sd->exposure_step += 2;
21038c2ecf20Sopenharmony_ci	}
21048c2ecf20Sopenharmony_ci	if (avg_lum > MAX_AVG_LUM) {
21058c2ecf20Sopenharmony_ci		if (cur_exp < min)
21068c2ecf20Sopenharmony_ci			return;
21078c2ecf20Sopenharmony_ci		new_exp = cur_exp - sd->exposure_step;
21088c2ecf20Sopenharmony_ci		if (new_exp > max)
21098c2ecf20Sopenharmony_ci			new_exp = max;
21108c2ecf20Sopenharmony_ci		if (new_exp < min)
21118c2ecf20Sopenharmony_ci			new_exp = min;
21128c2ecf20Sopenharmony_ci		v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
21138c2ecf20Sopenharmony_ci		sd->older_step = sd->old_step;
21148c2ecf20Sopenharmony_ci		sd->old_step = 0;
21158c2ecf20Sopenharmony_ci
21168c2ecf20Sopenharmony_ci		if (sd->old_step ^ sd->older_step)
21178c2ecf20Sopenharmony_ci			sd->exposure_step /= 2;
21188c2ecf20Sopenharmony_ci		else
21198c2ecf20Sopenharmony_ci			sd->exposure_step += 2;
21208c2ecf20Sopenharmony_ci	}
21218c2ecf20Sopenharmony_ci}
21228c2ecf20Sopenharmony_ci
21238c2ecf20Sopenharmony_cistatic void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
21248c2ecf20Sopenharmony_ci{
21258c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21268c2ecf20Sopenharmony_ci	s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
21298c2ecf20Sopenharmony_ci		v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
21308c2ecf20Sopenharmony_ci	if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
21318c2ecf20Sopenharmony_ci		v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
21328c2ecf20Sopenharmony_ci}
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_cistatic void sd_dqcallback(struct gspca_dev *gspca_dev)
21358c2ecf20Sopenharmony_ci{
21368c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21378c2ecf20Sopenharmony_ci	int avg_lum;
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci	if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
21408c2ecf20Sopenharmony_ci		return;
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	avg_lum = atomic_read(&sd->avg_lum);
21438c2ecf20Sopenharmony_ci	if (sd->sensor == SENSOR_SOI968)
21448c2ecf20Sopenharmony_ci		do_autogain(gspca_dev, avg_lum);
21458c2ecf20Sopenharmony_ci	else
21468c2ecf20Sopenharmony_ci		do_autoexposure(gspca_dev, avg_lum);
21478c2ecf20Sopenharmony_ci}
21488c2ecf20Sopenharmony_ci
21498c2ecf20Sopenharmony_ci/* JPEG quality update */
21508c2ecf20Sopenharmony_ci/* This function is executed from a work queue. */
21518c2ecf20Sopenharmony_cistatic void qual_upd(struct work_struct *work)
21528c2ecf20Sopenharmony_ci{
21538c2ecf20Sopenharmony_ci	struct sd *sd = container_of(work, struct sd, work);
21548c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev = &sd->gspca_dev;
21558c2ecf20Sopenharmony_ci	s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
21568c2ecf20Sopenharmony_ci
21578c2ecf20Sopenharmony_ci	/* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
21588c2ecf20Sopenharmony_ci	mutex_lock(&gspca_dev->usb_lock);
21598c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_STREAM, "qual_upd %d%%\n", qual);
21608c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
21618c2ecf20Sopenharmony_ci	set_quality(gspca_dev, qual);
21628c2ecf20Sopenharmony_ci	mutex_unlock(&gspca_dev->usb_lock);
21638c2ecf20Sopenharmony_ci}
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
21668c2ecf20Sopenharmony_cistatic int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
21678c2ecf20Sopenharmony_ci			u8 *data,		/* interrupt packet */
21688c2ecf20Sopenharmony_ci			int len)		/* interrupt packet length */
21698c2ecf20Sopenharmony_ci{
21708c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci	if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
21738c2ecf20Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
21748c2ecf20Sopenharmony_ci		input_sync(gspca_dev->input_dev);
21758c2ecf20Sopenharmony_ci		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
21768c2ecf20Sopenharmony_ci		input_sync(gspca_dev->input_dev);
21778c2ecf20Sopenharmony_ci		return 0;
21788c2ecf20Sopenharmony_ci	}
21798c2ecf20Sopenharmony_ci	return -EINVAL;
21808c2ecf20Sopenharmony_ci}
21818c2ecf20Sopenharmony_ci#endif
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci/* check the JPEG compression */
21848c2ecf20Sopenharmony_cistatic void transfer_check(struct gspca_dev *gspca_dev,
21858c2ecf20Sopenharmony_ci			u8 *data)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
21888c2ecf20Sopenharmony_ci	int new_qual, r;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	new_qual = 0;
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	/* if USB error, discard the frame and decrease the quality */
21938c2ecf20Sopenharmony_ci	if (data[6] & 0x08) {				/* USB FIFO full */
21948c2ecf20Sopenharmony_ci		gspca_dev->last_packet_type = DISCARD_PACKET;
21958c2ecf20Sopenharmony_ci		new_qual = -5;
21968c2ecf20Sopenharmony_ci	} else {
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci		/* else, compute the filling rate and a new JPEG quality */
21998c2ecf20Sopenharmony_ci		r = (sd->pktsz * 100) /
22008c2ecf20Sopenharmony_ci			(sd->npkt *
22018c2ecf20Sopenharmony_ci				gspca_dev->urb[0]->iso_frame_desc[0].length);
22028c2ecf20Sopenharmony_ci		if (r >= 85)
22038c2ecf20Sopenharmony_ci			new_qual = -3;
22048c2ecf20Sopenharmony_ci		else if (r < 75)
22058c2ecf20Sopenharmony_ci			new_qual = 2;
22068c2ecf20Sopenharmony_ci	}
22078c2ecf20Sopenharmony_ci	if (new_qual != 0) {
22088c2ecf20Sopenharmony_ci		sd->nchg += new_qual;
22098c2ecf20Sopenharmony_ci		if (sd->nchg < -6 || sd->nchg >= 12) {
22108c2ecf20Sopenharmony_ci			/* Note: we are in interrupt context, so we can't
22118c2ecf20Sopenharmony_ci			   use v4l2_ctrl_g/s_ctrl here. Access the value
22128c2ecf20Sopenharmony_ci			   directly instead. */
22138c2ecf20Sopenharmony_ci			s32 curqual = sd->jpegqual->cur.val;
22148c2ecf20Sopenharmony_ci			sd->nchg = 0;
22158c2ecf20Sopenharmony_ci			new_qual += curqual;
22168c2ecf20Sopenharmony_ci			if (new_qual < sd->jpegqual->minimum)
22178c2ecf20Sopenharmony_ci				new_qual = sd->jpegqual->minimum;
22188c2ecf20Sopenharmony_ci			else if (new_qual > sd->jpegqual->maximum)
22198c2ecf20Sopenharmony_ci				new_qual = sd->jpegqual->maximum;
22208c2ecf20Sopenharmony_ci			if (new_qual != curqual) {
22218c2ecf20Sopenharmony_ci				sd->jpegqual->cur.val = new_qual;
22228c2ecf20Sopenharmony_ci				schedule_work(&sd->work);
22238c2ecf20Sopenharmony_ci			}
22248c2ecf20Sopenharmony_ci		}
22258c2ecf20Sopenharmony_ci	} else {
22268c2ecf20Sopenharmony_ci		sd->nchg = 0;
22278c2ecf20Sopenharmony_ci	}
22288c2ecf20Sopenharmony_ci	sd->pktsz = sd->npkt = 0;
22298c2ecf20Sopenharmony_ci}
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
22328c2ecf20Sopenharmony_ci			u8 *data,			/* isoc packet */
22338c2ecf20Sopenharmony_ci			int len)			/* iso packet length */
22348c2ecf20Sopenharmony_ci{
22358c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
22368c2ecf20Sopenharmony_ci	int avg_lum, is_jpeg;
22378c2ecf20Sopenharmony_ci	static const u8 frame_header[] = {
22388c2ecf20Sopenharmony_ci		0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96
22398c2ecf20Sopenharmony_ci	};
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci	is_jpeg = (sd->fmt & 0x03) == 0;
22428c2ecf20Sopenharmony_ci	if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
22438c2ecf20Sopenharmony_ci		avg_lum = ((data[35] >> 2) & 3) |
22448c2ecf20Sopenharmony_ci			   (data[20] << 2) |
22458c2ecf20Sopenharmony_ci			   (data[19] << 10);
22468c2ecf20Sopenharmony_ci		avg_lum += ((data[35] >> 4) & 3) |
22478c2ecf20Sopenharmony_ci			    (data[22] << 2) |
22488c2ecf20Sopenharmony_ci			    (data[21] << 10);
22498c2ecf20Sopenharmony_ci		avg_lum += ((data[35] >> 6) & 3) |
22508c2ecf20Sopenharmony_ci			    (data[24] << 2) |
22518c2ecf20Sopenharmony_ci			    (data[23] << 10);
22528c2ecf20Sopenharmony_ci		avg_lum += (data[36] & 3) |
22538c2ecf20Sopenharmony_ci			   (data[26] << 2) |
22548c2ecf20Sopenharmony_ci			   (data[25] << 10);
22558c2ecf20Sopenharmony_ci		avg_lum += ((data[36] >> 2) & 3) |
22568c2ecf20Sopenharmony_ci			    (data[28] << 2) |
22578c2ecf20Sopenharmony_ci			    (data[27] << 10);
22588c2ecf20Sopenharmony_ci		avg_lum += ((data[36] >> 4) & 3) |
22598c2ecf20Sopenharmony_ci			    (data[30] << 2) |
22608c2ecf20Sopenharmony_ci			    (data[29] << 10);
22618c2ecf20Sopenharmony_ci		avg_lum += ((data[36] >> 6) & 3) |
22628c2ecf20Sopenharmony_ci			    (data[32] << 2) |
22638c2ecf20Sopenharmony_ci			    (data[31] << 10);
22648c2ecf20Sopenharmony_ci		avg_lum += ((data[44] >> 4) & 3) |
22658c2ecf20Sopenharmony_ci			    (data[34] << 2) |
22668c2ecf20Sopenharmony_ci			    (data[33] << 10);
22678c2ecf20Sopenharmony_ci		avg_lum >>= 9;
22688c2ecf20Sopenharmony_ci		atomic_set(&sd->avg_lum, avg_lum);
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci		if (is_jpeg)
22718c2ecf20Sopenharmony_ci			transfer_check(gspca_dev, data);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
22748c2ecf20Sopenharmony_ci		len -= 64;
22758c2ecf20Sopenharmony_ci		if (len == 0)
22768c2ecf20Sopenharmony_ci			return;
22778c2ecf20Sopenharmony_ci		data += 64;
22788c2ecf20Sopenharmony_ci	}
22798c2ecf20Sopenharmony_ci	if (gspca_dev->last_packet_type == LAST_PACKET) {
22808c2ecf20Sopenharmony_ci		if (is_jpeg) {
22818c2ecf20Sopenharmony_ci			gspca_frame_add(gspca_dev, FIRST_PACKET,
22828c2ecf20Sopenharmony_ci				sd->jpeg_hdr, JPEG_HDR_SZ);
22838c2ecf20Sopenharmony_ci			gspca_frame_add(gspca_dev, INTER_PACKET,
22848c2ecf20Sopenharmony_ci				data, len);
22858c2ecf20Sopenharmony_ci		} else {
22868c2ecf20Sopenharmony_ci			gspca_frame_add(gspca_dev, FIRST_PACKET,
22878c2ecf20Sopenharmony_ci				data, len);
22888c2ecf20Sopenharmony_ci		}
22898c2ecf20Sopenharmony_ci	} else {
22908c2ecf20Sopenharmony_ci		/* if JPEG, count the packets and their size */
22918c2ecf20Sopenharmony_ci		if (is_jpeg) {
22928c2ecf20Sopenharmony_ci			sd->npkt++;
22938c2ecf20Sopenharmony_ci			sd->pktsz += len;
22948c2ecf20Sopenharmony_ci		}
22958c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
22968c2ecf20Sopenharmony_ci	}
22978c2ecf20Sopenharmony_ci}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci/* sub-driver description */
23008c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = {
23018c2ecf20Sopenharmony_ci	.name = KBUILD_MODNAME,
23028c2ecf20Sopenharmony_ci	.config = sd_config,
23038c2ecf20Sopenharmony_ci	.init = sd_init,
23048c2ecf20Sopenharmony_ci	.init_controls = sd_init_controls,
23058c2ecf20Sopenharmony_ci	.isoc_init = sd_isoc_init,
23068c2ecf20Sopenharmony_ci	.start = sd_start,
23078c2ecf20Sopenharmony_ci	.stopN = sd_stopN,
23088c2ecf20Sopenharmony_ci	.stop0 = sd_stop0,
23098c2ecf20Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
23108c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_INPUT)
23118c2ecf20Sopenharmony_ci	.int_pkt_scan = sd_int_pkt_scan,
23128c2ecf20Sopenharmony_ci#endif
23138c2ecf20Sopenharmony_ci	.dq_callback = sd_dqcallback,
23148c2ecf20Sopenharmony_ci#ifdef CONFIG_VIDEO_ADV_DEBUG
23158c2ecf20Sopenharmony_ci	.set_register = sd_dbg_s_register,
23168c2ecf20Sopenharmony_ci	.get_register = sd_dbg_g_register,
23178c2ecf20Sopenharmony_ci	.get_chip_info = sd_chip_info,
23188c2ecf20Sopenharmony_ci#endif
23198c2ecf20Sopenharmony_ci};
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci#define SN9C20X(sensor, i2c_addr, flags) \
23228c2ecf20Sopenharmony_ci	.driver_info =  ((flags & 0xff) << 16) \
23238c2ecf20Sopenharmony_ci			| (SENSOR_ ## sensor << 8) \
23248c2ecf20Sopenharmony_ci			| (i2c_addr)
23258c2ecf20Sopenharmony_ci
23268c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = {
23278c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
23288c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
23298c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
23308c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
23318c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
23328c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
23338c2ecf20Sopenharmony_ci					     (FLIP_DETECT | HAS_NO_BUTTON))},
23348c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
23358c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
23368c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
23378c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
23388c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
23398c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
23408c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
23418c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
23428c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
23438c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
23448c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
23458c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
23468c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
23478c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
23488c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
23498c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
23508c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
23518c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
23528c2ecf20Sopenharmony_ci	{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
23538c2ecf20Sopenharmony_ci	{USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
23548c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
23558c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x7045), SN9C20X(MT9M112, 0x5d, LED_REVERSE)},
23568c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
23578c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
23588c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
23598c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
23608c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
23618c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
23628c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
23638c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
23648c2ecf20Sopenharmony_ci	{USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
23658c2ecf20Sopenharmony_ci	{}
23668c2ecf20Sopenharmony_ci};
23678c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci/* -- device connect -- */
23708c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
23718c2ecf20Sopenharmony_ci		    const struct usb_device_id *id)
23728c2ecf20Sopenharmony_ci{
23738c2ecf20Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
23748c2ecf20Sopenharmony_ci				THIS_MODULE);
23758c2ecf20Sopenharmony_ci}
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = {
23788c2ecf20Sopenharmony_ci	.name = KBUILD_MODNAME,
23798c2ecf20Sopenharmony_ci	.id_table = device_table,
23808c2ecf20Sopenharmony_ci	.probe = sd_probe,
23818c2ecf20Sopenharmony_ci	.disconnect = gspca_disconnect,
23828c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
23838c2ecf20Sopenharmony_ci	.suspend = gspca_suspend,
23848c2ecf20Sopenharmony_ci	.resume = gspca_resume,
23858c2ecf20Sopenharmony_ci	.reset_resume = gspca_resume,
23868c2ecf20Sopenharmony_ci#endif
23878c2ecf20Sopenharmony_ci};
23888c2ecf20Sopenharmony_ci
23898c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver);
2390