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