Merge branch 'v6v7' into devel
[linux/fpc-iii.git] / drivers / media / video / gspca / pac7311.c
blobf8801b50e64f2f20b5c5030bb76faaeafef073c8
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 <linux/input.h>
55 #include "gspca.h"
57 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
58 MODULE_DESCRIPTION("Pixart PAC7311");
59 MODULE_LICENSE("GPL");
61 /* specific webcam descriptor for pac7311 */
62 struct sd {
63 struct gspca_dev gspca_dev; /* !! must be the first item */
65 unsigned char contrast;
66 unsigned char gain;
67 unsigned char exposure;
68 unsigned char autogain;
69 __u8 hflip;
70 __u8 vflip;
72 u8 sof_read;
73 u8 autogain_ignore_frames;
75 atomic_t avg_lum;
78 /* V4L2 controls supported by the driver */
79 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
85 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92 static const struct ctrl sd_ctrls[] = {
93 /* This control is for both the 7302 and the 7311 */
96 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast",
99 .minimum = 0,
100 #define CONTRAST_MAX 255
101 .maximum = CONTRAST_MAX,
102 .step = 1,
103 #define CONTRAST_DEF 127
104 .default_value = CONTRAST_DEF,
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
109 /* All controls below are for both the 7302 and the 7311 */
112 .id = V4L2_CID_GAIN,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Gain",
115 .minimum = 0,
116 #define GAIN_MAX 255
117 .maximum = GAIN_MAX,
118 .step = 1,
119 #define GAIN_DEF 127
120 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
121 .default_value = GAIN_DEF,
123 .set = sd_setgain,
124 .get = sd_getgain,
128 .id = V4L2_CID_EXPOSURE,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Exposure",
131 .minimum = 0,
132 #define EXPOSURE_MAX 255
133 .maximum = EXPOSURE_MAX,
134 .step = 1,
135 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .default_value = EXPOSURE_DEF,
139 .set = sd_setexposure,
140 .get = sd_getexposure,
144 .id = V4L2_CID_AUTOGAIN,
145 .type = V4L2_CTRL_TYPE_BOOLEAN,
146 .name = "Auto Gain",
147 .minimum = 0,
148 .maximum = 1,
149 .step = 1,
150 #define AUTOGAIN_DEF 1
151 .default_value = AUTOGAIN_DEF,
153 .set = sd_setautogain,
154 .get = sd_getautogain,
158 .id = V4L2_CID_HFLIP,
159 .type = V4L2_CTRL_TYPE_BOOLEAN,
160 .name = "Mirror",
161 .minimum = 0,
162 .maximum = 1,
163 .step = 1,
164 #define HFLIP_DEF 0
165 .default_value = HFLIP_DEF,
167 .set = sd_sethflip,
168 .get = sd_gethflip,
172 .id = V4L2_CID_VFLIP,
173 .type = V4L2_CTRL_TYPE_BOOLEAN,
174 .name = "Vflip",
175 .minimum = 0,
176 .maximum = 1,
177 .step = 1,
178 #define VFLIP_DEF 0
179 .default_value = VFLIP_DEF,
181 .set = sd_setvflip,
182 .get = sd_getvflip,
186 static const struct v4l2_pix_format vga_mode[] = {
187 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
188 .bytesperline = 160,
189 .sizeimage = 160 * 120 * 3 / 8 + 590,
190 .colorspace = V4L2_COLORSPACE_JPEG,
191 .priv = 2},
192 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
193 .bytesperline = 320,
194 .sizeimage = 320 * 240 * 3 / 8 + 590,
195 .colorspace = V4L2_COLORSPACE_JPEG,
196 .priv = 1},
197 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
198 .bytesperline = 640,
199 .sizeimage = 640 * 480 * 3 / 8 + 590,
200 .colorspace = V4L2_COLORSPACE_JPEG,
201 .priv = 0},
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 void reg_w_buf(struct gspca_dev *gspca_dev,
263 __u8 index,
264 const u8 *buffer, int len)
266 int ret;
268 if (gspca_dev->usb_err < 0)
269 return;
270 memcpy(gspca_dev->usb_buf, buffer, len);
271 ret = usb_control_msg(gspca_dev->dev,
272 usb_sndctrlpipe(gspca_dev->dev, 0),
273 0, /* request */
274 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
275 0, /* value */
276 index, gspca_dev->usb_buf, len,
277 500);
278 if (ret < 0) {
279 err("reg_w_buf() failed index 0x%02x, error %d",
280 index, ret);
281 gspca_dev->usb_err = ret;
286 static void reg_w(struct gspca_dev *gspca_dev,
287 __u8 index,
288 __u8 value)
290 int ret;
292 if (gspca_dev->usb_err < 0)
293 return;
294 gspca_dev->usb_buf[0] = value;
295 ret = usb_control_msg(gspca_dev->dev,
296 usb_sndctrlpipe(gspca_dev->dev, 0),
297 0, /* request */
298 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
299 0, index, gspca_dev->usb_buf, 1,
300 500);
301 if (ret < 0) {
302 err("reg_w() failed index 0x%02x, value 0x%02x, error %d",
303 index, value, ret);
304 gspca_dev->usb_err = ret;
308 static void reg_w_seq(struct gspca_dev *gspca_dev,
309 const __u8 *seq, int len)
311 while (--len >= 0) {
312 reg_w(gspca_dev, seq[0], seq[1]);
313 seq += 2;
317 /* load the beginning of a page */
318 static void reg_w_page(struct gspca_dev *gspca_dev,
319 const __u8 *page, int len)
321 int index;
322 int ret = 0;
324 if (gspca_dev->usb_err < 0)
325 return;
326 for (index = 0; index < len; index++) {
327 if (page[index] == SKIP) /* skip this index */
328 continue;
329 gspca_dev->usb_buf[0] = page[index];
330 ret = usb_control_msg(gspca_dev->dev,
331 usb_sndctrlpipe(gspca_dev->dev, 0),
332 0, /* request */
333 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
334 0, index, gspca_dev->usb_buf, 1,
335 500);
336 if (ret < 0) {
337 err("reg_w_page() failed index 0x%02x, "
338 "value 0x%02x, error %d",
339 index, page[index], ret);
340 gspca_dev->usb_err = ret;
341 break;
346 /* output a variable sequence */
347 static void reg_w_var(struct gspca_dev *gspca_dev,
348 const __u8 *seq,
349 const __u8 *page4, unsigned int page4_len)
351 int index, len;
353 for (;;) {
354 index = *seq++;
355 len = *seq++;
356 switch (len) {
357 case END_OF_SEQUENCE:
358 return;
359 case LOAD_PAGE4:
360 reg_w_page(gspca_dev, page4, page4_len);
361 break;
362 default:
363 if (len > USB_BUF_SZ) {
364 PDEBUG(D_ERR|D_STREAM,
365 "Incorrect variable sequence");
366 return;
368 while (len > 0) {
369 if (len < 8) {
370 reg_w_buf(gspca_dev,
371 index, seq, len);
372 seq += len;
373 break;
375 reg_w_buf(gspca_dev, index, seq, 8);
376 seq += 8;
377 index += 8;
378 len -= 8;
382 /* not reached */
385 /* this function is called at probe time for pac7311 */
386 static int sd_config(struct gspca_dev *gspca_dev,
387 const struct usb_device_id *id)
389 struct sd *sd = (struct sd *) gspca_dev;
390 struct cam *cam;
392 cam = &gspca_dev->cam;
394 PDEBUG(D_CONF, "Find Sensor PAC7311");
395 cam->cam_mode = vga_mode;
396 cam->nmodes = ARRAY_SIZE(vga_mode);
398 sd->contrast = CONTRAST_DEF;
399 sd->gain = GAIN_DEF;
400 sd->exposure = EXPOSURE_DEF;
401 sd->autogain = AUTOGAIN_DEF;
402 sd->hflip = HFLIP_DEF;
403 sd->vflip = VFLIP_DEF;
404 return 0;
407 /* This function is used by pac7311 only */
408 static void setcontrast(struct gspca_dev *gspca_dev)
410 struct sd *sd = (struct sd *) gspca_dev;
412 reg_w(gspca_dev, 0xff, 0x04);
413 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
414 /* load registers to sensor (Bit 0, auto clear) */
415 reg_w(gspca_dev, 0x11, 0x01);
418 static void setgain(struct gspca_dev *gspca_dev)
420 struct sd *sd = (struct sd *) gspca_dev;
421 int gain = GAIN_MAX - sd->gain;
423 if (gain < 1)
424 gain = 1;
425 else if (gain > 245)
426 gain = 245;
427 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
428 reg_w(gspca_dev, 0x0e, 0x00);
429 reg_w(gspca_dev, 0x0f, gain);
431 /* load registers to sensor (Bit 0, auto clear) */
432 reg_w(gspca_dev, 0x11, 0x01);
435 static void setexposure(struct gspca_dev *gspca_dev)
437 struct sd *sd = (struct sd *) gspca_dev;
438 __u8 reg;
440 /* register 2 of frame 3/4 contains the clock divider configuring the
441 no fps according to the formula: 60 / reg. sd->exposure is the
442 desired exposure time in ms. */
443 reg = 120 * sd->exposure / 1000;
444 if (reg < 2)
445 reg = 2;
446 else if (reg > 63)
447 reg = 63;
449 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
450 reg_w(gspca_dev, 0x02, reg);
452 /* Page 1 register 8 must always be 0x08 except when not in
453 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
454 reg_w(gspca_dev, 0xff, 0x01);
455 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
456 reg <= 3) {
457 reg_w(gspca_dev, 0x08, 0x09);
458 } else {
459 reg_w(gspca_dev, 0x08, 0x08);
462 /* load registers to sensor (Bit 0, auto clear) */
463 reg_w(gspca_dev, 0x11, 0x01);
466 static void sethvflip(struct gspca_dev *gspca_dev)
468 struct sd *sd = (struct sd *) gspca_dev;
469 __u8 data;
471 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
472 data = (sd->hflip ? 0x04 : 0x00) | (sd->vflip ? 0x08 : 0x00);
473 reg_w(gspca_dev, 0x21, data);
475 /* load registers to sensor (Bit 0, auto clear) */
476 reg_w(gspca_dev, 0x11, 0x01);
479 /* this function is called at probe and resume time for pac7311 */
480 static int sd_init(struct gspca_dev *gspca_dev)
482 reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
483 return gspca_dev->usb_err;
486 static int sd_start(struct gspca_dev *gspca_dev)
488 struct sd *sd = (struct sd *) gspca_dev;
490 sd->sof_read = 0;
492 reg_w_var(gspca_dev, start_7311,
493 page4_7311, sizeof(page4_7311));
494 setcontrast(gspca_dev);
495 setgain(gspca_dev);
496 setexposure(gspca_dev);
497 sethvflip(gspca_dev);
499 /* set correct resolution */
500 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
501 case 2: /* 160x120 pac7311 */
502 reg_w(gspca_dev, 0xff, 0x01);
503 reg_w(gspca_dev, 0x17, 0x20);
504 reg_w(gspca_dev, 0x87, 0x10);
505 break;
506 case 1: /* 320x240 pac7311 */
507 reg_w(gspca_dev, 0xff, 0x01);
508 reg_w(gspca_dev, 0x17, 0x30);
509 reg_w(gspca_dev, 0x87, 0x11);
510 break;
511 case 0: /* 640x480 */
512 reg_w(gspca_dev, 0xff, 0x01);
513 reg_w(gspca_dev, 0x17, 0x00);
514 reg_w(gspca_dev, 0x87, 0x12);
515 break;
518 sd->sof_read = 0;
519 sd->autogain_ignore_frames = 0;
520 atomic_set(&sd->avg_lum, -1);
522 /* start stream */
523 reg_w(gspca_dev, 0xff, 0x01);
524 reg_w(gspca_dev, 0x78, 0x05);
526 return gspca_dev->usb_err;
529 static void sd_stopN(struct gspca_dev *gspca_dev)
531 reg_w(gspca_dev, 0xff, 0x04);
532 reg_w(gspca_dev, 0x27, 0x80);
533 reg_w(gspca_dev, 0x28, 0xca);
534 reg_w(gspca_dev, 0x29, 0x53);
535 reg_w(gspca_dev, 0x2a, 0x0e);
536 reg_w(gspca_dev, 0xff, 0x01);
537 reg_w(gspca_dev, 0x3e, 0x20);
538 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
539 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
540 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
543 /* called on streamoff with alt 0 and on disconnect for 7311 */
544 static void sd_stop0(struct gspca_dev *gspca_dev)
548 /* Include pac common sof detection functions */
549 #include "pac_common.h"
551 static void do_autogain(struct gspca_dev *gspca_dev)
553 struct sd *sd = (struct sd *) gspca_dev;
554 int avg_lum = atomic_read(&sd->avg_lum);
555 int desired_lum, deadzone;
557 if (avg_lum == -1)
558 return;
560 desired_lum = 200;
561 deadzone = 20;
563 if (sd->autogain_ignore_frames > 0)
564 sd->autogain_ignore_frames--;
565 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
566 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
567 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
570 /* JPEG header, part 1 */
571 static const unsigned char pac_jpeg_header1[] = {
572 0xff, 0xd8, /* SOI: Start of Image */
574 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
575 0x00, 0x11, /* length = 17 bytes (including this length field) */
576 0x08 /* Precision: 8 */
577 /* 2 bytes is placed here: number of image lines */
578 /* 2 bytes is placed here: samples per line */
581 /* JPEG header, continued */
582 static const unsigned char pac_jpeg_header2[] = {
583 0x03, /* Number of image components: 3 */
584 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
585 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
586 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
588 0xff, 0xda, /* SOS: Start Of Scan */
589 0x00, 0x0c, /* length = 12 bytes (including this length field) */
590 0x03, /* number of components: 3 */
591 0x01, 0x00, /* selector 1, table 0x00 */
592 0x02, 0x11, /* selector 2, table 0x11 */
593 0x03, 0x11, /* selector 3, table 0x11 */
594 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
595 0x00 /* Successive approximation: 0 */
598 static void pac_start_frame(struct gspca_dev *gspca_dev,
599 __u16 lines, __u16 samples_per_line)
601 unsigned char tmpbuf[4];
603 gspca_frame_add(gspca_dev, FIRST_PACKET,
604 pac_jpeg_header1, sizeof(pac_jpeg_header1));
606 tmpbuf[0] = lines >> 8;
607 tmpbuf[1] = lines & 0xff;
608 tmpbuf[2] = samples_per_line >> 8;
609 tmpbuf[3] = samples_per_line & 0xff;
611 gspca_frame_add(gspca_dev, INTER_PACKET,
612 tmpbuf, sizeof(tmpbuf));
613 gspca_frame_add(gspca_dev, INTER_PACKET,
614 pac_jpeg_header2, sizeof(pac_jpeg_header2));
617 /* this function is run at interrupt level */
618 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
619 u8 *data, /* isoc packet */
620 int len) /* iso packet length */
622 struct sd *sd = (struct sd *) gspca_dev;
623 u8 *image;
624 unsigned char *sof;
626 sof = pac_find_sof(&sd->sof_read, data, len);
627 if (sof) {
628 int n, lum_offset, footer_length;
630 /* 6 bytes after the FF D9 EOF marker a number of lumination
631 bytes are send corresponding to different parts of the
632 image, the 14th and 15th byte after the EOF seem to
633 correspond to the center of the image */
634 lum_offset = 24 + sizeof pac_sof_marker;
635 footer_length = 26;
637 /* Finish decoding current frame */
638 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
639 if (n < 0) {
640 gspca_dev->image_len += n;
641 n = 0;
642 } else {
643 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
645 image = gspca_dev->image;
646 if (image != NULL
647 && image[gspca_dev->image_len - 2] == 0xff
648 && image[gspca_dev->image_len - 1] == 0xd9)
649 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
651 n = sof - data;
652 len -= n;
653 data = sof;
655 /* Get average lumination */
656 if (gspca_dev->last_packet_type == LAST_PACKET &&
657 n >= lum_offset)
658 atomic_set(&sd->avg_lum, data[-lum_offset] +
659 data[-lum_offset + 1]);
660 else
661 atomic_set(&sd->avg_lum, -1);
663 /* Start the new frame with the jpeg header */
664 pac_start_frame(gspca_dev,
665 gspca_dev->height, gspca_dev->width);
667 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
670 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
672 struct sd *sd = (struct sd *) gspca_dev;
674 sd->contrast = val;
675 if (gspca_dev->streaming)
676 setcontrast(gspca_dev);
677 return gspca_dev->usb_err;
680 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
682 struct sd *sd = (struct sd *) gspca_dev;
684 *val = sd->contrast;
685 return 0;
688 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
690 struct sd *sd = (struct sd *) gspca_dev;
692 sd->gain = val;
693 if (gspca_dev->streaming)
694 setgain(gspca_dev);
695 return gspca_dev->usb_err;
698 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
700 struct sd *sd = (struct sd *) gspca_dev;
702 *val = sd->gain;
703 return 0;
706 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
708 struct sd *sd = (struct sd *) gspca_dev;
710 sd->exposure = val;
711 if (gspca_dev->streaming)
712 setexposure(gspca_dev);
713 return gspca_dev->usb_err;
716 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
718 struct sd *sd = (struct sd *) gspca_dev;
720 *val = sd->exposure;
721 return 0;
724 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
726 struct sd *sd = (struct sd *) gspca_dev;
728 sd->autogain = val;
729 /* when switching to autogain set defaults to make sure
730 we are on a valid point of the autogain gain /
731 exposure knee graph, and give this change time to
732 take effect before doing autogain. */
733 if (sd->autogain) {
734 sd->exposure = EXPOSURE_DEF;
735 sd->gain = GAIN_DEF;
736 if (gspca_dev->streaming) {
737 sd->autogain_ignore_frames =
738 PAC_AUTOGAIN_IGNORE_FRAMES;
739 setexposure(gspca_dev);
740 setgain(gspca_dev);
744 return gspca_dev->usb_err;
747 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
749 struct sd *sd = (struct sd *) gspca_dev;
751 *val = sd->autogain;
752 return 0;
755 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
757 struct sd *sd = (struct sd *) gspca_dev;
759 sd->hflip = val;
760 if (gspca_dev->streaming)
761 sethvflip(gspca_dev);
762 return gspca_dev->usb_err;
765 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
767 struct sd *sd = (struct sd *) gspca_dev;
769 *val = sd->hflip;
770 return 0;
773 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
775 struct sd *sd = (struct sd *) gspca_dev;
777 sd->vflip = val;
778 if (gspca_dev->streaming)
779 sethvflip(gspca_dev);
780 return gspca_dev->usb_err;
783 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
785 struct sd *sd = (struct sd *) gspca_dev;
787 *val = sd->vflip;
788 return 0;
791 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
792 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
793 u8 *data, /* interrupt packet data */
794 int len) /* interrupt packet length */
796 int ret = -EINVAL;
797 u8 data0, data1;
799 if (len == 2) {
800 data0 = data[0];
801 data1 = data[1];
802 if ((data0 == 0x00 && data1 == 0x11) ||
803 (data0 == 0x22 && data1 == 0x33) ||
804 (data0 == 0x44 && data1 == 0x55) ||
805 (data0 == 0x66 && data1 == 0x77) ||
806 (data0 == 0x88 && data1 == 0x99) ||
807 (data0 == 0xaa && data1 == 0xbb) ||
808 (data0 == 0xcc && data1 == 0xdd) ||
809 (data0 == 0xee && data1 == 0xff)) {
810 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
811 input_sync(gspca_dev->input_dev);
812 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
813 input_sync(gspca_dev->input_dev);
814 ret = 0;
818 return ret;
820 #endif
822 /* sub-driver description for pac7311 */
823 static const struct sd_desc sd_desc = {
824 .name = MODULE_NAME,
825 .ctrls = sd_ctrls,
826 .nctrls = ARRAY_SIZE(sd_ctrls),
827 .config = sd_config,
828 .init = sd_init,
829 .start = sd_start,
830 .stopN = sd_stopN,
831 .stop0 = sd_stop0,
832 .pkt_scan = sd_pkt_scan,
833 .dq_callback = do_autogain,
834 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
835 .int_pkt_scan = sd_int_pkt_scan,
836 #endif
839 /* -- module initialisation -- */
840 static const struct usb_device_id device_table[] = {
841 {USB_DEVICE(0x093a, 0x2600)},
842 {USB_DEVICE(0x093a, 0x2601)},
843 {USB_DEVICE(0x093a, 0x2603)},
844 {USB_DEVICE(0x093a, 0x2608)},
845 {USB_DEVICE(0x093a, 0x260e)},
846 {USB_DEVICE(0x093a, 0x260f)},
849 MODULE_DEVICE_TABLE(usb, device_table);
851 /* -- device connect -- */
852 static int sd_probe(struct usb_interface *intf,
853 const struct usb_device_id *id)
855 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
856 THIS_MODULE);
859 static struct usb_driver sd_driver = {
860 .name = MODULE_NAME,
861 .id_table = device_table,
862 .probe = sd_probe,
863 .disconnect = gspca_disconnect,
864 #ifdef CONFIG_PM
865 .suspend = gspca_suspend,
866 .resume = gspca_resume,
867 #endif
870 /* -- module insert / remove -- */
871 static int __init sd_mod_init(void)
873 return usb_register(&sd_driver);
875 static void __exit sd_mod_exit(void)
877 usb_deregister(&sd_driver);
880 module_init(sd_mod_init);
881 module_exit(sd_mod_exit);