xref: /openbmc/linux/drivers/media/usb/gspca/t613.c (revision 12eb4683)
1 /*
2  * T613 subdriver
3  *
4  * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  *Notes: * t613  + tas5130A
21  *	* Focus to light do not balance well as in win.
22  *	  Quality in win is not good, but its kinda better.
23  *	 * Fix some "extraneous bytes", most of apps will show the image anyway
24  *	 * Gamma table, is there, but its really doing something?
25  *	 * 7~8 Fps, its ok, max on win its 10.
26  *			Costantino Leandro
27  */
28 
29 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
30 
31 #define MODULE_NAME "t613"
32 
33 #include <linux/input.h>
34 #include <linux/slab.h>
35 #include "gspca.h"
36 
37 MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38 MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39 MODULE_LICENSE("GPL");
40 
41 struct sd {
42 	struct gspca_dev gspca_dev;	/* !! must be the first item */
43 	struct v4l2_ctrl *freq;
44 	struct { /* awb / color gains control cluster */
45 		struct v4l2_ctrl *awb;
46 		struct v4l2_ctrl *gain;
47 		struct v4l2_ctrl *red_balance;
48 		struct v4l2_ctrl *blue_balance;
49 	};
50 
51 	u8 sensor;
52 	u8 button_pressed;
53 };
54 enum sensors {
55 	SENSOR_OM6802,
56 	SENSOR_OTHER,
57 	SENSOR_TAS5130A,
58 	SENSOR_LT168G,		/* must verify if this is the actual model */
59 };
60 
61 static const struct v4l2_pix_format vga_mode_t16[] = {
62 	{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
63 		.bytesperline = 160,
64 		.sizeimage = 160 * 120 * 4 / 8 + 590,
65 		.colorspace = V4L2_COLORSPACE_JPEG,
66 		.priv = 4},
67 #if 0 /* HDG: broken with my test cam, so lets disable it */
68 	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
69 		.bytesperline = 176,
70 		.sizeimage = 176 * 144 * 3 / 8 + 590,
71 		.colorspace = V4L2_COLORSPACE_JPEG,
72 		.priv = 3},
73 #endif
74 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
75 		.bytesperline = 320,
76 		.sizeimage = 320 * 240 * 3 / 8 + 590,
77 		.colorspace = V4L2_COLORSPACE_JPEG,
78 		.priv = 2},
79 #if 0 /* HDG: broken with my test cam, so lets disable it */
80 	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
81 		.bytesperline = 352,
82 		.sizeimage = 352 * 288 * 3 / 8 + 590,
83 		.colorspace = V4L2_COLORSPACE_JPEG,
84 		.priv = 1},
85 #endif
86 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
87 		.bytesperline = 640,
88 		.sizeimage = 640 * 480 * 3 / 8 + 590,
89 		.colorspace = V4L2_COLORSPACE_JPEG,
90 		.priv = 0},
91 };
92 
93 /* sensor specific data */
94 struct additional_sensor_data {
95 	const u8 n3[6];
96 	const u8 *n4, n4sz;
97 	const u8 reg80, reg8e;
98 	const u8 nset8[6];
99 	const u8 data1[10];
100 	const u8 data2[9];
101 	const u8 data3[9];
102 	const u8 data5[6];
103 	const u8 stream[4];
104 };
105 
106 static const u8 n4_om6802[] = {
107 	0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
108 	0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
109 	0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
110 	0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
111 	0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
112 	0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
113 	0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
114 	0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
115 	0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
116 };
117 static const u8 n4_other[] = {
118 	0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
119 	0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
120 	0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
121 	0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
122 	0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
123 	0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
124 	0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
125 	0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
126 };
127 static const u8 n4_tas5130a[] = {
128 	0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
129 	0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
130 	0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
131 	0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
132 	0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
133 	0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
134 	0xc6, 0xda
135 };
136 static const u8 n4_lt168g[] = {
137 	0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
138 	0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
139 	0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
140 	0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
141 	0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
142 	0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
143 	0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
144 	0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
145 	0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
146 };
147 
148 static const struct additional_sensor_data sensor_data[] = {
149 [SENSOR_OM6802] = {
150 	.n3 =
151 		{0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
152 	.n4 = n4_om6802,
153 	.n4sz = sizeof n4_om6802,
154 	.reg80 = 0x3c,
155 	.reg8e = 0x33,
156 	.nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
157 	.data1 =
158 		{0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
159 		 0xb3, 0xfc},
160 	.data2 =
161 		{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
162 		 0xff},
163 	.data3 =
164 		{0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
165 		 0xff},
166 	.data5 =	/* this could be removed later */
167 		{0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
168 	.stream =
169 		{0x0b, 0x04, 0x0a, 0x78},
170     },
171 [SENSOR_OTHER] = {
172 	.n3 =
173 		{0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
174 	.n4 = n4_other,
175 	.n4sz = sizeof n4_other,
176 	.reg80 = 0xac,
177 	.reg8e = 0xb8,
178 	.nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
179 	.data1 =
180 		{0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
181 		 0xe8, 0xfc},
182 	.data2 =
183 		{0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
184 		 0xd9},
185 	.data3 =
186 		{0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
187 		 0xd9},
188 	.data5 =
189 		{0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
190 	.stream =
191 		{0x0b, 0x04, 0x0a, 0x00},
192     },
193 [SENSOR_TAS5130A] = {
194 	.n3 =
195 		{0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
196 	.n4 = n4_tas5130a,
197 	.n4sz = sizeof n4_tas5130a,
198 	.reg80 = 0x3c,
199 	.reg8e = 0xb4,
200 	.nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
201 	.data1 =
202 		{0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
203 		 0xc8, 0xfc},
204 	.data2 =
205 		{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
206 		 0xe0},
207 	.data3 =
208 		{0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
209 		 0xe0},
210 	.data5 =
211 		{0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
212 	.stream =
213 		{0x0b, 0x04, 0x0a, 0x40},
214     },
215 [SENSOR_LT168G] = {
216 	.n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
217 	.n4 = n4_lt168g,
218 	.n4sz = sizeof n4_lt168g,
219 	.reg80 = 0x7c,
220 	.reg8e = 0xb3,
221 	.nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
222 	.data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
223 		 0xb0, 0xf4},
224 	.data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
225 		 0xff},
226 	.data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
227 		 0xff},
228 	.data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
229 	.stream = {0x0b, 0x04, 0x0a, 0x28},
230     },
231 };
232 
233 #define MAX_EFFECTS 7
234 static const u8 effects_table[MAX_EFFECTS][6] = {
235 	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},	/* Normal */
236 	{0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},	/* Repujar */
237 	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},	/* Monochrome */
238 	{0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},	/* Sepia */
239 	{0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},	/* Croquis */
240 	{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},	/* Sun Effect */
241 	{0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},	/* Negative */
242 };
243 
244 #define GAMMA_MAX (15)
245 static const u8 gamma_table[GAMMA_MAX+1][17] = {
246 /* gamma table from cam1690.ini */
247 	{0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,	/* 0 */
248 	 0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
249 	 0xff},
250 	{0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,	/* 1 */
251 	 0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
252 	 0xff},
253 	{0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,	/* 2 */
254 	 0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
255 	 0xff},
256 	{0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,	/* 3 */
257 	 0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
258 	 0xff},
259 	{0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,	/* 4 */
260 	 0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
261 	 0xff},
262 	{0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,	/* 5 */
263 	 0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
264 	 0xff},
265 	{0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,	/* 6 */
266 	 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
267 	 0xff},
268 	{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,	/* 7 */
269 	 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
270 	 0xff},
271 	{0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,	/* 8 */
272 	 0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
273 	 0xff},
274 	{0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,	/* 9 */
275 	 0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
276 	 0xff},
277 	{0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,	/* 10 */
278 	 0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
279 	 0xff},
280 	{0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,	/* 11 */
281 	 0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
282 	 0xff},
283 	{0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,	/* 12 */
284 	 0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
285 	 0xff},
286 	{0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,	/* 13 */
287 	 0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
288 	 0xff},
289 	{0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,	/* 14 */
290 	 0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
291 	 0xff},
292 	{0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,	/* 15 */
293 	 0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
294 	 0xff}
295 };
296 
297 static const u8 tas5130a_sensor_init[][8] = {
298 	{0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
299 	{0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
300 	{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
301 };
302 
303 static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
304 
305 /* read 1 byte */
306 static u8 reg_r(struct gspca_dev *gspca_dev,
307 		   u16 index)
308 {
309 	usb_control_msg(gspca_dev->dev,
310 			usb_rcvctrlpipe(gspca_dev->dev, 0),
311 			0,		/* request */
312 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
313 			0,		/* value */
314 			index,
315 			gspca_dev->usb_buf, 1, 500);
316 	return gspca_dev->usb_buf[0];
317 }
318 
319 static void reg_w(struct gspca_dev *gspca_dev,
320 		  u16 index)
321 {
322 	usb_control_msg(gspca_dev->dev,
323 			usb_sndctrlpipe(gspca_dev->dev, 0),
324 			0,
325 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
326 			0, index,
327 			NULL, 0, 500);
328 }
329 
330 static void reg_w_buf(struct gspca_dev *gspca_dev,
331 		  const u8 *buffer, u16 len)
332 {
333 	if (len <= USB_BUF_SZ) {
334 		memcpy(gspca_dev->usb_buf, buffer, len);
335 		usb_control_msg(gspca_dev->dev,
336 				usb_sndctrlpipe(gspca_dev->dev, 0),
337 				0,
338 			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
339 				0x01, 0,
340 				gspca_dev->usb_buf, len, 500);
341 	} else {
342 		u8 *tmpbuf;
343 
344 		tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
345 		if (!tmpbuf) {
346 			pr_err("Out of memory\n");
347 			return;
348 		}
349 		usb_control_msg(gspca_dev->dev,
350 				usb_sndctrlpipe(gspca_dev->dev, 0),
351 				0,
352 			   USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
353 				0x01, 0,
354 				tmpbuf, len, 500);
355 		kfree(tmpbuf);
356 	}
357 }
358 
359 /* write values to consecutive registers */
360 static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
361 			u8 reg,
362 			const u8 *buffer, u16 len)
363 {
364 	int i;
365 	u8 *p, *tmpbuf;
366 
367 	if (len * 2 <= USB_BUF_SZ) {
368 		p = tmpbuf = gspca_dev->usb_buf;
369 	} else {
370 		p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
371 		if (!tmpbuf) {
372 			pr_err("Out of memory\n");
373 			return;
374 		}
375 	}
376 	i = len;
377 	while (--i >= 0) {
378 		*p++ = reg++;
379 		*p++ = *buffer++;
380 	}
381 	usb_control_msg(gspca_dev->dev,
382 			usb_sndctrlpipe(gspca_dev->dev, 0),
383 			0,
384 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
385 			0x01, 0,
386 			tmpbuf, len * 2, 500);
387 	if (len * 2 > USB_BUF_SZ)
388 		kfree(tmpbuf);
389 }
390 
391 static void om6802_sensor_init(struct gspca_dev *gspca_dev)
392 {
393 	int i;
394 	const u8 *p;
395 	u8 byte;
396 	u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
397 	static const u8 sensor_init[] = {
398 		0xdf, 0x6d,
399 		0xdd, 0x18,
400 		0x5a, 0xe0,
401 		0x5c, 0x07,
402 		0x5d, 0xb0,
403 		0x5e, 0x1e,
404 		0x60, 0x71,
405 		0xef, 0x00,
406 		0xe9, 0x00,
407 		0xea, 0x00,
408 		0x90, 0x24,
409 		0x91, 0xb2,
410 		0x82, 0x32,
411 		0xfd, 0x41,
412 		0x00			/* table end */
413 	};
414 
415 	reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
416 	msleep(100);
417 	i = 4;
418 	while (--i > 0) {
419 		byte = reg_r(gspca_dev, 0x0060);
420 		if (!(byte & 0x01))
421 			break;
422 		msleep(100);
423 	}
424 	byte = reg_r(gspca_dev, 0x0063);
425 	if (byte != 0x17) {
426 		pr_err("Bad sensor reset %02x\n", byte);
427 		/* continue? */
428 	}
429 
430 	p = sensor_init;
431 	while (*p != 0) {
432 		val[1] = *p++;
433 		val[3] = *p++;
434 		if (*p == 0)
435 			reg_w(gspca_dev, 0x3c80);
436 		reg_w_buf(gspca_dev, val, sizeof val);
437 		i = 4;
438 		while (--i >= 0) {
439 			msleep(15);
440 			byte = reg_r(gspca_dev, 0x60);
441 			if (!(byte & 0x01))
442 				break;
443 		}
444 	}
445 	msleep(15);
446 	reg_w(gspca_dev, 0x3c80);
447 }
448 
449 /* this function is called at probe time */
450 static int sd_config(struct gspca_dev *gspca_dev,
451 		     const struct usb_device_id *id)
452 {
453 	struct cam *cam  = &gspca_dev->cam;
454 
455 	cam->cam_mode = vga_mode_t16;
456 	cam->nmodes = ARRAY_SIZE(vga_mode_t16);
457 
458 	return 0;
459 }
460 
461 static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
462 {
463 	u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
464 
465 	if (brightness < 7) {
466 		set6[1] = 0x26;
467 		set6[3] = 0x70 - brightness * 0x10;
468 	} else {
469 		set6[3] = 0x00 + ((brightness - 7) * 0x10);
470 	}
471 
472 	reg_w_buf(gspca_dev, set6, sizeof set6);
473 }
474 
475 static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
476 {
477 	u16 reg_to_write;
478 
479 	if (contrast < 7)
480 		reg_to_write = 0x8ea9 - contrast * 0x200;
481 	else
482 		reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
483 
484 	reg_w(gspca_dev, reg_to_write);
485 }
486 
487 static void setcolors(struct gspca_dev *gspca_dev, s32 val)
488 {
489 	u16 reg_to_write;
490 
491 	reg_to_write = 0x80bb + val * 0x100;	/* was 0xc0 */
492 	reg_w(gspca_dev, reg_to_write);
493 }
494 
495 static void setgamma(struct gspca_dev *gspca_dev, s32 val)
496 {
497 	PDEBUG(D_CONF, "Gamma: %d", val);
498 	reg_w_ixbuf(gspca_dev, 0x90,
499 		gamma_table[val], sizeof gamma_table[0]);
500 }
501 
502 static void setawb_n_RGB(struct gspca_dev *gspca_dev)
503 {
504 	struct sd *sd = (struct sd *) gspca_dev;
505 	u8 all_gain_reg[8] = {
506 		0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
507 	s32 red_gain, blue_gain, green_gain;
508 
509 	green_gain = sd->gain->val;
510 
511 	red_gain = green_gain + sd->red_balance->val;
512 	if (red_gain > 0x40)
513 		red_gain = 0x40;
514 	else if (red_gain < 0x10)
515 		red_gain = 0x10;
516 
517 	blue_gain = green_gain + sd->blue_balance->val;
518 	if (blue_gain > 0x40)
519 		blue_gain = 0x40;
520 	else if (blue_gain < 0x10)
521 		blue_gain = 0x10;
522 
523 	all_gain_reg[1] = red_gain;
524 	all_gain_reg[3] = blue_gain;
525 	all_gain_reg[5] = green_gain;
526 	all_gain_reg[7] = sensor_data[sd->sensor].reg80;
527 	if (!sd->awb->val)
528 		all_gain_reg[7] &= ~0x04; /* AWB off */
529 
530 	reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
531 }
532 
533 static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
534 {
535 	u16 reg_to_write;
536 
537 	reg_to_write = 0x0aa6 + 0x1000 * val;
538 
539 	reg_w(gspca_dev, reg_to_write);
540 }
541 
542 static void setfreq(struct gspca_dev *gspca_dev, s32 val)
543 {
544 	struct sd *sd = (struct sd *) gspca_dev;
545 	u8 reg66;
546 	u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
547 
548 	switch (sd->sensor) {
549 	case SENSOR_LT168G:
550 		if (val != 0)
551 			freq[3] = 0xa8;
552 		reg66 = 0x41;
553 		break;
554 	case SENSOR_OM6802:
555 		reg66 = 0xca;
556 		break;
557 	default:
558 		reg66 = 0x40;
559 		break;
560 	}
561 	switch (val) {
562 	case 0:				/* no flicker */
563 		freq[3] = 0xf0;
564 		break;
565 	case 2:				/* 60Hz */
566 		reg66 &= ~0x40;
567 		break;
568 	}
569 	freq[1] = reg66;
570 
571 	reg_w_buf(gspca_dev, freq, sizeof freq);
572 }
573 
574 /* this function is called at probe and resume time */
575 static int sd_init(struct gspca_dev *gspca_dev)
576 {
577 	/* some of this registers are not really neded, because
578 	 * they are overriden by setbrigthness, setcontrast, etc,
579 	 * but wont hurt anyway, and can help someone with similar webcam
580 	 * to see the initial parameters.*/
581 	struct sd *sd = (struct sd *) gspca_dev;
582 	const struct additional_sensor_data *sensor;
583 	int i;
584 	u16 sensor_id;
585 	u8 test_byte = 0;
586 
587 	static const u8 read_indexs[] =
588 		{ 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
589 		  0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
590 	static const u8 n1[] =
591 			{0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
592 	static const u8 n2[] =
593 			{0x08, 0x00};
594 
595 	sensor_id = (reg_r(gspca_dev, 0x06) << 8)
596 			| reg_r(gspca_dev, 0x07);
597 	switch (sensor_id & 0xff0f) {
598 	case 0x0801:
599 		PDEBUG(D_PROBE, "sensor tas5130a");
600 		sd->sensor = SENSOR_TAS5130A;
601 		break;
602 	case 0x0802:
603 		PDEBUG(D_PROBE, "sensor lt168g");
604 		sd->sensor = SENSOR_LT168G;
605 		break;
606 	case 0x0803:
607 		PDEBUG(D_PROBE, "sensor 'other'");
608 		sd->sensor = SENSOR_OTHER;
609 		break;
610 	case 0x0807:
611 		PDEBUG(D_PROBE, "sensor om6802");
612 		sd->sensor = SENSOR_OM6802;
613 		break;
614 	default:
615 		pr_err("unknown sensor %04x\n", sensor_id);
616 		return -EINVAL;
617 	}
618 
619 	if (sd->sensor == SENSOR_OM6802) {
620 		reg_w_buf(gspca_dev, n1, sizeof n1);
621 		i = 5;
622 		while (--i >= 0) {
623 			reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
624 			test_byte = reg_r(gspca_dev, 0x0063);
625 			msleep(100);
626 			if (test_byte == 0x17)
627 				break;		/* OK */
628 		}
629 		if (i < 0) {
630 			pr_err("Bad sensor reset %02x\n", test_byte);
631 			return -EIO;
632 		}
633 		reg_w_buf(gspca_dev, n2, sizeof n2);
634 	}
635 
636 	i = 0;
637 	while (read_indexs[i] != 0x00) {
638 		test_byte = reg_r(gspca_dev, read_indexs[i]);
639 		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
640 		       test_byte);
641 		i++;
642 	}
643 
644 	sensor = &sensor_data[sd->sensor];
645 	reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
646 	reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
647 
648 	if (sd->sensor == SENSOR_LT168G) {
649 		test_byte = reg_r(gspca_dev, 0x80);
650 		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
651 		       test_byte);
652 		reg_w(gspca_dev, 0x6c80);
653 	}
654 
655 	reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
656 	reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
657 	reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
658 
659 	reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
660 	reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
661 	reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
662 	reg_w(gspca_dev, (0x20 << 8) + 0x87);
663 	reg_w(gspca_dev, (0x20 << 8) + 0x88);
664 	reg_w(gspca_dev, (0x20 << 8) + 0x89);
665 
666 	reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
667 	reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
668 	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
669 
670 	if (sd->sensor == SENSOR_LT168G) {
671 		test_byte = reg_r(gspca_dev, 0x80);
672 		PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
673 		       test_byte);
674 		reg_w(gspca_dev, 0x6c80);
675 	}
676 
677 	reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
678 	reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
679 	reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
680 
681 	return 0;
682 }
683 
684 static void setmirror(struct gspca_dev *gspca_dev, s32 val)
685 {
686 	u8 hflipcmd[8] =
687 		{0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
688 
689 	if (val)
690 		hflipcmd[3] = 0x01;
691 
692 	reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
693 }
694 
695 static void seteffect(struct gspca_dev *gspca_dev, s32 val)
696 {
697 	int idx = 0;
698 
699 	switch (val) {
700 	case V4L2_COLORFX_NONE:
701 		break;
702 	case V4L2_COLORFX_BW:
703 		idx = 2;
704 		break;
705 	case V4L2_COLORFX_SEPIA:
706 		idx = 3;
707 		break;
708 	case V4L2_COLORFX_SKETCH:
709 		idx = 4;
710 		break;
711 	case V4L2_COLORFX_NEGATIVE:
712 		idx = 6;
713 		break;
714 	default:
715 		break;
716 	}
717 
718 	reg_w_buf(gspca_dev, effects_table[idx],
719 				sizeof effects_table[0]);
720 
721 	if (val == V4L2_COLORFX_SKETCH)
722 		reg_w(gspca_dev, 0x4aa6);
723 	else
724 		reg_w(gspca_dev, 0xfaa6);
725 }
726 
727 /* Is this really needed?
728  * i added some module parameters for test with some users */
729 static void poll_sensor(struct gspca_dev *gspca_dev)
730 {
731 	static const u8 poll1[] =
732 		{0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
733 		 0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
734 		 0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
735 		 0x60, 0x14};
736 	static const u8 poll2[] =
737 		{0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
738 		 0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
739 	static const u8 noise03[] =	/* (some differences / ms-drv) */
740 		{0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
741 		 0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
742 		 0xc2, 0x80, 0xc3, 0x10};
743 
744 	PDEBUG(D_STREAM, "[Sensor requires polling]");
745 	reg_w_buf(gspca_dev, poll1, sizeof poll1);
746 	reg_w_buf(gspca_dev, poll2, sizeof poll2);
747 	reg_w_buf(gspca_dev, noise03, sizeof noise03);
748 }
749 
750 static int sd_start(struct gspca_dev *gspca_dev)
751 {
752 	struct sd *sd = (struct sd *) gspca_dev;
753 	const struct additional_sensor_data *sensor;
754 	int i, mode;
755 	u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
756 	static const u8 t3[] =
757 		{ 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
758 
759 	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
760 	switch (mode) {
761 	case 0:		/* 640x480 (0x00) */
762 		break;
763 	case 1:		/* 352x288 */
764 		t2[1] = 0x40;
765 		break;
766 	case 2:		/* 320x240 */
767 		t2[1] = 0x10;
768 		break;
769 	case 3:		/* 176x144 */
770 		t2[1] = 0x50;
771 		break;
772 	default:
773 /*	case 4:		 * 160x120 */
774 		t2[1] = 0x20;
775 		break;
776 	}
777 
778 	switch (sd->sensor) {
779 	case SENSOR_OM6802:
780 		om6802_sensor_init(gspca_dev);
781 		break;
782 	case SENSOR_TAS5130A:
783 		i = 0;
784 		for (;;) {
785 			reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
786 					 sizeof tas5130a_sensor_init[0]);
787 			if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
788 				break;
789 			i++;
790 		}
791 		reg_w(gspca_dev, 0x3c80);
792 		/* just in case and to keep sync with logs (for mine) */
793 		reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
794 				 sizeof tas5130a_sensor_init[0]);
795 		reg_w(gspca_dev, 0x3c80);
796 		break;
797 	}
798 	sensor = &sensor_data[sd->sensor];
799 	setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
800 	reg_r(gspca_dev, 0x0012);
801 	reg_w_buf(gspca_dev, t2, sizeof t2);
802 	reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
803 	reg_w(gspca_dev, 0x0013);
804 	msleep(15);
805 	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
806 	reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
807 
808 	if (sd->sensor == SENSOR_OM6802)
809 		poll_sensor(gspca_dev);
810 
811 	return 0;
812 }
813 
814 static void sd_stopN(struct gspca_dev *gspca_dev)
815 {
816 	struct sd *sd = (struct sd *) gspca_dev;
817 
818 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
819 			sizeof sensor_data[sd->sensor].stream);
820 	reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
821 			sizeof sensor_data[sd->sensor].stream);
822 	if (sd->sensor == SENSOR_OM6802) {
823 		msleep(20);
824 		reg_w(gspca_dev, 0x0309);
825 	}
826 #if IS_ENABLED(CONFIG_INPUT)
827 	/* If the last button state is pressed, release it now! */
828 	if (sd->button_pressed) {
829 		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
830 		input_sync(gspca_dev->input_dev);
831 		sd->button_pressed = 0;
832 	}
833 #endif
834 }
835 
836 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
837 			u8 *data,			/* isoc packet */
838 			int len)			/* iso packet length */
839 {
840 	struct sd *sd = (struct sd *) gspca_dev;
841 	int pkt_type;
842 
843 	if (data[0] == 0x5a) {
844 #if IS_ENABLED(CONFIG_INPUT)
845 		if (len > 20) {
846 			u8 state = (data[20] & 0x80) ? 1 : 0;
847 			if (sd->button_pressed != state) {
848 				input_report_key(gspca_dev->input_dev,
849 						 KEY_CAMERA, state);
850 				input_sync(gspca_dev->input_dev);
851 				sd->button_pressed = state;
852 			}
853 		}
854 #endif
855 		/* Control Packet, after this came the header again,
856 		 * but extra bytes came in the packet before this,
857 		 * sometimes an EOF arrives, sometimes not... */
858 		return;
859 	}
860 	data += 2;
861 	len -= 2;
862 	if (data[0] == 0xff && data[1] == 0xd8)
863 		pkt_type = FIRST_PACKET;
864 	else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
865 		pkt_type = LAST_PACKET;
866 	else
867 		pkt_type = INTER_PACKET;
868 	gspca_frame_add(gspca_dev, pkt_type, data, len);
869 }
870 
871 static int sd_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
872 {
873 	struct gspca_dev *gspca_dev =
874 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
875 	struct sd *sd = (struct sd *)gspca_dev;
876 	s32 red_gain, blue_gain, green_gain;
877 
878 	gspca_dev->usb_err = 0;
879 
880 	switch (ctrl->id) {
881 	case V4L2_CID_AUTO_WHITE_BALANCE:
882 		red_gain = reg_r(gspca_dev, 0x0087);
883 		if (red_gain > 0x40)
884 			red_gain = 0x40;
885 		else if (red_gain < 0x10)
886 			red_gain = 0x10;
887 
888 		blue_gain = reg_r(gspca_dev, 0x0088);
889 		if (blue_gain > 0x40)
890 			blue_gain = 0x40;
891 		else if (blue_gain < 0x10)
892 			blue_gain = 0x10;
893 
894 		green_gain = reg_r(gspca_dev, 0x0089);
895 		if (green_gain > 0x40)
896 			green_gain = 0x40;
897 		else if (green_gain < 0x10)
898 			green_gain = 0x10;
899 
900 		sd->gain->val = green_gain;
901 		sd->red_balance->val = red_gain - green_gain;
902 		sd->blue_balance->val = blue_gain - green_gain;
903 		break;
904 	}
905 	return 0;
906 }
907 
908 static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
909 {
910 	struct gspca_dev *gspca_dev =
911 		container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
912 
913 	gspca_dev->usb_err = 0;
914 
915 	if (!gspca_dev->streaming)
916 		return 0;
917 
918 	switch (ctrl->id) {
919 	case V4L2_CID_BRIGHTNESS:
920 		setbrightness(gspca_dev, ctrl->val);
921 		break;
922 	case V4L2_CID_CONTRAST:
923 		setcontrast(gspca_dev, ctrl->val);
924 		break;
925 	case V4L2_CID_SATURATION:
926 		setcolors(gspca_dev, ctrl->val);
927 		break;
928 	case V4L2_CID_GAMMA:
929 		setgamma(gspca_dev, ctrl->val);
930 		break;
931 	case V4L2_CID_HFLIP:
932 		setmirror(gspca_dev, ctrl->val);
933 		break;
934 	case V4L2_CID_SHARPNESS:
935 		setsharpness(gspca_dev, ctrl->val);
936 		break;
937 	case V4L2_CID_POWER_LINE_FREQUENCY:
938 		setfreq(gspca_dev, ctrl->val);
939 		break;
940 	case V4L2_CID_BACKLIGHT_COMPENSATION:
941 		reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
942 		break;
943 	case V4L2_CID_AUTO_WHITE_BALANCE:
944 		setawb_n_RGB(gspca_dev);
945 		break;
946 	case V4L2_CID_COLORFX:
947 		seteffect(gspca_dev, ctrl->val);
948 		break;
949 	}
950 	return gspca_dev->usb_err;
951 }
952 
953 static const struct v4l2_ctrl_ops sd_ctrl_ops = {
954 	.g_volatile_ctrl = sd_g_volatile_ctrl,
955 	.s_ctrl = sd_s_ctrl,
956 };
957 
958 static int sd_init_controls(struct gspca_dev *gspca_dev)
959 {
960 	struct sd *sd = (struct sd *)gspca_dev;
961 	struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
962 
963 	gspca_dev->vdev.ctrl_handler = hdl;
964 	v4l2_ctrl_handler_init(hdl, 12);
965 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
966 			V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
967 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
968 			V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
969 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
970 			V4L2_CID_SATURATION, 0, 0xf, 1, 5);
971 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
972 			V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
973 	/* Activate lowlight, some apps dont bring up the
974 	   backlight_compensation control) */
975 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
976 			V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
977 	if (sd->sensor == SENSOR_TAS5130A)
978 		v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
979 				V4L2_CID_HFLIP, 0, 1, 1, 0);
980 	sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
981 			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
982 	sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
983 			V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
984 	sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
985 			V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
986 	sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
987 			V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
988 	v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
989 			V4L2_CID_SHARPNESS, 0, 15, 1, 6);
990 	v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
991 			V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
992 			~((1 << V4L2_COLORFX_NONE) |
993 			  (1 << V4L2_COLORFX_BW) |
994 			  (1 << V4L2_COLORFX_SEPIA) |
995 			  (1 << V4L2_COLORFX_SKETCH) |
996 			  (1 << V4L2_COLORFX_NEGATIVE)),
997 			V4L2_COLORFX_NONE);
998 	sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
999 			V4L2_CID_POWER_LINE_FREQUENCY,
1000 			V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
1001 			V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
1002 
1003 	if (hdl->error) {
1004 		pr_err("Could not initialize controls\n");
1005 		return hdl->error;
1006 	}
1007 
1008 	v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
1009 
1010 	return 0;
1011 }
1012 
1013 /* sub-driver description */
1014 static const struct sd_desc sd_desc = {
1015 	.name = MODULE_NAME,
1016 	.config = sd_config,
1017 	.init = sd_init,
1018 	.init_controls = sd_init_controls,
1019 	.start = sd_start,
1020 	.stopN = sd_stopN,
1021 	.pkt_scan = sd_pkt_scan,
1022 #if IS_ENABLED(CONFIG_INPUT)
1023 	.other_input = 1,
1024 #endif
1025 };
1026 
1027 /* -- module initialisation -- */
1028 static const struct usb_device_id device_table[] = {
1029 	{USB_DEVICE(0x17a1, 0x0128)},
1030 	{}
1031 };
1032 MODULE_DEVICE_TABLE(usb, device_table);
1033 
1034 /* -- device connect -- */
1035 static int sd_probe(struct usb_interface *intf,
1036 		    const struct usb_device_id *id)
1037 {
1038 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1039 			       THIS_MODULE);
1040 }
1041 
1042 static struct usb_driver sd_driver = {
1043 	.name = MODULE_NAME,
1044 	.id_table = device_table,
1045 	.probe = sd_probe,
1046 	.disconnect = gspca_disconnect,
1047 #ifdef CONFIG_PM
1048 	.suspend = gspca_suspend,
1049 	.resume = gspca_resume,
1050 	.reset_resume = gspca_resume,
1051 #endif
1052 };
1053 
1054 module_usb_driver(sd_driver);
1055