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