V4L/DVB (13899): gspca - all subdrivers: Make control descriptors constant.
[linux-2.6/btrfs-unstable.git] / drivers / media / video / gspca / pac7311.c
blob704cf67e1788913682cf6097dd0abaff66bdf2d9
1 /*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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.
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.
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
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.
28 Register page 1:
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
38 Register page 3/4:
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.
52 #define MODULE_NAME "pac7311"
54 #include "gspca.h"
56 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
57 MODULE_DESCRIPTION("Pixart PAC7311");
58 MODULE_LICENSE("GPL");
60 /* specific webcam descriptor for pac7311 */
61 struct sd {
62 struct gspca_dev gspca_dev; /* !! must be the first item */
64 unsigned char contrast;
65 unsigned char gain;
66 unsigned char exposure;
67 unsigned char autogain;
68 __u8 hflip;
69 __u8 vflip;
71 u8 sof_read;
72 u8 autogain_ignore_frames;
74 atomic_t avg_lum;
77 /* V4L2 controls supported by the driver */
78 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
79 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
80 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91 static const struct ctrl sd_ctrls[] = {
92 /* This control is for both the 7302 and the 7311 */
95 .id = V4L2_CID_CONTRAST,
96 .type = V4L2_CTRL_TYPE_INTEGER,
97 .name = "Contrast",
98 .minimum = 0,
99 #define CONTRAST_MAX 255
100 .maximum = CONTRAST_MAX,
101 .step = 1,
102 #define CONTRAST_DEF 127
103 .default_value = CONTRAST_DEF,
105 .set = sd_setcontrast,
106 .get = sd_getcontrast,
108 /* All controls below are for both the 7302 and the 7311 */
111 .id = V4L2_CID_GAIN,
112 .type = V4L2_CTRL_TYPE_INTEGER,
113 .name = "Gain",
114 .minimum = 0,
115 #define GAIN_MAX 255
116 .maximum = GAIN_MAX,
117 .step = 1,
118 #define GAIN_DEF 127
119 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
120 .default_value = GAIN_DEF,
122 .set = sd_setgain,
123 .get = sd_getgain,
127 .id = V4L2_CID_EXPOSURE,
128 .type = V4L2_CTRL_TYPE_INTEGER,
129 .name = "Exposure",
130 .minimum = 0,
131 #define EXPOSURE_MAX 255
132 .maximum = EXPOSURE_MAX,
133 .step = 1,
134 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
135 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
136 .default_value = EXPOSURE_DEF,
138 .set = sd_setexposure,
139 .get = sd_getexposure,
143 .id = V4L2_CID_AUTOGAIN,
144 .type = V4L2_CTRL_TYPE_BOOLEAN,
145 .name = "Auto Gain",
146 .minimum = 0,
147 .maximum = 1,
148 .step = 1,
149 #define AUTOGAIN_DEF 1
150 .default_value = AUTOGAIN_DEF,
152 .set = sd_setautogain,
153 .get = sd_getautogain,
157 .id = V4L2_CID_HFLIP,
158 .type = V4L2_CTRL_TYPE_BOOLEAN,
159 .name = "Mirror",
160 .minimum = 0,
161 .maximum = 1,
162 .step = 1,
163 #define HFLIP_DEF 0
164 .default_value = HFLIP_DEF,
166 .set = sd_sethflip,
167 .get = sd_gethflip,
171 .id = V4L2_CID_VFLIP,
172 .type = V4L2_CTRL_TYPE_BOOLEAN,
173 .name = "Vflip",
174 .minimum = 0,
175 .maximum = 1,
176 .step = 1,
177 #define VFLIP_DEF 0
178 .default_value = VFLIP_DEF,
180 .set = sd_setvflip,
181 .get = sd_getvflip,
185 static const struct v4l2_pix_format vga_mode[] = {
186 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
187 .bytesperline = 160,
188 .sizeimage = 160 * 120 * 3 / 8 + 590,
189 .colorspace = V4L2_COLORSPACE_JPEG,
190 .priv = 2},
191 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
192 .bytesperline = 320,
193 .sizeimage = 320 * 240 * 3 / 8 + 590,
194 .colorspace = V4L2_COLORSPACE_JPEG,
195 .priv = 1},
196 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
197 .bytesperline = 640,
198 .sizeimage = 640 * 480 * 3 / 8 + 590,
199 .colorspace = V4L2_COLORSPACE_JPEG,
200 .priv = 0},
203 #define LOAD_PAGE3 255
204 #define LOAD_PAGE4 254
205 #define END_OF_SEQUENCE 0
207 /* pac 7311 */
208 static const __u8 init_7311[] = {
209 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
210 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
211 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
212 0xff, 0x04,
213 0x27, 0x80,
214 0x28, 0xca,
215 0x29, 0x53,
216 0x2a, 0x0e,
217 0xff, 0x01,
218 0x3e, 0x20,
221 static const __u8 start_7311[] = {
222 /* index, len, [value]* */
223 0xff, 1, 0x01, /* page 1 */
224 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
225 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
226 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
227 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00,
230 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
231 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
232 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
233 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
234 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
235 0xd0, 0xff,
236 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
237 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
238 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
239 0x18, 0x20,
240 0x96, 3, 0x01, 0x08, 0x04,
241 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
242 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
243 0x3f, 0x00, 0x0a, 0x01, 0x00,
244 0xff, 1, 0x04, /* page 4 */
245 0, LOAD_PAGE4, /* load the page 4 */
246 0x11, 1, 0x01,
247 0, END_OF_SEQUENCE /* end of sequence */
250 #define SKIP 0xaa
251 /* page 4 - the value SKIP says skip the index - see reg_w_page() */
252 static const __u8 page4_7311[] = {
253 SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
254 0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
255 0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
257 SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
258 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
259 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
262 static int reg_w_buf(struct gspca_dev *gspca_dev,
263 __u8 index,
264 const char *buffer, int len)
266 int ret;
268 memcpy(gspca_dev->usb_buf, buffer, len);
269 ret = usb_control_msg(gspca_dev->dev,
270 usb_sndctrlpipe(gspca_dev->dev, 0),
271 1, /* request */
272 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
273 0, /* value */
274 index, gspca_dev->usb_buf, len,
275 500);
276 if (ret < 0)
277 PDEBUG(D_ERR, "reg_w_buf(): "
278 "Failed to write registers to index 0x%x, error %i",
279 index, ret);
280 return ret;
284 static int reg_w(struct gspca_dev *gspca_dev,
285 __u8 index,
286 __u8 value)
288 int ret;
290 gspca_dev->usb_buf[0] = value;
291 ret = usb_control_msg(gspca_dev->dev,
292 usb_sndctrlpipe(gspca_dev->dev, 0),
293 0, /* request */
294 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
295 0, index, gspca_dev->usb_buf, 1,
296 500);
297 if (ret < 0)
298 PDEBUG(D_ERR, "reg_w(): "
299 "Failed to write register to index 0x%x, value 0x%x, error %i",
300 index, value, ret);
301 return ret;
304 static int reg_w_seq(struct gspca_dev *gspca_dev,
305 const __u8 *seq, int len)
307 int ret = 0;
308 while (--len >= 0) {
309 if (0 <= ret)
310 ret = reg_w(gspca_dev, seq[0], seq[1]);
311 seq += 2;
313 return ret;
316 /* load the beginning of a page */
317 static int reg_w_page(struct gspca_dev *gspca_dev,
318 const __u8 *page, int len)
320 int index;
321 int ret = 0;
323 for (index = 0; index < len; index++) {
324 if (page[index] == SKIP) /* skip this index */
325 continue;
326 gspca_dev->usb_buf[0] = page[index];
327 ret = usb_control_msg(gspca_dev->dev,
328 usb_sndctrlpipe(gspca_dev->dev, 0),
329 0, /* request */
330 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
331 0, index, gspca_dev->usb_buf, 1,
332 500);
333 if (ret < 0) {
334 PDEBUG(D_ERR, "reg_w_page(): "
335 "Failed to write register to index 0x%x, "
336 "value 0x%x, error %i",
337 index, page[index], ret);
338 break;
341 return ret;
344 /* output a variable sequence */
345 static int reg_w_var(struct gspca_dev *gspca_dev,
346 const __u8 *seq,
347 const __u8 *page3, unsigned int page3_len,
348 const __u8 *page4, unsigned int page4_len)
350 int index, len;
351 int ret = 0;
353 for (;;) {
354 index = *seq++;
355 len = *seq++;
356 switch (len) {
357 case END_OF_SEQUENCE:
358 return ret;
359 case LOAD_PAGE4:
360 ret = reg_w_page(gspca_dev, page4, page4_len);
361 break;
362 case LOAD_PAGE3:
363 ret = reg_w_page(gspca_dev, page3, page3_len);
364 break;
365 default:
366 if (len > USB_BUF_SZ) {
367 PDEBUG(D_ERR|D_STREAM,
368 "Incorrect variable sequence");
369 return -EINVAL;
371 while (len > 0) {
372 if (len < 8) {
373 ret = reg_w_buf(gspca_dev,
374 index, seq, len);
375 if (ret < 0)
376 return ret;
377 seq += len;
378 break;
380 ret = reg_w_buf(gspca_dev, index, seq, 8);
381 seq += 8;
382 index += 8;
383 len -= 8;
386 if (ret < 0)
387 return ret;
389 /* not reached */
392 /* this function is called at probe time for pac7311 */
393 static int sd_config(struct gspca_dev *gspca_dev,
394 const struct usb_device_id *id)
396 struct sd *sd = (struct sd *) gspca_dev;
397 struct cam *cam;
399 cam = &gspca_dev->cam;
401 PDEBUG(D_CONF, "Find Sensor PAC7311");
402 cam->cam_mode = vga_mode;
403 cam->nmodes = ARRAY_SIZE(vga_mode);
405 sd->contrast = CONTRAST_DEF;
406 sd->gain = GAIN_DEF;
407 sd->exposure = EXPOSURE_DEF;
408 sd->autogain = AUTOGAIN_DEF;
409 sd->hflip = HFLIP_DEF;
410 sd->vflip = VFLIP_DEF;
411 return 0;
414 /* This function is used by pac7311 only */
415 static int setcontrast(struct gspca_dev *gspca_dev)
417 struct sd *sd = (struct sd *) gspca_dev;
418 int ret;
420 ret = reg_w(gspca_dev, 0xff, 0x04);
421 if (0 <= ret)
422 ret = reg_w(gspca_dev, 0x10, sd->contrast >> 4);
423 /* load registers to sensor (Bit 0, auto clear) */
424 if (0 <= ret)
425 ret = reg_w(gspca_dev, 0x11, 0x01);
426 return ret;
429 static int setgain(struct gspca_dev *gspca_dev)
431 struct sd *sd = (struct sd *) gspca_dev;
432 int gain = GAIN_MAX - sd->gain;
433 int ret;
435 if (gain < 1)
436 gain = 1;
437 else if (gain > 245)
438 gain = 245;
439 ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
440 if (0 <= ret)
441 ret = reg_w(gspca_dev, 0x0e, 0x00);
442 if (0 <= ret)
443 ret = reg_w(gspca_dev, 0x0f, gain);
445 /* load registers to sensor (Bit 0, auto clear) */
446 if (0 <= ret)
447 ret = reg_w(gspca_dev, 0x11, 0x01);
448 return ret;
451 static int setexposure(struct gspca_dev *gspca_dev)
453 struct sd *sd = (struct sd *) gspca_dev;
454 int ret;
455 __u8 reg;
457 /* register 2 of frame 3/4 contains the clock divider configuring the
458 no fps according to the formula: 60 / reg. sd->exposure is the
459 desired exposure time in ms. */
460 reg = 120 * sd->exposure / 1000;
461 if (reg < 2)
462 reg = 2;
463 else if (reg > 63)
464 reg = 63;
466 ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
467 if (0 <= ret)
468 ret = reg_w(gspca_dev, 0x02, reg);
469 /* Page 1 register 8 must always be 0x08 except when not in
470 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
471 if (0 <= ret)
472 ret = reg_w(gspca_dev, 0xff, 0x01);
473 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
474 reg <= 3) {
475 if (0 <= ret)
476 ret = reg_w(gspca_dev, 0x08, 0x09);
477 } else {
478 if (0 <= ret)
479 ret = reg_w(gspca_dev, 0x08, 0x08);
482 /* load registers to sensor (Bit 0, auto clear) */
483 if (0 <= ret)
484 ret = reg_w(gspca_dev, 0x11, 0x01);
485 return ret;
488 static int sethvflip(struct gspca_dev *gspca_dev)
490 struct sd *sd = (struct sd *) gspca_dev;
491 int ret;
492 __u8 data;
494 ret = reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
495 data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
496 if (0 <= ret)
497 ret = reg_w(gspca_dev, 0x21, data);
498 /* load registers to sensor (Bit 0, auto clear) */
499 if (0 <= ret)
500 ret = reg_w(gspca_dev, 0x11, 0x01);
501 return ret;
504 /* this function is called at probe and resume time for pac7311 */
505 static int sd_init(struct gspca_dev *gspca_dev)
507 return reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
510 static int sd_start(struct gspca_dev *gspca_dev)
512 struct sd *sd = (struct sd *) gspca_dev;
513 int ret;
515 sd->sof_read = 0;
517 ret = reg_w_var(gspca_dev, start_7311,
518 NULL, 0,
519 page4_7311, sizeof(page4_7311));
520 if (0 <= ret)
521 ret = setcontrast(gspca_dev);
522 if (0 <= ret)
523 ret = setgain(gspca_dev);
524 if (0 <= ret)
525 ret = setexposure(gspca_dev);
526 if (0 <= ret)
527 ret = sethvflip(gspca_dev);
529 /* set correct resolution */
530 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
531 case 2: /* 160x120 pac7311 */
532 if (0 <= ret)
533 ret = reg_w(gspca_dev, 0xff, 0x01);
534 if (0 <= ret)
535 ret = reg_w(gspca_dev, 0x17, 0x20);
536 if (0 <= ret)
537 ret = reg_w(gspca_dev, 0x87, 0x10);
538 break;
539 case 1: /* 320x240 pac7311 */
540 if (0 <= ret)
541 ret = reg_w(gspca_dev, 0xff, 0x01);
542 if (0 <= ret)
543 ret = reg_w(gspca_dev, 0x17, 0x30);
544 if (0 <= ret)
545 ret = reg_w(gspca_dev, 0x87, 0x11);
546 break;
547 case 0: /* 640x480 */
548 if (0 <= ret)
549 ret = reg_w(gspca_dev, 0xff, 0x01);
550 if (0 <= ret)
551 ret = reg_w(gspca_dev, 0x17, 0x00);
552 if (0 <= ret)
553 ret = reg_w(gspca_dev, 0x87, 0x12);
554 break;
557 sd->sof_read = 0;
558 sd->autogain_ignore_frames = 0;
559 atomic_set(&sd->avg_lum, -1);
561 /* start stream */
562 if (0 <= ret)
563 ret = reg_w(gspca_dev, 0xff, 0x01);
564 if (0 <= ret)
565 ret = reg_w(gspca_dev, 0x78, 0x05);
567 return ret;
570 static void sd_stopN(struct gspca_dev *gspca_dev)
572 int ret;
574 ret = reg_w(gspca_dev, 0xff, 0x04);
575 if (0 <= ret)
576 ret = reg_w(gspca_dev, 0x27, 0x80);
577 if (0 <= ret)
578 ret = reg_w(gspca_dev, 0x28, 0xca);
579 if (0 <= ret)
580 ret = reg_w(gspca_dev, 0x29, 0x53);
581 if (0 <= ret)
582 ret = reg_w(gspca_dev, 0x2a, 0x0e);
583 if (0 <= ret)
584 ret = reg_w(gspca_dev, 0xff, 0x01);
585 if (0 <= ret)
586 ret = reg_w(gspca_dev, 0x3e, 0x20);
587 if (0 <= ret)
588 ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
589 if (0 <= ret)
590 ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
591 if (0 <= ret)
592 ret = reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
595 /* called on streamoff with alt 0 and on disconnect for 7311 */
596 static void sd_stop0(struct gspca_dev *gspca_dev)
600 /* Include pac common sof detection functions */
601 #include "pac_common.h"
603 static void do_autogain(struct gspca_dev *gspca_dev)
605 struct sd *sd = (struct sd *) gspca_dev;
606 int avg_lum = atomic_read(&sd->avg_lum);
607 int desired_lum, deadzone;
609 if (avg_lum == -1)
610 return;
612 desired_lum = 200;
613 deadzone = 20;
615 if (sd->autogain_ignore_frames > 0)
616 sd->autogain_ignore_frames--;
617 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
618 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
619 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
622 /* JPEG header, part 1 */
623 static const unsigned char pac_jpeg_header1[] = {
624 0xff, 0xd8, /* SOI: Start of Image */
626 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
627 0x00, 0x11, /* length = 17 bytes (including this length field) */
628 0x08 /* Precision: 8 */
629 /* 2 bytes is placed here: number of image lines */
630 /* 2 bytes is placed here: samples per line */
633 /* JPEG header, continued */
634 static const unsigned char pac_jpeg_header2[] = {
635 0x03, /* Number of image components: 3 */
636 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
637 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
638 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
640 0xff, 0xda, /* SOS: Start Of Scan */
641 0x00, 0x0c, /* length = 12 bytes (including this length field) */
642 0x03, /* number of components: 3 */
643 0x01, 0x00, /* selector 1, table 0x00 */
644 0x02, 0x11, /* selector 2, table 0x11 */
645 0x03, 0x11, /* selector 3, table 0x11 */
646 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
647 0x00 /* Successive approximation: 0 */
650 static void pac_start_frame(struct gspca_dev *gspca_dev,
651 struct gspca_frame *frame,
652 __u16 lines, __u16 samples_per_line)
654 unsigned char tmpbuf[4];
656 gspca_frame_add(gspca_dev, FIRST_PACKET,
657 pac_jpeg_header1, sizeof(pac_jpeg_header1));
659 tmpbuf[0] = lines >> 8;
660 tmpbuf[1] = lines & 0xff;
661 tmpbuf[2] = samples_per_line >> 8;
662 tmpbuf[3] = samples_per_line & 0xff;
664 gspca_frame_add(gspca_dev, INTER_PACKET,
665 tmpbuf, sizeof(tmpbuf));
666 gspca_frame_add(gspca_dev, INTER_PACKET,
667 pac_jpeg_header2, sizeof(pac_jpeg_header2));
670 /* this function is run at interrupt level */
671 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
672 u8 *data, /* isoc packet */
673 int len) /* iso packet length */
675 struct sd *sd = (struct sd *) gspca_dev;
676 unsigned char *sof;
677 struct gspca_frame *frame;
679 sof = pac_find_sof(&sd->sof_read, data, len);
680 if (sof) {
681 int n, lum_offset, footer_length;
683 frame = gspca_get_i_frame(gspca_dev);
684 if (frame == NULL) {
685 gspca_dev->last_packet_type = DISCARD_PACKET;
686 return;
689 /* 6 bytes after the FF D9 EOF marker a number of lumination
690 bytes are send corresponding to different parts of the
691 image, the 14th and 15th byte after the EOF seem to
692 correspond to the center of the image */
693 lum_offset = 24 + sizeof pac_sof_marker;
694 footer_length = 26;
696 /* Finish decoding current frame */
697 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
698 if (n < 0) {
699 frame->data_end += n;
700 n = 0;
702 gspca_frame_add(gspca_dev, INTER_PACKET,
703 data, n);
704 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
705 frame->data_end[-2] == 0xff &&
706 frame->data_end[-1] == 0xd9)
707 gspca_frame_add(gspca_dev, LAST_PACKET,
708 NULL, 0);
710 n = sof - data;
711 len -= n;
712 data = sof;
714 /* Get average lumination */
715 if (gspca_dev->last_packet_type == LAST_PACKET &&
716 n >= lum_offset)
717 atomic_set(&sd->avg_lum, data[-lum_offset] +
718 data[-lum_offset + 1]);
719 else
720 atomic_set(&sd->avg_lum, -1);
722 /* Start the new frame with the jpeg header */
723 pac_start_frame(gspca_dev, frame,
724 gspca_dev->height, gspca_dev->width);
726 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
729 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
731 struct sd *sd = (struct sd *) gspca_dev;
733 sd->contrast = val;
734 if (gspca_dev->streaming) {
735 setcontrast(gspca_dev);
737 return 0;
740 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
742 struct sd *sd = (struct sd *) gspca_dev;
744 *val = sd->contrast;
745 return 0;
748 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
750 struct sd *sd = (struct sd *) gspca_dev;
752 sd->gain = val;
753 if (gspca_dev->streaming)
754 setgain(gspca_dev);
755 return 0;
758 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
760 struct sd *sd = (struct sd *) gspca_dev;
762 *val = sd->gain;
763 return 0;
766 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
768 struct sd *sd = (struct sd *) gspca_dev;
770 sd->exposure = val;
771 if (gspca_dev->streaming)
772 setexposure(gspca_dev);
773 return 0;
776 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
778 struct sd *sd = (struct sd *) gspca_dev;
780 *val = sd->exposure;
781 return 0;
784 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
786 struct sd *sd = (struct sd *) gspca_dev;
788 sd->autogain = val;
789 /* when switching to autogain set defaults to make sure
790 we are on a valid point of the autogain gain /
791 exposure knee graph, and give this change time to
792 take effect before doing autogain. */
793 if (sd->autogain) {
794 sd->exposure = EXPOSURE_DEF;
795 sd->gain = GAIN_DEF;
796 if (gspca_dev->streaming) {
797 sd->autogain_ignore_frames =
798 PAC_AUTOGAIN_IGNORE_FRAMES;
799 setexposure(gspca_dev);
800 setgain(gspca_dev);
804 return 0;
807 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
809 struct sd *sd = (struct sd *) gspca_dev;
811 *val = sd->autogain;
812 return 0;
815 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
817 struct sd *sd = (struct sd *) gspca_dev;
819 sd->hflip = val;
820 if (gspca_dev->streaming)
821 sethvflip(gspca_dev);
822 return 0;
825 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
827 struct sd *sd = (struct sd *) gspca_dev;
829 *val = sd->hflip;
830 return 0;
833 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
835 struct sd *sd = (struct sd *) gspca_dev;
837 sd->vflip = val;
838 if (gspca_dev->streaming)
839 sethvflip(gspca_dev);
840 return 0;
843 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
845 struct sd *sd = (struct sd *) gspca_dev;
847 *val = sd->vflip;
848 return 0;
851 /* sub-driver description for pac7311 */
852 static const struct sd_desc sd_desc = {
853 .name = MODULE_NAME,
854 .ctrls = sd_ctrls,
855 .nctrls = ARRAY_SIZE(sd_ctrls),
856 .config = sd_config,
857 .init = sd_init,
858 .start = sd_start,
859 .stopN = sd_stopN,
860 .stop0 = sd_stop0,
861 .pkt_scan = sd_pkt_scan,
862 .dq_callback = do_autogain,
865 /* -- module initialisation -- */
866 static const struct usb_device_id device_table[] __devinitconst = {
867 {USB_DEVICE(0x093a, 0x2600)},
868 {USB_DEVICE(0x093a, 0x2601)},
869 {USB_DEVICE(0x093a, 0x2603)},
870 {USB_DEVICE(0x093a, 0x2608)},
871 {USB_DEVICE(0x093a, 0x260e)},
872 {USB_DEVICE(0x093a, 0x260f)},
875 MODULE_DEVICE_TABLE(usb, device_table);
877 /* -- device connect -- */
878 static int __devinit sd_probe(struct usb_interface *intf,
879 const struct usb_device_id *id)
881 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
882 THIS_MODULE);
885 static struct usb_driver sd_driver = {
886 .name = MODULE_NAME,
887 .id_table = device_table,
888 .probe = sd_probe,
889 .disconnect = gspca_disconnect,
890 #ifdef CONFIG_PM
891 .suspend = gspca_suspend,
892 .resume = gspca_resume,
893 #endif
896 /* -- module insert / remove -- */
897 static int __init sd_mod_init(void)
899 int ret;
900 ret = usb_register(&sd_driver);
901 if (ret < 0)
902 return ret;
903 PDEBUG(D_PROBE, "registered");
904 return 0;
906 static void __exit sd_mod_exit(void)
908 usb_deregister(&sd_driver);
909 PDEBUG(D_PROBE, "deregistered");
912 module_init(sd_mod_init);
913 module_exit(sd_mod_exit);