1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52#define MODULE_NAME "pac7311"
53
54#include "gspca.h"
55
56MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
57MODULE_DESCRIPTION("Pixart PAC7311");
58MODULE_LICENSE("GPL");
59
60
61struct sd {
62 struct gspca_dev gspca_dev;
63
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;
72
73 __u8 sensor;
74#define SENSOR_PAC7302 0
75#define SENSOR_PAC7311 1
76
77 u8 sof_read;
78 u8 autogain_ignore_frames;
79
80 atomic_t avg_lum;
81};
82
83
84static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
85static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
86static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
87static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
88static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
96static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
97static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
98static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
99static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
100
101static struct ctrl sd_ctrls[] = {
102
103#define BRIGHTNESS_IDX 0
104 {
105 {
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,
115 },
116 .set = sd_setbrightness,
117 .get = sd_getbrightness,
118 },
119
120 {
121 {
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,
131 },
132 .set = sd_setcontrast,
133 .get = sd_getcontrast,
134 },
135
136#define SATURATION_IDX 2
137 {
138 {
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,
148 },
149 .set = sd_setcolors,
150 .get = sd_getcolors,
151 },
152
153 {
154 {
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
164 .default_value = GAIN_DEF,
165 },
166 .set = sd_setgain,
167 .get = sd_getgain,
168 },
169 {
170 {
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
179#define EXPOSURE_KNEE 50
180 .default_value = EXPOSURE_DEF,
181 },
182 .set = sd_setexposure,
183 .get = sd_getexposure,
184 },
185 {
186 {
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,
195 },
196 .set = sd_setautogain,
197 .get = sd_getautogain,
198 },
199 {
200 {
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,
209 },
210 .set = sd_sethflip,
211 .get = sd_gethflip,
212 },
213 {
214 {
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,
223 },
224 .set = sd_setvflip,
225 .get = sd_getvflip,
226 },
227};
228
229static 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},
245};
246
247
248static const __u8 init_7302[] = {
249
250 0xff, 0x01,
251 0x78, 0x00,
252 0xff, 0x01,
253 0x78, 0x40,
254};
255static const __u8 start_7302[] = {
256
257 0xff, 1, 0x00,
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,
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,
303 0x22, 1, 0x00,
304 0xff, 1, 0x03,
305 0x00, 255,
306 0x11, 1, 0x01,
307 0xff, 1, 0x02,
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,
315 0x78, 1, 0x00,
316 0, 0
317};
318
319
320static 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
341};
342
343
344static const __u8 init_7311[] = {
345 0x78, 0x40,
346 0x78, 0x40,
347 0x78, 0x44,
348 0xff, 0x04,
349 0x27, 0x80,
350 0x28, 0xca,
351 0x29, 0x53,
352 0x2a, 0x0e,
353 0xff, 0x01,
354 0x3e, 0x20,
355};
356
357static const __u8 start_7311[] = {
358
359 0xff, 1, 0x01,
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,
381 0x00, 254,
382 0x11, 1, 0x01,
383 0, 0
384};
385
386
387static 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
395};
396
397static void reg_w_buf(struct gspca_dev *gspca_dev,
398 __u8 index,
399 const char *buffer, int len)
400{
401 memcpy(gspca_dev->usb_buf, buffer, len);
402 usb_control_msg(gspca_dev->dev,
403 usb_sndctrlpipe(gspca_dev->dev, 0),
404 1,
405 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
406 0,
407 index, gspca_dev->usb_buf, len,
408 500);
409}
410
411
412static void reg_w(struct gspca_dev *gspca_dev,
413 __u8 index,
414 __u8 value)
415{
416 gspca_dev->usb_buf[0] = value;
417 usb_control_msg(gspca_dev->dev,
418 usb_sndctrlpipe(gspca_dev->dev, 0),
419 0,
420 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
421 0, index, gspca_dev->usb_buf, 1,
422 500);
423}
424
425static void reg_w_seq(struct gspca_dev *gspca_dev,
426 const __u8 *seq, int len)
427{
428 while (--len >= 0) {
429 reg_w(gspca_dev, seq[0], seq[1]);
430 seq += 2;
431 }
432}
433
434
435static void reg_w_page(struct gspca_dev *gspca_dev,
436 const __u8 *page, int len)
437{
438 int index;
439
440 for (index = 0; index < len; index++) {
441 if (page[index] == 0xaa)
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,
447 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
448 0, index, gspca_dev->usb_buf, 1,
449 500);
450 }
451}
452
453
454static void reg_w_var(struct gspca_dev *gspca_dev,
455 const __u8 *seq)
456{
457 int index, len;
458
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;
476 }
477 while (len > 0) {
478 if (len < 8) {
479 reg_w_buf(gspca_dev, index, seq, len);
480 seq += len;
481 break;
482 }
483 reg_w_buf(gspca_dev, index, seq, 8);
484 seq += 8;
485 index += 8;
486 len -= 8;
487 }
488 }
489 }
490
491}
492
493
494static int sd_config(struct gspca_dev *gspca_dev,
495 const struct usb_device_id *id)
496{
497 struct sd *sd = (struct sd *) gspca_dev;
498 struct cam *cam;
499
500 cam = &gspca_dev->cam;
501
502 sd->sensor = id->driver_info;
503 if (sd->sensor == SENSOR_PAC7302) {
504 PDEBUG(D_CONF, "Find Sensor PAC7302");
505 cam->cam_mode = &vga_mode[2];
506 cam->nmodes = 1;
507 } else {
508 PDEBUG(D_CONF, "Find Sensor PAC7311");
509 cam->cam_mode = vga_mode;
510 cam->nmodes = ARRAY_SIZE(vga_mode);
511 gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
512 | (1 << SATURATION_IDX);
513 }
514
515 sd->brightness = BRIGHTNESS_DEF;
516 sd->contrast = CONTRAST_DEF;
517 sd->colors = COLOR_DEF;
518 sd->gain = GAIN_DEF;
519 sd->exposure = EXPOSURE_DEF;
520 sd->autogain = AUTOGAIN_DEF;
521 sd->hflip = HFLIP_DEF;
522 sd->vflip = VFLIP_DEF;
523 return 0;
524}
525
526
527static void setbrightcont(struct gspca_dev *gspca_dev)
528{
529 struct sd *sd = (struct sd *) gspca_dev;
530 int i, v;
531 static const __u8 max[10] =
532 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
533 0xd4, 0xec};
534 static const __u8 delta[10] =
535 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
536 0x11, 0x0b};
537
538 reg_w(gspca_dev, 0xff, 0x00);
539 for (i = 0; i < 10; i++) {
540 v = max[i];
541 v += (sd->brightness - BRIGHTNESS_MAX)
542 * 150 / BRIGHTNESS_MAX;
543 v -= delta[i] * sd->contrast / CONTRAST_MAX;
544 if (v < 0)
545 v = 0;
546 else if (v > 0xff)
547 v = 0xff;
548 reg_w(gspca_dev, 0xa2 + i, v);
549 }
550 reg_w(gspca_dev, 0xdc, 0x01);
551}
552
553
554static void setcontrast(struct gspca_dev *gspca_dev)
555{
556 struct sd *sd = (struct sd *) gspca_dev;
557
558 reg_w(gspca_dev, 0xff, 0x04);
559 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
560
561 reg_w(gspca_dev, 0x11, 0x01);
562}
563
564
565static void setcolors(struct gspca_dev *gspca_dev)
566{
567 struct sd *sd = (struct sd *) gspca_dev;
568 int i, v;
569 static const int a[9] =
570 {217, -212, 0, -101, 170, -67, -38, -315, 355};
571 static const int b[9] =
572 {19, 106, 0, 19, 106, 1, 19, 106, 1};
573
574 reg_w(gspca_dev, 0xff, 0x03);
575 reg_w(gspca_dev, 0x11, 0x01);
576 reg_w(gspca_dev, 0xff, 0x00);
577 reg_w(gspca_dev, 0xff, 0x00);
578 for (i = 0; i < 9; i++) {
579 v = a[i] * sd->colors / COLOR_MAX + b[i];
580 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
581 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
582 }
583 reg_w(gspca_dev, 0xdc, 0x01);
584 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
585}
586
587static void setgain(struct gspca_dev *gspca_dev)
588{
589 struct sd *sd = (struct sd *) gspca_dev;
590
591 if (sd->sensor == SENSOR_PAC7302) {
592 reg_w(gspca_dev, 0xff, 0x03);
593 reg_w(gspca_dev, 0x10, sd->gain >> 3);
594 } else {
595 int gain = GAIN_MAX - sd->gain;
596 if (gain < 1)
597 gain = 1;
598 else if (gain > 245)
599 gain = 245;
600 reg_w(gspca_dev, 0xff, 0x04);
601 reg_w(gspca_dev, 0x0e, 0x00);
602 reg_w(gspca_dev, 0x0f, gain);
603 }
604
605 reg_w(gspca_dev, 0x11, 0x01);
606}
607
608static void setexposure(struct gspca_dev *gspca_dev)
609{
610 struct sd *sd = (struct sd *) gspca_dev;
611 __u8 reg;
612
613
614
615
616 reg = 120 * sd->exposure / 1000;
617 if (reg < 2)
618 reg = 2;
619 else if (reg > 63)
620 reg = 63;
621
622 if (sd->sensor == SENSOR_PAC7302) {
623
624
625 if (reg < 6 || reg > 12)
626 reg = ((reg + 1) / 3) * 3;
627 reg_w(gspca_dev, 0xff, 0x03);
628 reg_w(gspca_dev, 0x02, reg);
629 } else {
630 reg_w(gspca_dev, 0xff, 0x04);
631 reg_w(gspca_dev, 0x02, reg);
632
633
634 reg_w(gspca_dev, 0xff, 0x01);
635 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
636 reg <= 3)
637 reg_w(gspca_dev, 0x08, 0x09);
638 else
639 reg_w(gspca_dev, 0x08, 0x08);
640 }
641
642 reg_w(gspca_dev, 0x11, 0x01);
643}
644
645static void sethvflip(struct gspca_dev *gspca_dev)
646{
647 struct sd *sd = (struct sd *) gspca_dev;
648 __u8 data;
649
650 if (sd->sensor == SENSOR_PAC7302) {
651 reg_w(gspca_dev, 0xff, 0x03);
652 data = (sd->hflip ? 0x08 : 0x00)
653 | (sd->vflip ? 0x04 : 0x00);
654 } else {
655 reg_w(gspca_dev, 0xff, 0x04);
656 data = (sd->hflip ? 0x04 : 0x00)
657 | (sd->vflip ? 0x08 : 0x00);
658 }
659 reg_w(gspca_dev, 0x21, data);
660
661 reg_w(gspca_dev, 0x11, 0x01);
662}
663
664
665static int sd_init(struct gspca_dev *gspca_dev)
666{
667 struct sd *sd = (struct sd *) gspca_dev;
668
669 if (sd->sensor == SENSOR_PAC7302)
670 reg_w_seq(gspca_dev, init_7302, sizeof init_7302);
671 else
672 reg_w_seq(gspca_dev, init_7311, sizeof init_7311);
673
674 return 0;
675}
676
677static int sd_start(struct gspca_dev *gspca_dev)
678{
679 struct sd *sd = (struct sd *) gspca_dev;
680
681 sd->sof_read = 0;
682
683 if (sd->sensor == SENSOR_PAC7302) {
684 reg_w_var(gspca_dev, start_7302);
685 setbrightcont(gspca_dev);
686 setcolors(gspca_dev);
687 } else {
688 reg_w_var(gspca_dev, start_7311);
689 setcontrast(gspca_dev);
690 }
691 setgain(gspca_dev);
692 setexposure(gspca_dev);
693 sethvflip(gspca_dev);
694
695
696 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
697 case 2:
698 reg_w(gspca_dev, 0xff, 0x01);
699 reg_w(gspca_dev, 0x17, 0x20);
700 reg_w(gspca_dev, 0x87, 0x10);
701 break;
702 case 1:
703 reg_w(gspca_dev, 0xff, 0x01);
704 reg_w(gspca_dev, 0x17, 0x30);
705 reg_w(gspca_dev, 0x87, 0x11);
706 break;
707 case 0:
708 if (sd->sensor == SENSOR_PAC7302)
709 break;
710 reg_w(gspca_dev, 0xff, 0x01);
711 reg_w(gspca_dev, 0x17, 0x00);
712 reg_w(gspca_dev, 0x87, 0x12);
713 break;
714 }
715
716 sd->sof_read = 0;
717 sd->autogain_ignore_frames = 0;
718 atomic_set(&sd->avg_lum, -1);
719
720
721 reg_w(gspca_dev, 0xff, 0x01);
722 if (sd->sensor == SENSOR_PAC7302)
723 reg_w(gspca_dev, 0x78, 0x01);
724 else
725 reg_w(gspca_dev, 0x78, 0x05);
726 return 0;
727}
728
729static void sd_stopN(struct gspca_dev *gspca_dev)
730{
731 struct sd *sd = (struct sd *) gspca_dev;
732
733 if (sd->sensor == SENSOR_PAC7302) {
734 reg_w(gspca_dev, 0xff, 0x01);
735 reg_w(gspca_dev, 0x78, 0x00);
736 reg_w(gspca_dev, 0x78, 0x00);
737 return;
738 }
739 reg_w(gspca_dev, 0xff, 0x04);
740 reg_w(gspca_dev, 0x27, 0x80);
741 reg_w(gspca_dev, 0x28, 0xca);
742 reg_w(gspca_dev, 0x29, 0x53);
743 reg_w(gspca_dev, 0x2a, 0x0e);
744 reg_w(gspca_dev, 0xff, 0x01);
745 reg_w(gspca_dev, 0x3e, 0x20);
746 reg_w(gspca_dev, 0x78, 0x44);
747 reg_w(gspca_dev, 0x78, 0x44);
748 reg_w(gspca_dev, 0x78, 0x44);
749}
750
751
752static void sd_stop0(struct gspca_dev *gspca_dev)
753{
754 struct sd *sd = (struct sd *) gspca_dev;
755
756 if (!gspca_dev->present)
757 return;
758 if (sd->sensor == SENSOR_PAC7302) {
759 reg_w(gspca_dev, 0xff, 0x01);
760 reg_w(gspca_dev, 0x78, 0x40);
761 }
762}
763
764
765#include "pac_common.h"
766
767static void do_autogain(struct gspca_dev *gspca_dev)
768{
769 struct sd *sd = (struct sd *) gspca_dev;
770 int avg_lum = atomic_read(&sd->avg_lum);
771 int desired_lum, deadzone;
772
773 if (avg_lum == -1)
774 return;
775
776 if (sd->sensor == SENSOR_PAC7302) {
777 desired_lum = 270 + sd->brightness * 4;
778
779
780
781
782 if (desired_lum > avg_lum && sd->gain == GAIN_DEF &&
783 sd->exposure > EXPOSURE_DEF &&
784 sd->exposure < 42)
785 deadzone = 90;
786 else
787 deadzone = 30;
788 } else {
789 desired_lum = 200;
790 deadzone = 20;
791 }
792
793 if (sd->autogain_ignore_frames > 0)
794 sd->autogain_ignore_frames--;
795 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
796 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
797 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
798}
799
800static const unsigned char pac7311_jpeg_header1[] = {
801 0xff, 0xd8, 0xff, 0xc0, 0x00, 0x11, 0x08
802};
803
804static const unsigned char pac7311_jpeg_header2[] = {
805 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda,
806 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
807};
808
809
810static void sd_pkt_scan(struct gspca_dev *gspca_dev,
811 struct gspca_frame *frame,
812 __u8 *data,
813 int len)
814{
815 struct sd *sd = (struct sd *) gspca_dev;
816 unsigned char *sof;
817
818 sof = pac_find_sof(gspca_dev, data, len);
819 if (sof) {
820 unsigned char tmpbuf[4];
821 int n, lum_offset, footer_length;
822
823 if (sd->sensor == SENSOR_PAC7302) {
824
825
826
827
828 lum_offset = 61 + sizeof pac_sof_marker;
829 footer_length = 74;
830 } else {
831 lum_offset = 24 + sizeof pac_sof_marker;
832 footer_length = 26;
833 }
834
835
836 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
837 if (n < 0) {
838 frame->data_end += n;
839 n = 0;
840 }
841 frame = gspca_frame_add(gspca_dev, INTER_PACKET, frame,
842 data, n);
843 if (gspca_dev->last_packet_type != DISCARD_PACKET &&
844 frame->data_end[-2] == 0xff &&
845 frame->data_end[-1] == 0xd9)
846 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
847 NULL, 0);
848
849 n = sof - data;
850 len -= n;
851 data = sof;
852
853
854 if (gspca_dev->last_packet_type == LAST_PACKET &&
855 n >= lum_offset)
856 atomic_set(&sd->avg_lum, data[-lum_offset] +
857 data[-lum_offset + 1]);
858 else
859 atomic_set(&sd->avg_lum, -1);
860
861
862 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
863 pac7311_jpeg_header1, sizeof(pac7311_jpeg_header1));
864 if (sd->sensor == SENSOR_PAC7302) {
865
866 tmpbuf[0] = gspca_dev->width >> 8;
867 tmpbuf[1] = gspca_dev->width & 0xff;
868 tmpbuf[2] = gspca_dev->height >> 8;
869 tmpbuf[3] = gspca_dev->height & 0xff;
870 } else {
871 tmpbuf[0] = gspca_dev->height >> 8;
872 tmpbuf[1] = gspca_dev->height & 0xff;
873 tmpbuf[2] = gspca_dev->width >> 8;
874 tmpbuf[3] = gspca_dev->width & 0xff;
875 }
876 gspca_frame_add(gspca_dev, INTER_PACKET, frame, tmpbuf, 4);
877 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
878 pac7311_jpeg_header2, sizeof(pac7311_jpeg_header2));
879 }
880 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
881}
882
883static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
884{
885 struct sd *sd = (struct sd *) gspca_dev;
886
887 sd->brightness = val;
888 if (gspca_dev->streaming)
889 setbrightcont(gspca_dev);
890 return 0;
891}
892
893static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
894{
895 struct sd *sd = (struct sd *) gspca_dev;
896
897 *val = sd->brightness;
898 return 0;
899}
900
901static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
902{
903 struct sd *sd = (struct sd *) gspca_dev;
904
905 sd->contrast = val;
906 if (gspca_dev->streaming) {
907 if (sd->sensor == SENSOR_PAC7302)
908 setbrightcont(gspca_dev);
909 else
910 setcontrast(gspca_dev);
911 }
912 return 0;
913}
914
915static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
916{
917 struct sd *sd = (struct sd *) gspca_dev;
918
919 *val = sd->contrast;
920 return 0;
921}
922
923static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
924{
925 struct sd *sd = (struct sd *) gspca_dev;
926
927 sd->colors = val;
928 if (gspca_dev->streaming)
929 setcolors(gspca_dev);
930 return 0;
931}
932
933static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
934{
935 struct sd *sd = (struct sd *) gspca_dev;
936
937 *val = sd->colors;
938 return 0;
939}
940
941static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
942{
943 struct sd *sd = (struct sd *) gspca_dev;
944
945 sd->gain = val;
946 if (gspca_dev->streaming)
947 setgain(gspca_dev);
948 return 0;
949}
950
951static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
952{
953 struct sd *sd = (struct sd *) gspca_dev;
954
955 *val = sd->gain;
956 return 0;
957}
958
959static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
960{
961 struct sd *sd = (struct sd *) gspca_dev;
962
963 sd->exposure = val;
964 if (gspca_dev->streaming)
965 setexposure(gspca_dev);
966 return 0;
967}
968
969static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
970{
971 struct sd *sd = (struct sd *) gspca_dev;
972
973 *val = sd->exposure;
974 return 0;
975}
976
977static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 sd->autogain = val;
982
983
984
985
986 if (sd->autogain) {
987 sd->exposure = EXPOSURE_DEF;
988 sd->gain = GAIN_DEF;
989 if (gspca_dev->streaming) {
990 sd->autogain_ignore_frames =
991 PAC_AUTOGAIN_IGNORE_FRAMES;
992 setexposure(gspca_dev);
993 setgain(gspca_dev);
994 }
995 }
996
997 return 0;
998}
999
1000static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1001{
1002 struct sd *sd = (struct sd *) gspca_dev;
1003
1004 *val = sd->autogain;
1005 return 0;
1006}
1007
1008static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1009{
1010 struct sd *sd = (struct sd *) gspca_dev;
1011
1012 sd->hflip = val;
1013 if (gspca_dev->streaming)
1014 sethvflip(gspca_dev);
1015 return 0;
1016}
1017
1018static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1019{
1020 struct sd *sd = (struct sd *) gspca_dev;
1021
1022 *val = sd->hflip;
1023 return 0;
1024}
1025
1026static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1027{
1028 struct sd *sd = (struct sd *) gspca_dev;
1029
1030 sd->vflip = val;
1031 if (gspca_dev->streaming)
1032 sethvflip(gspca_dev);
1033 return 0;
1034}
1035
1036static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039
1040 *val = sd->vflip;
1041 return 0;
1042}
1043
1044
1045static struct sd_desc sd_desc = {
1046 .name = MODULE_NAME,
1047 .ctrls = sd_ctrls,
1048 .nctrls = ARRAY_SIZE(sd_ctrls),
1049 .config = sd_config,
1050 .init = sd_init,
1051 .start = sd_start,
1052 .stopN = sd_stopN,
1053 .stop0 = sd_stop0,
1054 .pkt_scan = sd_pkt_scan,
1055 .dq_callback = do_autogain,
1056};
1057
1058
1059static __devinitdata struct usb_device_id device_table[] = {
1060 {USB_DEVICE(0x06f8, 0x3009), .driver_info = SENSOR_PAC7302},
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, 0x2629), .driver_info = SENSOR_PAC7302},
1073 {USB_DEVICE(0x093a, 0x262a), .driver_info = SENSOR_PAC7302},
1074 {USB_DEVICE(0x093a, 0x262c), .driver_info = SENSOR_PAC7302},
1075 {}
1076};
1077MODULE_DEVICE_TABLE(usb, device_table);
1078
1079
1080static int sd_probe(struct usb_interface *intf,
1081 const struct usb_device_id *id)
1082{
1083 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1084 THIS_MODULE);
1085}
1086
1087static struct usb_driver sd_driver = {
1088 .name = MODULE_NAME,
1089 .id_table = device_table,
1090 .probe = sd_probe,
1091 .disconnect = gspca_disconnect,
1092#ifdef CONFIG_PM
1093 .suspend = gspca_suspend,
1094 .resume = gspca_resume,
1095#endif
1096};
1097
1098
1099static int __init sd_mod_init(void)
1100{
1101 int ret;
1102 ret = usb_register(&sd_driver);
1103 if (ret < 0)
1104 return ret;
1105 PDEBUG(D_PROBE, "registered");
1106 return 0;
1107}
1108static void __exit sd_mod_exit(void)
1109{
1110 usb_deregister(&sd_driver);
1111 PDEBUG(D_PROBE, "deregistered");
1112}
1113
1114module_init(sd_mod_init);
1115module_exit(sd_mod_exit);
1116