18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * SPCA505 chip based cameras initialization data
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define MODULE_NAME "spca505"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include "gspca.h"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
168c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/* specific webcam descriptor */
198c2ecf20Sopenharmony_cistruct sd {
208c2ecf20Sopenharmony_ci	struct gspca_dev gspca_dev;		/* !! must be the first item */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	u8 subtype;
238c2ecf20Sopenharmony_ci#define IntelPCCameraPro 0
248c2ecf20Sopenharmony_ci#define Nxultra 1
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic const struct v4l2_pix_format vga_mode[] = {
288c2ecf20Sopenharmony_ci	{160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
298c2ecf20Sopenharmony_ci		.bytesperline = 160,
308c2ecf20Sopenharmony_ci		.sizeimage = 160 * 120 * 3 / 2,
318c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
328c2ecf20Sopenharmony_ci		.priv = 4},
338c2ecf20Sopenharmony_ci	{176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
348c2ecf20Sopenharmony_ci		.bytesperline = 176,
358c2ecf20Sopenharmony_ci		.sizeimage = 176 * 144 * 3 / 2,
368c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
378c2ecf20Sopenharmony_ci		.priv = 3},
388c2ecf20Sopenharmony_ci	{320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
398c2ecf20Sopenharmony_ci		.bytesperline = 320,
408c2ecf20Sopenharmony_ci		.sizeimage = 320 * 240 * 3 / 2,
418c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
428c2ecf20Sopenharmony_ci		.priv = 2},
438c2ecf20Sopenharmony_ci	{352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
448c2ecf20Sopenharmony_ci		.bytesperline = 352,
458c2ecf20Sopenharmony_ci		.sizeimage = 352 * 288 * 3 / 2,
468c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
478c2ecf20Sopenharmony_ci		.priv = 1},
488c2ecf20Sopenharmony_ci	{640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
498c2ecf20Sopenharmony_ci		.bytesperline = 640,
508c2ecf20Sopenharmony_ci		.sizeimage = 640 * 480 * 3 / 2,
518c2ecf20Sopenharmony_ci		.colorspace = V4L2_COLORSPACE_SRGB,
528c2ecf20Sopenharmony_ci		.priv = 0},
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define SPCA50X_OFFSET_DATA 10
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define SPCA50X_REG_USB 0x02	/* spca505 501 */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define SPCA50X_USB_CTRL 0x00	/* spca505 */
608c2ecf20Sopenharmony_ci#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define SPCA50X_REG_GLOBAL 0x03	/* spca505 */
638c2ecf20Sopenharmony_ci#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
648c2ecf20Sopenharmony_ci#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
678c2ecf20Sopenharmony_ci#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
688c2ecf20Sopenharmony_ci#define SPCA50X_GMISC3_SAA7113RST 0x20	/* Not sure about this one spca505 */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* Image format and compression control */
718c2ecf20Sopenharmony_ci#define SPCA50X_REG_COMPRESS 0x04
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/*
748c2ecf20Sopenharmony_ci * Data to initialize a SPCA505. Common to the CCD and external modes
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_cistatic const u8 spca505_init_data[][3] = {
778c2ecf20Sopenharmony_ci	/* bmRequest,value,index */
788c2ecf20Sopenharmony_ci	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
798c2ecf20Sopenharmony_ci	/* Sensor reset */
808c2ecf20Sopenharmony_ci	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
818c2ecf20Sopenharmony_ci	{SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
828c2ecf20Sopenharmony_ci	/* Block USB reset */
838c2ecf20Sopenharmony_ci	{SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	{0x05, 0x01, 0x10},
868c2ecf20Sopenharmony_ci					/* Maybe power down some stuff */
878c2ecf20Sopenharmony_ci	{0x05, 0x0f, 0x11},
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	/* Setup internal CCD  ? */
908c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x08},
918c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x09},
928c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0a},
938c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0b},
948c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x0c},
958c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0d},
968c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0e},
978c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0f},
988c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x10},
998c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x11},
1008c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x12},
1018c2ecf20Sopenharmony_ci	{0x06, 0x04, 0x13},
1028c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x14},
1038c2ecf20Sopenharmony_ci	{0x06, 0x8a, 0x51},
1048c2ecf20Sopenharmony_ci	{0x06, 0x40, 0x52},
1058c2ecf20Sopenharmony_ci	{0x06, 0xb6, 0x53},
1068c2ecf20Sopenharmony_ci	{0x06, 0x3d, 0x54},
1078c2ecf20Sopenharmony_ci	{}
1088c2ecf20Sopenharmony_ci};
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/*
1118c2ecf20Sopenharmony_ci * Data to initialize the camera using the internal CCD
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_cistatic const u8 spca505_open_data_ccd[][3] = {
1148c2ecf20Sopenharmony_ci	/* bmRequest,value,index */
1158c2ecf20Sopenharmony_ci	/* Internal CCD data set */
1168c2ecf20Sopenharmony_ci	{0x03, 0x04, 0x01},
1178c2ecf20Sopenharmony_ci	/* This could be a reset */
1188c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x01},
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	/* Setup compression and image registers. 0x6 and 0x7 seem to be
1218c2ecf20Sopenharmony_ci	   related to H&V hold, and are resolution mode specific */
1228c2ecf20Sopenharmony_ci		{0x04, 0x10, 0x01},
1238c2ecf20Sopenharmony_ci		/* DIFF(0x50), was (0x10) */
1248c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
1258c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
1268c2ecf20Sopenharmony_ci	{0x04, 0x20, 0x06},
1278c2ecf20Sopenharmony_ci	{0x04, 0x20, 0x07},
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	{0x08, 0x0a, 0x00},
1308c2ecf20Sopenharmony_ci	/* DIFF (0x4a), was (0xa) */
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x10},
1338c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x11},
1348c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x00},
1358c2ecf20Sopenharmony_ci	/* DIFF not written */
1368c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x01},
1378c2ecf20Sopenharmony_ci	/* DIFF not written */
1388c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x02},
1398c2ecf20Sopenharmony_ci	/* DIFF not written */
1408c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x03},
1418c2ecf20Sopenharmony_ci	/* DIFF not written */
1428c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x04},
1438c2ecf20Sopenharmony_ci	/* DIFF not written */
1448c2ecf20Sopenharmony_ci		{0x05, 0x80, 0x05},
1458c2ecf20Sopenharmony_ci		/* DIFF not written */
1468c2ecf20Sopenharmony_ci		{0x05, 0xe0, 0x06},
1478c2ecf20Sopenharmony_ci		/* DIFF not written */
1488c2ecf20Sopenharmony_ci		{0x05, 0x20, 0x07},
1498c2ecf20Sopenharmony_ci		/* DIFF not written */
1508c2ecf20Sopenharmony_ci		{0x05, 0xa0, 0x08},
1518c2ecf20Sopenharmony_ci		/* DIFF not written */
1528c2ecf20Sopenharmony_ci		{0x05, 0x0, 0x12},
1538c2ecf20Sopenharmony_ci		/* DIFF not written */
1548c2ecf20Sopenharmony_ci	{0x05, 0x02, 0x0f},
1558c2ecf20Sopenharmony_ci	/* DIFF not written */
1568c2ecf20Sopenharmony_ci		{0x05, 0x10, 0x46},
1578c2ecf20Sopenharmony_ci		/* DIFF not written */
1588c2ecf20Sopenharmony_ci		{0x05, 0x8, 0x4a},
1598c2ecf20Sopenharmony_ci		/* DIFF not written */
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	{0x03, 0x08, 0x03},
1628c2ecf20Sopenharmony_ci	/* DIFF (0x3,0x28,0x3) */
1638c2ecf20Sopenharmony_ci	{0x03, 0x08, 0x01},
1648c2ecf20Sopenharmony_ci	{0x03, 0x0c, 0x03},
1658c2ecf20Sopenharmony_ci	/* DIFF not written */
1668c2ecf20Sopenharmony_ci		{0x03, 0x21, 0x00},
1678c2ecf20Sopenharmony_ci		/* DIFF (0x39) */
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/* Extra block copied from init to hopefully ensure CCD is in a sane state */
1708c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x08},
1718c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x09},
1728c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0a},
1738c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0b},
1748c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x0c},
1758c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0d},
1768c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0e},
1778c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0f},
1788c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x10},
1798c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x11},
1808c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x12},
1818c2ecf20Sopenharmony_ci	{0x06, 0x04, 0x13},
1828c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x14},
1838c2ecf20Sopenharmony_ci	{0x06, 0x8a, 0x51},
1848c2ecf20Sopenharmony_ci	{0x06, 0x40, 0x52},
1858c2ecf20Sopenharmony_ci	{0x06, 0xb6, 0x53},
1868c2ecf20Sopenharmony_ci	{0x06, 0x3d, 0x54},
1878c2ecf20Sopenharmony_ci	/* End of extra block */
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		{0x06, 0x3f, 0x1},
1908c2ecf20Sopenharmony_ci		/* Block skipped */
1918c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x02},
1928c2ecf20Sopenharmony_ci	{0x06, 0x64, 0x07},
1938c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x08},
1948c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x09},
1958c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0a},
1968c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0b},
1978c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x0c},
1988c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0d},
1998c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0e},
2008c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x0f},
2018c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x10},
2028c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x11},
2038c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x12},
2048c2ecf20Sopenharmony_ci	{0x06, 0x04, 0x13},
2058c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x14},
2068c2ecf20Sopenharmony_ci	{0x06, 0x8a, 0x51},
2078c2ecf20Sopenharmony_ci	{0x06, 0x40, 0x52},
2088c2ecf20Sopenharmony_ci	{0x06, 0xb6, 0x53},
2098c2ecf20Sopenharmony_ci	{0x06, 0x3d, 0x54},
2108c2ecf20Sopenharmony_ci	{0x06, 0x60, 0x57},
2118c2ecf20Sopenharmony_ci	{0x06, 0x20, 0x58},
2128c2ecf20Sopenharmony_ci	{0x06, 0x15, 0x59},
2138c2ecf20Sopenharmony_ci	{0x06, 0x05, 0x5a},
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	{0x05, 0x01, 0xc0},
2168c2ecf20Sopenharmony_ci	{0x05, 0x10, 0xcb},
2178c2ecf20Sopenharmony_ci		{0x05, 0x80, 0xc1},
2188c2ecf20Sopenharmony_ci		/* */
2198c2ecf20Sopenharmony_ci		{0x05, 0x0, 0xc2},
2208c2ecf20Sopenharmony_ci		/* 4 was 0 */
2218c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2228c2ecf20Sopenharmony_ci		{0x05, 0x80, 0xc1},
2238c2ecf20Sopenharmony_ci		/*  */
2248c2ecf20Sopenharmony_ci	{0x05, 0x04, 0xc2},
2258c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2268c2ecf20Sopenharmony_ci		{0x05, 0x0, 0xc1},
2278c2ecf20Sopenharmony_ci		/*  */
2288c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xc2},
2298c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2308c2ecf20Sopenharmony_ci		{0x05, 0x40, 0xc1},
2318c2ecf20Sopenharmony_ci		/* */
2328c2ecf20Sopenharmony_ci	{0x05, 0x17, 0xc2},
2338c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2348c2ecf20Sopenharmony_ci		{0x05, 0x80, 0xc1},
2358c2ecf20Sopenharmony_ci		/* */
2368c2ecf20Sopenharmony_ci	{0x05, 0x06, 0xc2},
2378c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2388c2ecf20Sopenharmony_ci		{0x05, 0x80, 0xc1},
2398c2ecf20Sopenharmony_ci		/* */
2408c2ecf20Sopenharmony_ci	{0x05, 0x04, 0xc2},
2418c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	{0x03, 0x4c, 0x3},
2448c2ecf20Sopenharmony_ci	{0x03, 0x18, 0x1},
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	{0x06, 0x70, 0x51},
2478c2ecf20Sopenharmony_ci	{0x06, 0xbe, 0x53},
2488c2ecf20Sopenharmony_ci	{0x06, 0x71, 0x57},
2498c2ecf20Sopenharmony_ci	{0x06, 0x20, 0x58},
2508c2ecf20Sopenharmony_ci	{0x06, 0x05, 0x59},
2518c2ecf20Sopenharmony_ci	{0x06, 0x15, 0x5a},
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x08},
2548c2ecf20Sopenharmony_ci	/* Compress = OFF (0x1 to turn on) */
2558c2ecf20Sopenharmony_ci	{0x04, 0x12, 0x09},
2568c2ecf20Sopenharmony_ci	{0x04, 0x21, 0x0a},
2578c2ecf20Sopenharmony_ci	{0x04, 0x10, 0x0b},
2588c2ecf20Sopenharmony_ci	{0x04, 0x21, 0x0c},
2598c2ecf20Sopenharmony_ci	{0x04, 0x05, 0x00},
2608c2ecf20Sopenharmony_ci	/* was 5 (Image Type ? ) */
2618c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x01},
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	{0x06, 0x3f, 0x01},
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
2668c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
2678c2ecf20Sopenharmony_ci	{0x04, 0x40, 0x06},
2688c2ecf20Sopenharmony_ci	{0x04, 0x40, 0x07},
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	{0x06, 0x1c, 0x17},
2718c2ecf20Sopenharmony_ci	{0x06, 0xe2, 0x19},
2728c2ecf20Sopenharmony_ci	{0x06, 0x1c, 0x1b},
2738c2ecf20Sopenharmony_ci	{0x06, 0xe2, 0x1d},
2748c2ecf20Sopenharmony_ci	{0x06, 0xaa, 0x1f},
2758c2ecf20Sopenharmony_ci	{0x06, 0x70, 0x20},
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	{0x05, 0x01, 0x10},
2788c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x11},
2798c2ecf20Sopenharmony_ci	{0x05, 0x01, 0x00},
2808c2ecf20Sopenharmony_ci	{0x05, 0x05, 0x01},
2818c2ecf20Sopenharmony_ci		{0x05, 0x00, 0xc1},
2828c2ecf20Sopenharmony_ci		/* */
2838c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xc2},
2848c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	{0x06, 0x70, 0x51},
2878c2ecf20Sopenharmony_ci	{0x06, 0xbe, 0x53},
2888c2ecf20Sopenharmony_ci	{}
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci/*
2928c2ecf20Sopenharmony_ci * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
2938c2ecf20Sopenharmony_ci * SPCA505b chip based cameras initialization data
2948c2ecf20Sopenharmony_ci */
2958c2ecf20Sopenharmony_ci/* jfm */
2968c2ecf20Sopenharmony_ci#define initial_brightness 0x7f	/* 0x0(white)-0xff(black) */
2978c2ecf20Sopenharmony_ci/* #define initial_brightness 0x0	//0x0(white)-0xff(black) */
2988c2ecf20Sopenharmony_ci/*
2998c2ecf20Sopenharmony_ci * Data to initialize a SPCA505. Common to the CCD and external modes
3008c2ecf20Sopenharmony_ci */
3018c2ecf20Sopenharmony_cistatic const u8 spca505b_init_data[][3] = {
3028c2ecf20Sopenharmony_ci/* start */
3038c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x00},		/* init */
3048c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x01},
3058c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x02},
3068c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x03},
3078c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x04},
3088c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x05},
3098c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x06},
3108c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x07},
3118c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x08},
3128c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x09},
3138c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x00},
3148c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x01},
3158c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x02},
3168c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x03},
3178c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x04},
3188c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x05},
3198c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x06},
3208c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x00},
3218c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x02},
3228c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
3238c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
3248c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x06},
3258c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x07},
3268c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x08},
3278c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x09},
3288c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x0a},
3298c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x0b},
3308c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x0c},
3318c2ecf20Sopenharmony_ci	{0x07, 0x00, 0x00},
3328c2ecf20Sopenharmony_ci	{0x07, 0x00, 0x03},
3338c2ecf20Sopenharmony_ci	{0x08, 0x00, 0x00},
3348c2ecf20Sopenharmony_ci	{0x08, 0x00, 0x01},
3358c2ecf20Sopenharmony_ci	{0x08, 0x00, 0x02},
3368c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x08},
3378c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x09},
3388c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0a},
3398c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0b},
3408c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x0c},
3418c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0d},
3428c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0e},
3438c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0f},
3448c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x10},
3458c2ecf20Sopenharmony_ci	{0x06, 0xfe, 0x12},
3468c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x11},
3478c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x14},
3488c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x13},
3498c2ecf20Sopenharmony_ci	{0x06, 0x28, 0x51},
3508c2ecf20Sopenharmony_ci	{0x06, 0xff, 0x53},
3518c2ecf20Sopenharmony_ci	{0x02, 0x00, 0x08},
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x03},
3548c2ecf20Sopenharmony_ci	{0x03, 0x10, 0x03},
3558c2ecf20Sopenharmony_ci	{}
3568c2ecf20Sopenharmony_ci};
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci/*
3598c2ecf20Sopenharmony_ci * Data to initialize the camera using the internal CCD
3608c2ecf20Sopenharmony_ci */
3618c2ecf20Sopenharmony_cistatic const u8 spca505b_open_data_ccd[][3] = {
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci/* {0x02,0x00,0x00}, */
3648c2ecf20Sopenharmony_ci	{0x03, 0x04, 0x01},		/* rst */
3658c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x01},
3668c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x00},
3678c2ecf20Sopenharmony_ci	{0x03, 0x21, 0x00},
3688c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x04},
3698c2ecf20Sopenharmony_ci	{0x03, 0x00, 0x03},
3708c2ecf20Sopenharmony_ci	{0x03, 0x18, 0x03},
3718c2ecf20Sopenharmony_ci	{0x03, 0x08, 0x01},
3728c2ecf20Sopenharmony_ci	{0x03, 0x1c, 0x03},
3738c2ecf20Sopenharmony_ci	{0x03, 0x5c, 0x03},
3748c2ecf20Sopenharmony_ci	{0x03, 0x5c, 0x03},
3758c2ecf20Sopenharmony_ci	{0x03, 0x18, 0x01},
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/* same as 505 */
3788c2ecf20Sopenharmony_ci	{0x04, 0x10, 0x01},
3798c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
3808c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
3818c2ecf20Sopenharmony_ci	{0x04, 0x20, 0x06},
3828c2ecf20Sopenharmony_ci	{0x04, 0x20, 0x07},
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	{0x08, 0x0a, 0x00},
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x10},
3878c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x11},
3888c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x12},
3898c2ecf20Sopenharmony_ci	{0x05, 0x6f, 0x00},
3908c2ecf20Sopenharmony_ci	{0x05, initial_brightness >> 6, 0x00},
3918c2ecf20Sopenharmony_ci	{0x05, (initial_brightness << 2) & 0xff, 0x01},
3928c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x02},
3938c2ecf20Sopenharmony_ci	{0x05, 0x01, 0x03},
3948c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x04},
3958c2ecf20Sopenharmony_ci	{0x05, 0x03, 0x05},
3968c2ecf20Sopenharmony_ci	{0x05, 0xe0, 0x06},
3978c2ecf20Sopenharmony_ci	{0x05, 0x20, 0x07},
3988c2ecf20Sopenharmony_ci	{0x05, 0xa0, 0x08},
3998c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x12},
4008c2ecf20Sopenharmony_ci	{0x05, 0x02, 0x0f},
4018c2ecf20Sopenharmony_ci	{0x05, 0x80, 0x14},		/* max exposure off (0=on) */
4028c2ecf20Sopenharmony_ci	{0x05, 0x01, 0xb0},
4038c2ecf20Sopenharmony_ci	{0x05, 0x01, 0xbf},
4048c2ecf20Sopenharmony_ci	{0x03, 0x02, 0x06},
4058c2ecf20Sopenharmony_ci	{0x05, 0x10, 0x46},
4068c2ecf20Sopenharmony_ci	{0x05, 0x08, 0x4a},
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x01},
4098c2ecf20Sopenharmony_ci	{0x06, 0x10, 0x02},
4108c2ecf20Sopenharmony_ci	{0x06, 0x64, 0x07},
4118c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x08},
4128c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x09},
4138c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0a},
4148c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0b},
4158c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x01},
4168c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x0c},
4178c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0d},
4188c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0e},
4198c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0f},
4208c2ecf20Sopenharmony_ci	{0x06, 0x11, 0x10},		/* contrast */
4218c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x11},
4228c2ecf20Sopenharmony_ci	{0x06, 0xfe, 0x12},
4238c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x13},
4248c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x14},
4258c2ecf20Sopenharmony_ci	{0x06, 0x9d, 0x51},
4268c2ecf20Sopenharmony_ci	{0x06, 0x40, 0x52},
4278c2ecf20Sopenharmony_ci	{0x06, 0x7c, 0x53},
4288c2ecf20Sopenharmony_ci	{0x06, 0x40, 0x54},
4298c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x57},
4308c2ecf20Sopenharmony_ci	{0x06, 0x03, 0x58},
4318c2ecf20Sopenharmony_ci	{0x06, 0x15, 0x59},
4328c2ecf20Sopenharmony_ci	{0x06, 0x05, 0x5a},
4338c2ecf20Sopenharmony_ci	{0x06, 0x03, 0x56},
4348c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x3f},
4358c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x40},
4368c2ecf20Sopenharmony_ci	{0x06, 0x39, 0x41},
4378c2ecf20Sopenharmony_ci	{0x06, 0x69, 0x42},
4388c2ecf20Sopenharmony_ci	{0x06, 0x87, 0x43},
4398c2ecf20Sopenharmony_ci	{0x06, 0x9e, 0x44},
4408c2ecf20Sopenharmony_ci	{0x06, 0xb1, 0x45},
4418c2ecf20Sopenharmony_ci	{0x06, 0xbf, 0x46},
4428c2ecf20Sopenharmony_ci	{0x06, 0xcc, 0x47},
4438c2ecf20Sopenharmony_ci	{0x06, 0xd5, 0x48},
4448c2ecf20Sopenharmony_ci	{0x06, 0xdd, 0x49},
4458c2ecf20Sopenharmony_ci	{0x06, 0xe3, 0x4a},
4468c2ecf20Sopenharmony_ci	{0x06, 0xe8, 0x4b},
4478c2ecf20Sopenharmony_ci	{0x06, 0xed, 0x4c},
4488c2ecf20Sopenharmony_ci	{0x06, 0xf2, 0x4d},
4498c2ecf20Sopenharmony_ci	{0x06, 0xf7, 0x4e},
4508c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x4f},
4518c2ecf20Sopenharmony_ci	{0x06, 0xff, 0x50},
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	{0x05, 0x01, 0xc0},
4548c2ecf20Sopenharmony_ci	{0x05, 0x10, 0xcb},
4558c2ecf20Sopenharmony_ci	{0x05, 0x40, 0xc1},
4568c2ecf20Sopenharmony_ci	{0x05, 0x04, 0xc2},
4578c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
4588c2ecf20Sopenharmony_ci	{0x05, 0x40, 0xc1},
4598c2ecf20Sopenharmony_ci	{0x05, 0x09, 0xc2},
4608c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
4618c2ecf20Sopenharmony_ci	{0x05, 0xc0, 0xc1},
4628c2ecf20Sopenharmony_ci	{0x05, 0x09, 0xc2},
4638c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
4648c2ecf20Sopenharmony_ci	{0x05, 0x40, 0xc1},
4658c2ecf20Sopenharmony_ci	{0x05, 0x59, 0xc2},
4668c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
4678c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x01},
4688c2ecf20Sopenharmony_ci	{0x05, 0x80, 0xc1},
4698c2ecf20Sopenharmony_ci	{0x05, 0xec, 0xc2},
4708c2ecf20Sopenharmony_ci	{0x05, 0x0, 0xca},
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	{0x06, 0x02, 0x57},
4738c2ecf20Sopenharmony_ci	{0x06, 0x01, 0x58},
4748c2ecf20Sopenharmony_ci	{0x06, 0x15, 0x59},
4758c2ecf20Sopenharmony_ci	{0x06, 0x0a, 0x5a},
4768c2ecf20Sopenharmony_ci	{0x06, 0x01, 0x57},
4778c2ecf20Sopenharmony_ci	{0x06, 0x8a, 0x03},
4788c2ecf20Sopenharmony_ci	{0x06, 0x0a, 0x6c},
4798c2ecf20Sopenharmony_ci	{0x06, 0x30, 0x01},
4808c2ecf20Sopenharmony_ci	{0x06, 0x20, 0x02},
4818c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x03},
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	{0x05, 0x8c, 0x25},
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	{0x06, 0x4d, 0x51},		/* maybe saturation (4d) */
4868c2ecf20Sopenharmony_ci	{0x06, 0x84, 0x53},		/* making green (84) */
4878c2ecf20Sopenharmony_ci	{0x06, 0x00, 0x57},		/* sharpness (1) */
4888c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x08},
4898c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x09},
4908c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0a},
4918c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0b},
4928c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x0c},		/* maybe hue (18) */
4938c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0d},
4948c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0e},
4958c2ecf20Sopenharmony_ci	{0x06, 0xfc, 0x0f},
4968c2ecf20Sopenharmony_ci	{0x06, 0x18, 0x10},		/* maybe contrast (18) */
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	{0x05, 0x01, 0x02},
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x08},		/* compression */
5018c2ecf20Sopenharmony_ci	{0x04, 0x12, 0x09},
5028c2ecf20Sopenharmony_ci	{0x04, 0x21, 0x0a},
5038c2ecf20Sopenharmony_ci	{0x04, 0x10, 0x0b},
5048c2ecf20Sopenharmony_ci	{0x04, 0x21, 0x0c},
5058c2ecf20Sopenharmony_ci	{0x04, 0x1d, 0x00},		/* imagetype (1d) */
5068c2ecf20Sopenharmony_ci	{0x04, 0x41, 0x01},		/* hardware snapcontrol */
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
5098c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
5108c2ecf20Sopenharmony_ci	{0x04, 0x10, 0x06},
5118c2ecf20Sopenharmony_ci	{0x04, 0x10, 0x07},
5128c2ecf20Sopenharmony_ci	{0x04, 0x40, 0x06},
5138c2ecf20Sopenharmony_ci	{0x04, 0x40, 0x07},
5148c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x04},
5158c2ecf20Sopenharmony_ci	{0x04, 0x00, 0x05},
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	{0x06, 0x1c, 0x17},
5188c2ecf20Sopenharmony_ci	{0x06, 0xe2, 0x19},
5198c2ecf20Sopenharmony_ci	{0x06, 0x1c, 0x1b},
5208c2ecf20Sopenharmony_ci	{0x06, 0xe2, 0x1d},
5218c2ecf20Sopenharmony_ci	{0x06, 0x5f, 0x1f},
5228c2ecf20Sopenharmony_ci	{0x06, 0x32, 0x20},
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	{0x05, initial_brightness >> 6, 0x00},
5258c2ecf20Sopenharmony_ci	{0x05, (initial_brightness << 2) & 0xff, 0x01},
5268c2ecf20Sopenharmony_ci	{0x05, 0x06, 0xc1},
5278c2ecf20Sopenharmony_ci	{0x05, 0x58, 0xc2},
5288c2ecf20Sopenharmony_ci	{0x05, 0x00, 0xca},
5298c2ecf20Sopenharmony_ci	{0x05, 0x00, 0x11},
5308c2ecf20Sopenharmony_ci	{}
5318c2ecf20Sopenharmony_ci};
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistatic int reg_write(struct gspca_dev *gspca_dev,
5348c2ecf20Sopenharmony_ci		     u16 req, u16 index, u16 value)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	int ret;
5378c2ecf20Sopenharmony_ci	struct usb_device *dev = gspca_dev->dev;
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	ret = usb_control_msg(dev,
5408c2ecf20Sopenharmony_ci			usb_sndctrlpipe(dev, 0),
5418c2ecf20Sopenharmony_ci			req,
5428c2ecf20Sopenharmony_ci			USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5438c2ecf20Sopenharmony_ci			value, index, NULL, 0, 500);
5448c2ecf20Sopenharmony_ci	gspca_dbg(gspca_dev, D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d\n",
5458c2ecf20Sopenharmony_ci		  req, index, value, ret);
5468c2ecf20Sopenharmony_ci	if (ret < 0)
5478c2ecf20Sopenharmony_ci		pr_err("reg write: error %d\n", ret);
5488c2ecf20Sopenharmony_ci	return ret;
5498c2ecf20Sopenharmony_ci}
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci/* returns: negative is error, pos or zero is data */
5528c2ecf20Sopenharmony_cistatic int reg_read(struct gspca_dev *gspca_dev,
5538c2ecf20Sopenharmony_ci			u16 req,	/* bRequest */
5548c2ecf20Sopenharmony_ci			u16 index)	/* wIndex */
5558c2ecf20Sopenharmony_ci{
5568c2ecf20Sopenharmony_ci	int ret;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	ret = usb_control_msg(gspca_dev->dev,
5598c2ecf20Sopenharmony_ci			usb_rcvctrlpipe(gspca_dev->dev, 0),
5608c2ecf20Sopenharmony_ci			req,
5618c2ecf20Sopenharmony_ci			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
5628c2ecf20Sopenharmony_ci			0,			/* value */
5638c2ecf20Sopenharmony_ci			index,
5648c2ecf20Sopenharmony_ci			gspca_dev->usb_buf, 2,
5658c2ecf20Sopenharmony_ci			500);			/* timeout */
5668c2ecf20Sopenharmony_ci	if (ret < 0)
5678c2ecf20Sopenharmony_ci		return ret;
5688c2ecf20Sopenharmony_ci	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_cistatic int write_vector(struct gspca_dev *gspca_dev,
5728c2ecf20Sopenharmony_ci			const u8 data[][3])
5738c2ecf20Sopenharmony_ci{
5748c2ecf20Sopenharmony_ci	int ret, i = 0;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	while (data[i][0] != 0) {
5778c2ecf20Sopenharmony_ci		ret = reg_write(gspca_dev, data[i][0], data[i][2],
5788c2ecf20Sopenharmony_ci								data[i][1]);
5798c2ecf20Sopenharmony_ci		if (ret < 0)
5808c2ecf20Sopenharmony_ci			return ret;
5818c2ecf20Sopenharmony_ci		i++;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci	return 0;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci/* this function is called at probe time */
5878c2ecf20Sopenharmony_cistatic int sd_config(struct gspca_dev *gspca_dev,
5888c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
5918c2ecf20Sopenharmony_ci	struct cam *cam;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	cam = &gspca_dev->cam;
5948c2ecf20Sopenharmony_ci	cam->cam_mode = vga_mode;
5958c2ecf20Sopenharmony_ci	sd->subtype = id->driver_info;
5968c2ecf20Sopenharmony_ci	if (sd->subtype != IntelPCCameraPro)
5978c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(vga_mode);
5988c2ecf20Sopenharmony_ci	else			/* no 640x480 for IntelPCCameraPro */
5998c2ecf20Sopenharmony_ci		cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	return 0;
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci/* this function is called at probe and resume time */
6058c2ecf20Sopenharmony_cistatic int sd_init(struct gspca_dev *gspca_dev)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci	if (write_vector(gspca_dev,
6108c2ecf20Sopenharmony_ci			 sd->subtype == Nxultra
6118c2ecf20Sopenharmony_ci				? spca505b_init_data
6128c2ecf20Sopenharmony_ci				: spca505_init_data))
6138c2ecf20Sopenharmony_ci		return -EIO;
6148c2ecf20Sopenharmony_ci	return 0;
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_cistatic void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
6188c2ecf20Sopenharmony_ci{
6198c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x05, 0x00, (255 - brightness) >> 6);
6208c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x05, 0x01, (255 - brightness) << 2);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cistatic int sd_start(struct gspca_dev *gspca_dev)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci	struct sd *sd = (struct sd *) gspca_dev;
6268c2ecf20Sopenharmony_ci	int ret, mode;
6278c2ecf20Sopenharmony_ci	static u8 mode_tb[][3] = {
6288c2ecf20Sopenharmony_ci	/*	  r00   r06   r07	*/
6298c2ecf20Sopenharmony_ci		{0x00, 0x10, 0x10},	/* 640x480 */
6308c2ecf20Sopenharmony_ci		{0x01, 0x1a, 0x1a},	/* 352x288 */
6318c2ecf20Sopenharmony_ci		{0x02, 0x1c, 0x1d},	/* 320x240 */
6328c2ecf20Sopenharmony_ci		{0x04, 0x34, 0x34},	/* 176x144 */
6338c2ecf20Sopenharmony_ci		{0x05, 0x40, 0x40}	/* 160x120 */
6348c2ecf20Sopenharmony_ci	};
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	if (sd->subtype == Nxultra)
6378c2ecf20Sopenharmony_ci		write_vector(gspca_dev, spca505b_open_data_ccd);
6388c2ecf20Sopenharmony_ci	else
6398c2ecf20Sopenharmony_ci		write_vector(gspca_dev, spca505_open_data_ccd);
6408c2ecf20Sopenharmony_ci	ret = reg_read(gspca_dev, 0x06, 0x16);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	if (ret < 0) {
6438c2ecf20Sopenharmony_ci		gspca_err(gspca_dev, "register read failed err: %d\n", ret);
6448c2ecf20Sopenharmony_ci		return ret;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci	if (ret != 0x0101) {
6478c2ecf20Sopenharmony_ci		pr_err("After vector read returns 0x%04x should be 0x0101\n",
6488c2ecf20Sopenharmony_ci		       ret);
6498c2ecf20Sopenharmony_ci	}
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	ret = reg_write(gspca_dev, 0x06, 0x16, 0x0a);
6528c2ecf20Sopenharmony_ci	if (ret < 0)
6538c2ecf20Sopenharmony_ci		return ret;
6548c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x05, 0xc2, 0x12);
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	/* necessary because without it we can see stream
6578c2ecf20Sopenharmony_ci	 * only once after loading module */
6588c2ecf20Sopenharmony_ci	/* stopping usb registers Tomasz change */
6598c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x02, 0x00, 0x00);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6628c2ecf20Sopenharmony_ci	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
6638c2ecf20Sopenharmony_ci	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
6648c2ecf20Sopenharmony_ci	reg_write(gspca_dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	return reg_write(gspca_dev, SPCA50X_REG_USB,
6678c2ecf20Sopenharmony_ci			 SPCA50X_USB_CTRL,
6688c2ecf20Sopenharmony_ci			 SPCA50X_CUSB_ENABLE);
6698c2ecf20Sopenharmony_ci}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_cistatic void sd_stopN(struct gspca_dev *gspca_dev)
6728c2ecf20Sopenharmony_ci{
6738c2ecf20Sopenharmony_ci	/* Disable ISO packet machine */
6748c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x02, 0x00, 0x00);
6758c2ecf20Sopenharmony_ci}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci/* called on streamoff with alt 0 and on disconnect */
6788c2ecf20Sopenharmony_cistatic void sd_stop0(struct gspca_dev *gspca_dev)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	if (!gspca_dev->present)
6818c2ecf20Sopenharmony_ci		return;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	/* This maybe reset or power control */
6848c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x03, 0x03, 0x20);
6858c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x03, 0x01, 0x00);
6868c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x03, 0x00, 0x01);
6878c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x05, 0x10, 0x01);
6888c2ecf20Sopenharmony_ci	reg_write(gspca_dev, 0x05, 0x11, 0x0f);
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic void sd_pkt_scan(struct gspca_dev *gspca_dev,
6928c2ecf20Sopenharmony_ci			u8 *data,			/* isoc packet */
6938c2ecf20Sopenharmony_ci			int len)			/* iso packet length */
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	switch (data[0]) {
6968c2ecf20Sopenharmony_ci	case 0:				/* start of frame */
6978c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
6988c2ecf20Sopenharmony_ci		data += SPCA50X_OFFSET_DATA;
6998c2ecf20Sopenharmony_ci		len -= SPCA50X_OFFSET_DATA;
7008c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
7018c2ecf20Sopenharmony_ci		break;
7028c2ecf20Sopenharmony_ci	case 0xff:			/* drop */
7038c2ecf20Sopenharmony_ci		break;
7048c2ecf20Sopenharmony_ci	default:
7058c2ecf20Sopenharmony_ci		data += 1;
7068c2ecf20Sopenharmony_ci		len -= 1;
7078c2ecf20Sopenharmony_ci		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
7088c2ecf20Sopenharmony_ci		break;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_cistatic int sd_s_ctrl(struct v4l2_ctrl *ctrl)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	struct gspca_dev *gspca_dev =
7158c2ecf20Sopenharmony_ci		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	gspca_dev->usb_err = 0;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	if (!gspca_dev->streaming)
7208c2ecf20Sopenharmony_ci		return 0;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	switch (ctrl->id) {
7238c2ecf20Sopenharmony_ci	case V4L2_CID_BRIGHTNESS:
7248c2ecf20Sopenharmony_ci		setbrightness(gspca_dev, ctrl->val);
7258c2ecf20Sopenharmony_ci		break;
7268c2ecf20Sopenharmony_ci	}
7278c2ecf20Sopenharmony_ci	return gspca_dev->usb_err;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_cistatic const struct v4l2_ctrl_ops sd_ctrl_ops = {
7318c2ecf20Sopenharmony_ci	.s_ctrl = sd_s_ctrl,
7328c2ecf20Sopenharmony_ci};
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_cistatic int sd_init_controls(struct gspca_dev *gspca_dev)
7358c2ecf20Sopenharmony_ci{
7368c2ecf20Sopenharmony_ci	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	gspca_dev->vdev.ctrl_handler = hdl;
7398c2ecf20Sopenharmony_ci	v4l2_ctrl_handler_init(hdl, 5);
7408c2ecf20Sopenharmony_ci	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
7418c2ecf20Sopenharmony_ci			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	if (hdl->error) {
7448c2ecf20Sopenharmony_ci		pr_err("Could not initialize controls\n");
7458c2ecf20Sopenharmony_ci		return hdl->error;
7468c2ecf20Sopenharmony_ci	}
7478c2ecf20Sopenharmony_ci	return 0;
7488c2ecf20Sopenharmony_ci}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci/* sub-driver description */
7518c2ecf20Sopenharmony_cistatic const struct sd_desc sd_desc = {
7528c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
7538c2ecf20Sopenharmony_ci	.config = sd_config,
7548c2ecf20Sopenharmony_ci	.init_controls = sd_init_controls,
7558c2ecf20Sopenharmony_ci	.init = sd_init,
7568c2ecf20Sopenharmony_ci	.start = sd_start,
7578c2ecf20Sopenharmony_ci	.stopN = sd_stopN,
7588c2ecf20Sopenharmony_ci	.stop0 = sd_stop0,
7598c2ecf20Sopenharmony_ci	.pkt_scan = sd_pkt_scan,
7608c2ecf20Sopenharmony_ci};
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci/* -- module initialisation -- */
7638c2ecf20Sopenharmony_cistatic const struct usb_device_id device_table[] = {
7648c2ecf20Sopenharmony_ci	{USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
7658c2ecf20Sopenharmony_ci	{USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
7668c2ecf20Sopenharmony_ci/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
7678c2ecf20Sopenharmony_ci	{}
7688c2ecf20Sopenharmony_ci};
7698c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(usb, device_table);
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci/* -- device connect -- */
7728c2ecf20Sopenharmony_cistatic int sd_probe(struct usb_interface *intf,
7738c2ecf20Sopenharmony_ci			const struct usb_device_id *id)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
7768c2ecf20Sopenharmony_ci				THIS_MODULE);
7778c2ecf20Sopenharmony_ci}
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_cistatic struct usb_driver sd_driver = {
7808c2ecf20Sopenharmony_ci	.name = MODULE_NAME,
7818c2ecf20Sopenharmony_ci	.id_table = device_table,
7828c2ecf20Sopenharmony_ci	.probe = sd_probe,
7838c2ecf20Sopenharmony_ci	.disconnect = gspca_disconnect,
7848c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
7858c2ecf20Sopenharmony_ci	.suspend = gspca_suspend,
7868c2ecf20Sopenharmony_ci	.resume = gspca_resume,
7878c2ecf20Sopenharmony_ci	.reset_resume = gspca_resume,
7888c2ecf20Sopenharmony_ci#endif
7898c2ecf20Sopenharmony_ci};
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cimodule_usb_driver(sd_driver);
792