File Index
Files and directories
Sign in
FILE

ov534_9.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/usb/gspca/ov534_9.c C
   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);
~/ Read-only file preview.