cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ov534_9.c (41652B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ov534-ov9xxx gspca driver
      4 *
      5 * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
      6 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
      7 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
      8 *
      9 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
     10 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
     11 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
     12 */
     13
     14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     15
     16#define MODULE_NAME "ov534_9"
     17
     18#include "gspca.h"
     19
     20#define OV534_REG_ADDRESS	0xf1	/* sensor address */
     21#define OV534_REG_SUBADDR	0xf2
     22#define OV534_REG_WRITE		0xf3
     23#define OV534_REG_READ		0xf4
     24#define OV534_REG_OPERATION	0xf5
     25#define OV534_REG_STATUS	0xf6
     26
     27#define OV534_OP_WRITE_3	0x37
     28#define OV534_OP_WRITE_2	0x33
     29#define OV534_OP_READ_2		0xf9
     30
     31#define CTRL_TIMEOUT 500
     32
     33MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
     34MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
     35MODULE_LICENSE("GPL");
     36
     37/* specific webcam descriptor */
     38struct sd {
     39	struct gspca_dev gspca_dev;	/* !! must be the first item */
     40	__u32 last_pts;
     41	u8 last_fid;
     42
     43	u8 sensor;
     44};
     45enum sensors {
     46	SENSOR_OV965x,		/* ov9657 */
     47	SENSOR_OV971x,		/* ov9712 */
     48	SENSOR_OV562x,		/* ov5621 */
     49	SENSOR_OV361x,		/* ov3610 */
     50	NSENSORS
     51};
     52
     53static const struct v4l2_pix_format ov965x_mode[] = {
     54#define QVGA_MODE 0
     55	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
     56		.bytesperline = 320,
     57		.sizeimage = 320 * 240 * 3 / 8 + 590,
     58		.colorspace = V4L2_COLORSPACE_JPEG},
     59#define VGA_MODE 1
     60	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
     61		.bytesperline = 640,
     62		.sizeimage = 640 * 480 * 3 / 8 + 590,
     63		.colorspace = V4L2_COLORSPACE_JPEG},
     64#define SVGA_MODE 2
     65	{800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
     66		.bytesperline = 800,
     67		.sizeimage = 800 * 600 * 3 / 8 + 590,
     68		.colorspace = V4L2_COLORSPACE_JPEG},
     69#define XGA_MODE 3
     70	{1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
     71		.bytesperline = 1024,
     72		.sizeimage = 1024 * 768 * 3 / 8 + 590,
     73		.colorspace = V4L2_COLORSPACE_JPEG},
     74#define SXGA_MODE 4
     75	{1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
     76		.bytesperline = 1280,
     77		.sizeimage = 1280 * 1024 * 3 / 8 + 590,
     78		.colorspace = V4L2_COLORSPACE_JPEG},
     79};
     80
     81static const struct v4l2_pix_format ov971x_mode[] = {
     82	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
     83		.bytesperline = 640,
     84		.sizeimage = 640 * 480,
     85		.colorspace = V4L2_COLORSPACE_SRGB
     86	}
     87};
     88
     89static const struct v4l2_pix_format ov562x_mode[] = {
     90	{2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
     91		.bytesperline = 2592,
     92		.sizeimage = 2592 * 1680,
     93		.colorspace = V4L2_COLORSPACE_SRGB
     94	}
     95};
     96
     97enum ov361x {
     98	ov361x_2048 = 0,
     99	ov361x_1600,
    100	ov361x_1024,
    101	ov361x_640,
    102	ov361x_320,
    103	ov361x_160,
    104	ov361x_last
    105};
    106
    107static const struct v4l2_pix_format ov361x_mode[] = {
    108	{0x800, 0x600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    109		.bytesperline = 0x800,
    110		.sizeimage = 0x800 * 0x600,
    111		.colorspace = V4L2_COLORSPACE_SRGB},
    112	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    113		.bytesperline = 1600,
    114		.sizeimage = 1600 * 1200,
    115		.colorspace = V4L2_COLORSPACE_SRGB},
    116	{1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    117		.bytesperline = 768,
    118		.sizeimage = 1024 * 768,
    119		.colorspace = V4L2_COLORSPACE_SRGB},
    120	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    121		.bytesperline = 640,
    122		.sizeimage = 640 * 480,
    123		.colorspace = V4L2_COLORSPACE_SRGB},
    124	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    125		.bytesperline = 320,
    126		.sizeimage = 320 * 240,
    127		.colorspace = V4L2_COLORSPACE_SRGB},
    128	{160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
    129		.bytesperline = 160,
    130		.sizeimage = 160 * 120,
    131		.colorspace = V4L2_COLORSPACE_SRGB}
    132};
    133
    134static const u8 ov361x_start_2048[][2] = {
    135	{0x12, 0x80},
    136	{0x13, 0xcf},
    137	{0x14, 0x40},
    138	{0x15, 0x00},
    139	{0x01, 0x80},
    140	{0x02, 0x80},
    141	{0x04, 0x70},
    142	{0x0d, 0x40},
    143	{0x0f, 0x47},
    144	{0x11, 0x81},
    145	{0x32, 0x36},
    146	{0x33, 0x0c},
    147	{0x34, 0x00},
    148	{0x35, 0x90},
    149	{0x12, 0x00},
    150	{0x17, 0x10},
    151	{0x18, 0x90},
    152	{0x19, 0x00},
    153	{0x1a, 0xc0},
    154};
    155static const u8 ov361x_bridge_start_2048[][2] = {
    156	{0xf1, 0x60},
    157	{0x88, 0x00},
    158	{0x89, 0x08},
    159	{0x8a, 0x00},
    160	{0x8b, 0x06},
    161	{0x8c, 0x01},
    162	{0x8d, 0x10},
    163	{0x1c, 0x00},
    164	{0x1d, 0x48},
    165	{0x1d, 0x00},
    166	{0x1d, 0xff},
    167	{0x1c, 0x0a},
    168	{0x1d, 0x2e},
    169	{0x1d, 0x1e},
    170};
    171
    172static const u8 ov361x_start_1600[][2] = {
    173	{0x12, 0x80},
    174	{0x13, 0xcf},
    175	{0x14, 0x40},
    176	{0x15, 0x00},
    177	{0x01, 0x80},
    178	{0x02, 0x80},
    179	{0x04, 0x70},
    180	{0x0d, 0x40},
    181	{0x0f, 0x47},
    182	{0x11, 0x81},
    183	{0x32, 0x36},
    184	{0x33, 0x0C},
    185	{0x34, 0x00},
    186	{0x35, 0x90},
    187	{0x12, 0x00},
    188	{0x17, 0x10},
    189	{0x18, 0x90},
    190	{0x19, 0x00},
    191	{0x1a, 0xc0},
    192};
    193static const u8 ov361x_bridge_start_1600[][2] = {
    194	{0xf1, 0x60},  /* Hsize[7:0] */
    195	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
    196	{0x89, 0x08},  /* Vsize[7:0] */
    197	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
    198	{0x8b, 0x06},  /* for Iso */
    199	{0x8c, 0x01},  /* RAW input */
    200	{0x8d, 0x10},
    201	{0x1c, 0x00},  /* RAW output, Iso transfer */
    202	{0x1d, 0x48},
    203	{0x1d, 0x00},
    204	{0x1d, 0xff},
    205	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
    206	{0x1d, 0x2e},  /* for Iso */
    207	{0x1d, 0x1e},
    208};
    209
    210static const u8 ov361x_start_1024[][2] = {
    211	{0x12, 0x80},
    212	{0x13, 0xcf},
    213	{0x14, 0x40},
    214	{0x15, 0x00},
    215	{0x01, 0x80},
    216	{0x02, 0x80},
    217	{0x04, 0x70},
    218	{0x0d, 0x40},
    219	{0x0f, 0x47},
    220	{0x11, 0x81},
    221	{0x32, 0x36},
    222	{0x33, 0x0C},
    223	{0x34, 0x00},
    224	{0x35, 0x90},
    225	{0x12, 0x40},
    226	{0x17, 0x1f},
    227	{0x18, 0x5f},
    228	{0x19, 0x00},
    229	{0x1a, 0x68},
    230};
    231static const u8 ov361x_bridge_start_1024[][2] = {
    232	{0xf1, 0x60},  /* Hsize[7:0] */
    233	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
    234	{0x89, 0x04},  /* Vsize[7:0] */
    235	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
    236	{0x8b, 0x03},  /* for Iso */
    237	{0x8c, 0x01},  /* RAW input  */
    238	{0x8d, 0x10},
    239	{0x1c, 0x00},  /* RAW output, Iso transfer */
    240	{0x1d, 0x48},
    241	{0x1d, 0x00},
    242	{0x1d, 0xff},
    243	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
    244	{0x1d, 0x2e},  /* for Iso */
    245	{0x1d, 0x1e},
    246};
    247
    248static const u8 ov361x_start_640[][2] = {
    249	{0x12, 0x80},
    250	{0x13, 0xcf},
    251	{0x14, 0x40},
    252	{0x15, 0x00},
    253	{0x01, 0x80},
    254	{0x02, 0x80},
    255	{0x04, 0x70},
    256	{0x0d, 0x40},
    257	{0x0f, 0x47},
    258	{0x11, 0x81},
    259	{0x32, 0x36},
    260	{0x33, 0x0C},
    261	{0x34, 0x00},
    262	{0x35, 0x90},
    263	{0x12, 0x40},
    264	{0x17, 0x1f},
    265	{0x18, 0x5f},
    266	{0x19, 0x00},
    267	{0x1a, 0x68},
    268};
    269
    270static const u8 ov361x_bridge_start_640[][2] = {
    271	{0xf1, 0x60},  /* Hsize[7:0]*/
    272	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
    273	{0x89, 0x04},  /* Vsize[7:0] */
    274	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
    275	{0x8b, 0x03},  /* for Iso */
    276	{0x8c, 0x01},  /* RAW input */
    277	{0x8d, 0x10},
    278	{0x1c, 0x00},  /* RAW output, Iso transfer */
    279	{0x1d, 0x48},
    280	{0x1d, 0x00},
    281	{0x1d, 0xff},
    282	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
    283	{0x1d, 0x2e},  /* for Iso */
    284	{0x1d, 0x1e},
    285};
    286
    287static const u8 ov361x_start_320[][2] = {
    288	{0x12, 0x80},
    289	{0x13, 0xcf},
    290	{0x14, 0x40},
    291	{0x15, 0x00},
    292	{0x01, 0x80},
    293	{0x02, 0x80},
    294	{0x04, 0x70},
    295	{0x0d, 0x40},
    296	{0x0f, 0x47},
    297	{0x11, 0x81},
    298	{0x32, 0x36},
    299	{0x33, 0x0C},
    300	{0x34, 0x00},
    301	{0x35, 0x90},
    302	{0x12, 0x40},
    303	{0x17, 0x1f},
    304	{0x18, 0x5f},
    305	{0x19, 0x00},
    306	{0x1a, 0x68},
    307};
    308
    309static const u8 ov361x_bridge_start_320[][2] = {
    310	{0xf1, 0x60},  /* Hsize[7:0] */
    311	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
    312	{0x89, 0x04},  /* Vsize[7:0] */
    313	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
    314	{0x8b, 0x03},  /* for Iso */
    315	{0x8c, 0x01},  /* RAW input */
    316	{0x8d, 0x10},
    317	{0x1c, 0x00},  /* RAW output, Iso transfer; */
    318	{0x1d, 0x48},
    319	{0x1d, 0x00},
    320	{0x1d, 0xff},
    321	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
    322	{0x1d, 0x2e},  /* for Iso */
    323	{0x1d, 0x1e},
    324};
    325
    326static const u8 ov361x_start_160[][2] = {
    327	{0x12, 0x80},
    328	{0x13, 0xcf},
    329	{0x14, 0x40},
    330	{0x15, 0x00},
    331	{0x01, 0x80},
    332	{0x02, 0x80},
    333	{0x04, 0x70},
    334	{0x0d, 0x40},
    335	{0x0f, 0x47},
    336	{0x11, 0x81},
    337	{0x32, 0x36},
    338	{0x33, 0x0C},
    339	{0x34, 0x00},
    340	{0x35, 0x90},
    341	{0x12, 0x40},
    342	{0x17, 0x1f},
    343	{0x18, 0x5f},
    344	{0x19, 0x00},
    345	{0x1a, 0x68},
    346};
    347
    348static const u8 ov361x_bridge_start_160[][2] = {
    349	{0xf1, 0x60},  /* Hsize[7:0] */
    350	{0x88, 0x00},  /* Hsize[15:8] Write Only, can't read */
    351	{0x89, 0x04},  /* Vsize[7:0] */
    352	{0x8a, 0x00},  /* Vsize[15:8] Write Only, can't read */
    353	{0x8b, 0x03},  /* for Iso */
    354	{0x8c, 0x01},  /* RAW input */
    355	{0x8d, 0x10},
    356	{0x1c, 0x00},  /* RAW output, Iso transfer */
    357	{0x1d, 0x48},
    358	{0x1d, 0x00},
    359	{0x1d, 0xff},
    360	{0x1c, 0x0a},  /* turn off JPEG, Iso mode */
    361	{0x1d, 0x2e},  /* for Iso */
    362	{0x1d, 0x1e},
    363};
    364
    365static const u8 bridge_init[][2] = {
    366	{0x88, 0xf8},
    367	{0x89, 0xff},
    368	{0x76, 0x03},
    369	{0x92, 0x03},
    370	{0x95, 0x10},
    371	{0xe2, 0x00},
    372	{0xe7, 0x3e},
    373	{0x8d, 0x1c},
    374	{0x8e, 0x00},
    375	{0x8f, 0x00},
    376	{0x1f, 0x00},
    377	{0xc3, 0xf9},
    378	{0x89, 0xff},
    379	{0x88, 0xf8},
    380	{0x76, 0x03},
    381	{0x92, 0x01},
    382	{0x93, 0x18},
    383	{0x1c, 0x0a},
    384	{0x1d, 0x48},
    385	{0xc0, 0x50},
    386	{0xc1, 0x3c},
    387	{0x34, 0x05},
    388	{0xc2, 0x0c},
    389	{0xc3, 0xf9},
    390	{0x34, 0x05},
    391	{0xe7, 0x2e},
    392	{0x31, 0xf9},
    393	{0x35, 0x02},
    394	{0xd9, 0x10},
    395	{0x25, 0x42},
    396	{0x94, 0x11},
    397};
    398
    399static const u8 ov965x_init[][2] = {
    400	{0x12, 0x80},	/* com7 - SSCB reset */
    401	{0x00, 0x00},	/* gain */
    402	{0x01, 0x80},	/* blue */
    403	{0x02, 0x80},	/* red */
    404	{0x03, 0x1b},	/* vref */
    405	{0x04, 0x03},	/* com1 - exposure low bits */
    406	{0x0b, 0x57},	/* ver */
    407	{0x0e, 0x61},	/* com5 */
    408	{0x0f, 0x42},	/* com6 */
    409	{0x11, 0x00},	/* clkrc */
    410	{0x12, 0x02},	/* com7 - 15fps VGA YUYV */
    411	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    412	{0x14, 0x28},	/* com9 */
    413	{0x16, 0x24},	/* reg16 */
    414	{0x17, 0x1d},	/* hstart*/
    415	{0x18, 0xbd},	/* hstop */
    416	{0x19, 0x01},	/* vstrt */
    417	{0x1a, 0x81},	/* vstop*/
    418	{0x1e, 0x04},	/* mvfp */
    419	{0x24, 0x3c},	/* aew */
    420	{0x25, 0x36},	/* aeb */
    421	{0x26, 0x71},	/* vpt */
    422	{0x27, 0x08},	/* bbias */
    423	{0x28, 0x08},	/* gbbias */
    424	{0x29, 0x15},	/* gr com */
    425	{0x2a, 0x00},	/* exhch */
    426	{0x2b, 0x00},	/* exhcl */
    427	{0x2c, 0x08},	/* rbias */
    428	{0x32, 0xff},	/* href */
    429	{0x33, 0x00},	/* chlf */
    430	{0x34, 0x3f},	/* aref1 */
    431	{0x35, 0x00},	/* aref2 */
    432	{0x36, 0xf8},	/* aref3 */
    433	{0x38, 0x72},	/* adc2 */
    434	{0x39, 0x57},	/* aref4 */
    435	{0x3a, 0x80},	/* tslb - yuyv */
    436	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
    437	{0x3d, 0x99},	/* com13 */
    438	{0x3f, 0xc1},	/* edge */
    439	{0x40, 0xc0},	/* com15 */
    440	{0x41, 0x40},	/* com16 */
    441	{0x42, 0xc0},	/* com17 */
    442	{0x43, 0x0a},	/* rsvd */
    443	{0x44, 0xf0},
    444	{0x45, 0x46},
    445	{0x46, 0x62},
    446	{0x47, 0x2a},
    447	{0x48, 0x3c},
    448	{0x4a, 0xfc},
    449	{0x4b, 0xfc},
    450	{0x4c, 0x7f},
    451	{0x4d, 0x7f},
    452	{0x4e, 0x7f},
    453	{0x4f, 0x98},	/* matrix */
    454	{0x50, 0x98},
    455	{0x51, 0x00},
    456	{0x52, 0x28},
    457	{0x53, 0x70},
    458	{0x54, 0x98},
    459	{0x58, 0x1a},	/* matrix coef sign */
    460	{0x59, 0x85},	/* AWB control */
    461	{0x5a, 0xa9},
    462	{0x5b, 0x64},
    463	{0x5c, 0x84},
    464	{0x5d, 0x53},
    465	{0x5e, 0x0e},
    466	{0x5f, 0xf0},	/* AWB blue limit */
    467	{0x60, 0xf0},	/* AWB red limit */
    468	{0x61, 0xf0},	/* AWB green limit */
    469	{0x62, 0x00},	/* lcc1 */
    470	{0x63, 0x00},	/* lcc2 */
    471	{0x64, 0x02},	/* lcc3 */
    472	{0x65, 0x16},	/* lcc4 */
    473	{0x66, 0x01},	/* lcc5 */
    474	{0x69, 0x02},	/* hv */
    475	{0x6b, 0x5a},	/* dbvl */
    476	{0x6c, 0x04},
    477	{0x6d, 0x55},
    478	{0x6e, 0x00},
    479	{0x6f, 0x9d},
    480	{0x70, 0x21},	/* dnsth */
    481	{0x71, 0x78},
    482	{0x72, 0x00},	/* poidx */
    483	{0x73, 0x01},	/* pckdv */
    484	{0x74, 0x3a},	/* xindx */
    485	{0x75, 0x35},	/* yindx */
    486	{0x76, 0x01},
    487	{0x77, 0x02},
    488	{0x7a, 0x12},	/* gamma curve */
    489	{0x7b, 0x08},
    490	{0x7c, 0x16},
    491	{0x7d, 0x30},
    492	{0x7e, 0x5e},
    493	{0x7f, 0x72},
    494	{0x80, 0x82},
    495	{0x81, 0x8e},
    496	{0x82, 0x9a},
    497	{0x83, 0xa4},
    498	{0x84, 0xac},
    499	{0x85, 0xb8},
    500	{0x86, 0xc3},
    501	{0x87, 0xd6},
    502	{0x88, 0xe6},
    503	{0x89, 0xf2},
    504	{0x8a, 0x03},
    505	{0x8c, 0x89},	/* com19 */
    506	{0x14, 0x28},	/* com9 */
    507	{0x90, 0x7d},
    508	{0x91, 0x7b},
    509	{0x9d, 0x03},	/* lcc6 */
    510	{0x9e, 0x04},	/* lcc7 */
    511	{0x9f, 0x7a},
    512	{0xa0, 0x79},
    513	{0xa1, 0x40},	/* aechm */
    514	{0xa4, 0x50},	/* com21 */
    515	{0xa5, 0x68},	/* com26 */
    516	{0xa6, 0x4a},	/* AWB green */
    517	{0xa8, 0xc1},	/* refa8 */
    518	{0xa9, 0xef},	/* refa9 */
    519	{0xaa, 0x92},
    520	{0xab, 0x04},
    521	{0xac, 0x80},	/* black level control */
    522	{0xad, 0x80},
    523	{0xae, 0x80},
    524	{0xaf, 0x80},
    525	{0xb2, 0xf2},
    526	{0xb3, 0x20},
    527	{0xb4, 0x20},	/* ctrlb4 */
    528	{0xb5, 0x00},
    529	{0xb6, 0xaf},
    530	{0xbb, 0xae},
    531	{0xbc, 0x7f},	/* ADC channel offsets */
    532	{0xdb, 0x7f},
    533	{0xbe, 0x7f},
    534	{0xbf, 0x7f},
    535	{0xc0, 0xe2},
    536	{0xc1, 0xc0},
    537	{0xc2, 0x01},
    538	{0xc3, 0x4e},
    539	{0xc6, 0x85},
    540	{0xc7, 0x80},	/* com24 */
    541	{0xc9, 0xe0},
    542	{0xca, 0xe8},
    543	{0xcb, 0xf0},
    544	{0xcc, 0xd8},
    545	{0xcd, 0xf1},
    546	{0x4f, 0x98},	/* matrix */
    547	{0x50, 0x98},
    548	{0x51, 0x00},
    549	{0x52, 0x28},
    550	{0x53, 0x70},
    551	{0x54, 0x98},
    552	{0x58, 0x1a},
    553	{0xff, 0x41},	/* read 41, write ff 00 */
    554	{0x41, 0x40},	/* com16 */
    555
    556	{0xc5, 0x03},	/* 60 Hz banding filter */
    557	{0x6a, 0x02},	/* 50 Hz banding filter */
    558
    559	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
    560	{0x36, 0xfa},	/* aref3 */
    561	{0x69, 0x0a},	/* hv */
    562	{0x8c, 0x89},	/* com22 */
    563	{0x14, 0x28},	/* com9 */
    564	{0x3e, 0x0c},
    565	{0x41, 0x40},	/* com16 */
    566	{0x72, 0x00},
    567	{0x73, 0x00},
    568	{0x74, 0x3a},
    569	{0x75, 0x35},
    570	{0x76, 0x01},
    571	{0xc7, 0x80},
    572	{0x03, 0x12},	/* vref */
    573	{0x17, 0x16},	/* hstart */
    574	{0x18, 0x02},	/* hstop */
    575	{0x19, 0x01},	/* vstrt */
    576	{0x1a, 0x3d},	/* vstop */
    577	{0x32, 0xff},	/* href */
    578	{0xc0, 0xaa},
    579};
    580
    581static const u8 bridge_init_2[][2] = {
    582	{0x94, 0xaa},
    583	{0xf1, 0x60},
    584	{0xe5, 0x04},
    585	{0xc0, 0x50},
    586	{0xc1, 0x3c},
    587	{0x8c, 0x00},
    588	{0x8d, 0x1c},
    589	{0x34, 0x05},
    590
    591	{0xc2, 0x0c},
    592	{0xc3, 0xf9},
    593	{0xda, 0x01},
    594	{0x50, 0x00},
    595	{0x51, 0xa0},
    596	{0x52, 0x3c},
    597	{0x53, 0x00},
    598	{0x54, 0x00},
    599	{0x55, 0x00},
    600	{0x57, 0x00},
    601	{0x5c, 0x00},
    602	{0x5a, 0xa0},
    603	{0x5b, 0x78},
    604	{0x35, 0x02},
    605	{0xd9, 0x10},
    606	{0x94, 0x11},
    607};
    608
    609static const u8 ov965x_init_2[][2] = {
    610	{0x3b, 0xc4},
    611	{0x1e, 0x04},	/* mvfp */
    612	{0x13, 0xe0},	/* com8 */
    613	{0x00, 0x00},	/* gain */
    614	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    615	{0x11, 0x03},	/* clkrc */
    616	{0x6b, 0x5a},	/* dblv */
    617	{0x6a, 0x05},
    618	{0xc5, 0x07},
    619	{0xa2, 0x4b},
    620	{0xa3, 0x3e},
    621	{0x2d, 0x00},
    622	{0xff, 0x42},	/* read 42, write ff 00 */
    623	{0x42, 0xc0},	/* com17 */
    624	{0x2d, 0x00},
    625	{0xff, 0x42},	/* read 42, write ff 00 */
    626	{0x42, 0xc1},	/* com17 */
    627/* sharpness */
    628	{0x3f, 0x01},
    629	{0xff, 0x42},	/* read 42, write ff 00 */
    630	{0x42, 0xc1},	/* com17 */
    631/* saturation */
    632	{0x4f, 0x98},	/* matrix */
    633	{0x50, 0x98},
    634	{0x51, 0x00},
    635	{0x52, 0x28},
    636	{0x53, 0x70},
    637	{0x54, 0x98},
    638	{0x58, 0x1a},
    639	{0xff, 0x41},	/* read 41, write ff 00 */
    640	{0x41, 0x40},	/* com16 */
    641/* contrast */
    642	{0x56, 0x40},
    643/* brightness */
    644	{0x55, 0x8f},
    645/* expo */
    646	{0x10, 0x25},	/* aech - exposure high bits */
    647	{0xff, 0x13},	/* read 13, write ff 00 */
    648	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    649};
    650
    651static const u8 ov971x_init[][2] = {
    652	{0x12, 0x80},
    653	{0x09, 0x10},
    654	{0x1e, 0x07},
    655	{0x5f, 0x18},
    656	{0x69, 0x04},
    657	{0x65, 0x2a},
    658	{0x68, 0x0a},
    659	{0x39, 0x28},
    660	{0x4d, 0x90},
    661	{0xc1, 0x80},
    662	{0x0c, 0x30},
    663	{0x6d, 0x02},
    664	{0x96, 0xf1},
    665	{0xbc, 0x68},
    666	{0x12, 0x00},
    667	{0x3b, 0x00},
    668	{0x97, 0x80},
    669	{0x17, 0x25},
    670	{0x18, 0xa2},
    671	{0x19, 0x01},
    672	{0x1a, 0xca},
    673	{0x03, 0x0a},
    674	{0x32, 0x07},
    675	{0x98, 0x40},	/*{0x98, 0x00},*/
    676	{0x99, 0xA0},	/*{0x99, 0x00},*/
    677	{0x9a, 0x01},	/*{0x9a, 0x00},*/
    678	{0x57, 0x00},
    679	{0x58, 0x78},	/*{0x58, 0xc8},*/
    680	{0x59, 0x50},	/*{0x59, 0xa0},*/
    681	{0x4c, 0x13},
    682	{0x4b, 0x36},
    683	{0x3d, 0x3c},
    684	{0x3e, 0x03},
    685	{0xbd, 0x50},	/*{0xbd, 0xa0},*/
    686	{0xbe, 0x78},	/*{0xbe, 0xc8},*/
    687	{0x4e, 0x55},
    688	{0x4f, 0x55},
    689	{0x50, 0x55},
    690	{0x51, 0x55},
    691	{0x24, 0x55},
    692	{0x25, 0x40},
    693	{0x26, 0xa1},
    694	{0x5c, 0x59},
    695	{0x5d, 0x00},
    696	{0x11, 0x00},
    697	{0x2a, 0x98},
    698	{0x2b, 0x06},
    699	{0x2d, 0x00},
    700	{0x2e, 0x00},
    701	{0x13, 0xa5},
    702	{0x14, 0x40},
    703	{0x4a, 0x00},
    704	{0x49, 0xce},
    705	{0x22, 0x03},
    706	{0x09, 0x00}
    707};
    708
    709static const u8 ov965x_start_1_vga[][2] = {	/* same for qvga */
    710	{0x12, 0x62},	/* com7 - 30fps VGA YUV */
    711	{0x36, 0xfa},	/* aref3 */
    712	{0x69, 0x0a},	/* hv */
    713	{0x8c, 0x89},	/* com22 */
    714	{0x14, 0x28},	/* com9 */
    715	{0x3e, 0x0c},	/* com14 */
    716	{0x41, 0x40},	/* com16 */
    717	{0x72, 0x00},
    718	{0x73, 0x00},
    719	{0x74, 0x3a},
    720	{0x75, 0x35},
    721	{0x76, 0x01},
    722	{0xc7, 0x80},	/* com24 */
    723	{0x03, 0x12},	/* vref */
    724	{0x17, 0x16},	/* hstart */
    725	{0x18, 0x02},	/* hstop */
    726	{0x19, 0x01},	/* vstrt */
    727	{0x1a, 0x3d},	/* vstop */
    728	{0x32, 0xff},	/* href */
    729	{0xc0, 0xaa},
    730};
    731
    732static const u8 ov965x_start_1_svga[][2] = {
    733	{0x12, 0x02},	/* com7 - YUYV - VGA 15 full resolution */
    734	{0x36, 0xf8},	/* aref3 */
    735	{0x69, 0x02},	/* hv */
    736	{0x8c, 0x0d},	/* com22 */
    737	{0x3e, 0x0c},	/* com14 */
    738	{0x41, 0x40},	/* com16 */
    739	{0x72, 0x00},
    740	{0x73, 0x01},
    741	{0x74, 0x3a},
    742	{0x75, 0x35},
    743	{0x76, 0x01},
    744	{0xc7, 0x80},	/* com24 */
    745	{0x03, 0x1b},	/* vref */
    746	{0x17, 0x1d},	/* hstart */
    747	{0x18, 0xbd},	/* hstop */
    748	{0x19, 0x01},	/* vstrt */
    749	{0x1a, 0x81},	/* vstop */
    750	{0x32, 0xff},	/* href */
    751	{0xc0, 0xe2},
    752};
    753
    754static const u8 ov965x_start_1_xga[][2] = {
    755	{0x12, 0x02},	/* com7 */
    756	{0x36, 0xf8},	/* aref3 */
    757	{0x69, 0x02},	/* hv */
    758	{0x8c, 0x89},	/* com22 */
    759	{0x14, 0x28},	/* com9 */
    760	{0x3e, 0x0c},	/* com14 */
    761	{0x41, 0x40},	/* com16 */
    762	{0x72, 0x00},
    763	{0x73, 0x01},
    764	{0x74, 0x3a},
    765	{0x75, 0x35},
    766	{0x76, 0x01},
    767	{0xc7, 0x80},	/* com24 */
    768	{0x03, 0x1b},	/* vref */
    769	{0x17, 0x1d},	/* hstart */
    770	{0x18, 0xbd},	/* hstop */
    771	{0x19, 0x01},	/* vstrt */
    772	{0x1a, 0x81},	/* vstop */
    773	{0x32, 0xff},	/* href */
    774	{0xc0, 0xe2},
    775};
    776
    777static const u8 ov965x_start_1_sxga[][2] = {
    778	{0x12, 0x02},	/* com7 */
    779	{0x36, 0xf8},	/* aref3 */
    780	{0x69, 0x02},	/* hv */
    781	{0x8c, 0x89},	/* com22 */
    782	{0x14, 0x28},	/* com9 */
    783	{0x3e, 0x0c},	/* com14 */
    784	{0x41, 0x40},	/* com16 */
    785	{0x72, 0x00},
    786	{0x73, 0x01},
    787	{0x74, 0x3a},
    788	{0x75, 0x35},
    789	{0x76, 0x01},
    790	{0xc7, 0x80},	/* com24 */
    791	{0x03, 0x1b},	/* vref */
    792	{0x17, 0x1d},	/* hstart */
    793	{0x18, 0x02},	/* hstop */
    794	{0x19, 0x01},	/* vstrt */
    795	{0x1a, 0x81},	/* vstop */
    796	{0x32, 0xff},	/* href */
    797	{0xc0, 0xe2},
    798};
    799
    800static const u8 bridge_start_qvga[][2] = {
    801	{0x94, 0xaa},
    802	{0xf1, 0x60},
    803	{0xe5, 0x04},
    804	{0xc0, 0x50},
    805	{0xc1, 0x3c},
    806	{0x8c, 0x00},
    807	{0x8d, 0x1c},
    808	{0x34, 0x05},
    809
    810	{0xc2, 0x4c},
    811	{0xc3, 0xf9},
    812	{0xda, 0x00},
    813	{0x50, 0x00},
    814	{0x51, 0xa0},
    815	{0x52, 0x78},
    816	{0x53, 0x00},
    817	{0x54, 0x00},
    818	{0x55, 0x00},
    819	{0x57, 0x00},
    820	{0x5c, 0x00},
    821	{0x5a, 0x50},
    822	{0x5b, 0x3c},
    823	{0x35, 0x02},
    824	{0xd9, 0x10},
    825	{0x94, 0x11},
    826};
    827
    828static const u8 bridge_start_vga[][2] = {
    829	{0x94, 0xaa},
    830	{0xf1, 0x60},
    831	{0xe5, 0x04},
    832	{0xc0, 0x50},
    833	{0xc1, 0x3c},
    834	{0x8c, 0x00},
    835	{0x8d, 0x1c},
    836	{0x34, 0x05},
    837	{0xc2, 0x0c},
    838	{0xc3, 0xf9},
    839	{0xda, 0x01},
    840	{0x50, 0x00},
    841	{0x51, 0xa0},
    842	{0x52, 0x3c},
    843	{0x53, 0x00},
    844	{0x54, 0x00},
    845	{0x55, 0x00},
    846	{0x57, 0x00},
    847	{0x5c, 0x00},
    848	{0x5a, 0xa0},
    849	{0x5b, 0x78},
    850	{0x35, 0x02},
    851	{0xd9, 0x10},
    852	{0x94, 0x11},
    853};
    854
    855static const u8 bridge_start_svga[][2] = {
    856	{0x94, 0xaa},
    857	{0xf1, 0x60},
    858	{0xe5, 0x04},
    859	{0xc0, 0xa0},
    860	{0xc1, 0x80},
    861	{0x8c, 0x00},
    862	{0x8d, 0x1c},
    863	{0x34, 0x05},
    864	{0xc2, 0x4c},
    865	{0xc3, 0xf9},
    866	{0x50, 0x00},
    867	{0x51, 0x40},
    868	{0x52, 0x00},
    869	{0x53, 0x00},
    870	{0x54, 0x00},
    871	{0x55, 0x88},
    872	{0x57, 0x00},
    873	{0x5c, 0x00},
    874	{0x5a, 0xc8},
    875	{0x5b, 0x96},
    876	{0x35, 0x02},
    877	{0xd9, 0x10},
    878	{0xda, 0x00},
    879	{0x94, 0x11},
    880};
    881
    882static const u8 bridge_start_xga[][2] = {
    883	{0x94, 0xaa},
    884	{0xf1, 0x60},
    885	{0xe5, 0x04},
    886	{0xc0, 0xa0},
    887	{0xc1, 0x80},
    888	{0x8c, 0x00},
    889	{0x8d, 0x1c},
    890	{0x34, 0x05},
    891	{0xc2, 0x4c},
    892	{0xc3, 0xf9},
    893	{0x50, 0x00},
    894	{0x51, 0x40},
    895	{0x52, 0x00},
    896	{0x53, 0x00},
    897	{0x54, 0x00},
    898	{0x55, 0x88},
    899	{0x57, 0x00},
    900	{0x5c, 0x01},
    901	{0x5a, 0x00},
    902	{0x5b, 0xc0},
    903	{0x35, 0x02},
    904	{0xd9, 0x10},
    905	{0xda, 0x01},
    906	{0x94, 0x11},
    907};
    908
    909static const u8 bridge_start_sxga[][2] = {
    910	{0x94, 0xaa},
    911	{0xf1, 0x60},
    912	{0xe5, 0x04},
    913	{0xc0, 0xa0},
    914	{0xc1, 0x80},
    915	{0x8c, 0x00},
    916	{0x8d, 0x1c},
    917	{0x34, 0x05},
    918	{0xc2, 0x0c},
    919	{0xc3, 0xf9},
    920	{0xda, 0x00},
    921	{0x35, 0x02},
    922	{0xd9, 0x10},
    923	{0x94, 0x11},
    924};
    925
    926static const u8 ov965x_start_2_qvga[][2] = {
    927	{0x3b, 0xe4},	/* com11 - night mode 1/4 frame rate */
    928	{0x1e, 0x04},	/* mvfp */
    929	{0x13, 0xe0},	/* com8 */
    930	{0x00, 0x00},
    931	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    932	{0x11, 0x01},	/* clkrc */
    933	{0x6b, 0x5a},	/* dblv */
    934	{0x6a, 0x02},	/* 50 Hz banding filter */
    935	{0xc5, 0x03},	/* 60 Hz banding filter */
    936	{0xa2, 0x96},	/* bd50 */
    937	{0xa3, 0x7d},	/* bd60 */
    938
    939	{0xff, 0x13},	/* read 13, write ff 00 */
    940	{0x13, 0xe7},
    941	{0x3a, 0x80},	/* tslb - yuyv */
    942};
    943
    944static const u8 ov965x_start_2_vga[][2] = {
    945	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
    946	{0x1e, 0x04},	/* mvfp */
    947	{0x13, 0xe0},	/* com8 */
    948	{0x00, 0x00},
    949	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    950	{0x11, 0x03},	/* clkrc */
    951	{0x6b, 0x5a},	/* dblv */
    952	{0x6a, 0x05},	/* 50 Hz banding filter */
    953	{0xc5, 0x07},	/* 60 Hz banding filter */
    954	{0xa2, 0x4b},	/* bd50 */
    955	{0xa3, 0x3e},	/* bd60 */
    956
    957	{0x2d, 0x00},	/* advfl */
    958};
    959
    960static const u8 ov965x_start_2_svga[][2] = {	/* same for xga */
    961	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
    962	{0x1e, 0x04},	/* mvfp */
    963	{0x13, 0xe0},	/* com8 */
    964	{0x00, 0x00},
    965	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    966	{0x11, 0x01},	/* clkrc */
    967	{0x6b, 0x5a},	/* dblv */
    968	{0x6a, 0x0c},	/* 50 Hz banding filter */
    969	{0xc5, 0x0f},	/* 60 Hz banding filter */
    970	{0xa2, 0x4e},	/* bd50 */
    971	{0xa3, 0x41},	/* bd60 */
    972};
    973
    974static const u8 ov965x_start_2_sxga[][2] = {
    975	{0x13, 0xe0},	/* com8 */
    976	{0x00, 0x00},
    977	{0x13, 0xe7},	/* com8 - everything (AGC, AWB and AEC) */
    978	{0x3b, 0xc4},	/* com11 - night mode 1/4 frame rate */
    979	{0x1e, 0x04},	/* mvfp */
    980	{0x11, 0x01},	/* clkrc */
    981	{0x6b, 0x5a},	/* dblv */
    982	{0x6a, 0x0c},	/* 50 Hz banding filter */
    983	{0xc5, 0x0f},	/* 60 Hz banding filter */
    984	{0xa2, 0x4e},	/* bd50 */
    985	{0xa3, 0x41},	/* bd60 */
    986};
    987
    988static const u8 ov562x_init[][2] = {
    989	{0x88, 0x20},
    990	{0x89, 0x0a},
    991	{0x8a, 0x90},
    992	{0x8b, 0x06},
    993	{0x8c, 0x01},
    994	{0x8d, 0x10},
    995	{0x1c, 0x00},
    996	{0x1d, 0x48},
    997	{0x1d, 0x00},
    998	{0x1d, 0xff},
    999	{0x1c, 0x0a},
   1000	{0x1d, 0x2e},
   1001	{0x1d, 0x1e},
   1002};
   1003
   1004static const u8 ov562x_init_2[][2] = {
   1005	{0x12, 0x80},
   1006	{0x11, 0x41},
   1007	{0x13, 0x00},
   1008	{0x10, 0x1e},
   1009	{0x3b, 0x07},
   1010	{0x5b, 0x40},
   1011	{0x39, 0x07},
   1012	{0x53, 0x02},
   1013	{0x54, 0x60},
   1014	{0x04, 0x20},
   1015	{0x27, 0x04},
   1016	{0x3d, 0x40},
   1017	{0x36, 0x00},
   1018	{0xc5, 0x04},
   1019	{0x4e, 0x00},
   1020	{0x4f, 0x93},
   1021	{0x50, 0x7b},
   1022	{0xca, 0x0c},
   1023	{0xcb, 0x0f},
   1024	{0x39, 0x07},
   1025	{0x4a, 0x10},
   1026	{0x3e, 0x0a},
   1027	{0x3d, 0x00},
   1028	{0x0c, 0x38},
   1029	{0x38, 0x90},
   1030	{0x46, 0x30},
   1031	{0x4f, 0x93},
   1032	{0x50, 0x7b},
   1033	{0xab, 0x00},
   1034	{0xca, 0x0c},
   1035	{0xcb, 0x0f},
   1036	{0x37, 0x02},
   1037	{0x44, 0x48},
   1038	{0x8d, 0x44},
   1039	{0x2a, 0x00},
   1040	{0x2b, 0x00},
   1041	{0x32, 0x00},
   1042	{0x38, 0x90},
   1043	{0x53, 0x02},
   1044	{0x54, 0x60},
   1045	{0x12, 0x00},
   1046	{0x17, 0x12},
   1047	{0x18, 0xb4},
   1048	{0x19, 0x0c},
   1049	{0x1a, 0xf4},
   1050	{0x03, 0x4a},
   1051	{0x89, 0x20},
   1052	{0x83, 0x80},
   1053	{0xb7, 0x9d},
   1054	{0xb6, 0x11},
   1055	{0xb5, 0x55},
   1056	{0xb4, 0x00},
   1057	{0xa9, 0xf0},
   1058	{0xa8, 0x0a},
   1059	{0xb8, 0xf0},
   1060	{0xb9, 0xf0},
   1061	{0xba, 0xf0},
   1062	{0x81, 0x07},
   1063	{0x63, 0x44},
   1064	{0x13, 0xc7},
   1065	{0x14, 0x60},
   1066	{0x33, 0x75},
   1067	{0x2c, 0x00},
   1068	{0x09, 0x00},
   1069	{0x35, 0x30},
   1070	{0x27, 0x04},
   1071	{0x3c, 0x07},
   1072	{0x3a, 0x0a},
   1073	{0x3b, 0x07},
   1074	{0x01, 0x40},
   1075	{0x02, 0x40},
   1076	{0x16, 0x40},
   1077	{0x52, 0xb0},
   1078	{0x51, 0x83},
   1079	{0x21, 0xbb},
   1080	{0x22, 0x10},
   1081	{0x23, 0x03},
   1082	{0x35, 0x38},
   1083	{0x20, 0x90},
   1084	{0x28, 0x30},
   1085	{0x73, 0xe1},
   1086	{0x6c, 0x00},
   1087	{0x6d, 0x80},
   1088	{0x6e, 0x00},
   1089	{0x70, 0x04},
   1090	{0x71, 0x00},
   1091	{0x8d, 0x04},
   1092	{0x64, 0x00},
   1093	{0x65, 0x00},
   1094	{0x66, 0x00},
   1095	{0x67, 0x00},
   1096	{0x68, 0x00},
   1097	{0x69, 0x00},
   1098	{0x6a, 0x00},
   1099	{0x6b, 0x00},
   1100	{0x71, 0x94},
   1101	{0x74, 0x20},
   1102	{0x80, 0x09},
   1103	{0x85, 0xc0},
   1104};
   1105
   1106static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
   1107{
   1108	struct usb_device *udev = gspca_dev->dev;
   1109	int ret;
   1110
   1111	if (gspca_dev->usb_err < 0)
   1112		return;
   1113	gspca_dev->usb_buf[0] = val;
   1114	ret = usb_control_msg(udev,
   1115			      usb_sndctrlpipe(udev, 0),
   1116			      0x01,
   1117			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
   1118			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
   1119	if (ret < 0) {
   1120		pr_err("reg_w failed %d\n", ret);
   1121		gspca_dev->usb_err = ret;
   1122	}
   1123}
   1124
   1125static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
   1126{
   1127	gspca_dbg(gspca_dev, D_USBO, "reg_w [%04x] = %02x\n", reg, val);
   1128	reg_w_i(gspca_dev, reg, val);
   1129}
   1130
   1131static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
   1132{
   1133	struct usb_device *udev = gspca_dev->dev;
   1134	int ret;
   1135
   1136	if (gspca_dev->usb_err < 0)
   1137		return 0;
   1138	ret = usb_control_msg(udev,
   1139			      usb_rcvctrlpipe(udev, 0),
   1140			      0x01,
   1141			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
   1142			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
   1143	gspca_dbg(gspca_dev, D_USBI, "reg_r [%04x] -> %02x\n",
   1144		  reg, gspca_dev->usb_buf[0]);
   1145	if (ret < 0) {
   1146		pr_err("reg_r err %d\n", ret);
   1147		gspca_dev->usb_err = ret;
   1148		return 0;
   1149	}
   1150	return gspca_dev->usb_buf[0];
   1151}
   1152
   1153static int sccb_check_status(struct gspca_dev *gspca_dev)
   1154{
   1155	u8 data;
   1156	int i;
   1157
   1158	for (i = 0; i < 5; i++) {
   1159		msleep(20);
   1160		data = reg_r(gspca_dev, OV534_REG_STATUS);
   1161
   1162		switch (data) {
   1163		case 0x00:
   1164			return 1;
   1165		case 0x04:
   1166			return 0;
   1167		case 0x03:
   1168			break;
   1169		default:
   1170			gspca_dbg(gspca_dev, D_USBI|D_USBO,
   1171				  "sccb status 0x%02x, attempt %d/5\n",
   1172				  data, i + 1);
   1173		}
   1174	}
   1175	return 0;
   1176}
   1177
   1178static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
   1179{
   1180	gspca_dbg(gspca_dev, D_USBO, "sccb_write [%02x] = %02x\n", reg, val);
   1181	reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
   1182	reg_w_i(gspca_dev, OV534_REG_WRITE, val);
   1183	reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
   1184
   1185	if (!sccb_check_status(gspca_dev))
   1186		pr_err("sccb_write failed\n");
   1187}
   1188
   1189static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
   1190{
   1191	reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
   1192	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
   1193	if (!sccb_check_status(gspca_dev))
   1194		pr_err("sccb_read failed 1\n");
   1195
   1196	reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
   1197	if (!sccb_check_status(gspca_dev))
   1198		pr_err("sccb_read failed 2\n");
   1199
   1200	return reg_r(gspca_dev, OV534_REG_READ);
   1201}
   1202
   1203/* output a bridge sequence (reg - val) */
   1204static void reg_w_array(struct gspca_dev *gspca_dev,
   1205			const u8 (*data)[2], int len)
   1206{
   1207	while (--len >= 0) {
   1208		reg_w(gspca_dev, (*data)[0], (*data)[1]);
   1209		data++;
   1210	}
   1211}
   1212
   1213/* output a sensor sequence (reg - val) */
   1214static void sccb_w_array(struct gspca_dev *gspca_dev,
   1215			const u8 (*data)[2], int len)
   1216{
   1217	while (--len >= 0) {
   1218		if ((*data)[0] != 0xff) {
   1219			sccb_write(gspca_dev, (*data)[0], (*data)[1]);
   1220		} else {
   1221			sccb_read(gspca_dev, (*data)[1]);
   1222			sccb_write(gspca_dev, 0xff, 0x00);
   1223		}
   1224		data++;
   1225	}
   1226}
   1227
   1228/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
   1229 * (direction and output)? */
   1230static void set_led(struct gspca_dev *gspca_dev, int status)
   1231{
   1232	u8 data;
   1233
   1234	gspca_dbg(gspca_dev, D_CONF, "led status: %d\n", status);
   1235
   1236	data = reg_r(gspca_dev, 0x21);
   1237	data |= 0x80;
   1238	reg_w(gspca_dev, 0x21, data);
   1239
   1240	data = reg_r(gspca_dev, 0x23);
   1241	if (status)
   1242		data |= 0x80;
   1243	else
   1244		data &= ~0x80;
   1245
   1246	reg_w(gspca_dev, 0x23, data);
   1247
   1248	if (!status) {
   1249		data = reg_r(gspca_dev, 0x21);
   1250		data &= ~0x80;
   1251		reg_w(gspca_dev, 0x21, data);
   1252	}
   1253}
   1254
   1255static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
   1256{
   1257	struct sd *sd = (struct sd *) gspca_dev;
   1258	u8 val;
   1259	s8 sval;
   1260
   1261	if (sd->sensor == SENSOR_OV562x) {
   1262		sval = brightness;
   1263		val = 0x76;
   1264		val += sval;
   1265		sccb_write(gspca_dev, 0x24, val);
   1266		val = 0x6a;
   1267		val += sval;
   1268		sccb_write(gspca_dev, 0x25, val);
   1269		if (sval < -40)
   1270			val = 0x71;
   1271		else if (sval < 20)
   1272			val = 0x94;
   1273		else
   1274			val = 0xe6;
   1275		sccb_write(gspca_dev, 0x26, val);
   1276	} else {
   1277		val = brightness;
   1278		if (val < 8)
   1279			val = 15 - val;		/* f .. 8 */
   1280		else
   1281			val = val - 8;		/* 0 .. 7 */
   1282		sccb_write(gspca_dev, 0x55,	/* brtn - brightness adjustment */
   1283				0x0f | (val << 4));
   1284	}
   1285}
   1286
   1287static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
   1288{
   1289	sccb_write(gspca_dev, 0x56,	/* cnst1 - contrast 1 ctrl coeff */
   1290			val << 4);
   1291}
   1292
   1293static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
   1294{
   1295	u8 val;
   1296
   1297/*fixme: should adjust agc/awb/aec by different controls */
   1298	val = sccb_read(gspca_dev, 0x13);		/* com8 */
   1299	sccb_write(gspca_dev, 0xff, 0x00);
   1300	if (autogain)
   1301		val |= 0x05;		/* agc & aec */
   1302	else
   1303		val &= 0xfa;
   1304	sccb_write(gspca_dev, 0x13, val);
   1305}
   1306
   1307static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
   1308{
   1309	static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
   1310	u8 val;
   1311
   1312	sccb_write(gspca_dev, 0x10, expo[exposure]);	/* aec[9:2] */
   1313
   1314	val = sccb_read(gspca_dev, 0x13);		/* com8 */
   1315	sccb_write(gspca_dev, 0xff, 0x00);
   1316	sccb_write(gspca_dev, 0x13, val);
   1317
   1318	val = sccb_read(gspca_dev, 0xa1);		/* aech */
   1319	sccb_write(gspca_dev, 0xff, 0x00);
   1320	sccb_write(gspca_dev, 0xa1, val & 0xe0);	/* aec[15:10] = 0 */
   1321}
   1322
   1323static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
   1324{
   1325	if (val < 0) {				/* auto */
   1326		val = sccb_read(gspca_dev, 0x42);	/* com17 */
   1327		sccb_write(gspca_dev, 0xff, 0x00);
   1328		sccb_write(gspca_dev, 0x42, val | 0x40);
   1329				/* Edge enhancement strength auto adjust */
   1330		return;
   1331	}
   1332	if (val != 0)
   1333		val = 1 << (val - 1);
   1334	sccb_write(gspca_dev, 0x3f,	/* edge - edge enhance. factor */
   1335			val);
   1336	val = sccb_read(gspca_dev, 0x42);		/* com17 */
   1337	sccb_write(gspca_dev, 0xff, 0x00);
   1338	sccb_write(gspca_dev, 0x42, val & 0xbf);
   1339}
   1340
   1341static void setsatur(struct gspca_dev *gspca_dev, s32 val)
   1342{
   1343	u8 val1, val2, val3;
   1344	static const u8 matrix[5][2] = {
   1345		{0x14, 0x38},
   1346		{0x1e, 0x54},
   1347		{0x28, 0x70},
   1348		{0x32, 0x8c},
   1349		{0x48, 0x90}
   1350	};
   1351
   1352	val1 = matrix[val][0];
   1353	val2 = matrix[val][1];
   1354	val3 = val1 + val2;
   1355	sccb_write(gspca_dev, 0x4f, val3);	/* matrix coeff */
   1356	sccb_write(gspca_dev, 0x50, val3);
   1357	sccb_write(gspca_dev, 0x51, 0x00);
   1358	sccb_write(gspca_dev, 0x52, val1);
   1359	sccb_write(gspca_dev, 0x53, val2);
   1360	sccb_write(gspca_dev, 0x54, val3);
   1361	sccb_write(gspca_dev, 0x58, 0x1a);	/* mtxs - coeff signs */
   1362
   1363	val1 = sccb_read(gspca_dev, 0x41);	/* com16 */
   1364	sccb_write(gspca_dev, 0xff, 0x00);
   1365	sccb_write(gspca_dev, 0x41, val1);
   1366}
   1367
   1368static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
   1369{
   1370	u8 val;
   1371
   1372	val = sccb_read(gspca_dev, 0x13);		/* com8 */
   1373	sccb_write(gspca_dev, 0xff, 0x00);
   1374	if (freq == 0) {
   1375		sccb_write(gspca_dev, 0x13, val & 0xdf);
   1376		return;
   1377	}
   1378	sccb_write(gspca_dev, 0x13, val | 0x20);
   1379
   1380	val = sccb_read(gspca_dev, 0x42);		/* com17 */
   1381	sccb_write(gspca_dev, 0xff, 0x00);
   1382	if (freq == 1)
   1383		val |= 0x01;
   1384	else
   1385		val &= 0xfe;
   1386	sccb_write(gspca_dev, 0x42, val);
   1387}
   1388
   1389/* this function is called at probe time */
   1390static int sd_config(struct gspca_dev *gspca_dev,
   1391		     const struct usb_device_id *id)
   1392{
   1393	return 0;
   1394}
   1395
   1396/* this function is called at probe and resume time */
   1397static int sd_init(struct gspca_dev *gspca_dev)
   1398{
   1399	struct sd *sd = (struct sd *) gspca_dev;
   1400	u16 sensor_id;
   1401
   1402	/* reset bridge */
   1403	reg_w(gspca_dev, 0xe7, 0x3a);
   1404	reg_w(gspca_dev, 0xe0, 0x08);
   1405	msleep(100);
   1406
   1407	/* initialize the sensor address */
   1408	reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
   1409
   1410	/* reset sensor */
   1411	sccb_write(gspca_dev, 0x12, 0x80);
   1412	msleep(10);
   1413
   1414	/* probe the sensor */
   1415	sccb_read(gspca_dev, 0x0a);
   1416	sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
   1417	sccb_read(gspca_dev, 0x0b);
   1418	sensor_id |= sccb_read(gspca_dev, 0x0b);
   1419	gspca_dbg(gspca_dev, D_PROBE, "Sensor ID: %04x\n", sensor_id);
   1420
   1421	/* initialize */
   1422	if ((sensor_id & 0xfff0) == 0x9650) {
   1423		sd->sensor = SENSOR_OV965x;
   1424
   1425		gspca_dev->cam.cam_mode = ov965x_mode;
   1426		gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
   1427
   1428		reg_w_array(gspca_dev, bridge_init,
   1429				ARRAY_SIZE(bridge_init));
   1430		sccb_w_array(gspca_dev, ov965x_init,
   1431				ARRAY_SIZE(ov965x_init));
   1432		reg_w_array(gspca_dev, bridge_init_2,
   1433				ARRAY_SIZE(bridge_init_2));
   1434		sccb_w_array(gspca_dev, ov965x_init_2,
   1435				ARRAY_SIZE(ov965x_init_2));
   1436		reg_w(gspca_dev, 0xe0, 0x00);
   1437		reg_w(gspca_dev, 0xe0, 0x01);
   1438		set_led(gspca_dev, 0);
   1439		reg_w(gspca_dev, 0xe0, 0x00);
   1440	} else if ((sensor_id & 0xfff0) == 0x9710) {
   1441		const char *p;
   1442		int l;
   1443
   1444		sd->sensor = SENSOR_OV971x;
   1445
   1446		gspca_dev->cam.cam_mode = ov971x_mode;
   1447		gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
   1448
   1449		gspca_dev->cam.bulk = 1;
   1450		gspca_dev->cam.bulk_size = 16384;
   1451		gspca_dev->cam.bulk_nurbs = 2;
   1452
   1453		sccb_w_array(gspca_dev, ov971x_init,
   1454				ARRAY_SIZE(ov971x_init));
   1455
   1456		/* set video format on bridge processor */
   1457		/* access bridge processor's video format registers at: 0x00 */
   1458		reg_w(gspca_dev, 0x1c, 0x00);
   1459		/*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
   1460		reg_w(gspca_dev, 0x1d, 0x00);
   1461
   1462		/* Will W. specific stuff
   1463		 * set VSYNC to
   1464		 *	output (0x1f) if first webcam
   1465		 *	input (0x17) if 2nd or 3rd webcam */
   1466		p = video_device_node_name(&gspca_dev->vdev);
   1467		l = strlen(p) - 1;
   1468		if (p[l] == '0')
   1469			reg_w(gspca_dev, 0x56, 0x1f);
   1470		else
   1471			reg_w(gspca_dev, 0x56, 0x17);
   1472	} else if ((sensor_id & 0xfff0) == 0x5620) {
   1473		sd->sensor = SENSOR_OV562x;
   1474		gspca_dev->cam.cam_mode = ov562x_mode;
   1475		gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
   1476
   1477		reg_w_array(gspca_dev, ov562x_init,
   1478				ARRAY_SIZE(ov562x_init));
   1479		sccb_w_array(gspca_dev, ov562x_init_2,
   1480				ARRAY_SIZE(ov562x_init_2));
   1481		reg_w(gspca_dev, 0xe0, 0x00);
   1482	} else if ((sensor_id & 0xfff0) == 0x3610) {
   1483		sd->sensor = SENSOR_OV361x;
   1484		gspca_dev->cam.cam_mode = ov361x_mode;
   1485		gspca_dev->cam.nmodes = ARRAY_SIZE(ov361x_mode);
   1486		reg_w(gspca_dev, 0xe7, 0x3a);
   1487		reg_w(gspca_dev, 0xf1, 0x60);
   1488		sccb_write(gspca_dev, 0x12, 0x80);
   1489	} else {
   1490		pr_err("Unknown sensor %04x", sensor_id);
   1491		return -EINVAL;
   1492	}
   1493
   1494	return gspca_dev->usb_err;
   1495}
   1496
   1497static int sd_start_ov361x(struct gspca_dev *gspca_dev)
   1498{
   1499	sccb_write(gspca_dev, 0x12, 0x80);
   1500	msleep(20);
   1501	switch (gspca_dev->curr_mode % (ov361x_last)) {
   1502	case ov361x_2048:
   1503		reg_w_array(gspca_dev, ov361x_bridge_start_2048,
   1504			    ARRAY_SIZE(ov361x_bridge_start_2048));
   1505		sccb_w_array(gspca_dev, ov361x_start_2048,
   1506			     ARRAY_SIZE(ov361x_start_2048));
   1507		break;
   1508	case ov361x_1600:
   1509		reg_w_array(gspca_dev, ov361x_bridge_start_1600,
   1510			    ARRAY_SIZE(ov361x_bridge_start_1600));
   1511		sccb_w_array(gspca_dev, ov361x_start_1600,
   1512			     ARRAY_SIZE(ov361x_start_1600));
   1513		break;
   1514	case ov361x_1024:
   1515		reg_w_array(gspca_dev, ov361x_bridge_start_1024,
   1516			    ARRAY_SIZE(ov361x_bridge_start_1024));
   1517		sccb_w_array(gspca_dev, ov361x_start_1024,
   1518			     ARRAY_SIZE(ov361x_start_1024));
   1519		break;
   1520	case ov361x_640:
   1521		reg_w_array(gspca_dev, ov361x_bridge_start_640,
   1522			    ARRAY_SIZE(ov361x_bridge_start_640));
   1523		sccb_w_array(gspca_dev, ov361x_start_640,
   1524			     ARRAY_SIZE(ov361x_start_640));
   1525		break;
   1526	case ov361x_320:
   1527		reg_w_array(gspca_dev, ov361x_bridge_start_320,
   1528			    ARRAY_SIZE(ov361x_bridge_start_320));
   1529		sccb_w_array(gspca_dev, ov361x_start_320,
   1530			     ARRAY_SIZE(ov361x_start_320));
   1531		break;
   1532	case ov361x_160:
   1533		reg_w_array(gspca_dev, ov361x_bridge_start_160,
   1534			    ARRAY_SIZE(ov361x_bridge_start_160));
   1535		sccb_w_array(gspca_dev, ov361x_start_160,
   1536			     ARRAY_SIZE(ov361x_start_160));
   1537		break;
   1538	}
   1539	reg_w(gspca_dev, 0xe0, 0x00); /* start transfer */
   1540
   1541	return gspca_dev->usb_err;
   1542}
   1543
   1544static int sd_start(struct gspca_dev *gspca_dev)
   1545{
   1546	struct sd *sd = (struct sd *) gspca_dev;
   1547
   1548	if (sd->sensor == SENSOR_OV971x)
   1549		return gspca_dev->usb_err;
   1550	if (sd->sensor == SENSOR_OV562x)
   1551		return gspca_dev->usb_err;
   1552	if (sd->sensor == SENSOR_OV361x)
   1553		return sd_start_ov361x(gspca_dev);
   1554
   1555	switch (gspca_dev->curr_mode) {
   1556	case QVGA_MODE:			/* 320x240 */
   1557		sccb_w_array(gspca_dev, ov965x_start_1_vga,
   1558				ARRAY_SIZE(ov965x_start_1_vga));
   1559		reg_w_array(gspca_dev, bridge_start_qvga,
   1560				ARRAY_SIZE(bridge_start_qvga));
   1561		sccb_w_array(gspca_dev, ov965x_start_2_qvga,
   1562				ARRAY_SIZE(ov965x_start_2_qvga));
   1563		break;
   1564	case VGA_MODE:			/* 640x480 */
   1565		sccb_w_array(gspca_dev, ov965x_start_1_vga,
   1566				ARRAY_SIZE(ov965x_start_1_vga));
   1567		reg_w_array(gspca_dev, bridge_start_vga,
   1568				ARRAY_SIZE(bridge_start_vga));
   1569		sccb_w_array(gspca_dev, ov965x_start_2_vga,
   1570				ARRAY_SIZE(ov965x_start_2_vga));
   1571		break;
   1572	case SVGA_MODE:			/* 800x600 */
   1573		sccb_w_array(gspca_dev, ov965x_start_1_svga,
   1574				ARRAY_SIZE(ov965x_start_1_svga));
   1575		reg_w_array(gspca_dev, bridge_start_svga,
   1576				ARRAY_SIZE(bridge_start_svga));
   1577		sccb_w_array(gspca_dev, ov965x_start_2_svga,
   1578				ARRAY_SIZE(ov965x_start_2_svga));
   1579		break;
   1580	case XGA_MODE:			/* 1024x768 */
   1581		sccb_w_array(gspca_dev, ov965x_start_1_xga,
   1582				ARRAY_SIZE(ov965x_start_1_xga));
   1583		reg_w_array(gspca_dev, bridge_start_xga,
   1584				ARRAY_SIZE(bridge_start_xga));
   1585		sccb_w_array(gspca_dev, ov965x_start_2_svga,
   1586				ARRAY_SIZE(ov965x_start_2_svga));
   1587		break;
   1588	default:
   1589/*	case SXGA_MODE:			 * 1280x1024 */
   1590		sccb_w_array(gspca_dev, ov965x_start_1_sxga,
   1591				ARRAY_SIZE(ov965x_start_1_sxga));
   1592		reg_w_array(gspca_dev, bridge_start_sxga,
   1593				ARRAY_SIZE(bridge_start_sxga));
   1594		sccb_w_array(gspca_dev, ov965x_start_2_sxga,
   1595				ARRAY_SIZE(ov965x_start_2_sxga));
   1596		break;
   1597	}
   1598
   1599	reg_w(gspca_dev, 0xe0, 0x00);
   1600	reg_w(gspca_dev, 0xe0, 0x00);
   1601	set_led(gspca_dev, 1);
   1602	return gspca_dev->usb_err;
   1603}
   1604
   1605static void sd_stopN(struct gspca_dev *gspca_dev)
   1606{
   1607	if (((struct sd *)gspca_dev)->sensor == SENSOR_OV361x) {
   1608		reg_w(gspca_dev, 0xe0, 0x01); /* stop transfer */
   1609		/* reg_w(gspca_dev, 0x31, 0x09); */
   1610		return;
   1611	}
   1612	reg_w(gspca_dev, 0xe0, 0x01);
   1613	set_led(gspca_dev, 0);
   1614	reg_w(gspca_dev, 0xe0, 0x00);
   1615}
   1616
   1617/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
   1618#define UVC_STREAM_EOH	(1 << 7)
   1619#define UVC_STREAM_ERR	(1 << 6)
   1620#define UVC_STREAM_STI	(1 << 5)
   1621#define UVC_STREAM_RES	(1 << 4)
   1622#define UVC_STREAM_SCR	(1 << 3)
   1623#define UVC_STREAM_PTS	(1 << 2)
   1624#define UVC_STREAM_EOF	(1 << 1)
   1625#define UVC_STREAM_FID	(1 << 0)
   1626
   1627static void sd_pkt_scan(struct gspca_dev *gspca_dev,
   1628			u8 *data, int len)
   1629{
   1630	struct sd *sd = (struct sd *) gspca_dev;
   1631	__u32 this_pts;
   1632	u8 this_fid;
   1633	int remaining_len = len;
   1634	int payload_len;
   1635
   1636	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
   1637	do {
   1638		len = min(remaining_len, payload_len);
   1639
   1640		/* Payloads are prefixed with a UVC-style header.  We
   1641		   consider a frame to start when the FID toggles, or the PTS
   1642		   changes.  A frame ends when EOF is set, and we've received
   1643		   the correct number of bytes. */
   1644
   1645		/* Verify UVC header.  Header length is always 12 */
   1646		if (data[0] != 12 || len < 12) {
   1647			gspca_dbg(gspca_dev, D_PACK, "bad header\n");
   1648			goto discard;
   1649		}
   1650
   1651		/* Check errors */
   1652		if (data[1] & UVC_STREAM_ERR) {
   1653			gspca_dbg(gspca_dev, D_PACK, "payload error\n");
   1654			goto discard;
   1655		}
   1656
   1657		/* Extract PTS and FID */
   1658		if (!(data[1] & UVC_STREAM_PTS)) {
   1659			gspca_dbg(gspca_dev, D_PACK, "PTS not present\n");
   1660			goto discard;
   1661		}
   1662		this_pts = (data[5] << 24) | (data[4] << 16)
   1663						| (data[3] << 8) | data[2];
   1664		this_fid = data[1] & UVC_STREAM_FID;
   1665
   1666		/* If PTS or FID has changed, start a new frame. */
   1667		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
   1668			if (gspca_dev->last_packet_type == INTER_PACKET)
   1669				gspca_frame_add(gspca_dev, LAST_PACKET,
   1670						NULL, 0);
   1671			sd->last_pts = this_pts;
   1672			sd->last_fid = this_fid;
   1673			gspca_frame_add(gspca_dev, FIRST_PACKET,
   1674					data + 12, len - 12);
   1675		/* If this packet is marked as EOF, end the frame */
   1676		} else if (data[1] & UVC_STREAM_EOF) {
   1677			sd->last_pts = 0;
   1678			gspca_frame_add(gspca_dev, LAST_PACKET,
   1679					data + 12, len - 12);
   1680		} else {
   1681
   1682			/* Add the data from this payload */
   1683			gspca_frame_add(gspca_dev, INTER_PACKET,
   1684					data + 12, len - 12);
   1685		}
   1686
   1687		/* Done this payload */
   1688		goto scan_next;
   1689
   1690discard:
   1691		/* Discard data until a new frame starts. */
   1692		gspca_dev->last_packet_type = DISCARD_PACKET;
   1693
   1694scan_next:
   1695		remaining_len -= len;
   1696		data += len;
   1697	} while (remaining_len > 0);
   1698}
   1699
   1700static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
   1701{
   1702	struct gspca_dev *gspca_dev =
   1703		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
   1704
   1705	gspca_dev->usb_err = 0;
   1706
   1707	if (!gspca_dev->streaming)
   1708		return 0;
   1709
   1710	switch (ctrl->id) {
   1711	case V4L2_CID_BRIGHTNESS:
   1712		setbrightness(gspca_dev, ctrl->val);
   1713		break;
   1714	case V4L2_CID_CONTRAST:
   1715		setcontrast(gspca_dev, ctrl->val);
   1716		break;
   1717	case V4L2_CID_SATURATION:
   1718		setsatur(gspca_dev, ctrl->val);
   1719		break;
   1720	case V4L2_CID_POWER_LINE_FREQUENCY:
   1721		setlightfreq(gspca_dev, ctrl->val);
   1722		break;
   1723	case V4L2_CID_SHARPNESS:
   1724		setsharpness(gspca_dev, ctrl->val);
   1725		break;
   1726	case V4L2_CID_AUTOGAIN:
   1727		if (ctrl->is_new)
   1728			setautogain(gspca_dev, ctrl->val);
   1729		if (!ctrl->val && gspca_dev->exposure->is_new)
   1730			setexposure(gspca_dev, gspca_dev->exposure->val);
   1731		break;
   1732	}
   1733	return gspca_dev->usb_err;
   1734}
   1735
   1736static const struct v4l2_ctrl_ops sd_ctrl_ops = {
   1737	.s_ctrl = sd_s_ctrl,
   1738};
   1739
   1740static int sd_init_controls(struct gspca_dev *gspca_dev)
   1741{
   1742	struct sd *sd = (struct sd *)gspca_dev;
   1743	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
   1744
   1745	if (sd->sensor == SENSOR_OV971x)
   1746		return 0;
   1747	if (sd->sensor == SENSOR_OV361x)
   1748		return 0;
   1749	gspca_dev->vdev.ctrl_handler = hdl;
   1750	v4l2_ctrl_handler_init(hdl, 7);
   1751	if (sd->sensor == SENSOR_OV562x) {
   1752		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1753			V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
   1754	} else {
   1755		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1756			V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
   1757		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1758			V4L2_CID_CONTRAST, 0, 15, 1, 3);
   1759		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1760			V4L2_CID_SATURATION, 0, 4, 1, 2);
   1761		/* -1 = auto */
   1762		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1763			V4L2_CID_SHARPNESS, -1, 4, 1, -1);
   1764		gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1765			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
   1766		gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
   1767			V4L2_CID_EXPOSURE, 0, 3, 1, 0);
   1768		v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
   1769			V4L2_CID_POWER_LINE_FREQUENCY,
   1770			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
   1771		v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
   1772	}
   1773
   1774	if (hdl->error) {
   1775		pr_err("Could not initialize controls\n");
   1776		return hdl->error;
   1777	}
   1778	return 0;
   1779}
   1780
   1781/* sub-driver description */
   1782static const struct sd_desc sd_desc = {
   1783	.name     = MODULE_NAME,
   1784	.config   = sd_config,
   1785	.init     = sd_init,
   1786	.init_controls = sd_init_controls,
   1787	.start    = sd_start,
   1788	.stopN    = sd_stopN,
   1789	.pkt_scan = sd_pkt_scan,
   1790};
   1791
   1792/* -- module initialisation -- */
   1793static const struct usb_device_id device_table[] = {
   1794	{USB_DEVICE(0x05a9, 0x8065)},
   1795	{USB_DEVICE(0x06f8, 0x3003)},
   1796	{USB_DEVICE(0x05a9, 0x1550)},
   1797	{}
   1798};
   1799
   1800MODULE_DEVICE_TABLE(usb, device_table);
   1801
   1802/* -- device connect -- */
   1803static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
   1804{
   1805	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
   1806				THIS_MODULE);
   1807}
   1808
   1809static struct usb_driver sd_driver = {
   1810	.name       = MODULE_NAME,
   1811	.id_table   = device_table,
   1812	.probe      = sd_probe,
   1813	.disconnect = gspca_disconnect,
   1814#ifdef CONFIG_PM
   1815	.suspend    = gspca_suspend,
   1816	.resume     = gspca_resume,
   1817	.reset_resume = gspca_resume,
   1818#endif
   1819};
   1820
   1821module_usb_driver(sd_driver);