• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *		Pixart PAC7311 library
3  *		Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4  *
5  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 /* Some documentation about various registers as determined by trial and error.
23    When the register addresses differ between the 7202 and the 7311 the 2
24    different addresses are written as 7302addr/7311addr, when one of the 2
25    addresses is a - sign that register description is not valid for the
26    matching IC.
27 
28    Register page 1:
29 
30    Address	Description
31    -/0x08	Unknown compressor related, must always be 8 except when not
32 		in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
33    -/0x1b	Auto white balance related, bit 0 is AWB enable (inverted)
34 		bits 345 seem to toggle per color gains on/off (inverted)
35    0x78		Global control, bit 6 controls the LED (inverted)
36    -/0x80	JPEG compression ratio ? Best not touched
37 
38    Register page 3/4:
39 
40    Address	Description
41    0x02		Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
42 		the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
43    -/0x0f	Master gain 1-245, low value = high gain
44    0x10/-	Master gain 0-31
45    -/0x10	Another gain 0-15, limited influence (1-2x gain I guess)
46    0x21		Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47    -/0x27	Seems to toggle various gains on / off, Setting bit 7 seems to
48 		completely disable the analog amplification block. Set to 0x68
49 		for max gain, 0x14 for minimal gain.
50 */
51 
52 #define MODULE_NAME "pac7311"
53 
54 #include "gspca.h"
55 
56 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
57 MODULE_DESCRIPTION("Pixart PAC7311");
58 MODULE_LICENSE("GPL");
59 
60 /* specific webcam descriptor */
61 struct sd {
62 	struct gspca_dev gspca_dev;		/* !! must be the first item */
63 
64 	unsigned char brightness;
65 	unsigned char contrast;
66 	unsigned char colors;
67 	unsigned char gain;
68 	unsigned char exposure;
69 	unsigned char autogain;
70 	__u8 hflip;
71 	__u8 vflip;
72 
73 	__u8 sensor;
74 #define SENSOR_PAC7302 0
75 #define SENSOR_PAC7311 1
76 
77 	u8 sof_read;
78 	u8 autogain_ignore_frames;
79 
80 	atomic_t avg_lum;
81 };
82 
83 /* V4L2 controls supported by the driver */
84 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
96 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
97 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
98 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
99 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
100 
101 static struct ctrl sd_ctrls[] = {
102 /* This control is pac7302 only */
103 #define BRIGHTNESS_IDX 0
104 	{
105 	    {
106 		.id      = V4L2_CID_BRIGHTNESS,
107 		.type    = V4L2_CTRL_TYPE_INTEGER,
108 		.name    = "Brightness",
109 		.minimum = 0,
110 #define BRIGHTNESS_MAX 0x20
111 		.maximum = BRIGHTNESS_MAX,
112 		.step    = 1,
113 #define BRIGHTNESS_DEF 0x10
114 		.default_value = BRIGHTNESS_DEF,
115 	    },
116 	    .set = sd_setbrightness,
117 	    .get = sd_getbrightness,
118 	},
119 /* This control is for both the 7302 and the 7311 */
120 	{
121 	    {
122 		.id      = V4L2_CID_CONTRAST,
123 		.type    = V4L2_CTRL_TYPE_INTEGER,
124 		.name    = "Contrast",
125 		.minimum = 0,
126 #define CONTRAST_MAX 255
127 		.maximum = CONTRAST_MAX,
128 		.step    = 1,
129 #define CONTRAST_DEF 127
130 		.default_value = CONTRAST_DEF,
131 	    },
132 	    .set = sd_setcontrast,
133 	    .get = sd_getcontrast,
134 	},
135 /* This control is pac7302 only */
136 #define SATURATION_IDX 2
137 	{
138 	    {
139 		.id      = V4L2_CID_SATURATION,
140 		.type    = V4L2_CTRL_TYPE_INTEGER,
141 		.name    = "Saturation",
142 		.minimum = 0,
143 #define COLOR_MAX 255
144 		.maximum = COLOR_MAX,
145 		.step    = 1,
146 #define COLOR_DEF 127
147 		.default_value = COLOR_DEF,
148 	    },
149 	    .set = sd_setcolors,
150 	    .get = sd_getcolors,
151 	},
152 /* All controls below are for both the 7302 and the 7311 */
153 	{
154 	    {
155 		.id      = V4L2_CID_GAIN,
156 		.type    = V4L2_CTRL_TYPE_INTEGER,
157 		.name    = "Gain",
158 		.minimum = 0,
159 #define GAIN_MAX 255
160 		.maximum = GAIN_MAX,
161 		.step    = 1,
162 #define GAIN_DEF 127
163 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
164 		.default_value = GAIN_DEF,
165 	    },
166 	    .set = sd_setgain,
167 	    .get = sd_getgain,
168 	},
169 	{
170 	    {
171 		.id      = V4L2_CID_EXPOSURE,
172 		.type    = V4L2_CTRL_TYPE_INTEGER,
173 		.name    = "Exposure",
174 		.minimum = 0,
175 #define EXPOSURE_MAX 255
176 		.maximum = EXPOSURE_MAX,
177 		.step    = 1,
178 #define EXPOSURE_DEF  16 /*  32 ms / 30 fps */
179 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
180 		.default_value = EXPOSURE_DEF,
181 	    },
182 	    .set = sd_setexposure,
183 	    .get = sd_getexposure,
184 	},
185 	{
186 	    {
187 		.id      = V4L2_CID_AUTOGAIN,
188 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
189 		.name    = "Auto Gain",
190 		.minimum = 0,
191 		.maximum = 1,
192 		.step    = 1,
193 #define AUTOGAIN_DEF 1
194 		.default_value = AUTOGAIN_DEF,
195 	    },
196 	    .set = sd_setautogain,
197 	    .get = sd_getautogain,
198 	},
199 	{
200 	    {
201 		.id      = V4L2_CID_HFLIP,
202 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
203 		.name    = "Mirror",
204 		.minimum = 0,
205 		.maximum = 1,
206 		.step    = 1,
207 #define HFLIP_DEF 0
208 		.default_value = HFLIP_DEF,
209 	    },
210 	    .set = sd_sethflip,
211 	    .get = sd_gethflip,
212 	},
213 	{
214 	    {
215 		.id      = V4L2_CID_VFLIP,
216 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
217 		.name    = "Vflip",
218 		.minimum = 0,
219 		.maximum = 1,
220 		.step    = 1,
221 #define VFLIP_DEF 0
222 		.default_value = VFLIP_DEF,
223 	    },
224 	    .set = sd_setvflip,
225 	    .get = sd_getvflip,
226 	},
227 };
228 
229 static const struct v4l2_pix_format vga_mode[] = {
230 	{160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
231 		.bytesperline = 160,
232 		.sizeimage = 160 * 120 * 3 / 8 + 590,
233 		.colorspace = V4L2_COLORSPACE_JPEG,
234 		.priv = 2},
235 	{320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
236 		.bytesperline = 320,
237 		.sizeimage = 320 * 240 * 3 / 8 + 590,
238 		.colorspace = V4L2_COLORSPACE_JPEG,
239 		.priv = 1},
240 	{640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
241 		.bytesperline = 640,
242 		.sizeimage = 640 * 480 * 3 / 8 + 590,
243 		.colorspace = V4L2_COLORSPACE_JPEG,
244 		.priv = 0},
245 };
246 
247 /* pac 7302 */
248 static const __u8 init_7302[] = {
249 /*	index,value */
250 	0xff, 0x01,		/* page 1 */
251 	0x78, 0x00,		/* deactivate */
252 	0xff, 0x01,
253 	0x78, 0x40,		/* led off */
254 };
255 static const __u8 start_7302[] = {
256 /*	index, len, [value]* */
257 	0xff, 1,	0x00,		/* page 0 */
258 	0x00, 12,	0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
259 			0x00, 0x00, 0x00, 0x00,
260 	0x0d, 24,	0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
261 			0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
262 			0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
263 	0x26, 2,	0xaa, 0xaa,
264 	0x2e, 1,	0x31,
265 	0x38, 1,	0x01,
266 	0x3a, 3,	0x14, 0xff, 0x5a,
267 	0x43, 11,	0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
268 			0x00, 0x54, 0x11,
269 	0x55, 1,	0x00,
270 	0x62, 4, 	0x10, 0x1e, 0x1e, 0x18,
271 	0x6b, 1,	0x00,
272 	0x6e, 3,	0x08, 0x06, 0x00,
273 	0x72, 3,	0x00, 0xff, 0x00,
274 	0x7d, 23,	0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
275 			0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
276 			0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
277 	0xa2, 10,	0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
278 			0xd2, 0xeb,
279 	0xaf, 1,	0x02,
280 	0xb5, 2,	0x08, 0x08,
281 	0xb8, 2,	0x08, 0x88,
282 	0xc4, 4,	0xae, 0x01, 0x04, 0x01,
283 	0xcc, 1,	0x00,
284 	0xd1, 11,	0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
285 			0xc1, 0xd7, 0xec,
286 	0xdc, 1,	0x01,
287 	0xff, 1,	0x01,		/* page 1 */
288 	0x12, 3,	0x02, 0x00, 0x01,
289 	0x3e, 2,	0x00, 0x00,
290 	0x76, 5,	0x01, 0x20, 0x40, 0x00, 0xf2,
291 	0x7c, 1,	0x00,
292 	0x7f, 10,	0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
293 			0x02, 0x00,
294 	0x96, 5,	0x01, 0x10, 0x04, 0x01, 0x04,
295 	0xc8, 14,	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
296 			0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
297 	0xd8, 1,	0x01,
298 	0xdb, 2,	0x00, 0x01,
299 	0xde, 7,	0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
300 	0xe6, 4,	0x00, 0x00, 0x00, 0x01,
301 	0xeb, 1,	0x00,
302 	0xff, 1,	0x02,		/* page 2 */
303 	0x22, 1,	0x00,
304 	0xff, 1,	0x03,		/* page 3 */
305 	0x00, 255,			/* load the page 3 */
306 	0x11, 1,	0x01,
307 	0xff, 1,	0x02,		/* page 2 */
308 	0x13, 1,	0x00,
309 	0x22, 4,	0x1f, 0xa4, 0xf0, 0x96,
310 	0x27, 2,	0x14, 0x0c,
311 	0x2a, 5,	0xc8, 0x00, 0x18, 0x12, 0x22,
312 	0x64, 8,	0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
313 	0x6e, 1,	0x08,
314 	0xff, 1,	0x01,		/* page 1 */
315 	0x78, 1,	0x00,
316 	0, 0				/* end of sequence */
317 };
318 
319 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
320 static const __u8 page3_7302[] = {
321 	0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
322 	0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
323 	0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 	0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
325 	0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
326 	0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
327 	0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
328 	0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 	0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
330 	0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
331 	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 	0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
333 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 	0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
335 	0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
336 	0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
337 	0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
338 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 	0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
340 	0x00
341 };
342 
343 /* pac 7311 */
344 static const __u8 init_7311[] = {
345 	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
346 	0x78, 0x40,	/* Bit_0=start stream, Bit_6=LED */
347 	0x78, 0x44,	/* Bit_0=start stream, Bit_6=LED */
348 	0xff, 0x04,
349 	0x27, 0x80,
350 	0x28, 0xca,
351 	0x29, 0x53,
352 	0x2a, 0x0e,
353 	0xff, 0x01,
354 	0x3e, 0x20,
355 };
356 
357 static const __u8 start_7311[] = {
358 /*	index, len, [value]* */
359 	0xff, 1,	0x01,		/* page 1 */
360 	0x02, 43,	0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
361 			0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
362 			0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
363 			0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
364 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 			0x00, 0x00, 0x00,
366 	0x3e, 42,	0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
367 			0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
368 			0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
369 			0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
370 			0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
371 			0xd0, 0xff,
372 	0x78, 6,	0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
373 	0x7f, 18,	0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
374 			0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
375 			0x18, 0x20,
376 	0x96, 3,	0x01, 0x08, 0x04,
377 	0xa0, 4,	0x44, 0x44, 0x44, 0x04,
378 	0xf0, 13,	0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
379 			0x3f, 0x00, 0x0a, 0x01, 0x00,
380 	0xff, 1,	0x04,		/* page 4 */
381 	0x00, 254,			/* load the page 4 */
382 	0x11, 1,	0x01,
383 	0, 0				/* end of sequence */
384 };
385 
386 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
387 static const __u8 page4_7311[] = {
388 	0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
389 	0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
390 	0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
391 	0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
392 	0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
393 	0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
394 	0x23, 0x28, 0x04, 0x11, 0x00, 0x00
395 };
396 
reg_w_buf(struct gspca_dev * gspca_dev,__u8 index,const char * buffer,int len)397 static void reg_w_buf(struct gspca_dev *gspca_dev,
398 		  __u8 index,
399 		  const char *buffer, int len)
400 {
401 	memcpy(gspca_dev->usb_buf, buffer, len);
402 	usb_control_msg(gspca_dev->dev,
403 			usb_sndctrlpipe(gspca_dev->dev, 0),
404 			1,		/* request */
405 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
406 			0,		/* value */
407 			index, gspca_dev->usb_buf, len,
408 			500);
409 }
410 
411 
reg_w(struct gspca_dev * gspca_dev,__u8 index,__u8 value)412 static void reg_w(struct gspca_dev *gspca_dev,
413 		  __u8 index,
414 		  __u8 value)
415 {
416 	gspca_dev->usb_buf[0] = value;
417 	usb_control_msg(gspca_dev->dev,
418 			usb_sndctrlpipe(gspca_dev->dev, 0),
419 			0,			/* request */
420 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
421 			0, index, gspca_dev->usb_buf, 1,
422 			500);
423 }
424 
reg_w_seq(struct gspca_dev * gspca_dev,const __u8 * seq,int len)425 static void reg_w_seq(struct gspca_dev *gspca_dev,
426 		const __u8 *seq, int len)
427 {
428 	while (--len >= 0) {
429 		reg_w(gspca_dev, seq[0], seq[1]);
430 		seq += 2;
431 	}
432 }
433 
434 /* load the beginning of a page */
reg_w_page(struct gspca_dev * gspca_dev,const __u8 * page,int len)435 static void reg_w_page(struct gspca_dev *gspca_dev,
436 			const __u8 *page, int len)
437 {
438 	int index;
439 
440 	for (index = 0; index < len; index++) {
441 		if (page[index] == 0xaa)		/* skip this index */
442 			continue;
443 		gspca_dev->usb_buf[0] = page[index];
444 		usb_control_msg(gspca_dev->dev,
445 				usb_sndctrlpipe(gspca_dev->dev, 0),
446 				0,			/* request */
447 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
448 				0, index, gspca_dev->usb_buf, 1,
449 				500);
450 	}
451 }
452 
453 /* output a variable sequence */
reg_w_var(struct gspca_dev * gspca_dev,const __u8 * seq)454 static void reg_w_var(struct gspca_dev *gspca_dev,
455 			const __u8 *seq)
456 {
457 	int index, len;
458 
459 	for (;;) {
460 		index = *seq++;
461 		len = *seq++;
462 		switch (len) {
463 		case 0:
464 			return;
465 		case 254:
466 			reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
467 			break;
468 		case 255:
469 			reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
470 			break;
471 		default:
472 			if (len > 64) {
473 				PDEBUG(D_ERR|D_STREAM,
474 					"Incorrect variable sequence");
475 				return;
476 			}
477 			while (len > 0) {
478 				if (len < 8) {
479 					reg_w_buf(gspca_dev, index, seq, len);
480 					seq += len;
481 					break;
482 				}
483 				reg_w_buf(gspca_dev, index, seq, 8);
484 				seq += 8;
485 				index += 8;
486 				len -= 8;
487 			}
488 		}
489 	}
490 	/* not reached */
491 }
492 
493 /* this function is called at probe time */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)494 static int sd_config(struct gspca_dev *gspca_dev,
495 			const struct usb_device_id *id)
496 {
497 	struct sd *sd = (struct sd *) gspca_dev;
498 	struct cam *cam;
499 
500 	cam = &gspca_dev->cam;
501 	cam->epaddr = 0x05;
502 
503 	sd->sensor = id->driver_info;
504 	if (sd->sensor == SENSOR_PAC7302) {
505 		PDEBUG(D_CONF, "Find Sensor PAC7302");
506 		cam->cam_mode = &vga_mode[2];	/* only 640x480 */
507 		cam->nmodes = 1;
508 	} else {
509 		PDEBUG(D_CONF, "Find Sensor PAC7311");
510 		cam->cam_mode = vga_mode;
511 		cam->nmodes = ARRAY_SIZE(vga_mode);
512 		gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
513 				| (1 << SATURATION_IDX);
514 	}
515 
516 	sd->brightness = BRIGHTNESS_DEF;
517 	sd->contrast = CONTRAST_DEF;
518 	sd->colors = COLOR_DEF;
519 	sd->gain = GAIN_DEF;
520 	sd->exposure = EXPOSURE_DEF;
521 	sd->autogain = AUTOGAIN_DEF;
522 	sd->hflip = HFLIP_DEF;
523 	sd->vflip = VFLIP_DEF;
524 	return 0;
525 }
526 
527 /* This function is used by pac7302 only */
setbrightcont(struct gspca_dev * gspca_dev)528 static void setbrightcont(struct gspca_dev *gspca_dev)
529 {
530 	struct sd *sd = (struct sd *) gspca_dev;
531 	int i, v;
532 	static const __u8 max[10] =
533 		{0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
534 		 0xd4, 0xec};
535 	static const __u8 delta[10] =
536 		{0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
537 		 0x11, 0x0b};
538 
539 	reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
540 	for (i = 0; i < 10; i++) {
541 		v = max[i];
542 		v += (sd->brightness - BRIGHTNESS_MAX)
543 			* 150 / BRIGHTNESS_MAX;		/* 200 ? */
544 		v -= delta[i] * sd->contrast / CONTRAST_MAX;
545 		if (v < 0)
546 			v = 0;
547 		else if (v > 0xff)
548 			v = 0xff;
549 		reg_w(gspca_dev, 0xa2 + i, v);
550 	}
551 	reg_w(gspca_dev, 0xdc, 0x01);
552 }
553 
554 /* This function is used by pac7311 only */
setcontrast(struct gspca_dev * gspca_dev)555 static void setcontrast(struct gspca_dev *gspca_dev)
556 {
557 	struct sd *sd = (struct sd *) gspca_dev;
558 
559 	reg_w(gspca_dev, 0xff, 0x04);
560 	reg_w(gspca_dev, 0x10, sd->contrast >> 4);
561 	/* load registers to sensor (Bit 0, auto clear) */
562 	reg_w(gspca_dev, 0x11, 0x01);
563 }
564 
565 /* This function is used by pac7302 only */
setcolors(struct gspca_dev * gspca_dev)566 static void setcolors(struct gspca_dev *gspca_dev)
567 {
568 	struct sd *sd = (struct sd *) gspca_dev;
569 	int i, v;
570 	static const int a[9] =
571 		{217, -212, 0, -101, 170, -67, -38, -315, 355};
572 	static const int b[9] =
573 		{19, 106, 0, 19, 106, 1, 19, 106, 1};
574 
575 	reg_w(gspca_dev, 0xff, 0x03);	/* page 3 */
576 	reg_w(gspca_dev, 0x11, 0x01);
577 	reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
578 	reg_w(gspca_dev, 0xff, 0x00);	/* page 0 */
579 	for (i = 0; i < 9; i++) {
580 		v = a[i] * sd->colors / COLOR_MAX + b[i];
581 		reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
582 		reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
583 	}
584 	reg_w(gspca_dev, 0xdc, 0x01);
585 	PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
586 }
587 
setgain(struct gspca_dev * gspca_dev)588 static void setgain(struct gspca_dev *gspca_dev)
589 {
590 	struct sd *sd = (struct sd *) gspca_dev;
591 
592 	if (sd->sensor == SENSOR_PAC7302) {
593 		reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
594 		reg_w(gspca_dev, 0x10, sd->gain >> 3);
595 	} else {
596 		int gain = GAIN_MAX - sd->gain;
597 		if (gain < 1)
598 			gain = 1;
599 		else if (gain > 245)
600 			gain = 245;
601 		reg_w(gspca_dev, 0xff, 0x04);		/* page 4 */
602 		reg_w(gspca_dev, 0x0e, 0x00);
603 		reg_w(gspca_dev, 0x0f, gain);
604 	}
605 	/* load registers to sensor (Bit 0, auto clear) */
606 	reg_w(gspca_dev, 0x11, 0x01);
607 }
608 
setexposure(struct gspca_dev * gspca_dev)609 static void setexposure(struct gspca_dev *gspca_dev)
610 {
611 	struct sd *sd = (struct sd *) gspca_dev;
612 	__u8 reg;
613 
614 	/* register 2 of frame 3/4 contains the clock divider configuring the
615 	   no fps according to the formula: 60 / reg. sd->exposure is the
616 	   desired exposure time in ms. */
617 	reg = 120 * sd->exposure / 1000;
618 	if (reg < 2)
619 		reg = 2;
620 	else if (reg > 63)
621 		reg = 63;
622 
623 	if (sd->sensor == SENSOR_PAC7302) {
624 		/* On the pac7302 reg2 MUST be a multiple of 3, so round it to
625 		   the nearest multiple of 3, except when between 6 and 12? */
626 		if (reg < 6 || reg > 12)
627 			reg = ((reg + 1) / 3) * 3;
628 		reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
629 		reg_w(gspca_dev, 0x02, reg);
630 	} else {
631 		reg_w(gspca_dev, 0xff, 0x04);		/* page 4 */
632 		reg_w(gspca_dev, 0x02, reg);
633 		/* Page 1 register 8 must always be 0x08 except when not in
634 		   640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
635 		reg_w(gspca_dev, 0xff, 0x01);
636 		if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
637 				reg <= 3)
638 			reg_w(gspca_dev, 0x08, 0x09);
639 		else
640 			reg_w(gspca_dev, 0x08, 0x08);
641 	}
642 	/* load registers to sensor (Bit 0, auto clear) */
643 	reg_w(gspca_dev, 0x11, 0x01);
644 }
645 
sethvflip(struct gspca_dev * gspca_dev)646 static void sethvflip(struct gspca_dev *gspca_dev)
647 {
648 	struct sd *sd = (struct sd *) gspca_dev;
649 	__u8 data;
650 
651 	if (sd->sensor == SENSOR_PAC7302) {
652 		reg_w(gspca_dev, 0xff, 0x03);		/* page 3 */
653 		data = (sd->hflip ? 0x08 : 0x00)
654 			| (sd->vflip ? 0x04 : 0x00);
655 	} else {
656 		reg_w(gspca_dev, 0xff, 0x04);		/* page 4 */
657 		data = (sd->hflip ? 0x04 : 0x00)
658 			| (sd->vflip ? 0x08 : 0x00);
659 	}
660 	reg_w(gspca_dev, 0x21, data);
661 	/* load registers to sensor (Bit 0, auto clear) */
662 	reg_w(gspca_dev, 0x11, 0x01);
663 }
664 
665 /* this function is called at probe and resume time */
sd_init(struct gspca_dev * gspca_dev)666 static int sd_init(struct gspca_dev *gspca_dev)
667 {
668 	struct sd *sd = (struct sd *) gspca_dev;
669 
670 	if (sd->sensor == SENSOR_PAC7302)
671 		reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
672 	else
673 		reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
674 
675 	return 0;
676 }
677 
sd_start(struct gspca_dev * gspca_dev)678 static int sd_start(struct gspca_dev *gspca_dev)
679 {
680 	struct sd *sd = (struct sd *) gspca_dev;
681 
682 	sd->sof_read = 0;
683 
684 	if (sd->sensor == SENSOR_PAC7302) {
685 		reg_w_var(gspca_dev, start_7302);
686 		setbrightcont(gspca_dev);
687 		setcolors(gspca_dev);
688 	} else {
689 		reg_w_var(gspca_dev, start_7311);
690 		setcontrast(gspca_dev);
691 	}
692 	setgain(gspca_dev);
693 	setexposure(gspca_dev);
694 	sethvflip(gspca_dev);
695 
696 	/* set correct resolution */
697 	switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
698 	case 2:					/* 160x120 pac7311 */
699 		reg_w(gspca_dev, 0xff, 0x01);
700 		reg_w(gspca_dev, 0x17, 0x20);
701 		reg_w(gspca_dev, 0x87, 0x10);
702 		break;
703 	case 1:					/* 320x240 pac7311 */
704 		reg_w(gspca_dev, 0xff, 0x01);
705 		reg_w(gspca_dev, 0x17, 0x30);
706 		reg_w(gspca_dev, 0x87, 0x11);
707 		break;
708 	case 0:					/* 640x480 */
709 		if (sd->sensor == SENSOR_PAC7302)
710 			break;
711 		reg_w(gspca_dev, 0xff, 0x01);
712 		reg_w(gspca_dev, 0x17, 0x00);
713 		reg_w(gspca_dev, 0x87, 0x12);
714 		break;
715 	}
716 
717 	sd->sof_read = 0;
718 	sd->autogain_ignore_frames = 0;
719 	atomic_set(&sd->avg_lum, -1);
720 
721 	/* start stream */
722 	reg_w(gspca_dev, 0xff, 0x01);
723 	if (sd->sensor == SENSOR_PAC7302)
724 		reg_w(gspca_dev, 0x78, 0x01);
725 	else
726 		reg_w(gspca_dev, 0x78, 0x05);
727 	return 0;
728 }
729 
sd_stopN(struct gspca_dev * gspca_dev)730 static void sd_stopN(struct gspca_dev *gspca_dev)
731 {
732 	struct sd *sd = (struct sd *) gspca_dev;
733 
734 	if (sd->sensor == SENSOR_PAC7302) {
735 		reg_w(gspca_dev, 0xff, 0x01);
736 		reg_w(gspca_dev, 0x78, 0x00);
737 		reg_w(gspca_dev, 0x78, 0x00);
738 		return;
739 	}
740 	reg_w(gspca_dev, 0xff, 0x04);
741 	reg_w(gspca_dev, 0x27, 0x80);
742 	reg_w(gspca_dev, 0x28, 0xca);
743 	reg_w(gspca_dev, 0x29, 0x53);
744 	reg_w(gspca_dev, 0x2a, 0x0e);
745 	reg_w(gspca_dev, 0xff, 0x01);
746 	reg_w(gspca_dev, 0x3e, 0x20);
747 	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
748 	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
749 	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
750 }
751 
752 /* called on streamoff with alt 0 and on disconnect */
sd_stop0(struct gspca_dev * gspca_dev)753 static void sd_stop0(struct gspca_dev *gspca_dev)
754 {
755 	struct sd *sd = (struct sd *) gspca_dev;
756 
757 	if (!gspca_dev->present)
758 		return;
759 	if (sd->sensor == SENSOR_PAC7302) {
760 		reg_w(gspca_dev, 0xff, 0x01);
761 		reg_w(gspca_dev, 0x78, 0x40);
762 	}
763 }
764 
765 /* Include pac common sof detection functions */
766 #include "pac_common.h"
767 
do_autogain(struct gspca_dev * gspca_dev)768 static void do_autogain(struct gspca_dev *gspca_dev)
769 {
770 	struct sd *sd = (struct sd *) gspca_dev;
771 	int avg_lum = atomic_read(&sd->avg_lum);
772 	int desired_lum, deadzone;
773 
774 	if (avg_lum == -1)
775 		return;
776 
777 	if (sd->sensor == SENSOR_PAC7302) {
778 		desired_lum = 270 + sd->brightness * 4;
779 		/* Hack hack, with the 7202 the first exposure step is
780 		   pretty large, so if we're about to make the first
781 		   exposure increase make the deadzone large to avoid
782 		   oscilating */
783 		if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
784 				sd->exposure > EXPOSURE_DEF &&
785 				sd->exposure < 42)
786 			deadzone = 90;
787 		else
788 			deadzone = 30;
789 	} else {
790 		desired_lum = 200;
791 		deadzone = 20;
792 	}
793 
794 	if (sd->autogain_ignore_frames > 0)
795 		sd->autogain_ignore_frames--;
796 	else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
797 			deadzone, GAIN_KNEE, EXPOSURE_KNEE))
798 		sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
799 }
800 
801 static const unsigned char pac7311_jpeg_header1[] = {
802   0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
803 };
804 
805 static const unsigned char pac7311_jpeg_header2[] = {
806   0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
807   0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
808 };
809 
810 /* this function is run at interrupt level */
sd_pkt_scan(struct gspca_dev * gspca_dev,struct gspca_frame * frame,__u8 * data,int len)811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
812 			struct gspca_frame *frame,	/* target */
813 			__u8 *data,			/* isoc packet */
814 			int len)			/* iso packet length */
815 {
816 	struct sd *sd = (struct sd *) gspca_dev;
817 	unsigned char *sof;
818 
819 	sof = pac_find_sof(gspca_dev, data, len);
820 	if (sof) {
821 		unsigned char tmpbuf[4];
822 		int n, lum_offset, footer_length;
823 
824 		if (sd->sensor == SENSOR_PAC7302) {
825 		  /* 6 bytes after the FF D9 EOF marker a number of lumination
826 		     bytes are send corresponding to different parts of the
827 		     image, the 14th and 15th byte after the EOF seem to
828 		     correspond to the center of the image */
829 		  lum_offset = 61 + sizeof pac_sof_marker;
830 		  footer_length = 74;
831 		} else {
832 		  lum_offset = 24 + sizeof pac_sof_marker;
833 		  footer_length = 26;
834 		}
835 
836 		/* Finish decoding current frame */
837 		n = (sof - data) - (footer_length + sizeof pac_sof_marker);
838 		if (n < 0) {
839 			frame->data_end += n;
840 			n = 0;
841 		}
842 		frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
843 					data, n);
844 		if (gspca_dev->last_packet_type != DISCARD_PACKET &&
845 				frame->data_end[-2] == 0xff &&
846 				frame->data_end[-1] == 0xd9)
847 			frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
848 						NULL, 0);
849 
850 		n = sof - data;
851 		len -= n;
852 		data = sof;
853 
854 		/* Get average lumination */
855 		if (gspca_dev->last_packet_type == LAST_PACKET &&
856 				n >= lum_offset)
857 			atomic_set(&sd->avg_lum, data[-lum_offset] +
858 						data[-lum_offset + 1]);
859 		else
860 			atomic_set(&sd->avg_lum, -1);
861 
862 		/* Start the new frame with the jpeg header */
863 		gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
864 			pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
865 		if (sd->sensor == SENSOR_PAC7302) {
866 			/* The PAC7302 has the image rotated 90 degrees */
867 			tmpbuf[0] = gspca_dev->width >> 8;
868 			tmpbuf[1] = gspca_dev->width & 0xff;
869 			tmpbuf[2] = gspca_dev->height >> 8;
870 			tmpbuf[3] = gspca_dev->height & 0xff;
871 		} else {
872 			tmpbuf[0] = gspca_dev->height >> 8;
873 			tmpbuf[1] = gspca_dev->height & 0xff;
874 			tmpbuf[2] = gspca_dev->width >> 8;
875 			tmpbuf[3] = gspca_dev->width & 0xff;
876 		}
877 		gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
878 		gspca_frame_add(gspca_dev, INTER_PACKET, frame,
879 			pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
880 	}
881 	gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
882 }
883 
sd_setbrightness(struct gspca_dev * gspca_dev,__s32 val)884 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
885 {
886 	struct sd *sd = (struct sd *) gspca_dev;
887 
888 	sd->brightness = val;
889 	if (gspca_dev->streaming)
890 		setbrightcont(gspca_dev);
891 	return 0;
892 }
893 
sd_getbrightness(struct gspca_dev * gspca_dev,__s32 * val)894 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
895 {
896 	struct sd *sd = (struct sd *) gspca_dev;
897 
898 	*val = sd->brightness;
899 	return 0;
900 }
901 
sd_setcontrast(struct gspca_dev * gspca_dev,__s32 val)902 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
903 {
904 	struct sd *sd = (struct sd *) gspca_dev;
905 
906 	sd->contrast = val;
907 	if (gspca_dev->streaming) {
908 		if (sd->sensor == SENSOR_PAC7302)
909 			setbrightcont(gspca_dev);
910 		else
911 			setcontrast(gspca_dev);
912 	}
913 	return 0;
914 }
915 
sd_getcontrast(struct gspca_dev * gspca_dev,__s32 * val)916 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
917 {
918 	struct sd *sd = (struct sd *) gspca_dev;
919 
920 	*val = sd->contrast;
921 	return 0;
922 }
923 
sd_setcolors(struct gspca_dev * gspca_dev,__s32 val)924 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
925 {
926 	struct sd *sd = (struct sd *) gspca_dev;
927 
928 	sd->colors = val;
929 	if (gspca_dev->streaming)
930 		setcolors(gspca_dev);
931 	return 0;
932 }
933 
sd_getcolors(struct gspca_dev * gspca_dev,__s32 * val)934 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
935 {
936 	struct sd *sd = (struct sd *) gspca_dev;
937 
938 	*val = sd->colors;
939 	return 0;
940 }
941 
sd_setgain(struct gspca_dev * gspca_dev,__s32 val)942 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
943 {
944 	struct sd *sd = (struct sd *) gspca_dev;
945 
946 	sd->gain = val;
947 	if (gspca_dev->streaming)
948 		setgain(gspca_dev);
949 	return 0;
950 }
951 
sd_getgain(struct gspca_dev * gspca_dev,__s32 * val)952 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
953 {
954 	struct sd *sd = (struct sd *) gspca_dev;
955 
956 	*val = sd->gain;
957 	return 0;
958 }
959 
sd_setexposure(struct gspca_dev * gspca_dev,__s32 val)960 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
961 {
962 	struct sd *sd = (struct sd *) gspca_dev;
963 
964 	sd->exposure = val;
965 	if (gspca_dev->streaming)
966 		setexposure(gspca_dev);
967 	return 0;
968 }
969 
sd_getexposure(struct gspca_dev * gspca_dev,__s32 * val)970 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
971 {
972 	struct sd *sd = (struct sd *) gspca_dev;
973 
974 	*val = sd->exposure;
975 	return 0;
976 }
977 
sd_setautogain(struct gspca_dev * gspca_dev,__s32 val)978 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
979 {
980 	struct sd *sd = (struct sd *) gspca_dev;
981 
982 	sd->autogain = val;
983 	/* when switching to autogain set defaults to make sure
984 	   we are on a valid point of the autogain gain /
985 	   exposure knee graph, and give this change time to
986 	   take effect before doing autogain. */
987 	if (sd->autogain) {
988 		sd->exposure = EXPOSURE_DEF;
989 		sd->gain = GAIN_DEF;
990 		if (gspca_dev->streaming) {
991 			sd->autogain_ignore_frames =
992 				PAC_AUTOGAIN_IGNORE_FRAMES;
993 			setexposure(gspca_dev);
994 			setgain(gspca_dev);
995 		}
996 	}
997 
998 	return 0;
999 }
1000 
sd_getautogain(struct gspca_dev * gspca_dev,__s32 * val)1001 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1002 {
1003 	struct sd *sd = (struct sd *) gspca_dev;
1004 
1005 	*val = sd->autogain;
1006 	return 0;
1007 }
1008 
sd_sethflip(struct gspca_dev * gspca_dev,__s32 val)1009 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1010 {
1011 	struct sd *sd = (struct sd *) gspca_dev;
1012 
1013 	sd->hflip = val;
1014 	if (gspca_dev->streaming)
1015 		sethvflip(gspca_dev);
1016 	return 0;
1017 }
1018 
sd_gethflip(struct gspca_dev * gspca_dev,__s32 * val)1019 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1020 {
1021 	struct sd *sd = (struct sd *) gspca_dev;
1022 
1023 	*val = sd->hflip;
1024 	return 0;
1025 }
1026 
sd_setvflip(struct gspca_dev * gspca_dev,__s32 val)1027 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1028 {
1029 	struct sd *sd = (struct sd *) gspca_dev;
1030 
1031 	sd->vflip = val;
1032 	if (gspca_dev->streaming)
1033 		sethvflip(gspca_dev);
1034 	return 0;
1035 }
1036 
sd_getvflip(struct gspca_dev * gspca_dev,__s32 * val)1037 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1038 {
1039 	struct sd *sd = (struct sd *) gspca_dev;
1040 
1041 	*val = sd->vflip;
1042 	return 0;
1043 }
1044 
1045 /* sub-driver description */
1046 static struct sd_desc sd_desc = {
1047 	.name = MODULE_NAME,
1048 	.ctrls = sd_ctrls,
1049 	.nctrls = ARRAY_SIZE(sd_ctrls),
1050 	.config = sd_config,
1051 	.init = sd_init,
1052 	.start = sd_start,
1053 	.stopN = sd_stopN,
1054 	.stop0 = sd_stop0,
1055 	.pkt_scan = sd_pkt_scan,
1056 	.dq_callback = do_autogain,
1057 };
1058 
1059 /* -- module initialisation -- */
1060 static __devinitdata struct usb_device_id device_table[] = {
1061 	{USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
1062 	{USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
1063 	{USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
1064 	{USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
1065 	{USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
1066 	{USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
1067 	{USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302},
1068 	{USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
1069 	{USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302},
1070 	{USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
1071 	{USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
1072 	{USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
1073 	{USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302},
1074 	{}
1075 };
1076 MODULE_DEVICE_TABLE(usb, device_table);
1077 
1078 /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)1079 static int sd_probe(struct usb_interface *intf,
1080 			const struct usb_device_id *id)
1081 {
1082 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1083 				THIS_MODULE);
1084 }
1085 
1086 static struct usb_driver sd_driver = {
1087 	.name = MODULE_NAME,
1088 	.id_table = device_table,
1089 	.probe = sd_probe,
1090 	.disconnect = gspca_disconnect,
1091 #ifdef CONFIG_PM
1092 	.suspend = gspca_suspend,
1093 	.resume = gspca_resume,
1094 #endif
1095 };
1096 
1097 /* -- module insert / remove -- */
sd_mod_init(void)1098 static int __init sd_mod_init(void)
1099 {
1100 	if (usb_register(&sd_driver) < 0)
1101 		return -1;
1102 	PDEBUG(D_PROBE, "registered");
1103 	return 0;
1104 }
sd_mod_exit(void)1105 static void __exit sd_mod_exit(void)
1106 {
1107 	usb_deregister(&sd_driver);
1108 	PDEBUG(D_PROBE, "deregistered");
1109 }
1110 
1111 module_init(sd_mod_init);
1112 module_exit(sd_mod_exit);
1113