added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / media / video / gspca / pac7311.c
bloba9c95cba710e350e14fb70df6121d2a721700fa1
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 */
61 struct sd {
62 struct gspca_dev gspca_dev; /* !! must be the first item */
64 unsigned char brightness;
65 unsigned char contrast;
66 unsigned char colors;
67 unsigned char gain;
68 unsigned char exposure;
69 unsigned char autogain;
70 __u8 hflip;
71 __u8 vflip;
73 __u8 sensor;
74 #define SENSOR_PAC7302 0
75 #define SENSOR_PAC7311 1
77 u8 sof_read;
78 u8 autogain_ignore_frames;
80 atomic_t avg_lum;
83 /* V4L2 controls supported by the driver */
84 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
96 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
97 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
98 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
99 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
101 static struct ctrl sd_ctrls[] = {
102 /* This control is pac7302 only */
103 #define BRIGHTNESS_IDX 0
106 .id = V4L2_CID_BRIGHTNESS,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Brightness",
109 .minimum = 0,
110 #define BRIGHTNESS_MAX 0x20
111 .maximum = BRIGHTNESS_MAX,
112 .step = 1,
113 #define BRIGHTNESS_DEF 0x10
114 .default_value = BRIGHTNESS_DEF,
116 .set = sd_setbrightness,
117 .get = sd_getbrightness,
119 /* This control is for both the 7302 and the 7311 */
122 .id = V4L2_CID_CONTRAST,
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "Contrast",
125 .minimum = 0,
126 #define CONTRAST_MAX 255
127 .maximum = CONTRAST_MAX,
128 .step = 1,
129 #define CONTRAST_DEF 127
130 .default_value = CONTRAST_DEF,
132 .set = sd_setcontrast,
133 .get = sd_getcontrast,
135 /* This control is pac7302 only */
136 #define SATURATION_IDX 2
139 .id = V4L2_CID_SATURATION,
140 .type = V4L2_CTRL_TYPE_INTEGER,
141 .name = "Saturation",
142 .minimum = 0,
143 #define COLOR_MAX 255
144 .maximum = COLOR_MAX,
145 .step = 1,
146 #define COLOR_DEF 127
147 .default_value = COLOR_DEF,
149 .set = sd_setcolors,
150 .get = sd_getcolors,
152 /* All controls below are for both the 7302 and the 7311 */
155 .id = V4L2_CID_GAIN,
156 .type = V4L2_CTRL_TYPE_INTEGER,
157 .name = "Gain",
158 .minimum = 0,
159 #define GAIN_MAX 255
160 .maximum = GAIN_MAX,
161 .step = 1,
162 #define GAIN_DEF 127
163 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
164 .default_value = GAIN_DEF,
166 .set = sd_setgain,
167 .get = sd_getgain,
171 .id = V4L2_CID_EXPOSURE,
172 .type = V4L2_CTRL_TYPE_INTEGER,
173 .name = "Exposure",
174 .minimum = 0,
175 #define EXPOSURE_MAX 255
176 .maximum = EXPOSURE_MAX,
177 .step = 1,
178 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
179 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
180 .default_value = EXPOSURE_DEF,
182 .set = sd_setexposure,
183 .get = sd_getexposure,
187 .id = V4L2_CID_AUTOGAIN,
188 .type = V4L2_CTRL_TYPE_BOOLEAN,
189 .name = "Auto Gain",
190 .minimum = 0,
191 .maximum = 1,
192 .step = 1,
193 #define AUTOGAIN_DEF 1
194 .default_value = AUTOGAIN_DEF,
196 .set = sd_setautogain,
197 .get = sd_getautogain,
201 .id = V4L2_CID_HFLIP,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
203 .name = "Mirror",
204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
207 #define HFLIP_DEF 0
208 .default_value = HFLIP_DEF,
210 .set = sd_sethflip,
211 .get = sd_gethflip,
215 .id = V4L2_CID_VFLIP,
216 .type = V4L2_CTRL_TYPE_BOOLEAN,
217 .name = "Vflip",
218 .minimum = 0,
219 .maximum = 1,
220 .step = 1,
221 #define VFLIP_DEF 0
222 .default_value = VFLIP_DEF,
224 .set = sd_setvflip,
225 .get = sd_getvflip,
229 static const struct v4l2_pix_format vga_mode[] = {
230 {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
231 .bytesperline = 160,
232 .sizeimage = 160 * 120 * 3 / 8 + 590,
233 .colorspace = V4L2_COLORSPACE_JPEG,
234 .priv = 2},
235 {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
236 .bytesperline = 320,
237 .sizeimage = 320 * 240 * 3 / 8 + 590,
238 .colorspace = V4L2_COLORSPACE_JPEG,
239 .priv = 1},
240 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
241 .bytesperline = 640,
242 .sizeimage = 640 * 480 * 3 / 8 + 590,
243 .colorspace = V4L2_COLORSPACE_JPEG,
244 .priv = 0},
247 /* pac 7302 */
248 static const __u8 init_7302[] = {
249 /* index,value */
250 0xff, 0x01, /* page 1 */
251 0x78, 0x00, /* deactivate */
252 0xff, 0x01,
253 0x78, 0x40, /* led off */
255 static const __u8 start_7302[] = {
256 /* index, len, [value]* */
257 0xff, 1, 0x00, /* page 0 */
258 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
259 0x00, 0x00, 0x00, 0x00,
260 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
261 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
262 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
263 0x26, 2, 0xaa, 0xaa,
264 0x2e, 1, 0x31,
265 0x38, 1, 0x01,
266 0x3a, 3, 0x14, 0xff, 0x5a,
267 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
268 0x00, 0x54, 0x11,
269 0x55, 1, 0x00,
270 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
271 0x6b, 1, 0x00,
272 0x6e, 3, 0x08, 0x06, 0x00,
273 0x72, 3, 0x00, 0xff, 0x00,
274 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
275 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
276 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
277 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
278 0xd2, 0xeb,
279 0xaf, 1, 0x02,
280 0xb5, 2, 0x08, 0x08,
281 0xb8, 2, 0x08, 0x88,
282 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
283 0xcc, 1, 0x00,
284 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
285 0xc1, 0xd7, 0xec,
286 0xdc, 1, 0x01,
287 0xff, 1, 0x01, /* page 1 */
288 0x12, 3, 0x02, 0x00, 0x01,
289 0x3e, 2, 0x00, 0x00,
290 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
291 0x7c, 1, 0x00,
292 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
293 0x02, 0x00,
294 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
295 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
296 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
297 0xd8, 1, 0x01,
298 0xdb, 2, 0x00, 0x01,
299 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
300 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
301 0xeb, 1, 0x00,
302 0xff, 1, 0x02, /* page 2 */
303 0x22, 1, 0x00,
304 0xff, 1, 0x03, /* page 3 */
305 0x00, 255, /* load the page 3 */
306 0x11, 1, 0x01,
307 0xff, 1, 0x02, /* page 2 */
308 0x13, 1, 0x00,
309 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
310 0x27, 2, 0x14, 0x0c,
311 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
312 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
313 0x6e, 1, 0x08,
314 0xff, 1, 0x01, /* page 1 */
315 0x78, 1, 0x00,
316 0, 0 /* end of sequence */
319 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
320 static const __u8 page3_7302[] = {
321 0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
322 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
323 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
325 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
326 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
327 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
328 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
331 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
335 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
336 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
337 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
340 0x00
343 /* pac 7311 */
344 static const __u8 init_7311[] = {
345 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
346 0x78, 0x40, /* Bit_0=start stream, Bit_6=LED */
347 0x78, 0x44, /* Bit_0=start stream, Bit_6=LED */
348 0xff, 0x04,
349 0x27, 0x80,
350 0x28, 0xca,
351 0x29, 0x53,
352 0x2a, 0x0e,
353 0xff, 0x01,
354 0x3e, 0x20,
357 static const __u8 start_7311[] = {
358 /* index, len, [value]* */
359 0xff, 1, 0x01, /* page 1 */
360 0x02, 43, 0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
361 0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
362 0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
363 0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00,
366 0x3e, 42, 0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
367 0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
368 0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
369 0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
370 0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
371 0xd0, 0xff,
372 0x78, 6, 0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
373 0x7f, 18, 0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
374 0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
375 0x18, 0x20,
376 0x96, 3, 0x01, 0x08, 0x04,
377 0xa0, 4, 0x44, 0x44, 0x44, 0x04,
378 0xf0, 13, 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
379 0x3f, 0x00, 0x0a, 0x01, 0x00,
380 0xff, 1, 0x04, /* page 4 */
381 0x00, 254, /* load the page 4 */
382 0x11, 1, 0x01,
383 0, 0 /* end of sequence */
386 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
387 static const __u8 page4_7311[] = {
388 0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
389 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
390 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
392 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
393 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
394 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
397 static void reg_w_buf(struct gspca_dev *gspca_dev,
398 __u8 index,
399 const char *buffer, int len)
401 memcpy(gspca_dev->usb_buf, buffer, len);
402 usb_control_msg(gspca_dev->dev,
403 usb_sndctrlpipe(gspca_dev->dev, 0),
404 1, /* request */
405 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
406 0, /* value */
407 index, gspca_dev->usb_buf, len,
408 500);
412 static void reg_w(struct gspca_dev *gspca_dev,
413 __u8 index,
414 __u8 value)
416 gspca_dev->usb_buf[0] = value;
417 usb_control_msg(gspca_dev->dev,
418 usb_sndctrlpipe(gspca_dev->dev, 0),
419 0, /* request */
420 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
421 0, index, gspca_dev->usb_buf, 1,
422 500);
425 static void reg_w_seq(struct gspca_dev *gspca_dev,
426 const __u8 *seq, int len)
428 while (--len >= 0) {
429 reg_w(gspca_dev, seq[0], seq[1]);
430 seq += 2;
434 /* load the beginning of a page */
435 static void reg_w_page(struct gspca_dev *gspca_dev,
436 const __u8 *page, int len)
438 int index;
440 for (index = 0; index < len; index++) {
441 if (page[index] == 0xaa) /* skip this index */
442 continue;
443 gspca_dev->usb_buf[0] = page[index];
444 usb_control_msg(gspca_dev->dev,
445 usb_sndctrlpipe(gspca_dev->dev, 0),
446 0, /* request */
447 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
448 0, index, gspca_dev->usb_buf, 1,
449 500);
453 /* output a variable sequence */
454 static void reg_w_var(struct gspca_dev *gspca_dev,
455 const __u8 *seq)
457 int index, len;
459 for (;;) {
460 index = *seq++;
461 len = *seq++;
462 switch (len) {
463 case 0:
464 return;
465 case 254:
466 reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
467 break;
468 case 255:
469 reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
470 break;
471 default:
472 if (len > 64) {
473 PDEBUG(D_ERR|D_STREAM,
474 "Incorrect variable sequence");
475 return;
477 while (len > 0) {
478 if (len < 8) {
479 reg_w_buf(gspca_dev, index, seq, len);
480 seq += len;
481 break;
483 reg_w_buf(gspca_dev, index, seq, 8);
484 seq += 8;
485 index += 8;
486 len -= 8;
490 /* not reached */
493 /* this function is called at probe time */
494 static int sd_config(struct gspca_dev *gspca_dev,
495 const struct usb_device_id *id)
497 struct sd *sd = (struct sd *) gspca_dev;
498 struct cam *cam;
500 cam = &gspca_dev->cam;
501 cam->epaddr = 0x05;
503 sd->sensor = id->driver_info;
504 if (sd->sensor == SENSOR_PAC7302) {
505 PDEBUG(D_CONF, "Find Sensor PAC7302");
506 cam->cam_mode = &vga_mode[2]; /* only 640x480 */
507 cam->nmodes = 1;
508 } else {
509 PDEBUG(D_CONF, "Find Sensor PAC7311");
510 cam->cam_mode = vga_mode;
511 cam->nmodes = ARRAY_SIZE(vga_mode);
512 gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
513 | (1 << SATURATION_IDX);
516 sd->brightness = BRIGHTNESS_DEF;
517 sd->contrast = CONTRAST_DEF;
518 sd->colors = COLOR_DEF;
519 sd->gain = GAIN_DEF;
520 sd->exposure = EXPOSURE_DEF;
521 sd->autogain = AUTOGAIN_DEF;
522 sd->hflip = HFLIP_DEF;
523 sd->vflip = VFLIP_DEF;
524 return 0;
527 /* This function is used by pac7302 only */
528 static void setbrightcont(struct gspca_dev *gspca_dev)
530 struct sd *sd = (struct sd *) gspca_dev;
531 int i, v;
532 static const __u8 max[10] =
533 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
534 0xd4, 0xec};
535 static const __u8 delta[10] =
536 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
537 0x11, 0x0b};
539 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
540 for (i = 0; i < 10; i++) {
541 v = max[i];
542 v += (sd->brightness - BRIGHTNESS_MAX)
543 * 150 / BRIGHTNESS_MAX; /* 200 ? */
544 v -= delta[i] * sd->contrast / CONTRAST_MAX;
545 if (v < 0)
546 v = 0;
547 else if (v > 0xff)
548 v = 0xff;
549 reg_w(gspca_dev, 0xa2 + i, v);
551 reg_w(gspca_dev, 0xdc, 0x01);
554 /* This function is used by pac7311 only */
555 static void setcontrast(struct gspca_dev *gspca_dev)
557 struct sd *sd = (struct sd *) gspca_dev;
559 reg_w(gspca_dev, 0xff, 0x04);
560 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
561 /* load registers to sensor (Bit 0, auto clear) */
562 reg_w(gspca_dev, 0x11, 0x01);
565 /* This function is used by pac7302 only */
566 static void setcolors(struct gspca_dev *gspca_dev)
568 struct sd *sd = (struct sd *) gspca_dev;
569 int i, v;
570 static const int a[9] =
571 {217, -212, 0, -101, 170, -67, -38, -315, 355};
572 static const int b[9] =
573 {19, 106, 0, 19, 106, 1, 19, 106, 1};
575 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
576 reg_w(gspca_dev, 0x11, 0x01);
577 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
578 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
579 for (i = 0; i < 9; i++) {
580 v = a[i] * sd->colors / COLOR_MAX + b[i];
581 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
582 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
584 reg_w(gspca_dev, 0xdc, 0x01);
585 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
588 static void setgain(struct gspca_dev *gspca_dev)
590 struct sd *sd = (struct sd *) gspca_dev;
592 if (sd->sensor == SENSOR_PAC7302) {
593 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
594 reg_w(gspca_dev, 0x10, sd->gain >> 3);
595 } else {
596 int gain = GAIN_MAX - sd->gain;
597 if (gain < 1)
598 gain = 1;
599 else if (gain > 245)
600 gain = 245;
601 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
602 reg_w(gspca_dev, 0x0e, 0x00);
603 reg_w(gspca_dev, 0x0f, gain);
605 /* load registers to sensor (Bit 0, auto clear) */
606 reg_w(gspca_dev, 0x11, 0x01);
609 static void setexposure(struct gspca_dev *gspca_dev)
611 struct sd *sd = (struct sd *) gspca_dev;
612 __u8 reg;
614 /* register 2 of frame 3/4 contains the clock divider configuring the
615 no fps according to the formula: 60 / reg. sd->exposure is the
616 desired exposure time in ms. */
617 reg = 120 * sd->exposure / 1000;
618 if (reg < 2)
619 reg = 2;
620 else if (reg > 63)
621 reg = 63;
623 if (sd->sensor == SENSOR_PAC7302) {
624 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
625 the nearest multiple of 3, except when between 6 and 12? */
626 if (reg < 6 || reg > 12)
627 reg = ((reg + 1) / 3) * 3;
628 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
629 reg_w(gspca_dev, 0x02, reg);
630 } else {
631 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
632 reg_w(gspca_dev, 0x02, reg);
633 /* Page 1 register 8 must always be 0x08 except when not in
634 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
635 reg_w(gspca_dev, 0xff, 0x01);
636 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
637 reg <= 3)
638 reg_w(gspca_dev, 0x08, 0x09);
639 else
640 reg_w(gspca_dev, 0x08, 0x08);
642 /* load registers to sensor (Bit 0, auto clear) */
643 reg_w(gspca_dev, 0x11, 0x01);
646 static void sethvflip(struct gspca_dev *gspca_dev)
648 struct sd *sd = (struct sd *) gspca_dev;
649 __u8 data;
651 if (sd->sensor == SENSOR_PAC7302) {
652 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
653 data = (sd->hflip ? 0x08 : 0x00)
654 | (sd->vflip ? 0x04 : 0x00);
655 } else {
656 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
657 data = (sd->hflip ? 0x04 : 0x00)
658 | (sd->vflip ? 0x08 : 0x00);
660 reg_w(gspca_dev, 0x21, data);
661 /* load registers to sensor (Bit 0, auto clear) */
662 reg_w(gspca_dev, 0x11, 0x01);
665 /* this function is called at probe and resume time */
666 static int sd_init(struct gspca_dev *gspca_dev)
668 struct sd *sd = (struct sd *) gspca_dev;
670 if (sd->sensor == SENSOR_PAC7302)
671 reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
672 else
673 reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
675 return 0;
678 static int sd_start(struct gspca_dev *gspca_dev)
680 struct sd *sd = (struct sd *) gspca_dev;
682 sd->sof_read = 0;
684 if (sd->sensor == SENSOR_PAC7302) {
685 reg_w_var(gspca_dev, start_7302);
686 setbrightcont(gspca_dev);
687 setcolors(gspca_dev);
688 } else {
689 reg_w_var(gspca_dev, start_7311);
690 setcontrast(gspca_dev);
692 setgain(gspca_dev);
693 setexposure(gspca_dev);
694 sethvflip(gspca_dev);
696 /* set correct resolution */
697 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
698 case 2: /* 160x120 pac7311 */
699 reg_w(gspca_dev, 0xff, 0x01);
700 reg_w(gspca_dev, 0x17, 0x20);
701 reg_w(gspca_dev, 0x87, 0x10);
702 break;
703 case 1: /* 320x240 pac7311 */
704 reg_w(gspca_dev, 0xff, 0x01);
705 reg_w(gspca_dev, 0x17, 0x30);
706 reg_w(gspca_dev, 0x87, 0x11);
707 break;
708 case 0: /* 640x480 */
709 if (sd->sensor == SENSOR_PAC7302)
710 break;
711 reg_w(gspca_dev, 0xff, 0x01);
712 reg_w(gspca_dev, 0x17, 0x00);
713 reg_w(gspca_dev, 0x87, 0x12);
714 break;
717 sd->sof_read = 0;
718 sd->autogain_ignore_frames = 0;
719 atomic_set(&sd->avg_lum, -1);
721 /* start stream */
722 reg_w(gspca_dev, 0xff, 0x01);
723 if (sd->sensor == SENSOR_PAC7302)
724 reg_w(gspca_dev, 0x78, 0x01);
725 else
726 reg_w(gspca_dev, 0x78, 0x05);
727 return 0;
730 static void sd_stopN(struct gspca_dev *gspca_dev)
732 struct sd *sd = (struct sd *) gspca_dev;
734 if (sd->sensor == SENSOR_PAC7302) {
735 reg_w(gspca_dev, 0xff, 0x01);
736 reg_w(gspca_dev, 0x78, 0x00);
737 reg_w(gspca_dev, 0x78, 0x00);
738 return;
740 reg_w(gspca_dev, 0xff, 0x04);
741 reg_w(gspca_dev, 0x27, 0x80);
742 reg_w(gspca_dev, 0x28, 0xca);
743 reg_w(gspca_dev, 0x29, 0x53);
744 reg_w(gspca_dev, 0x2a, 0x0e);
745 reg_w(gspca_dev, 0xff, 0x01);
746 reg_w(gspca_dev, 0x3e, 0x20);
747 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
748 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
749 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
752 /* called on streamoff with alt 0 and on disconnect */
753 static void sd_stop0(struct gspca_dev *gspca_dev)
755 struct sd *sd = (struct sd *) gspca_dev;
757 if (!gspca_dev->present)
758 return;
759 if (sd->sensor == SENSOR_PAC7302) {
760 reg_w(gspca_dev, 0xff, 0x01);
761 reg_w(gspca_dev, 0x78, 0x40);
765 /* Include pac common sof detection functions */
766 #include "pac_common.h"
768 static void do_autogain(struct gspca_dev *gspca_dev)
770 struct sd *sd = (struct sd *) gspca_dev;
771 int avg_lum = atomic_read(&sd->avg_lum);
772 int desired_lum, deadzone;
774 if (avg_lum == -1)
775 return;
777 if (sd->sensor == SENSOR_PAC7302) {
778 desired_lum = 270 + sd->brightness * 4;
779 /* Hack hack, with the 7202 the first exposure step is
780 pretty large, so if we're about to make the first
781 exposure increase make the deadzone large to avoid
782 oscilating */
783 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
784 sd->exposure > EXPOSURE_DEF &&
785 sd->exposure < 42)
786 deadzone = 90;
787 else
788 deadzone = 30;
789 } else {
790 desired_lum = 200;
791 deadzone = 20;
794 if (sd->autogain_ignore_frames > 0)
795 sd->autogain_ignore_frames--;
796 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
797 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
798 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
801 static const unsigned char pac7311_jpeg_header1[] = {
802 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
805 static const unsigned char pac7311_jpeg_header2[] = {
806 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
807 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
810 /* this function is run at interrupt level */
811 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
812 struct gspca_frame *frame, /* target */
813 __u8 *data, /* isoc packet */
814 int len) /* iso packet length */
816 struct sd *sd = (struct sd *) gspca_dev;
817 unsigned char *sof;
819 sof = pac_find_sof(gspca_dev, data, len);
820 if (sof) {
821 unsigned char tmpbuf[4];
822 int n, lum_offset, footer_length;
824 if (sd->sensor == SENSOR_PAC7302) {
825 /* 6 bytes after the FF D9 EOF marker a number of lumination
826 bytes are send corresponding to different parts of the
827 image, the 14th and 15th byte after the EOF seem to
828 correspond to the center of the image */
829 lum_offset = 61 + sizeof pac_sof_marker;
830 footer_length = 74;
831 } else {
832 lum_offset = 24 + sizeof pac_sof_marker;
833 footer_length = 26;
836 /* Finish decoding current frame */
837 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
838 if (n < 0) {
839 frame->data_end += n;
840 n = 0;
842 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
843 data, n);
844 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
845 frame->data_end[-2] == 0xff &&
846 frame->data_end[-1] == 0xd9)
847 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
848 NULL, 0);
850 n = sof - data;
851 len -= n;
852 data = sof;
854 /* Get average lumination */
855 if (gspca_dev->last_packet_type == LAST_PACKET &&
856 n >= lum_offset)
857 atomic_set(&sd->avg_lum, data[-lum_offset] +
858 data[-lum_offset + 1]);
859 else
860 atomic_set(&sd->avg_lum, -1);
862 /* Start the new frame with the jpeg header */
863 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
864 pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
865 if (sd->sensor == SENSOR_PAC7302) {
866 /* The PAC7302 has the image rotated 90 degrees */
867 tmpbuf[0] = gspca_dev->width >> 8;
868 tmpbuf[1] = gspca_dev->width & 0xff;
869 tmpbuf[2] = gspca_dev->height >> 8;
870 tmpbuf[3] = gspca_dev->height & 0xff;
871 } else {
872 tmpbuf[0] = gspca_dev->height >> 8;
873 tmpbuf[1] = gspca_dev->height & 0xff;
874 tmpbuf[2] = gspca_dev->width >> 8;
875 tmpbuf[3] = gspca_dev->width & 0xff;
877 gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
878 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
879 pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
881 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
884 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
886 struct sd *sd = (struct sd *) gspca_dev;
888 sd->brightness = val;
889 if (gspca_dev->streaming)
890 setbrightcont(gspca_dev);
891 return 0;
894 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
896 struct sd *sd = (struct sd *) gspca_dev;
898 *val = sd->brightness;
899 return 0;
902 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
904 struct sd *sd = (struct sd *) gspca_dev;
906 sd->contrast = val;
907 if (gspca_dev->streaming) {
908 if (sd->sensor == SENSOR_PAC7302)
909 setbrightcont(gspca_dev);
910 else
911 setcontrast(gspca_dev);
913 return 0;
916 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
918 struct sd *sd = (struct sd *) gspca_dev;
920 *val = sd->contrast;
921 return 0;
924 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
926 struct sd *sd = (struct sd *) gspca_dev;
928 sd->colors = val;
929 if (gspca_dev->streaming)
930 setcolors(gspca_dev);
931 return 0;
934 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
936 struct sd *sd = (struct sd *) gspca_dev;
938 *val = sd->colors;
939 return 0;
942 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
944 struct sd *sd = (struct sd *) gspca_dev;
946 sd->gain = val;
947 if (gspca_dev->streaming)
948 setgain(gspca_dev);
949 return 0;
952 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
954 struct sd *sd = (struct sd *) gspca_dev;
956 *val = sd->gain;
957 return 0;
960 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
962 struct sd *sd = (struct sd *) gspca_dev;
964 sd->exposure = val;
965 if (gspca_dev->streaming)
966 setexposure(gspca_dev);
967 return 0;
970 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
972 struct sd *sd = (struct sd *) gspca_dev;
974 *val = sd->exposure;
975 return 0;
978 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
980 struct sd *sd = (struct sd *) gspca_dev;
982 sd->autogain = val;
983 /* when switching to autogain set defaults to make sure
984 we are on a valid point of the autogain gain /
985 exposure knee graph, and give this change time to
986 take effect before doing autogain. */
987 if (sd->autogain) {
988 sd->exposure = EXPOSURE_DEF;
989 sd->gain = GAIN_DEF;
990 if (gspca_dev->streaming) {
991 sd->autogain_ignore_frames =
992 PAC_AUTOGAIN_IGNORE_FRAMES;
993 setexposure(gspca_dev);
994 setgain(gspca_dev);
998 return 0;
1001 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1003 struct sd *sd = (struct sd *) gspca_dev;
1005 *val = sd->autogain;
1006 return 0;
1009 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1011 struct sd *sd = (struct sd *) gspca_dev;
1013 sd->hflip = val;
1014 if (gspca_dev->streaming)
1015 sethvflip(gspca_dev);
1016 return 0;
1019 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1021 struct sd *sd = (struct sd *) gspca_dev;
1023 *val = sd->hflip;
1024 return 0;
1027 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1029 struct sd *sd = (struct sd *) gspca_dev;
1031 sd->vflip = val;
1032 if (gspca_dev->streaming)
1033 sethvflip(gspca_dev);
1034 return 0;
1037 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1039 struct sd *sd = (struct sd *) gspca_dev;
1041 *val = sd->vflip;
1042 return 0;
1045 /* sub-driver description */
1046 static struct sd_desc sd_desc = {
1047 .name = MODULE_NAME,
1048 .ctrls = sd_ctrls,
1049 .nctrls = ARRAY_SIZE(sd_ctrls),
1050 .config = sd_config,
1051 .init = sd_init,
1052 .start = sd_start,
1053 .stopN = sd_stopN,
1054 .stop0 = sd_stop0,
1055 .pkt_scan = sd_pkt_scan,
1056 .dq_callback = do_autogain,
1059 /* -- module initialisation -- */
1060 static __devinitdata struct usb_device_id device_table[] = {
1061 {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
1062 {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
1063 {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
1064 {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
1065 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
1066 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
1067 {USB_DEVICE(0x093a, 0x2620), .driver_info = SENSOR_PAC7302},
1068 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
1069 {USB_DEVICE(0x093a, 0x2622), .driver_info = SENSOR_PAC7302},
1070 {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
1071 {USB_DEVICE(0x093a, 0x2626), .driver_info = SENSOR_PAC7302},
1072 {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
1073 {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302},
1076 MODULE_DEVICE_TABLE(usb, device_table);
1078 /* -- device connect -- */
1079 static int sd_probe(struct usb_interface *intf,
1080 const struct usb_device_id *id)
1082 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1083 THIS_MODULE);
1086 static struct usb_driver sd_driver = {
1087 .name = MODULE_NAME,
1088 .id_table = device_table,
1089 .probe = sd_probe,
1090 .disconnect = gspca_disconnect,
1091 #ifdef CONFIG_PM
1092 .suspend = gspca_suspend,
1093 .resume = gspca_resume,
1094 #endif
1097 /* -- module insert / remove -- */
1098 static int __init sd_mod_init(void)
1100 if (usb_register(&sd_driver) < 0)
1101 return -1;
1102 PDEBUG(D_PROBE, "registered");
1103 return 0;
1105 static void __exit sd_mod_exit(void)
1107 usb_deregister(&sd_driver);
1108 PDEBUG(D_PROBE, "deregistered");
1111 module_init(sd_mod_init);
1112 module_exit(sd_mod_exit);