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);
1822