PageRenderTime 142ms CodeModel.GetById 18ms app.highlight 117ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/video/gspca/ov534.c

https://bitbucket.org/ndreys/linux-sunxi
C | 1546 lines | 1320 code | 140 blank | 86 comment | 100 complexity | c1044cf286dd1061b1edeef6e02bc877 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   1/*
   2 * ov534-ov7xxx gspca driver
   3 *
   4 * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
   5 * Copyright (C) 2008 Jim Paris <jim@jtan.com>
   6 * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
   7 *
   8 * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
   9 * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
  10 * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
  11 *
  12 * PS3 Eye camera enhanced by Richard Kaswy http://kaswy.free.fr
  13 * PS3 Eye camera - brightness, contrast, awb, agc, aec controls
  14 *                  added by Max Thrun <bear24rw@gmail.com>
  15 *
  16 * This program is free software; you can redistribute it and/or modify
  17 * it under the terms of the GNU General Public License as published by
  18 * the Free Software Foundation; either version 2 of the License, or
  19 * any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29 */
  30
  31#define MODULE_NAME "ov534"
  32
  33#include "gspca.h"
  34
  35#define OV534_REG_ADDRESS	0xf1	/* sensor address */
  36#define OV534_REG_SUBADDR	0xf2
  37#define OV534_REG_WRITE		0xf3
  38#define OV534_REG_READ		0xf4
  39#define OV534_REG_OPERATION	0xf5
  40#define OV534_REG_STATUS	0xf6
  41
  42#define OV534_OP_WRITE_3	0x37
  43#define OV534_OP_WRITE_2	0x33
  44#define OV534_OP_READ_2		0xf9
  45
  46#define CTRL_TIMEOUT 500
  47
  48MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
  49MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
  50MODULE_LICENSE("GPL");
  51
  52/* controls */
  53enum e_ctrl {
  54	BRIGHTNESS,
  55	CONTRAST,
  56	GAIN,
  57	EXPOSURE,
  58	AGC,
  59	AWB,
  60	AEC,
  61	SHARPNESS,
  62	HFLIP,
  63	VFLIP,
  64	COLORS,
  65	LIGHTFREQ,
  66	NCTRLS		/* number of controls */
  67};
  68
  69/* specific webcam descriptor */
  70struct sd {
  71	struct gspca_dev gspca_dev;	/* !! must be the first item */
  72
  73	struct gspca_ctrl ctrls[NCTRLS];
  74
  75	__u32 last_pts;
  76	u16 last_fid;
  77	u8 frame_rate;
  78
  79	u8 sensor;
  80};
  81enum sensors {
  82	SENSOR_OV767x,
  83	SENSOR_OV772x,
  84	NSENSORS
  85};
  86
  87/* V4L2 controls supported by the driver */
  88static void setbrightness(struct gspca_dev *gspca_dev);
  89static void setcontrast(struct gspca_dev *gspca_dev);
  90static void setgain(struct gspca_dev *gspca_dev);
  91static void setexposure(struct gspca_dev *gspca_dev);
  92static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val);
  93static void setawb(struct gspca_dev *gspca_dev);
  94static void setaec(struct gspca_dev *gspca_dev);
  95static void setsharpness(struct gspca_dev *gspca_dev);
  96static void sethvflip(struct gspca_dev *gspca_dev);
  97static void setcolors(struct gspca_dev *gspca_dev);
  98static void setlightfreq(struct gspca_dev *gspca_dev);
  99
 100static int sd_start(struct gspca_dev *gspca_dev);
 101static void sd_stopN(struct gspca_dev *gspca_dev);
 102
 103static const struct ctrl sd_ctrls[] = {
 104[BRIGHTNESS] = {
 105		{
 106			.id      = V4L2_CID_BRIGHTNESS,
 107			.type    = V4L2_CTRL_TYPE_INTEGER,
 108			.name    = "Brightness",
 109			.minimum = 0,
 110			.maximum = 255,
 111			.step    = 1,
 112			.default_value = 0,
 113		},
 114		.set_control = setbrightness
 115	},
 116[CONTRAST] = {
 117		{
 118			.id      = V4L2_CID_CONTRAST,
 119			.type    = V4L2_CTRL_TYPE_INTEGER,
 120			.name    = "Contrast",
 121			.minimum = 0,
 122			.maximum = 255,
 123			.step    = 1,
 124			.default_value = 32,
 125		},
 126		.set_control = setcontrast
 127	},
 128[GAIN] = {
 129		{
 130			.id      = V4L2_CID_GAIN,
 131			.type    = V4L2_CTRL_TYPE_INTEGER,
 132			.name    = "Main Gain",
 133			.minimum = 0,
 134			.maximum = 63,
 135			.step    = 1,
 136			.default_value = 20,
 137		},
 138		.set_control = setgain
 139	},
 140[EXPOSURE] = {
 141		{
 142			.id      = V4L2_CID_EXPOSURE,
 143			.type    = V4L2_CTRL_TYPE_INTEGER,
 144			.name    = "Exposure",
 145			.minimum = 0,
 146			.maximum = 255,
 147			.step    = 1,
 148			.default_value = 120,
 149		},
 150		.set_control = setexposure
 151	},
 152[AGC] = {
 153		{
 154			.id      = V4L2_CID_AUTOGAIN,
 155			.type    = V4L2_CTRL_TYPE_BOOLEAN,
 156			.name    = "Auto Gain",
 157			.minimum = 0,
 158			.maximum = 1,
 159			.step    = 1,
 160			.default_value = 1,
 161		},
 162		.set = sd_setagc
 163	},
 164[AWB] = {
 165		{
 166			.id      = V4L2_CID_AUTO_WHITE_BALANCE,
 167			.type    = V4L2_CTRL_TYPE_BOOLEAN,
 168			.name    = "Auto White Balance",
 169			.minimum = 0,
 170			.maximum = 1,
 171			.step    = 1,
 172			.default_value = 1,
 173		},
 174		.set_control = setawb
 175	},
 176[AEC] = {
 177		{
 178			.id      = V4L2_CID_EXPOSURE_AUTO,
 179			.type    = V4L2_CTRL_TYPE_BOOLEAN,
 180			.name    = "Auto Exposure",
 181			.minimum = 0,
 182			.maximum = 1,
 183			.step    = 1,
 184			.default_value = 1,
 185		},
 186		.set_control = setaec
 187	},
 188[SHARPNESS] = {
 189		{
 190			.id      = V4L2_CID_SHARPNESS,
 191			.type    = V4L2_CTRL_TYPE_INTEGER,
 192			.name    = "Sharpness",
 193			.minimum = 0,
 194			.maximum = 63,
 195			.step    = 1,
 196			.default_value = 0,
 197		},
 198		.set_control = setsharpness
 199	},
 200[HFLIP] = {
 201		{
 202			.id      = V4L2_CID_HFLIP,
 203			.type    = V4L2_CTRL_TYPE_BOOLEAN,
 204			.name    = "HFlip",
 205			.minimum = 0,
 206			.maximum = 1,
 207			.step    = 1,
 208			.default_value = 0,
 209		},
 210		.set_control = sethvflip
 211	},
 212[VFLIP] = {
 213		{
 214			.id      = V4L2_CID_VFLIP,
 215			.type    = V4L2_CTRL_TYPE_BOOLEAN,
 216			.name    = "VFlip",
 217			.minimum = 0,
 218			.maximum = 1,
 219			.step    = 1,
 220			.default_value = 0,
 221		},
 222		.set_control = sethvflip
 223	},
 224[COLORS] = {
 225		{
 226			.id      = V4L2_CID_SATURATION,
 227			.type    = V4L2_CTRL_TYPE_INTEGER,
 228			.name    = "Saturation",
 229			.minimum = 0,
 230			.maximum = 6,
 231			.step    = 1,
 232			.default_value = 3,
 233		},
 234		.set_control = setcolors
 235	},
 236[LIGHTFREQ] = {
 237		{
 238			.id      = V4L2_CID_POWER_LINE_FREQUENCY,
 239			.type    = V4L2_CTRL_TYPE_MENU,
 240			.name    = "Light Frequency Filter",
 241			.minimum = 0,
 242			.maximum = 1,
 243			.step    = 1,
 244			.default_value = 0,
 245		},
 246		.set_control = setlightfreq
 247	},
 248};
 249
 250static const struct v4l2_pix_format ov772x_mode[] = {
 251	{320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 252	 .bytesperline = 320 * 2,
 253	 .sizeimage = 320 * 240 * 2,
 254	 .colorspace = V4L2_COLORSPACE_SRGB,
 255	 .priv = 1},
 256	{640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
 257	 .bytesperline = 640 * 2,
 258	 .sizeimage = 640 * 480 * 2,
 259	 .colorspace = V4L2_COLORSPACE_SRGB,
 260	 .priv = 0},
 261};
 262static const struct v4l2_pix_format ov767x_mode[] = {
 263	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 264		.bytesperline = 320,
 265		.sizeimage = 320 * 240 * 3 / 8 + 590,
 266		.colorspace = V4L2_COLORSPACE_JPEG},
 267	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 268		.bytesperline = 640,
 269		.sizeimage = 640 * 480 * 3 / 8 + 590,
 270		.colorspace = V4L2_COLORSPACE_JPEG},
 271};
 272
 273static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
 274static const u8 vga_rates[] = {60, 50, 40, 30, 15};
 275
 276static const struct framerates ov772x_framerates[] = {
 277	{ /* 320x240 */
 278		.rates = qvga_rates,
 279		.nrates = ARRAY_SIZE(qvga_rates),
 280	},
 281	{ /* 640x480 */
 282		.rates = vga_rates,
 283		.nrates = ARRAY_SIZE(vga_rates),
 284	},
 285};
 286
 287struct reg_array {
 288	const u8 (*val)[2];
 289	int len;
 290};
 291
 292static const u8 bridge_init_767x[][2] = {
 293/* comments from the ms-win file apollo7670.set */
 294/* str1 */
 295	{0xf1, 0x42},
 296	{0x88, 0xf8},
 297	{0x89, 0xff},
 298	{0x76, 0x03},
 299	{0x92, 0x03},
 300	{0x95, 0x10},
 301	{0xe2, 0x00},
 302	{0xe7, 0x3e},
 303	{0x8d, 0x1c},
 304	{0x8e, 0x00},
 305	{0x8f, 0x00},
 306	{0x1f, 0x00},
 307	{0xc3, 0xf9},
 308	{0x89, 0xff},
 309	{0x88, 0xf8},
 310	{0x76, 0x03},
 311	{0x92, 0x01},
 312	{0x93, 0x18},
 313	{0x1c, 0x00},
 314	{0x1d, 0x48},
 315	{0x1d, 0x00},
 316	{0x1d, 0xff},
 317	{0x1d, 0x02},
 318	{0x1d, 0x58},
 319	{0x1d, 0x00},
 320	{0x1c, 0x0a},
 321	{0x1d, 0x0a},
 322	{0x1d, 0x0e},
 323	{0xc0, 0x50},	/* HSize 640 */
 324	{0xc1, 0x3c},	/* VSize 480 */
 325	{0x34, 0x05},	/* enable Audio Suspend mode */
 326	{0xc2, 0x0c},	/* Input YUV */
 327	{0xc3, 0xf9},	/* enable PRE */
 328	{0x34, 0x05},	/* enable Audio Suspend mode */
 329	{0xe7, 0x2e},	/* this solves failure of "SuspendResumeTest" */
 330	{0x31, 0xf9},	/* enable 1.8V Suspend */
 331	{0x35, 0x02},	/* turn on JPEG */
 332	{0xd9, 0x10},
 333	{0x25, 0x42},	/* GPIO[8]:Input */
 334	{0x94, 0x11},	/* If the default setting is loaded when
 335			 * system boots up, this flag is closed here */
 336};
 337static const u8 sensor_init_767x[][2] = {
 338	{0x12, 0x80},
 339	{0x11, 0x03},
 340	{0x3a, 0x04},
 341	{0x12, 0x00},
 342	{0x17, 0x13},
 343	{0x18, 0x01},
 344	{0x32, 0xb6},
 345	{0x19, 0x02},
 346	{0x1a, 0x7a},
 347	{0x03, 0x0a},
 348	{0x0c, 0x00},
 349	{0x3e, 0x00},
 350	{0x70, 0x3a},
 351	{0x71, 0x35},
 352	{0x72, 0x11},
 353	{0x73, 0xf0},
 354	{0xa2, 0x02},
 355	{0x7a, 0x2a},	/* set Gamma=1.6 below */
 356	{0x7b, 0x12},
 357	{0x7c, 0x1d},
 358	{0x7d, 0x2d},
 359	{0x7e, 0x45},
 360	{0x7f, 0x50},
 361	{0x80, 0x59},
 362	{0x81, 0x62},
 363	{0x82, 0x6b},
 364	{0x83, 0x73},
 365	{0x84, 0x7b},
 366	{0x85, 0x8a},
 367	{0x86, 0x98},
 368	{0x87, 0xb2},
 369	{0x88, 0xca},
 370	{0x89, 0xe0},
 371	{0x13, 0xe0},
 372	{0x00, 0x00},
 373	{0x10, 0x00},
 374	{0x0d, 0x40},
 375	{0x14, 0x38},	/* gain max 16x */
 376	{0xa5, 0x05},
 377	{0xab, 0x07},
 378	{0x24, 0x95},
 379	{0x25, 0x33},
 380	{0x26, 0xe3},
 381	{0x9f, 0x78},
 382	{0xa0, 0x68},
 383	{0xa1, 0x03},
 384	{0xa6, 0xd8},
 385	{0xa7, 0xd8},
 386	{0xa8, 0xf0},
 387	{0xa9, 0x90},
 388	{0xaa, 0x94},
 389	{0x13, 0xe5},
 390	{0x0e, 0x61},
 391	{0x0f, 0x4b},
 392	{0x16, 0x02},
 393	{0x21, 0x02},
 394	{0x22, 0x91},
 395	{0x29, 0x07},
 396	{0x33, 0x0b},
 397	{0x35, 0x0b},
 398	{0x37, 0x1d},
 399	{0x38, 0x71},
 400	{0x39, 0x2a},
 401	{0x3c, 0x78},
 402	{0x4d, 0x40},
 403	{0x4e, 0x20},
 404	{0x69, 0x00},
 405	{0x6b, 0x4a},
 406	{0x74, 0x10},
 407	{0x8d, 0x4f},
 408	{0x8e, 0x00},
 409	{0x8f, 0x00},
 410	{0x90, 0x00},
 411	{0x91, 0x00},
 412	{0x96, 0x00},
 413	{0x9a, 0x80},
 414	{0xb0, 0x84},
 415	{0xb1, 0x0c},
 416	{0xb2, 0x0e},
 417	{0xb3, 0x82},
 418	{0xb8, 0x0a},
 419	{0x43, 0x0a},
 420	{0x44, 0xf0},
 421	{0x45, 0x34},
 422	{0x46, 0x58},
 423	{0x47, 0x28},
 424	{0x48, 0x3a},
 425	{0x59, 0x88},
 426	{0x5a, 0x88},
 427	{0x5b, 0x44},
 428	{0x5c, 0x67},
 429	{0x5d, 0x49},
 430	{0x5e, 0x0e},
 431	{0x6c, 0x0a},
 432	{0x6d, 0x55},
 433	{0x6e, 0x11},
 434	{0x6f, 0x9f},
 435	{0x6a, 0x40},
 436	{0x01, 0x40},
 437	{0x02, 0x40},
 438	{0x13, 0xe7},
 439	{0x4f, 0x80},
 440	{0x50, 0x80},
 441	{0x51, 0x00},
 442	{0x52, 0x22},
 443	{0x53, 0x5e},
 444	{0x54, 0x80},
 445	{0x58, 0x9e},
 446	{0x41, 0x08},
 447	{0x3f, 0x00},
 448	{0x75, 0x04},
 449	{0x76, 0xe1},
 450	{0x4c, 0x00},
 451	{0x77, 0x01},
 452	{0x3d, 0xc2},
 453	{0x4b, 0x09},
 454	{0xc9, 0x60},
 455	{0x41, 0x38},	/* jfm: auto sharpness + auto de-noise  */
 456	{0x56, 0x40},
 457	{0x34, 0x11},
 458	{0x3b, 0xc2},
 459	{0xa4, 0x8a},	/* Night mode trigger point */
 460	{0x96, 0x00},
 461	{0x97, 0x30},
 462	{0x98, 0x20},
 463	{0x99, 0x20},
 464	{0x9a, 0x84},
 465	{0x9b, 0x29},
 466	{0x9c, 0x03},
 467	{0x9d, 0x4c},
 468	{0x9e, 0x3f},
 469	{0x78, 0x04},
 470	{0x79, 0x01},
 471	{0xc8, 0xf0},
 472	{0x79, 0x0f},
 473	{0xc8, 0x00},
 474	{0x79, 0x10},
 475	{0xc8, 0x7e},
 476	{0x79, 0x0a},
 477	{0xc8, 0x80},
 478	{0x79, 0x0b},
 479	{0xc8, 0x01},
 480	{0x79, 0x0c},
 481	{0xc8, 0x0f},
 482	{0x79, 0x0d},
 483	{0xc8, 0x20},
 484	{0x79, 0x09},
 485	{0xc8, 0x80},
 486	{0x79, 0x02},
 487	{0xc8, 0xc0},
 488	{0x79, 0x03},
 489	{0xc8, 0x20},
 490	{0x79, 0x26},
 491};
 492static const u8 bridge_start_vga_767x[][2] = {
 493/* str59 JPG */
 494	{0x94, 0xaa},
 495	{0xf1, 0x42},
 496	{0xe5, 0x04},
 497	{0xc0, 0x50},
 498	{0xc1, 0x3c},
 499	{0xc2, 0x0c},
 500	{0x35, 0x02},	/* turn on JPEG */
 501	{0xd9, 0x10},
 502	{0xda, 0x00},	/* for higher clock rate(30fps) */
 503	{0x34, 0x05},	/* enable Audio Suspend mode */
 504	{0xc3, 0xf9},	/* enable PRE */
 505	{0x8c, 0x00},	/* CIF VSize LSB[2:0] */
 506	{0x8d, 0x1c},	/* output YUV */
 507/*	{0x34, 0x05},	 * enable Audio Suspend mode (?) */
 508	{0x50, 0x00},	/* H/V divider=0 */
 509	{0x51, 0xa0},	/* input H=640/4 */
 510	{0x52, 0x3c},	/* input V=480/4 */
 511	{0x53, 0x00},	/* offset X=0 */
 512	{0x54, 0x00},	/* offset Y=0 */
 513	{0x55, 0x00},	/* H/V size[8]=0 */
 514	{0x57, 0x00},	/* H-size[9]=0 */
 515	{0x5c, 0x00},	/* output size[9:8]=0 */
 516	{0x5a, 0xa0},	/* output H=640/4 */
 517	{0x5b, 0x78},	/* output V=480/4 */
 518	{0x1c, 0x0a},
 519	{0x1d, 0x0a},
 520	{0x94, 0x11},
 521};
 522static const u8 sensor_start_vga_767x[][2] = {
 523	{0x11, 0x01},
 524	{0x1e, 0x04},
 525	{0x19, 0x02},
 526	{0x1a, 0x7a},
 527};
 528static const u8 bridge_start_qvga_767x[][2] = {
 529/* str86 JPG */
 530	{0x94, 0xaa},
 531	{0xf1, 0x42},
 532	{0xe5, 0x04},
 533	{0xc0, 0x80},
 534	{0xc1, 0x60},
 535	{0xc2, 0x0c},
 536	{0x35, 0x02},	/* turn on JPEG */
 537	{0xd9, 0x10},
 538	{0xc0, 0x50},	/* CIF HSize 640 */
 539	{0xc1, 0x3c},	/* CIF VSize 480 */
 540	{0x8c, 0x00},	/* CIF VSize LSB[2:0] */
 541	{0x8d, 0x1c},	/* output YUV */
 542	{0x34, 0x05},	/* enable Audio Suspend mode */
 543	{0xc2, 0x4c},	/* output YUV and Enable DCW */
 544	{0xc3, 0xf9},	/* enable PRE */
 545	{0x1c, 0x00},	/* indirect addressing */
 546	{0x1d, 0x48},	/* output YUV422 */
 547	{0x50, 0x89},	/* H/V divider=/2; plus DCW AVG */
 548	{0x51, 0xa0},	/* DCW input H=640/4 */
 549	{0x52, 0x78},	/* DCW input V=480/4 */
 550	{0x53, 0x00},	/* offset X=0 */
 551	{0x54, 0x00},	/* offset Y=0 */
 552	{0x55, 0x00},	/* H/V size[8]=0 */
 553	{0x57, 0x00},	/* H-size[9]=0 */
 554	{0x5c, 0x00},	/* DCW output size[9:8]=0 */
 555	{0x5a, 0x50},	/* DCW output H=320/4 */
 556	{0x5b, 0x3c},	/* DCW output V=240/4 */
 557	{0x1c, 0x0a},
 558	{0x1d, 0x0a},
 559	{0x94, 0x11},
 560};
 561static const u8 sensor_start_qvga_767x[][2] = {
 562	{0x11, 0x01},
 563	{0x1e, 0x04},
 564	{0x19, 0x02},
 565	{0x1a, 0x7a},
 566};
 567
 568static const u8 bridge_init_772x[][2] = {
 569	{ 0xc2, 0x0c },
 570	{ 0x88, 0xf8 },
 571	{ 0xc3, 0x69 },
 572	{ 0x89, 0xff },
 573	{ 0x76, 0x03 },
 574	{ 0x92, 0x01 },
 575	{ 0x93, 0x18 },
 576	{ 0x94, 0x10 },
 577	{ 0x95, 0x10 },
 578	{ 0xe2, 0x00 },
 579	{ 0xe7, 0x3e },
 580
 581	{ 0x96, 0x00 },
 582
 583	{ 0x97, 0x20 },
 584	{ 0x97, 0x20 },
 585	{ 0x97, 0x20 },
 586	{ 0x97, 0x0a },
 587	{ 0x97, 0x3f },
 588	{ 0x97, 0x4a },
 589	{ 0x97, 0x20 },
 590	{ 0x97, 0x15 },
 591	{ 0x97, 0x0b },
 592
 593	{ 0x8e, 0x40 },
 594	{ 0x1f, 0x81 },
 595	{ 0x34, 0x05 },
 596	{ 0xe3, 0x04 },
 597	{ 0x88, 0x00 },
 598	{ 0x89, 0x00 },
 599	{ 0x76, 0x00 },
 600	{ 0xe7, 0x2e },
 601	{ 0x31, 0xf9 },
 602	{ 0x25, 0x42 },
 603	{ 0x21, 0xf0 },
 604
 605	{ 0x1c, 0x00 },
 606	{ 0x1d, 0x40 },
 607	{ 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
 608	{ 0x1d, 0x00 }, /* payload size */
 609
 610	{ 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
 611	{ 0x1d, 0x58 }, /* frame size */
 612	{ 0x1d, 0x00 }, /* frame size */
 613
 614	{ 0x1c, 0x0a },
 615	{ 0x1d, 0x08 }, /* turn on UVC header */
 616	{ 0x1d, 0x0e }, /* .. */
 617
 618	{ 0x8d, 0x1c },
 619	{ 0x8e, 0x80 },
 620	{ 0xe5, 0x04 },
 621
 622	{ 0xc0, 0x50 },
 623	{ 0xc1, 0x3c },
 624	{ 0xc2, 0x0c },
 625};
 626static const u8 sensor_init_772x[][2] = {
 627	{ 0x12, 0x80 },
 628	{ 0x11, 0x01 },
 629/*fixme: better have a delay?*/
 630	{ 0x11, 0x01 },
 631	{ 0x11, 0x01 },
 632	{ 0x11, 0x01 },
 633	{ 0x11, 0x01 },
 634	{ 0x11, 0x01 },
 635	{ 0x11, 0x01 },
 636	{ 0x11, 0x01 },
 637	{ 0x11, 0x01 },
 638	{ 0x11, 0x01 },
 639	{ 0x11, 0x01 },
 640
 641	{ 0x3d, 0x03 },
 642	{ 0x17, 0x26 },
 643	{ 0x18, 0xa0 },
 644	{ 0x19, 0x07 },
 645	{ 0x1a, 0xf0 },
 646	{ 0x32, 0x00 },
 647	{ 0x29, 0xa0 },
 648	{ 0x2c, 0xf0 },
 649	{ 0x65, 0x20 },
 650	{ 0x11, 0x01 },
 651	{ 0x42, 0x7f },
 652	{ 0x63, 0xaa },		/* AWB - was e0 */
 653	{ 0x64, 0xff },
 654	{ 0x66, 0x00 },
 655	{ 0x13, 0xf0 },		/* com8 */
 656	{ 0x0d, 0x41 },
 657	{ 0x0f, 0xc5 },
 658	{ 0x14, 0x11 },
 659
 660	{ 0x22, 0x7f },
 661	{ 0x23, 0x03 },
 662	{ 0x24, 0x40 },
 663	{ 0x25, 0x30 },
 664	{ 0x26, 0xa1 },
 665	{ 0x2a, 0x00 },
 666	{ 0x2b, 0x00 },
 667	{ 0x6b, 0xaa },
 668	{ 0x13, 0xff },		/* AWB */
 669
 670	{ 0x90, 0x05 },
 671	{ 0x91, 0x01 },
 672	{ 0x92, 0x03 },
 673	{ 0x93, 0x00 },
 674	{ 0x94, 0x60 },
 675	{ 0x95, 0x3c },
 676	{ 0x96, 0x24 },
 677	{ 0x97, 0x1e },
 678	{ 0x98, 0x62 },
 679	{ 0x99, 0x80 },
 680	{ 0x9a, 0x1e },
 681	{ 0x9b, 0x08 },
 682	{ 0x9c, 0x20 },
 683	{ 0x9e, 0x81 },
 684
 685	{ 0xa6, 0x04 },
 686	{ 0x7e, 0x0c },
 687	{ 0x7f, 0x16 },
 688	{ 0x80, 0x2a },
 689	{ 0x81, 0x4e },
 690	{ 0x82, 0x61 },
 691	{ 0x83, 0x6f },
 692	{ 0x84, 0x7b },
 693	{ 0x85, 0x86 },
 694	{ 0x86, 0x8e },
 695	{ 0x87, 0x97 },
 696	{ 0x88, 0xa4 },
 697	{ 0x89, 0xaf },
 698	{ 0x8a, 0xc5 },
 699	{ 0x8b, 0xd7 },
 700	{ 0x8c, 0xe8 },
 701	{ 0x8d, 0x20 },
 702
 703	{ 0x0c, 0x90 },
 704
 705	{ 0x2b, 0x00 },
 706	{ 0x22, 0x7f },
 707	{ 0x23, 0x03 },
 708	{ 0x11, 0x01 },
 709	{ 0x0c, 0xd0 },
 710	{ 0x64, 0xff },
 711	{ 0x0d, 0x41 },
 712
 713	{ 0x14, 0x41 },
 714	{ 0x0e, 0xcd },
 715	{ 0xac, 0xbf },
 716	{ 0x8e, 0x00 },		/* De-noise threshold */
 717	{ 0x0c, 0xd0 }
 718};
 719static const u8 bridge_start_vga_772x[][2] = {
 720	{0x1c, 0x00},
 721	{0x1d, 0x40},
 722	{0x1d, 0x02},
 723	{0x1d, 0x00},
 724	{0x1d, 0x02},
 725	{0x1d, 0x58},
 726	{0x1d, 0x00},
 727	{0xc0, 0x50},
 728	{0xc1, 0x3c},
 729};
 730static const u8 sensor_start_vga_772x[][2] = {
 731	{0x12, 0x00},
 732	{0x17, 0x26},
 733	{0x18, 0xa0},
 734	{0x19, 0x07},
 735	{0x1a, 0xf0},
 736	{0x29, 0xa0},
 737	{0x2c, 0xf0},
 738	{0x65, 0x20},
 739};
 740static const u8 bridge_start_qvga_772x[][2] = {
 741	{0x1c, 0x00},
 742	{0x1d, 0x40},
 743	{0x1d, 0x02},
 744	{0x1d, 0x00},
 745	{0x1d, 0x01},
 746	{0x1d, 0x4b},
 747	{0x1d, 0x00},
 748	{0xc0, 0x28},
 749	{0xc1, 0x1e},
 750};
 751static const u8 sensor_start_qvga_772x[][2] = {
 752	{0x12, 0x40},
 753	{0x17, 0x3f},
 754	{0x18, 0x50},
 755	{0x19, 0x03},
 756	{0x1a, 0x78},
 757	{0x29, 0x50},
 758	{0x2c, 0x78},
 759	{0x65, 0x2f},
 760};
 761
 762static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
 763{
 764	struct usb_device *udev = gspca_dev->dev;
 765	int ret;
 766
 767	if (gspca_dev->usb_err < 0)
 768		return;
 769
 770	PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
 771	gspca_dev->usb_buf[0] = val;
 772	ret = usb_control_msg(udev,
 773			      usb_sndctrlpipe(udev, 0),
 774			      0x01,
 775			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 776			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 777	if (ret < 0) {
 778		err("write failed %d", ret);
 779		gspca_dev->usb_err = ret;
 780	}
 781}
 782
 783static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
 784{
 785	struct usb_device *udev = gspca_dev->dev;
 786	int ret;
 787
 788	if (gspca_dev->usb_err < 0)
 789		return 0;
 790	ret = usb_control_msg(udev,
 791			      usb_rcvctrlpipe(udev, 0),
 792			      0x01,
 793			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 794			      0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
 795	PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
 796	if (ret < 0) {
 797		err("read failed %d", ret);
 798		gspca_dev->usb_err = ret;
 799	}
 800	return gspca_dev->usb_buf[0];
 801}
 802
 803/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
 804 * (direction and output)? */
 805static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
 806{
 807	u8 data;
 808
 809	PDEBUG(D_CONF, "led status: %d", status);
 810
 811	data = ov534_reg_read(gspca_dev, 0x21);
 812	data |= 0x80;
 813	ov534_reg_write(gspca_dev, 0x21, data);
 814
 815	data = ov534_reg_read(gspca_dev, 0x23);
 816	if (status)
 817		data |= 0x80;
 818	else
 819		data &= ~0x80;
 820
 821	ov534_reg_write(gspca_dev, 0x23, data);
 822
 823	if (!status) {
 824		data = ov534_reg_read(gspca_dev, 0x21);
 825		data &= ~0x80;
 826		ov534_reg_write(gspca_dev, 0x21, data);
 827	}
 828}
 829
 830static int sccb_check_status(struct gspca_dev *gspca_dev)
 831{
 832	u8 data;
 833	int i;
 834
 835	for (i = 0; i < 5; i++) {
 836		data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
 837
 838		switch (data) {
 839		case 0x00:
 840			return 1;
 841		case 0x04:
 842			return 0;
 843		case 0x03:
 844			break;
 845		default:
 846			PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
 847			       data, i + 1);
 848		}
 849	}
 850	return 0;
 851}
 852
 853static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 854{
 855	PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
 856	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 857	ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
 858	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
 859
 860	if (!sccb_check_status(gspca_dev)) {
 861		err("sccb_reg_write failed");
 862		gspca_dev->usb_err = -EIO;
 863	}
 864}
 865
 866static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
 867{
 868	ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
 869	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
 870	if (!sccb_check_status(gspca_dev))
 871		err("sccb_reg_read failed 1");
 872
 873	ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
 874	if (!sccb_check_status(gspca_dev))
 875		err("sccb_reg_read failed 2");
 876
 877	return ov534_reg_read(gspca_dev, OV534_REG_READ);
 878}
 879
 880/* output a bridge sequence (reg - val) */
 881static void reg_w_array(struct gspca_dev *gspca_dev,
 882			const u8 (*data)[2], int len)
 883{
 884	while (--len >= 0) {
 885		ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
 886		data++;
 887	}
 888}
 889
 890/* output a sensor sequence (reg - val) */
 891static void sccb_w_array(struct gspca_dev *gspca_dev,
 892			const u8 (*data)[2], int len)
 893{
 894	while (--len >= 0) {
 895		if ((*data)[0] != 0xff) {
 896			sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
 897		} else {
 898			sccb_reg_read(gspca_dev, (*data)[1]);
 899			sccb_reg_write(gspca_dev, 0xff, 0x00);
 900		}
 901		data++;
 902	}
 903}
 904
 905/* ov772x specific controls */
 906static void set_frame_rate(struct gspca_dev *gspca_dev)
 907{
 908	struct sd *sd = (struct sd *) gspca_dev;
 909	int i;
 910	struct rate_s {
 911		u8 fps;
 912		u8 r11;
 913		u8 r0d;
 914		u8 re5;
 915	};
 916	const struct rate_s *r;
 917	static const struct rate_s rate_0[] = {	/* 640x480 */
 918		{60, 0x01, 0xc1, 0x04},
 919		{50, 0x01, 0x41, 0x02},
 920		{40, 0x02, 0xc1, 0x04},
 921		{30, 0x04, 0x81, 0x02},
 922		{15, 0x03, 0x41, 0x04},
 923	};
 924	static const struct rate_s rate_1[] = {	/* 320x240 */
 925		{125, 0x02, 0x81, 0x02},
 926		{100, 0x02, 0xc1, 0x04},
 927		{75, 0x03, 0xc1, 0x04},
 928		{60, 0x04, 0xc1, 0x04},
 929		{50, 0x02, 0x41, 0x04},
 930		{40, 0x03, 0x41, 0x04},
 931		{30, 0x04, 0x41, 0x04},
 932	};
 933
 934	if (sd->sensor != SENSOR_OV772x)
 935		return;
 936	if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
 937		r = rate_0;
 938		i = ARRAY_SIZE(rate_0);
 939	} else {
 940		r = rate_1;
 941		i = ARRAY_SIZE(rate_1);
 942	}
 943	while (--i > 0) {
 944		if (sd->frame_rate >= r->fps)
 945			break;
 946		r++;
 947	}
 948
 949	sccb_reg_write(gspca_dev, 0x11, r->r11);
 950	sccb_reg_write(gspca_dev, 0x0d, r->r0d);
 951	ov534_reg_write(gspca_dev, 0xe5, r->re5);
 952
 953	PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
 954}
 955
 956static void setbrightness(struct gspca_dev *gspca_dev)
 957{
 958	struct sd *sd = (struct sd *) gspca_dev;
 959	int val;
 960
 961	val = sd->ctrls[BRIGHTNESS].val;
 962	if (sd->sensor == SENSOR_OV767x) {
 963		if (val < 0)
 964			val = 0x80 - val;
 965		sccb_reg_write(gspca_dev, 0x55, val);	/* bright */
 966	} else {
 967		sccb_reg_write(gspca_dev, 0x9b, val);
 968	}
 969}
 970
 971static void setcontrast(struct gspca_dev *gspca_dev)
 972{
 973	struct sd *sd = (struct sd *) gspca_dev;
 974	u8 val;
 975
 976	val = sd->ctrls[CONTRAST].val;
 977	if (sd->sensor == SENSOR_OV767x)
 978		sccb_reg_write(gspca_dev, 0x56, val);	/* contras */
 979	else
 980		sccb_reg_write(gspca_dev, 0x9c, val);
 981}
 982
 983static void setgain(struct gspca_dev *gspca_dev)
 984{
 985	struct sd *sd = (struct sd *) gspca_dev;
 986	u8 val;
 987
 988	if (sd->ctrls[AGC].val)
 989		return;
 990
 991	val = sd->ctrls[GAIN].val;
 992	switch (val & 0x30) {
 993	case 0x00:
 994		val &= 0x0f;
 995		break;
 996	case 0x10:
 997		val &= 0x0f;
 998		val |= 0x30;
 999		break;
1000	case 0x20:
1001		val &= 0x0f;
1002		val |= 0x70;
1003		break;
1004	default:
1005/*	case 0x30: */
1006		val &= 0x0f;
1007		val |= 0xf0;
1008		break;
1009	}
1010	sccb_reg_write(gspca_dev, 0x00, val);
1011}
1012
1013static void setexposure(struct gspca_dev *gspca_dev)
1014{
1015	struct sd *sd = (struct sd *) gspca_dev;
1016	u8 val;
1017
1018	if (sd->ctrls[AEC].val)
1019		return;
1020
1021	val = sd->ctrls[EXPOSURE].val;
1022	if (sd->sensor == SENSOR_OV767x) {
1023
1024		/* set only aec[9:2] */
1025		sccb_reg_write(gspca_dev, 0x10, val);	/* aech */
1026	} else {
1027
1028		/* 'val' is one byte and represents half of the exposure value
1029		 * we are going to set into registers, a two bytes value:
1030		 *
1031		 *    MSB: ((u16) val << 1) >> 8   == val >> 7
1032		 *    LSB: ((u16) val << 1) & 0xff == val << 1
1033		 */
1034		sccb_reg_write(gspca_dev, 0x08, val >> 7);
1035		sccb_reg_write(gspca_dev, 0x10, val << 1);
1036	}
1037}
1038
1039static void setagc(struct gspca_dev *gspca_dev)
1040{
1041	struct sd *sd = (struct sd *) gspca_dev;
1042
1043	if (sd->ctrls[AGC].val) {
1044		sccb_reg_write(gspca_dev, 0x13,
1045				sccb_reg_read(gspca_dev, 0x13) | 0x04);
1046		sccb_reg_write(gspca_dev, 0x64,
1047				sccb_reg_read(gspca_dev, 0x64) | 0x03);
1048	} else {
1049		sccb_reg_write(gspca_dev, 0x13,
1050				sccb_reg_read(gspca_dev, 0x13) & ~0x04);
1051		sccb_reg_write(gspca_dev, 0x64,
1052				sccb_reg_read(gspca_dev, 0x64) & ~0x03);
1053
1054		setgain(gspca_dev);
1055	}
1056}
1057
1058static void setawb(struct gspca_dev *gspca_dev)
1059{
1060	struct sd *sd = (struct sd *) gspca_dev;
1061
1062	if (sd->ctrls[AWB].val) {
1063		sccb_reg_write(gspca_dev, 0x13,
1064				sccb_reg_read(gspca_dev, 0x13) | 0x02);
1065		if (sd->sensor == SENSOR_OV772x)
1066			sccb_reg_write(gspca_dev, 0x63,
1067				sccb_reg_read(gspca_dev, 0x63) | 0xc0);
1068	} else {
1069		sccb_reg_write(gspca_dev, 0x13,
1070				sccb_reg_read(gspca_dev, 0x13) & ~0x02);
1071		if (sd->sensor == SENSOR_OV772x)
1072			sccb_reg_write(gspca_dev, 0x63,
1073				sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
1074	}
1075}
1076
1077static void setaec(struct gspca_dev *gspca_dev)
1078{
1079	struct sd *sd = (struct sd *) gspca_dev;
1080	u8 data;
1081
1082	data = sd->sensor == SENSOR_OV767x ?
1083			0x05 :		/* agc + aec */
1084			0x01;		/* agc */
1085	if (sd->ctrls[AEC].val)
1086		sccb_reg_write(gspca_dev, 0x13,
1087				sccb_reg_read(gspca_dev, 0x13) | data);
1088	else {
1089		sccb_reg_write(gspca_dev, 0x13,
1090				sccb_reg_read(gspca_dev, 0x13) & ~data);
1091		if (sd->sensor == SENSOR_OV767x)
1092			sd->ctrls[EXPOSURE].val =
1093				sccb_reg_read(gspca_dev, 10);	/* aech */
1094		else
1095			setexposure(gspca_dev);
1096	}
1097}
1098
1099static void setsharpness(struct gspca_dev *gspca_dev)
1100{
1101	struct sd *sd = (struct sd *) gspca_dev;
1102	u8 val;
1103
1104	val = sd->ctrls[SHARPNESS].val;
1105	sccb_reg_write(gspca_dev, 0x91, val);	/* Auto de-noise threshold */
1106	sccb_reg_write(gspca_dev, 0x8e, val);	/* De-noise threshold */
1107}
1108
1109static void sethvflip(struct gspca_dev *gspca_dev)
1110{
1111	struct sd *sd = (struct sd *) gspca_dev;
1112	u8 val;
1113
1114	if (sd->sensor == SENSOR_OV767x) {
1115		val = sccb_reg_read(gspca_dev, 0x1e);	/* mvfp */
1116		val &= ~0x30;
1117		if (sd->ctrls[HFLIP].val)
1118			val |= 0x20;
1119		if (sd->ctrls[VFLIP].val)
1120			val |= 0x10;
1121		sccb_reg_write(gspca_dev, 0x1e, val);
1122	} else {
1123		val = sccb_reg_read(gspca_dev, 0x0c);
1124		val &= ~0xc0;
1125		if (sd->ctrls[HFLIP].val == 0)
1126			val |= 0x40;
1127		if (sd->ctrls[VFLIP].val == 0)
1128			val |= 0x80;
1129		sccb_reg_write(gspca_dev, 0x0c, val);
1130	}
1131}
1132
1133static void setcolors(struct gspca_dev *gspca_dev)
1134{
1135	struct sd *sd = (struct sd *) gspca_dev;
1136	u8 val;
1137	int i;
1138	static u8 color_tb[][6] = {
1139		{0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
1140		{0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
1141		{0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
1142		{0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
1143		{0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
1144		{0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
1145		{0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
1146	};
1147
1148	val = sd->ctrls[COLORS].val;
1149	for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
1150		sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
1151}
1152
1153static void setlightfreq(struct gspca_dev *gspca_dev)
1154{
1155	struct sd *sd = (struct sd *) gspca_dev;
1156	u8 val;
1157
1158	val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
1159	if (sd->sensor == SENSOR_OV767x) {
1160		sccb_reg_write(gspca_dev, 0x2a, 0x00);
1161		if (val)
1162			val = 0x9d;	/* insert dummy to 25fps for 50Hz */
1163	}
1164	sccb_reg_write(gspca_dev, 0x2b, val);
1165}
1166
1167
1168/* this function is called at probe time */
1169static int sd_config(struct gspca_dev *gspca_dev,
1170		     const struct usb_device_id *id)
1171{
1172	struct sd *sd = (struct sd *) gspca_dev;
1173	struct cam *cam;
1174
1175	cam = &gspca_dev->cam;
1176
1177	cam->ctrls = sd->ctrls;
1178
1179	/* the auto white balance control works only when auto gain is set */
1180	if (sd_ctrls[AGC].qctrl.default_value == 0)
1181		gspca_dev->ctrl_inac |= (1 << AWB);
1182
1183	cam->cam_mode = ov772x_mode;
1184	cam->nmodes = ARRAY_SIZE(ov772x_mode);
1185
1186	sd->frame_rate = 30;
1187
1188	return 0;
1189}
1190
1191/* this function is called at probe and resume time */
1192static int sd_init(struct gspca_dev *gspca_dev)
1193{
1194	struct sd *sd = (struct sd *) gspca_dev;
1195	u16 sensor_id;
1196	static const struct reg_array bridge_init[NSENSORS] = {
1197	[SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
1198	[SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
1199	};
1200	static const struct reg_array sensor_init[NSENSORS] = {
1201	[SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
1202	[SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
1203	};
1204
1205	/* reset bridge */
1206	ov534_reg_write(gspca_dev, 0xe7, 0x3a);
1207	ov534_reg_write(gspca_dev, 0xe0, 0x08);
1208	msleep(100);
1209
1210	/* initialize the sensor address */
1211	ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
1212
1213	/* reset sensor */
1214	sccb_reg_write(gspca_dev, 0x12, 0x80);
1215	msleep(10);
1216
1217	/* probe the sensor */
1218	sccb_reg_read(gspca_dev, 0x0a);
1219	sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
1220	sccb_reg_read(gspca_dev, 0x0b);
1221	sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
1222	PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
1223
1224	if ((sensor_id & 0xfff0) == 0x7670) {
1225		sd->sensor = SENSOR_OV767x;
1226		gspca_dev->ctrl_dis = (1 << GAIN) |
1227					(1 << AGC) |
1228					(1 << SHARPNESS);	/* auto */
1229		sd->ctrls[BRIGHTNESS].min = -127;
1230		sd->ctrls[BRIGHTNESS].max = 127;
1231		sd->ctrls[BRIGHTNESS].def = 0;
1232		sd->ctrls[CONTRAST].max = 0x80;
1233		sd->ctrls[CONTRAST].def = 0x40;
1234		sd->ctrls[EXPOSURE].min = 0x08;
1235		sd->ctrls[EXPOSURE].max = 0x60;
1236		sd->ctrls[EXPOSURE].def = 0x13;
1237		sd->ctrls[SHARPNESS].max = 9;
1238		sd->ctrls[SHARPNESS].def = 4;
1239		sd->ctrls[HFLIP].def = 1;
1240		gspca_dev->cam.cam_mode = ov767x_mode;
1241		gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
1242	} else {
1243		sd->sensor = SENSOR_OV772x;
1244		gspca_dev->ctrl_dis = (1 << COLORS);
1245		gspca_dev->cam.bulk = 1;
1246		gspca_dev->cam.bulk_size = 16384;
1247		gspca_dev->cam.bulk_nurbs = 2;
1248		gspca_dev->cam.mode_framerates = ov772x_framerates;
1249	}
1250
1251	/* initialize */
1252	reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
1253			bridge_init[sd->sensor].len);
1254	ov534_set_led(gspca_dev, 1);
1255	sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
1256			sensor_init[sd->sensor].len);
1257	if (sd->sensor == SENSOR_OV767x)
1258		sd_start(gspca_dev);
1259	sd_stopN(gspca_dev);
1260/*	set_frame_rate(gspca_dev);	*/
1261
1262	return gspca_dev->usb_err;
1263}
1264
1265static int sd_start(struct gspca_dev *gspca_dev)
1266{
1267	struct sd *sd = (struct sd *) gspca_dev;
1268	int mode;
1269	static const struct reg_array bridge_start[NSENSORS][2] = {
1270	[SENSOR_OV767x] = {{bridge_start_qvga_767x,
1271					ARRAY_SIZE(bridge_start_qvga_767x)},
1272			{bridge_start_vga_767x,
1273					ARRAY_SIZE(bridge_start_vga_767x)}},
1274	[SENSOR_OV772x] = {{bridge_start_qvga_772x,
1275					ARRAY_SIZE(bridge_start_qvga_772x)},
1276			{bridge_start_vga_772x,
1277					ARRAY_SIZE(bridge_start_vga_772x)}},
1278	};
1279	static const struct reg_array sensor_start[NSENSORS][2] = {
1280	[SENSOR_OV767x] = {{sensor_start_qvga_767x,
1281					ARRAY_SIZE(sensor_start_qvga_767x)},
1282			{sensor_start_vga_767x,
1283					ARRAY_SIZE(sensor_start_vga_767x)}},
1284	[SENSOR_OV772x] = {{sensor_start_qvga_772x,
1285					ARRAY_SIZE(sensor_start_qvga_772x)},
1286			{sensor_start_vga_772x,
1287					ARRAY_SIZE(sensor_start_vga_772x)}},
1288	};
1289
1290	/* (from ms-win trace) */
1291	if (sd->sensor == SENSOR_OV767x)
1292		sccb_reg_write(gspca_dev, 0x1e, 0x04);
1293					/* black sun enable ? */
1294
1295	mode = gspca_dev->curr_mode;	/* 0: 320x240, 1: 640x480 */
1296	reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
1297				bridge_start[sd->sensor][mode].len);
1298	sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
1299				sensor_start[sd->sensor][mode].len);
1300
1301	set_frame_rate(gspca_dev);
1302
1303	if (!(gspca_dev->ctrl_dis & (1 << AGC)))
1304		setagc(gspca_dev);
1305	setawb(gspca_dev);
1306	setaec(gspca_dev);
1307	if (!(gspca_dev->ctrl_dis & (1 << GAIN)))
1308		setgain(gspca_dev);
1309	setexposure(gspca_dev);
1310	setbrightness(gspca_dev);
1311	setcontrast(gspca_dev);
1312	if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS)))
1313		setsharpness(gspca_dev);
1314	sethvflip(gspca_dev);
1315	if (!(gspca_dev->ctrl_dis & (1 << COLORS)))
1316		setcolors(gspca_dev);
1317	setlightfreq(gspca_dev);
1318
1319	ov534_set_led(gspca_dev, 1);
1320	ov534_reg_write(gspca_dev, 0xe0, 0x00);
1321	return gspca_dev->usb_err;
1322}
1323
1324static void sd_stopN(struct gspca_dev *gspca_dev)
1325{
1326	ov534_reg_write(gspca_dev, 0xe0, 0x09);
1327	ov534_set_led(gspca_dev, 0);
1328}
1329
1330/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
1331#define UVC_STREAM_EOH	(1 << 7)
1332#define UVC_STREAM_ERR	(1 << 6)
1333#define UVC_STREAM_STI	(1 << 5)
1334#define UVC_STREAM_RES	(1 << 4)
1335#define UVC_STREAM_SCR	(1 << 3)
1336#define UVC_STREAM_PTS	(1 << 2)
1337#define UVC_STREAM_EOF	(1 << 1)
1338#define UVC_STREAM_FID	(1 << 0)
1339
1340static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1341			u8 *data, int len)
1342{
1343	struct sd *sd = (struct sd *) gspca_dev;
1344	__u32 this_pts;
1345	u16 this_fid;
1346	int remaining_len = len;
1347	int payload_len;
1348
1349	payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
1350	do {
1351		len = min(remaining_len, payload_len);
1352
1353		/* Payloads are prefixed with a UVC-style header.  We
1354		   consider a frame to start when the FID toggles, or the PTS
1355		   changes.  A frame ends when EOF is set, and we've received
1356		   the correct number of bytes. */
1357
1358		/* Verify UVC header.  Header length is always 12 */
1359		if (data[0] != 12 || len < 12) {
1360			PDEBUG(D_PACK, "bad header");
1361			goto discard;
1362		}
1363
1364		/* Check errors */
1365		if (data[1] & UVC_STREAM_ERR) {
1366			PDEBUG(D_PACK, "payload error");
1367			goto discard;
1368		}
1369
1370		/* Extract PTS and FID */
1371		if (!(data[1] & UVC_STREAM_PTS)) {
1372			PDEBUG(D_PACK, "PTS not present");
1373			goto discard;
1374		}
1375		this_pts = (data[5] << 24) | (data[4] << 16)
1376						| (data[3] << 8) | data[2];
1377		this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
1378
1379		/* If PTS or FID has changed, start a new frame. */
1380		if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
1381			if (gspca_dev->last_packet_type == INTER_PACKET)
1382				gspca_frame_add(gspca_dev, LAST_PACKET,
1383						NULL, 0);
1384			sd->last_pts = this_pts;
1385			sd->last_fid = this_fid;
1386			gspca_frame_add(gspca_dev, FIRST_PACKET,
1387					data + 12, len - 12);
1388		/* If this packet is marked as EOF, end the frame */
1389		} else if (data[1] & UVC_STREAM_EOF) {
1390			sd->last_pts = 0;
1391			if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
1392			 && gspca_dev->image_len + len - 12 !=
1393				   gspca_dev->width * gspca_dev->height * 2) {
1394				PDEBUG(D_PACK, "wrong sized frame");
1395				goto discard;
1396			}
1397			gspca_frame_add(gspca_dev, LAST_PACKET,
1398					data + 12, len - 12);
1399		} else {
1400
1401			/* Add the data from this payload */
1402			gspca_frame_add(gspca_dev, INTER_PACKET,
1403					data + 12, len - 12);
1404		}
1405
1406		/* Done this payload */
1407		goto scan_next;
1408
1409discard:
1410		/* Discard data until a new frame starts. */
1411		gspca_dev->last_packet_type = DISCARD_PACKET;
1412
1413scan_next:
1414		remaining_len -= len;
1415		data += len;
1416	} while (remaining_len > 0);
1417}
1418
1419static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val)
1420{
1421	struct sd *sd = (struct sd *) gspca_dev;
1422
1423	sd->ctrls[AGC].val = val;
1424
1425	/* the auto white balance control works only
1426	 * when auto gain is set */
1427	if (val) {
1428		gspca_dev->ctrl_inac &= ~(1 << AWB);
1429	} else {
1430		gspca_dev->ctrl_inac |= (1 << AWB);
1431		if (sd->ctrls[AWB].val) {
1432			sd->ctrls[AWB].val = 0;
1433			if (gspca_dev->streaming)
1434				setawb(gspca_dev);
1435		}
1436	}
1437	if (gspca_dev->streaming)
1438		setagc(gspca_dev);
1439	return gspca_dev->usb_err;
1440}
1441
1442static int sd_querymenu(struct gspca_dev *gspca_dev,
1443		struct v4l2_querymenu *menu)
1444{
1445	switch (menu->id) {
1446	case V4L2_CID_POWER_LINE_FREQUENCY:
1447		switch (menu->index) {
1448		case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1449			strcpy((char *) menu->name, "Disabled");
1450			return 0;
1451		case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1452			strcpy((char *) menu->name, "50 Hz");
1453			return 0;
1454		}
1455		break;
1456	}
1457
1458	return -EINVAL;
1459}
1460
1461/* get stream parameters (framerate) */
1462static void sd_get_streamparm(struct gspca_dev *gspca_dev,
1463			     struct v4l2_streamparm *parm)
1464{
1465	struct v4l2_captureparm *cp = &parm->parm.capture;
1466	struct v4l2_fract *tpf = &cp->timeperframe;
1467	struct sd *sd = (struct sd *) gspca_dev;
1468
1469	cp->capability |= V4L2_CAP_TIMEPERFRAME;
1470	tpf->numerator = 1;
1471	tpf->denominator = sd->frame_rate;
1472}
1473
1474/* set stream parameters (framerate) */
1475static void sd_set_streamparm(struct gspca_dev *gspca_dev,
1476			     struct v4l2_streamparm *parm)
1477{
1478	struct v4l2_captureparm *cp = &parm->parm.capture;
1479	struct v4l2_fract *tpf = &cp->timeperframe;
1480	struct sd *sd = (struct sd *) gspca_dev;
1481
1482	/* Set requested framerate */
1483	sd->frame_rate = tpf->denominator / tpf->numerator;
1484	if (gspca_dev->streaming)
1485		set_frame_rate(gspca_dev);
1486
1487	/* Return the actual framerate */
1488	tpf->numerator = 1;
1489	tpf->denominator = sd->frame_rate;
1490}
1491
1492/* sub-driver description */
1493static const struct sd_desc sd_desc = {
1494	.name     = MODULE_NAME,
1495	.ctrls    = sd_ctrls,
1496	.nctrls   = ARRAY_SIZE(sd_ctrls),
1497	.config   = sd_config,
1498	.init     = sd_init,
1499	.start    = sd_start,
1500	.stopN    = sd_stopN,
1501	.pkt_scan = sd_pkt_scan,
1502	.querymenu = sd_querymenu,
1503	.get_streamparm = sd_get_streamparm,
1504	.set_streamparm = sd_set_streamparm,
1505};
1506
1507/* -- module initialisation -- */
1508static const struct usb_device_id device_table[] = {
1509	{USB_DEVICE(0x1415, 0x2000)},
1510	{USB_DEVICE(0x06f8, 0x3002)},
1511	{}
1512};
1513
1514MODULE_DEVICE_TABLE(usb, device_table);
1515
1516/* -- device connect -- */
1517static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
1518{
1519	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1520				THIS_MODULE);
1521}
1522
1523static struct usb_driver sd_driver = {
1524	.name       = MODULE_NAME,
1525	.id_table   = device_table,
1526	.probe      = sd_probe,
1527	.disconnect = gspca_disconnect,
1528#ifdef CONFIG_PM
1529	.suspend    = gspca_suspend,
1530	.resume     = gspca_resume,
1531#endif
1532};
1533
1534/* -- module insert / remove -- */
1535static int __init sd_mod_init(void)
1536{
1537	return usb_register(&sd_driver);
1538}
1539
1540static void __exit sd_mod_exit(void)
1541{
1542	usb_deregister(&sd_driver);
1543}
1544
1545module_init(sd_mod_init);
1546module_exit(sd_mod_exit);