V4L/DVB (13382): gspca - pac7302: Remove redundant stream off command.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / gspca / pac7302.c
blobae1d90a85c5c69a5cdd1edbcfff89daa3024ea57
1 /*
2 * Pixart PAC7302 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 * Separated from Pixart PAC7311 library by Márton Németh <nm127@freemail.hu>
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.
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.
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
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.
30 Register page 1:
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
40 Register page 3/4:
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.
54 #define MODULE_NAME "pac7302"
56 #include "gspca.h"
58 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
59 MODULE_DESCRIPTION("Pixart PAC7302");
60 MODULE_LICENSE("GPL");
62 /* specific webcam descriptor for pac7302 */
63 struct sd {
64 struct gspca_dev gspca_dev; /* !! must be the first item */
66 unsigned char brightness;
67 unsigned char contrast;
68 unsigned char colors;
69 unsigned char gain;
70 unsigned char exposure;
71 unsigned char autogain;
72 __u8 hflip;
73 __u8 vflip;
75 u8 sof_read;
76 u8 autogain_ignore_frames;
78 atomic_t avg_lum;
81 /* V4L2 controls supported by the driver */
82 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
97 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
99 static struct ctrl sd_ctrls[] = {
100 /* This control is pac7302 only */
103 .id = V4L2_CID_BRIGHTNESS,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Brightness",
106 .minimum = 0,
107 #define BRIGHTNESS_MAX 0x20
108 .maximum = BRIGHTNESS_MAX,
109 .step = 1,
110 #define BRIGHTNESS_DEF 0x10
111 .default_value = BRIGHTNESS_DEF,
113 .set = sd_setbrightness,
114 .get = sd_getbrightness,
116 /* This control is for both the 7302 and the 7311 */
119 .id = V4L2_CID_CONTRAST,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Contrast",
122 .minimum = 0,
123 #define CONTRAST_MAX 255
124 .maximum = CONTRAST_MAX,
125 .step = 1,
126 #define CONTRAST_DEF 127
127 .default_value = CONTRAST_DEF,
129 .set = sd_setcontrast,
130 .get = sd_getcontrast,
132 /* This control is pac7302 only */
135 .id = V4L2_CID_SATURATION,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "Saturation",
138 .minimum = 0,
139 #define COLOR_MAX 255
140 .maximum = COLOR_MAX,
141 .step = 1,
142 #define COLOR_DEF 127
143 .default_value = COLOR_DEF,
145 .set = sd_setcolors,
146 .get = sd_getcolors,
148 /* All controls below are for both the 7302 and the 7311 */
151 .id = V4L2_CID_GAIN,
152 .type = V4L2_CTRL_TYPE_INTEGER,
153 .name = "Gain",
154 .minimum = 0,
155 #define GAIN_MAX 255
156 .maximum = GAIN_MAX,
157 .step = 1,
158 #define GAIN_DEF 127
159 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
160 .default_value = GAIN_DEF,
162 .set = sd_setgain,
163 .get = sd_getgain,
167 .id = V4L2_CID_EXPOSURE,
168 .type = V4L2_CTRL_TYPE_INTEGER,
169 .name = "Exposure",
170 .minimum = 0,
171 #define EXPOSURE_MAX 255
172 .maximum = EXPOSURE_MAX,
173 .step = 1,
174 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
175 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
176 .default_value = EXPOSURE_DEF,
178 .set = sd_setexposure,
179 .get = sd_getexposure,
183 .id = V4L2_CID_AUTOGAIN,
184 .type = V4L2_CTRL_TYPE_BOOLEAN,
185 .name = "Auto Gain",
186 .minimum = 0,
187 .maximum = 1,
188 .step = 1,
189 #define AUTOGAIN_DEF 1
190 .default_value = AUTOGAIN_DEF,
192 .set = sd_setautogain,
193 .get = sd_getautogain,
197 .id = V4L2_CID_HFLIP,
198 .type = V4L2_CTRL_TYPE_BOOLEAN,
199 .name = "Mirror",
200 .minimum = 0,
201 .maximum = 1,
202 .step = 1,
203 #define HFLIP_DEF 0
204 .default_value = HFLIP_DEF,
206 .set = sd_sethflip,
207 .get = sd_gethflip,
211 .id = V4L2_CID_VFLIP,
212 .type = V4L2_CTRL_TYPE_BOOLEAN,
213 .name = "Vflip",
214 .minimum = 0,
215 .maximum = 1,
216 .step = 1,
217 #define VFLIP_DEF 0
218 .default_value = VFLIP_DEF,
220 .set = sd_setvflip,
221 .get = sd_getvflip,
225 static const struct v4l2_pix_format vga_mode[] = {
226 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
227 .bytesperline = 640,
228 .sizeimage = 640 * 480 * 3 / 8 + 590,
229 .colorspace = V4L2_COLORSPACE_JPEG,
230 .priv = 0},
233 #define LOAD_PAGE3 255
234 #define LOAD_PAGE4 254
235 #define END_OF_SEQUENCE 0
237 /* pac 7302 */
238 static const __u8 init_7302[] = {
239 /* index,value */
240 0xff, 0x01, /* page 1 */
241 0x78, 0x00, /* deactivate */
242 0xff, 0x01,
243 0x78, 0x40, /* led off */
245 static const __u8 start_7302[] = {
246 /* index, len, [value]* */
247 0xff, 1, 0x00, /* page 0 */
248 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
249 0x00, 0x00, 0x00, 0x00,
250 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
251 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
252 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
253 0x26, 2, 0xaa, 0xaa,
254 0x2e, 1, 0x31,
255 0x38, 1, 0x01,
256 0x3a, 3, 0x14, 0xff, 0x5a,
257 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
258 0x00, 0x54, 0x11,
259 0x55, 1, 0x00,
260 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
261 0x6b, 1, 0x00,
262 0x6e, 3, 0x08, 0x06, 0x00,
263 0x72, 3, 0x00, 0xff, 0x00,
264 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
265 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
266 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
267 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
268 0xd2, 0xeb,
269 0xaf, 1, 0x02,
270 0xb5, 2, 0x08, 0x08,
271 0xb8, 2, 0x08, 0x88,
272 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
273 0xcc, 1, 0x00,
274 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
275 0xc1, 0xd7, 0xec,
276 0xdc, 1, 0x01,
277 0xff, 1, 0x01, /* page 1 */
278 0x12, 3, 0x02, 0x00, 0x01,
279 0x3e, 2, 0x00, 0x00,
280 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
281 0x7c, 1, 0x00,
282 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
283 0x02, 0x00,
284 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
285 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
286 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
287 0xd8, 1, 0x01,
288 0xdb, 2, 0x00, 0x01,
289 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
290 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
291 0xeb, 1, 0x00,
292 0xff, 1, 0x02, /* page 2 */
293 0x22, 1, 0x00,
294 0xff, 1, 0x03, /* page 3 */
295 0, LOAD_PAGE3, /* load the page 3 */
296 0x11, 1, 0x01,
297 0xff, 1, 0x02, /* page 2 */
298 0x13, 1, 0x00,
299 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
300 0x27, 2, 0x14, 0x0c,
301 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
302 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
303 0x6e, 1, 0x08,
304 0xff, 1, 0x01, /* page 1 */
305 0x78, 1, 0x00,
306 0, END_OF_SEQUENCE /* end of sequence */
309 #define SKIP 0xaa
310 /* page 3 - the value SKIP says skip the index - see reg_w_page() */
311 static const __u8 page3_7302[] = {
312 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
313 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
314 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
316 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
317 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
318 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
319 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
322 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
326 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
327 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
328 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
331 0x00
334 static void reg_w_buf(struct gspca_dev *gspca_dev,
335 __u8 index,
336 const char *buffer, int len)
338 int ret;
340 memcpy(gspca_dev->usb_buf, buffer, len);
341 ret = usb_control_msg(gspca_dev->dev,
342 usb_sndctrlpipe(gspca_dev->dev, 0),
343 1, /* request */
344 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
345 0, /* value */
346 index, gspca_dev->usb_buf, len,
347 500);
348 if (ret < 0)
349 PDEBUG(D_ERR, "reg_w_buf(): "
350 "Failed to write registers to index 0x%x, error %i",
351 index, ret);
355 static void reg_w(struct gspca_dev *gspca_dev,
356 __u8 index,
357 __u8 value)
359 int ret;
361 gspca_dev->usb_buf[0] = value;
362 ret = usb_control_msg(gspca_dev->dev,
363 usb_sndctrlpipe(gspca_dev->dev, 0),
364 0, /* request */
365 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
366 0, index, gspca_dev->usb_buf, 1,
367 500);
368 if (ret < 0)
369 PDEBUG(D_ERR, "reg_w(): "
370 "Failed to write register to index 0x%x, value 0x%x, error %i",
371 index, value, ret);
374 static void reg_w_seq(struct gspca_dev *gspca_dev,
375 const __u8 *seq, int len)
377 while (--len >= 0) {
378 reg_w(gspca_dev, seq[0], seq[1]);
379 seq += 2;
383 /* load the beginning of a page */
384 static void reg_w_page(struct gspca_dev *gspca_dev,
385 const __u8 *page, int len)
387 int index;
388 int ret;
390 for (index = 0; index < len; index++) {
391 if (page[index] == SKIP) /* skip this index */
392 continue;
393 gspca_dev->usb_buf[0] = page[index];
394 ret = usb_control_msg(gspca_dev->dev,
395 usb_sndctrlpipe(gspca_dev->dev, 0),
396 0, /* request */
397 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
398 0, index, gspca_dev->usb_buf, 1,
399 500);
400 if (ret < 0)
401 PDEBUG(D_ERR, "reg_w_page(): "
402 "Failed to write register to index 0x%x, "
403 "value 0x%x, error %i",
404 index, page[index], ret);
408 /* output a variable sequence */
409 static void reg_w_var(struct gspca_dev *gspca_dev,
410 const __u8 *seq,
411 const __u8 *page3, unsigned int page3_len,
412 const __u8 *page4, unsigned int page4_len)
414 int index, len;
416 for (;;) {
417 index = *seq++;
418 len = *seq++;
419 switch (len) {
420 case END_OF_SEQUENCE:
421 return;
422 case LOAD_PAGE4:
423 reg_w_page(gspca_dev, page4, page4_len);
424 break;
425 case LOAD_PAGE3:
426 reg_w_page(gspca_dev, page3, page3_len);
427 break;
428 default:
429 if (len > USB_BUF_SZ) {
430 PDEBUG(D_ERR|D_STREAM,
431 "Incorrect variable sequence");
432 return;
434 while (len > 0) {
435 if (len < 8) {
436 reg_w_buf(gspca_dev, index, seq, len);
437 seq += len;
438 break;
440 reg_w_buf(gspca_dev, index, seq, 8);
441 seq += 8;
442 index += 8;
443 len -= 8;
447 /* not reached */
450 /* this function is called at probe time for pac7302 */
451 static int sd_config(struct gspca_dev *gspca_dev,
452 const struct usb_device_id *id)
454 struct sd *sd = (struct sd *) gspca_dev;
455 struct cam *cam;
457 cam = &gspca_dev->cam;
459 PDEBUG(D_CONF, "Find Sensor PAC7302");
460 cam->cam_mode = vga_mode; /* only 640x480 */
461 cam->nmodes = ARRAY_SIZE(vga_mode);
463 sd->brightness = BRIGHTNESS_DEF;
464 sd->contrast = CONTRAST_DEF;
465 sd->colors = COLOR_DEF;
466 sd->gain = GAIN_DEF;
467 sd->exposure = EXPOSURE_DEF;
468 sd->autogain = AUTOGAIN_DEF;
469 sd->hflip = HFLIP_DEF;
470 sd->vflip = VFLIP_DEF;
471 return 0;
474 /* This function is used by pac7302 only */
475 static void setbrightcont(struct gspca_dev *gspca_dev)
477 struct sd *sd = (struct sd *) gspca_dev;
478 int i, v;
479 static const __u8 max[10] =
480 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
481 0xd4, 0xec};
482 static const __u8 delta[10] =
483 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
484 0x11, 0x0b};
486 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
487 for (i = 0; i < 10; i++) {
488 v = max[i];
489 v += (sd->brightness - BRIGHTNESS_MAX)
490 * 150 / BRIGHTNESS_MAX; /* 200 ? */
491 v -= delta[i] * sd->contrast / CONTRAST_MAX;
492 if (v < 0)
493 v = 0;
494 else if (v > 0xff)
495 v = 0xff;
496 reg_w(gspca_dev, 0xa2 + i, v);
498 reg_w(gspca_dev, 0xdc, 0x01);
501 /* This function is used by pac7302 only */
502 static void setcolors(struct gspca_dev *gspca_dev)
504 struct sd *sd = (struct sd *) gspca_dev;
505 int i, v;
506 static const int a[9] =
507 {217, -212, 0, -101, 170, -67, -38, -315, 355};
508 static const int b[9] =
509 {19, 106, 0, 19, 106, 1, 19, 106, 1};
511 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
512 reg_w(gspca_dev, 0x11, 0x01);
513 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
514 for (i = 0; i < 9; i++) {
515 v = a[i] * sd->colors / COLOR_MAX + b[i];
516 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
517 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
519 reg_w(gspca_dev, 0xdc, 0x01);
520 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
523 static void setgain(struct gspca_dev *gspca_dev)
525 struct sd *sd = (struct sd *) gspca_dev;
527 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
528 reg_w(gspca_dev, 0x10, sd->gain >> 3);
530 /* load registers to sensor (Bit 0, auto clear) */
531 reg_w(gspca_dev, 0x11, 0x01);
534 static void setexposure(struct gspca_dev *gspca_dev)
536 struct sd *sd = (struct sd *) gspca_dev;
537 __u8 reg;
539 /* register 2 of frame 3/4 contains the clock divider configuring the
540 no fps according to the formula: 60 / reg. sd->exposure is the
541 desired exposure time in ms. */
542 reg = 120 * sd->exposure / 1000;
543 if (reg < 2)
544 reg = 2;
545 else if (reg > 63)
546 reg = 63;
548 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
549 the nearest multiple of 3, except when between 6 and 12? */
550 if (reg < 6 || reg > 12)
551 reg = ((reg + 1) / 3) * 3;
552 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
553 reg_w(gspca_dev, 0x02, reg);
555 /* load registers to sensor (Bit 0, auto clear) */
556 reg_w(gspca_dev, 0x11, 0x01);
559 static void sethvflip(struct gspca_dev *gspca_dev)
561 struct sd *sd = (struct sd *) gspca_dev;
562 __u8 data;
564 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
565 data = (sd->hflip ? 0x08 : 0x00) | (sd->vflip ? 0x04 : 0x00);
566 reg_w(gspca_dev, 0x21, data);
567 /* load registers to sensor (Bit 0, auto clear) */
568 reg_w(gspca_dev, 0x11, 0x01);
571 /* this function is called at probe and resume time for pac7302 */
572 static int sd_init(struct gspca_dev *gspca_dev)
574 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
576 return 0;
579 static int sd_start(struct gspca_dev *gspca_dev)
581 struct sd *sd = (struct sd *) gspca_dev;
583 sd->sof_read = 0;
585 reg_w_var(gspca_dev, start_7302,
586 page3_7302, sizeof(page3_7302),
587 NULL, 0);
588 setbrightcont(gspca_dev);
589 setcolors(gspca_dev);
590 setgain(gspca_dev);
591 setexposure(gspca_dev);
592 sethvflip(gspca_dev);
594 /* only resolution 640x480 is supported for pac7302 */
596 sd->sof_read = 0;
597 sd->autogain_ignore_frames = 0;
598 atomic_set(&sd->avg_lum, -1);
600 /* start stream */
601 reg_w(gspca_dev, 0xff, 0x01);
602 reg_w(gspca_dev, 0x78, 0x01);
604 return 0;
607 static void sd_stopN(struct gspca_dev *gspca_dev)
609 /* stop stream */
610 reg_w(gspca_dev, 0xff, 0x01);
611 reg_w(gspca_dev, 0x78, 0x00);
614 /* called on streamoff with alt 0 and on disconnect for pac7302 */
615 static void sd_stop0(struct gspca_dev *gspca_dev)
617 if (!gspca_dev->present)
618 return;
619 reg_w(gspca_dev, 0xff, 0x01);
620 reg_w(gspca_dev, 0x78, 0x40);
623 /* Include pac common sof detection functions */
624 #include "pac_common.h"
626 static void do_autogain(struct gspca_dev *gspca_dev)
628 struct sd *sd = (struct sd *) gspca_dev;
629 int avg_lum = atomic_read(&sd->avg_lum);
630 int desired_lum, deadzone;
632 if (avg_lum == -1)
633 return;
635 desired_lum = 270 + sd->brightness * 4;
636 /* Hack hack, with the 7202 the first exposure step is
637 pretty large, so if we're about to make the first
638 exposure increase make the deadzone large to avoid
639 oscilating */
640 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
641 sd->exposure > EXPOSURE_DEF &&
642 sd->exposure < 42)
643 deadzone = 90;
644 else
645 deadzone = 30;
647 if (sd->autogain_ignore_frames > 0)
648 sd->autogain_ignore_frames--;
649 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
650 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
651 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
654 /* JPEG header, part 1 */
655 static const unsigned char pac_jpeg_header1[] = {
656 0xff, 0xd8, /* SOI: Start of Image */
658 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
659 0x00, 0x11, /* length = 17 bytes (including this length field) */
660 0x08 /* Precision: 8 */
661 /* 2 bytes is placed here: number of image lines */
662 /* 2 bytes is placed here: samples per line */
665 /* JPEG header, continued */
666 static const unsigned char pac_jpeg_header2[] = {
667 0x03, /* Number of image components: 3 */
668 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
669 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
670 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
672 0xff, 0xda, /* SOS: Start Of Scan */
673 0x00, 0x0c, /* length = 12 bytes (including this length field) */
674 0x03, /* number of components: 3 */
675 0x01, 0x00, /* selector 1, table 0x00 */
676 0x02, 0x11, /* selector 2, table 0x11 */
677 0x03, 0x11, /* selector 3, table 0x11 */
678 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
679 0x00 /* Successive approximation: 0 */
682 static void pac_start_frame(struct gspca_dev *gspca_dev,
683 struct gspca_frame *frame,
684 __u16 lines, __u16 samples_per_line)
686 unsigned char tmpbuf[4];
688 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
689 pac_jpeg_header1, sizeof(pac_jpeg_header1));
691 tmpbuf[0] = lines >> 8;
692 tmpbuf[1] = lines & 0xff;
693 tmpbuf[2] = samples_per_line >> 8;
694 tmpbuf[3] = samples_per_line & 0xff;
696 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
697 tmpbuf, sizeof(tmpbuf));
698 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
699 pac_jpeg_header2, sizeof(pac_jpeg_header2));
702 /* this function is run at interrupt level */
703 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
704 struct gspca_frame *frame, /* target */
705 __u8 *data, /* isoc packet */
706 int len) /* iso packet length */
708 struct sd *sd = (struct sd *) gspca_dev;
709 unsigned char *sof;
711 sof = pac_find_sof(&sd->sof_read, data, len);
712 if (sof) {
713 int n, lum_offset, footer_length;
715 /* 6 bytes after the FF D9 EOF marker a number of lumination
716 bytes are send corresponding to different parts of the
717 image, the 14th and 15th byte after the EOF seem to
718 correspond to the center of the image */
719 lum_offset = 61 + sizeof pac_sof_marker;
720 footer_length = 74;
722 /* Finish decoding current frame */
723 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
724 if (n < 0) {
725 frame->data_end += n;
726 n = 0;
728 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
729 data, n);
730 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
731 frame->data_end[-2] == 0xff &&
732 frame->data_end[-1] == 0xd9)
733 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
734 NULL, 0);
736 n = sof - data;
737 len -= n;
738 data = sof;
740 /* Get average lumination */
741 if (gspca_dev->last_packet_type == LAST_PACKET &&
742 n >= lum_offset)
743 atomic_set(&sd->avg_lum, data[-lum_offset] +
744 data[-lum_offset + 1]);
745 else
746 atomic_set(&sd->avg_lum, -1);
748 /* Start the new frame with the jpeg header */
749 /* The PAC7302 has the image rotated 90 degrees */
750 pac_start_frame(gspca_dev, frame,
751 gspca_dev->width, gspca_dev->height);
753 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
756 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
758 struct sd *sd = (struct sd *) gspca_dev;
760 sd->brightness = val;
761 if (gspca_dev->streaming)
762 setbrightcont(gspca_dev);
763 return 0;
766 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
768 struct sd *sd = (struct sd *) gspca_dev;
770 *val = sd->brightness;
771 return 0;
774 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
776 struct sd *sd = (struct sd *) gspca_dev;
778 sd->contrast = val;
779 if (gspca_dev->streaming) {
780 setbrightcont(gspca_dev);
782 return 0;
785 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
787 struct sd *sd = (struct sd *) gspca_dev;
789 *val = sd->contrast;
790 return 0;
793 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
795 struct sd *sd = (struct sd *) gspca_dev;
797 sd->colors = val;
798 if (gspca_dev->streaming)
799 setcolors(gspca_dev);
800 return 0;
803 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
805 struct sd *sd = (struct sd *) gspca_dev;
807 *val = sd->colors;
808 return 0;
811 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
813 struct sd *sd = (struct sd *) gspca_dev;
815 sd->gain = val;
816 if (gspca_dev->streaming)
817 setgain(gspca_dev);
818 return 0;
821 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
823 struct sd *sd = (struct sd *) gspca_dev;
825 *val = sd->gain;
826 return 0;
829 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
831 struct sd *sd = (struct sd *) gspca_dev;
833 sd->exposure = val;
834 if (gspca_dev->streaming)
835 setexposure(gspca_dev);
836 return 0;
839 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
841 struct sd *sd = (struct sd *) gspca_dev;
843 *val = sd->exposure;
844 return 0;
847 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
849 struct sd *sd = (struct sd *) gspca_dev;
851 sd->autogain = val;
852 /* when switching to autogain set defaults to make sure
853 we are on a valid point of the autogain gain /
854 exposure knee graph, and give this change time to
855 take effect before doing autogain. */
856 if (sd->autogain) {
857 sd->exposure = EXPOSURE_DEF;
858 sd->gain = GAIN_DEF;
859 if (gspca_dev->streaming) {
860 sd->autogain_ignore_frames =
861 PAC_AUTOGAIN_IGNORE_FRAMES;
862 setexposure(gspca_dev);
863 setgain(gspca_dev);
867 return 0;
870 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
872 struct sd *sd = (struct sd *) gspca_dev;
874 *val = sd->autogain;
875 return 0;
878 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
880 struct sd *sd = (struct sd *) gspca_dev;
882 sd->hflip = val;
883 if (gspca_dev->streaming)
884 sethvflip(gspca_dev);
885 return 0;
888 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
890 struct sd *sd = (struct sd *) gspca_dev;
892 *val = sd->hflip;
893 return 0;
896 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
898 struct sd *sd = (struct sd *) gspca_dev;
900 sd->vflip = val;
901 if (gspca_dev->streaming)
902 sethvflip(gspca_dev);
903 return 0;
906 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
908 struct sd *sd = (struct sd *) gspca_dev;
910 *val = sd->vflip;
911 return 0;
914 /* sub-driver description for pac7302 */
915 static struct sd_desc sd_desc = {
916 .name = MODULE_NAME,
917 .ctrls = sd_ctrls,
918 .nctrls = ARRAY_SIZE(sd_ctrls),
919 .config = sd_config,
920 .init = sd_init,
921 .start = sd_start,
922 .stopN = sd_stopN,
923 .stop0 = sd_stop0,
924 .pkt_scan = sd_pkt_scan,
925 .dq_callback = do_autogain,
928 /* -- module initialisation -- */
929 static __devinitdata struct usb_device_id device_table[] = {
930 {USB_DEVICE(0x06f8, 0x3009)},
931 {USB_DEVICE(0x093a, 0x2620)},
932 {USB_DEVICE(0x093a, 0x2621)},
933 {USB_DEVICE(0x093a, 0x2622)},
934 {USB_DEVICE(0x093a, 0x2624)},
935 {USB_DEVICE(0x093a, 0x2626)},
936 {USB_DEVICE(0x093a, 0x2628)},
937 {USB_DEVICE(0x093a, 0x2629)},
938 {USB_DEVICE(0x093a, 0x262a)},
939 {USB_DEVICE(0x093a, 0x262c)},
942 MODULE_DEVICE_TABLE(usb, device_table);
944 /* -- device connect -- */
945 static int sd_probe(struct usb_interface *intf,
946 const struct usb_device_id *id)
948 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
949 THIS_MODULE);
952 static struct usb_driver sd_driver = {
953 .name = MODULE_NAME,
954 .id_table = device_table,
955 .probe = sd_probe,
956 .disconnect = gspca_disconnect,
957 #ifdef CONFIG_PM
958 .suspend = gspca_suspend,
959 .resume = gspca_resume,
960 #endif
963 /* -- module insert / remove -- */
964 static int __init sd_mod_init(void)
966 int ret;
967 ret = usb_register(&sd_driver);
968 if (ret < 0)
969 return ret;
970 PDEBUG(D_PROBE, "registered");
971 return 0;
973 static void __exit sd_mod_exit(void)
975 usb_deregister(&sd_driver);
976 PDEBUG(D_PROBE, "deregistered");
979 module_init(sd_mod_init);
980 module_exit(sd_mod_exit);