2 * Pixart PAC7302 driver
4 * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
7 * Separated from Pixart PAC7311 library by Márton Németh
8 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /* Some documentation about various registers as determined by trial and error.
31 0x78 Global control, bit 6 controls the LED (inverted)
36 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
37 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
38 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
39 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
40 63 -> ~27 fps, the 2 msb's must always be 1 !!
41 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
42 1 -> ~30 fps, 2 -> ~20 fps
43 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
44 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
48 The registers are accessed in the following functions:
50 Page | Register | Function
51 -----+------------+---------------------------------------------------
52 0 | 0x0f..0x20 | setcolors()
53 0 | 0xa2..0xab | setbrightcont()
54 0 | 0xc5 | setredbalance()
55 0 | 0xc6 | setwhitebalance()
56 0 | 0xc7 | setbluebalance()
57 0 | 0xdc | setbrightcont(), setcolors()
58 3 | 0x02 | setexposure()
60 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
61 3 | 0x21 | sethvflip()
64 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
66 #include <linux/input.h>
67 #include <media/v4l2-chip-ident.h>
69 /* Include pac common sof detection functions */
70 #include "pac_common.h"
72 MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
73 "Thomas Kaiser thomas@kaiser-linux.li");
74 MODULE_DESCRIPTION("Pixart PAC7302");
75 MODULE_LICENSE("GPL");
89 NCTRLS
/* number of controls */
92 /* specific webcam descriptor for pac7302 */
94 struct gspca_dev gspca_dev
; /* !! must be the first item */
96 struct gspca_ctrl ctrls
[NCTRLS
];
99 #define FL_HFLIP 0x01 /* mirrored by default */
100 #define FL_VFLIP 0x02 /* vertical flipped by default */
103 s8 autogain_ignore_frames
;
108 /* V4L2 controls supported by the driver */
109 static void setbrightcont(struct gspca_dev
*gspca_dev
);
110 static void setcolors(struct gspca_dev
*gspca_dev
);
111 static void setwhitebalance(struct gspca_dev
*gspca_dev
);
112 static void setredbalance(struct gspca_dev
*gspca_dev
);
113 static void setbluebalance(struct gspca_dev
*gspca_dev
);
114 static void setgain(struct gspca_dev
*gspca_dev
);
115 static void setexposure(struct gspca_dev
*gspca_dev
);
116 static void setautogain(struct gspca_dev
*gspca_dev
);
117 static void sethvflip(struct gspca_dev
*gspca_dev
);
119 static const struct ctrl sd_ctrls
[] = {
122 .id
= V4L2_CID_BRIGHTNESS
,
123 .type
= V4L2_CTRL_TYPE_INTEGER
,
124 .name
= "Brightness",
126 #define BRIGHTNESS_MAX 0x20
127 .maximum
= BRIGHTNESS_MAX
,
129 .default_value
= 0x10,
131 .set_control
= setbrightcont
135 .id
= V4L2_CID_CONTRAST
,
136 .type
= V4L2_CTRL_TYPE_INTEGER
,
139 #define CONTRAST_MAX 255
140 .maximum
= CONTRAST_MAX
,
142 .default_value
= 127,
144 .set_control
= setbrightcont
148 .id
= V4L2_CID_SATURATION
,
149 .type
= V4L2_CTRL_TYPE_INTEGER
,
150 .name
= "Saturation",
152 #define COLOR_MAX 255
153 .maximum
= COLOR_MAX
,
157 .set_control
= setcolors
161 .id
= V4L2_CID_WHITE_BALANCE_TEMPERATURE
,
162 .type
= V4L2_CTRL_TYPE_INTEGER
,
163 .name
= "White Balance",
169 .set_control
= setwhitebalance
173 .id
= V4L2_CID_RED_BALANCE
,
174 .type
= V4L2_CTRL_TYPE_INTEGER
,
181 .set_control
= setredbalance
185 .id
= V4L2_CID_BLUE_BALANCE
,
186 .type
= V4L2_CTRL_TYPE_INTEGER
,
193 .set_control
= setbluebalance
198 .type
= V4L2_CTRL_TYPE_INTEGER
,
204 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
205 .default_value
= GAIN_DEF
,
207 .set_control
= setgain
211 .id
= V4L2_CID_EXPOSURE
,
212 .type
= V4L2_CTRL_TYPE_INTEGER
,
217 #define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
218 #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
219 .default_value
= EXPOSURE_DEF
,
221 .set_control
= setexposure
225 .id
= V4L2_CID_AUTOGAIN
,
226 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
231 #define AUTOGAIN_DEF 1
232 .default_value
= AUTOGAIN_DEF
,
234 .set_control
= setautogain
,
238 .id
= V4L2_CID_HFLIP
,
239 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
246 .set_control
= sethvflip
,
250 .id
= V4L2_CID_VFLIP
,
251 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
258 .set_control
= sethvflip
262 static const struct v4l2_pix_format vga_mode
[] = {
263 {640, 480, V4L2_PIX_FMT_PJPG
, V4L2_FIELD_NONE
,
265 .sizeimage
= 640 * 480 * 3 / 8 + 590,
266 .colorspace
= V4L2_COLORSPACE_JPEG
,
270 #define LOAD_PAGE3 255
271 #define END_OF_SEQUENCE 0
274 static const u8 init_7302
[] = {
276 0xff, 0x01, /* page 1 */
277 0x78, 0x00, /* deactivate */
279 0x78, 0x40, /* led off */
281 static const u8 start_7302
[] = {
282 /* index, len, [value]* */
283 0xff, 1, 0x00, /* page 0 */
284 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
285 0x00, 0x00, 0x00, 0x00,
286 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
287 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
288 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
292 0x3a, 3, 0x14, 0xff, 0x5a,
293 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
296 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
298 0x6e, 3, 0x08, 0x06, 0x00,
299 0x72, 3, 0x00, 0xff, 0x00,
300 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
301 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
302 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
303 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
308 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
310 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
313 0xff, 1, 0x01, /* page 1 */
314 0x12, 3, 0x02, 0x00, 0x01,
316 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
318 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
320 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
321 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
322 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
325 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
326 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
328 0xff, 1, 0x02, /* page 2 */
330 0xff, 1, 0x03, /* page 3 */
331 0, LOAD_PAGE3
, /* load the page 3 */
333 0xff, 1, 0x02, /* page 2 */
335 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
337 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
338 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
340 0xff, 1, 0x01, /* page 1 */
342 0, END_OF_SEQUENCE
/* end of sequence */
346 /* page 3 - the value SKIP says skip the index - see reg_w_page() */
347 static const u8 page3_7302
[] = {
348 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
349 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
350 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
351 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
352 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
353 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
354 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
355 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
357 SKIP
, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
358 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
362 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
363 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
364 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
370 static void reg_w_buf(struct gspca_dev
*gspca_dev
,
372 const u8
*buffer
, int len
)
376 if (gspca_dev
->usb_err
< 0)
378 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
379 ret
= usb_control_msg(gspca_dev
->dev
,
380 usb_sndctrlpipe(gspca_dev
->dev
, 0),
382 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
384 index
, gspca_dev
->usb_buf
, len
,
387 pr_err("reg_w_buf failed i: %02x error %d\n",
389 gspca_dev
->usb_err
= ret
;
394 static void reg_w(struct gspca_dev
*gspca_dev
,
400 if (gspca_dev
->usb_err
< 0)
402 gspca_dev
->usb_buf
[0] = value
;
403 ret
= usb_control_msg(gspca_dev
->dev
,
404 usb_sndctrlpipe(gspca_dev
->dev
, 0),
406 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
407 0, index
, gspca_dev
->usb_buf
, 1,
410 pr_err("reg_w() failed i: %02x v: %02x error %d\n",
412 gspca_dev
->usb_err
= ret
;
416 static void reg_w_seq(struct gspca_dev
*gspca_dev
,
417 const u8
*seq
, int len
)
420 reg_w(gspca_dev
, seq
[0], seq
[1]);
425 /* load the beginning of a page */
426 static void reg_w_page(struct gspca_dev
*gspca_dev
,
427 const u8
*page
, int len
)
432 if (gspca_dev
->usb_err
< 0)
434 for (index
= 0; index
< len
; index
++) {
435 if (page
[index
] == SKIP
) /* skip this index */
437 gspca_dev
->usb_buf
[0] = page
[index
];
438 ret
= usb_control_msg(gspca_dev
->dev
,
439 usb_sndctrlpipe(gspca_dev
->dev
, 0),
441 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
442 0, index
, gspca_dev
->usb_buf
, 1,
445 pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
446 index
, page
[index
], ret
);
447 gspca_dev
->usb_err
= ret
;
453 /* output a variable sequence */
454 static void reg_w_var(struct gspca_dev
*gspca_dev
,
456 const u8
*page3
, unsigned int page3_len
)
464 case END_OF_SEQUENCE
:
467 reg_w_page(gspca_dev
, page3
, page3_len
);
471 if (len
> USB_BUF_SZ
) {
472 PDEBUG(D_ERR
|D_STREAM
,
473 "Incorrect variable sequence");
484 reg_w_buf(gspca_dev
, index
, seq
, 8);
494 /* this function is called at probe time for pac7302 */
495 static int sd_config(struct gspca_dev
*gspca_dev
,
496 const struct usb_device_id
*id
)
498 struct sd
*sd
= (struct sd
*) gspca_dev
;
501 cam
= &gspca_dev
->cam
;
503 cam
->cam_mode
= vga_mode
; /* only 640x480 */
504 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
506 gspca_dev
->cam
.ctrls
= sd
->ctrls
;
508 sd
->flags
= id
->driver_info
;
512 /* This function is used by pac7302 only */
513 static void setbrightcont(struct gspca_dev
*gspca_dev
)
515 struct sd
*sd
= (struct sd
*) gspca_dev
;
517 static const u8 max
[10] =
518 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
520 static const u8 delta
[10] =
521 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
524 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
525 for (i
= 0; i
< 10; i
++) {
527 v
+= (sd
->ctrls
[BRIGHTNESS
].val
- BRIGHTNESS_MAX
)
528 * 150 / BRIGHTNESS_MAX
; /* 200 ? */
529 v
-= delta
[i
] * sd
->ctrls
[CONTRAST
].val
/ CONTRAST_MAX
;
534 reg_w(gspca_dev
, 0xa2 + i
, v
);
536 reg_w(gspca_dev
, 0xdc, 0x01);
539 /* This function is used by pac7302 only */
540 static void setcolors(struct gspca_dev
*gspca_dev
)
542 struct sd
*sd
= (struct sd
*) gspca_dev
;
544 static const int a
[9] =
545 {217, -212, 0, -101, 170, -67, -38, -315, 355};
546 static const int b
[9] =
547 {19, 106, 0, 19, 106, 1, 19, 106, 1};
549 reg_w(gspca_dev
, 0xff, 0x03); /* page 3 */
550 reg_w(gspca_dev
, 0x11, 0x01);
551 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
552 for (i
= 0; i
< 9; i
++) {
553 v
= a
[i
] * sd
->ctrls
[COLORS
].val
/ COLOR_MAX
+ b
[i
];
554 reg_w(gspca_dev
, 0x0f + 2 * i
, (v
>> 8) & 0x07);
555 reg_w(gspca_dev
, 0x0f + 2 * i
+ 1, v
);
557 reg_w(gspca_dev
, 0xdc, 0x01);
560 static void setwhitebalance(struct gspca_dev
*gspca_dev
)
562 struct sd
*sd
= (struct sd
*) gspca_dev
;
564 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
565 reg_w(gspca_dev
, 0xc6, sd
->ctrls
[WHITE_BALANCE
].val
);
567 reg_w(gspca_dev
, 0xdc, 0x01);
570 static void setredbalance(struct gspca_dev
*gspca_dev
)
572 struct sd
*sd
= (struct sd
*) gspca_dev
;
574 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
575 reg_w(gspca_dev
, 0xc5, sd
->ctrls
[RED_BALANCE
].val
);
577 reg_w(gspca_dev
, 0xdc, 0x01);
580 static void setbluebalance(struct gspca_dev
*gspca_dev
)
582 struct sd
*sd
= (struct sd
*) gspca_dev
;
584 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
585 reg_w(gspca_dev
, 0xc7, sd
->ctrls
[BLUE_BALANCE
].val
);
587 reg_w(gspca_dev
, 0xdc, 0x01);
590 static void setgain(struct gspca_dev
*gspca_dev
)
592 struct sd
*sd
= (struct sd
*) gspca_dev
;
594 reg_w(gspca_dev
, 0xff, 0x03); /* page 3 */
595 reg_w(gspca_dev
, 0x10, sd
->ctrls
[GAIN
].val
>> 3);
597 /* load registers to sensor (Bit 0, auto clear) */
598 reg_w(gspca_dev
, 0x11, 0x01);
601 static void setexposure(struct gspca_dev
*gspca_dev
)
603 struct sd
*sd
= (struct sd
*) gspca_dev
;
607 /* register 2 of frame 3 contains the clock divider configuring the
608 no fps according to the formula: 90 / reg. sd->exposure is the
609 desired exposure time in 0.5 ms. */
610 clockdiv
= (90 * sd
->ctrls
[EXPOSURE
].val
+ 1999) / 2000;
612 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
613 on the scene being recorded, the camera switches to another
614 quantization table for certain JPEG blocks, and we don't know how
615 to decompress these blocks. So we cap the framerate at 15 fps */
618 else if (clockdiv
> 63)
621 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
622 Always round up, otherwise we cannot get the desired frametime
623 using the partial frame time exposure control */
624 if (clockdiv
< 6 || clockdiv
> 12)
625 clockdiv
= ((clockdiv
+ 2) / 3) * 3;
627 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
628 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
629 exposure
= (sd
->ctrls
[EXPOSURE
].val
* 45 * 448) / (1000 * clockdiv
);
630 /* 0 = use full frametime, 448 = no exposure, reverse it */
631 exposure
= 448 - exposure
;
633 reg_w(gspca_dev
, 0xff, 0x03); /* page 3 */
634 reg_w(gspca_dev
, 0x02, clockdiv
);
635 reg_w(gspca_dev
, 0x0e, exposure
& 0xff);
636 reg_w(gspca_dev
, 0x0f, exposure
>> 8);
638 /* load registers to sensor (Bit 0, auto clear) */
639 reg_w(gspca_dev
, 0x11, 0x01);
642 static void setautogain(struct gspca_dev
*gspca_dev
)
644 struct sd
*sd
= (struct sd
*) gspca_dev
;
646 /* when switching to autogain set defaults to make sure
647 we are on a valid point of the autogain gain /
648 exposure knee graph, and give this change time to
649 take effect before doing autogain. */
650 if (sd
->ctrls
[AUTOGAIN
].val
) {
651 sd
->ctrls
[EXPOSURE
].val
= EXPOSURE_DEF
;
652 sd
->ctrls
[GAIN
].val
= GAIN_DEF
;
653 sd
->autogain_ignore_frames
=
654 PAC_AUTOGAIN_IGNORE_FRAMES
;
656 sd
->autogain_ignore_frames
= -1;
658 setexposure(gspca_dev
);
662 static void sethvflip(struct gspca_dev
*gspca_dev
)
664 struct sd
*sd
= (struct sd
*) gspca_dev
;
665 u8 data
, hflip
, vflip
;
667 hflip
= sd
->ctrls
[HFLIP
].val
;
668 if (sd
->flags
& FL_HFLIP
)
670 vflip
= sd
->ctrls
[VFLIP
].val
;
671 if (sd
->flags
& FL_VFLIP
)
674 reg_w(gspca_dev
, 0xff, 0x03); /* page 3 */
675 data
= (hflip
? 0x08 : 0x00) | (vflip
? 0x04 : 0x00);
676 reg_w(gspca_dev
, 0x21, data
);
678 /* load registers to sensor (Bit 0, auto clear) */
679 reg_w(gspca_dev
, 0x11, 0x01);
682 /* this function is called at probe and resume time for pac7302 */
683 static int sd_init(struct gspca_dev
*gspca_dev
)
685 reg_w_seq(gspca_dev
, init_7302
, sizeof(init_7302
)/2);
686 return gspca_dev
->usb_err
;
689 static int sd_start(struct gspca_dev
*gspca_dev
)
691 struct sd
*sd
= (struct sd
*) gspca_dev
;
693 reg_w_var(gspca_dev
, start_7302
,
694 page3_7302
, sizeof(page3_7302
));
695 setbrightcont(gspca_dev
);
696 setcolors(gspca_dev
);
697 setwhitebalance(gspca_dev
);
698 setredbalance(gspca_dev
);
699 setbluebalance(gspca_dev
);
700 setautogain(gspca_dev
);
701 sethvflip(gspca_dev
);
703 /* only resolution 640x480 is supported for pac7302 */
706 atomic_set(&sd
->avg_lum
, 270 + sd
->ctrls
[BRIGHTNESS
].val
);
709 reg_w(gspca_dev
, 0xff, 0x01);
710 reg_w(gspca_dev
, 0x78, 0x01);
712 return gspca_dev
->usb_err
;
715 static void sd_stopN(struct gspca_dev
*gspca_dev
)
719 reg_w(gspca_dev
, 0xff, 0x01);
720 reg_w(gspca_dev
, 0x78, 0x00);
723 /* called on streamoff with alt 0 and on disconnect for pac7302 */
724 static void sd_stop0(struct gspca_dev
*gspca_dev
)
726 if (!gspca_dev
->present
)
728 reg_w(gspca_dev
, 0xff, 0x01);
729 reg_w(gspca_dev
, 0x78, 0x40);
732 /* !! coarse_grained_expo_autogain is not used !! */
733 #define exp_too_low_cnt flags
734 #define exp_too_high_cnt sof_read
735 #include "autogain_functions.h"
737 static void do_autogain(struct gspca_dev
*gspca_dev
)
739 struct sd
*sd
= (struct sd
*) gspca_dev
;
740 int avg_lum
= atomic_read(&sd
->avg_lum
);
742 const int deadzone
= 30;
744 if (sd
->autogain_ignore_frames
< 0)
747 if (sd
->autogain_ignore_frames
> 0) {
748 sd
->autogain_ignore_frames
--;
750 desired_lum
= 270 + sd
->ctrls
[BRIGHTNESS
].val
;
752 auto_gain_n_exposure(gspca_dev
, avg_lum
, desired_lum
,
753 deadzone
, GAIN_KNEE
, EXPOSURE_KNEE
);
754 sd
->autogain_ignore_frames
= PAC_AUTOGAIN_IGNORE_FRAMES
;
759 static const u8 jpeg_header
[] = {
760 0xff, 0xd8, /* SOI: Start of Image */
762 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
763 0x00, 0x11, /* length = 17 bytes (including this length field) */
764 0x08, /* Precision: 8 */
765 0x02, 0x80, /* height = 640 (image rotated) */
766 0x01, 0xe0, /* width = 480 */
767 0x03, /* Number of image components: 3 */
768 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
769 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
770 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
772 0xff, 0xda, /* SOS: Start Of Scan */
773 0x00, 0x0c, /* length = 12 bytes (including this length field) */
774 0x03, /* number of components: 3 */
775 0x01, 0x00, /* selector 1, table 0x00 */
776 0x02, 0x11, /* selector 2, table 0x11 */
777 0x03, 0x11, /* selector 3, table 0x11 */
778 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
779 0x00 /* Successive approximation: 0 */
782 /* this function is run at interrupt level */
783 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
784 u8
*data
, /* isoc packet */
785 int len
) /* iso packet length */
787 struct sd
*sd
= (struct sd
*) gspca_dev
;
791 sof
= pac_find_sof(&sd
->sof_read
, data
, len
);
793 int n
, lum_offset
, footer_length
;
795 /* 6 bytes after the FF D9 EOF marker a number of lumination
796 bytes are send corresponding to different parts of the
797 image, the 14th and 15th byte after the EOF seem to
798 correspond to the center of the image */
799 lum_offset
= 61 + sizeof pac_sof_marker
;
802 /* Finish decoding current frame */
803 n
= (sof
- data
) - (footer_length
+ sizeof pac_sof_marker
);
805 gspca_dev
->image_len
+= n
;
808 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, n
);
811 image
= gspca_dev
->image
;
813 && image
[gspca_dev
->image_len
- 2] == 0xff
814 && image
[gspca_dev
->image_len
- 1] == 0xd9)
815 gspca_frame_add(gspca_dev
, LAST_PACKET
, NULL
, 0);
821 /* Get average lumination */
822 if (gspca_dev
->last_packet_type
== LAST_PACKET
&&
824 atomic_set(&sd
->avg_lum
, data
[-lum_offset
] +
825 data
[-lum_offset
+ 1]);
827 /* Start the new frame with the jpeg header */
828 /* The PAC7302 has the image rotated 90 degrees */
829 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
830 jpeg_header
, sizeof jpeg_header
);
832 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
835 #ifdef CONFIG_VIDEO_ADV_DEBUG
836 static int sd_dbg_s_register(struct gspca_dev
*gspca_dev
,
837 struct v4l2_dbg_register
*reg
)
842 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
845 if (reg
->match
.type
== V4L2_CHIP_MATCH_HOST
&&
846 reg
->match
.addr
== 0 &&
847 (reg
->reg
< 0x000000ff) &&
848 (reg
->val
<= 0x000000ff)
850 /* Currently writing to page 0 is only supported. */
851 /* reg_w() only supports 8bit index */
855 /* Note that there shall be no access to other page
856 by any other function between the page swith and
857 the actual register write */
858 reg_w(gspca_dev
, 0xff, 0x00); /* page 0 */
859 reg_w(gspca_dev
, index
, value
);
861 reg_w(gspca_dev
, 0xdc, 0x01);
863 return gspca_dev
->usb_err
;
866 static int sd_chip_ident(struct gspca_dev
*gspca_dev
,
867 struct v4l2_dbg_chip_ident
*chip
)
871 if (chip
->match
.type
== V4L2_CHIP_MATCH_HOST
&&
872 chip
->match
.addr
== 0) {
874 chip
->ident
= V4L2_IDENT_UNKNOWN
;
881 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
882 static int sd_int_pkt_scan(struct gspca_dev
*gspca_dev
,
883 u8
*data
, /* interrupt packet data */
884 int len
) /* interrput packet length */
892 if ((data0
== 0x00 && data1
== 0x11) ||
893 (data0
== 0x22 && data1
== 0x33) ||
894 (data0
== 0x44 && data1
== 0x55) ||
895 (data0
== 0x66 && data1
== 0x77) ||
896 (data0
== 0x88 && data1
== 0x99) ||
897 (data0
== 0xaa && data1
== 0xbb) ||
898 (data0
== 0xcc && data1
== 0xdd) ||
899 (data0
== 0xee && data1
== 0xff)) {
900 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 1);
901 input_sync(gspca_dev
->input_dev
);
902 input_report_key(gspca_dev
->input_dev
, KEY_CAMERA
, 0);
903 input_sync(gspca_dev
->input_dev
);
912 /* sub-driver description for pac7302 */
913 static const struct sd_desc sd_desc
= {
914 .name
= KBUILD_MODNAME
,
916 .nctrls
= ARRAY_SIZE(sd_ctrls
),
922 .pkt_scan
= sd_pkt_scan
,
923 .dq_callback
= do_autogain
,
924 #ifdef CONFIG_VIDEO_ADV_DEBUG
925 .set_register
= sd_dbg_s_register
,
926 .get_chip_ident
= sd_chip_ident
,
928 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
929 .int_pkt_scan
= sd_int_pkt_scan
,
933 /* -- module initialisation -- */
934 static const struct usb_device_id device_table
[] = {
935 {USB_DEVICE(0x06f8, 0x3009)},
936 {USB_DEVICE(0x06f8, 0x301b)},
937 {USB_DEVICE(0x093a, 0x2620)},
938 {USB_DEVICE(0x093a, 0x2621)},
939 {USB_DEVICE(0x093a, 0x2622), .driver_info
= FL_VFLIP
},
940 {USB_DEVICE(0x093a, 0x2624), .driver_info
= FL_VFLIP
},
941 {USB_DEVICE(0x093a, 0x2625)},
942 {USB_DEVICE(0x093a, 0x2626)},
943 {USB_DEVICE(0x093a, 0x2628)},
944 {USB_DEVICE(0x093a, 0x2629), .driver_info
= FL_VFLIP
},
945 {USB_DEVICE(0x093a, 0x262a)},
946 {USB_DEVICE(0x093a, 0x262c)},
947 {USB_DEVICE(0x145f, 0x013c)},
948 {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
951 MODULE_DEVICE_TABLE(usb
, device_table
);
953 /* -- device connect -- */
954 static int sd_probe(struct usb_interface
*intf
,
955 const struct usb_device_id
*id
)
957 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
961 static struct usb_driver sd_driver
= {
962 .name
= KBUILD_MODNAME
,
963 .id_table
= device_table
,
965 .disconnect
= gspca_disconnect
,
967 .suspend
= gspca_suspend
,
968 .resume
= gspca_resume
,
972 module_usb_driver(sd_driver
);