aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorHans de Goede <j.w.r.degoede@hhs.nl>2008-09-03 16:12:17 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-09-03 17:37:38 -0400
commit8a5b2e909d56a1d5edec5e8f8848e03aafbc588e (patch)
tree3be1a890f11988cc75a1883bc9e2bc25bb0283ef /drivers/media/video
parenta1e8288b1d80130119692818b46694660f28e03a (diff)
V4L/DVB (8825): gspca: More controls for pac73xx and new webcam 093a:2624.
-Add usb id for 093a:2624 (pac7302) -Report some controls to userspace with 7302 only, as they are 7302 only -Add gain and exposure controls -Add autogain -Fix 7302 imaged being mirrored by default Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl> Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/gspca/pac207.c16
-rw-r--r--drivers/media/video/gspca/pac7311.c301
-rw-r--r--drivers/media/video/gspca/pac_common.h9
3 files changed, 231 insertions, 95 deletions
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
index a15bccad947b..83b5f740c947 100644
--- a/drivers/media/video/gspca/pac207.c
+++ b/drivers/media/video/gspca/pac207.c
@@ -56,12 +56,6 @@ MODULE_LICENSE("GPL");
56#define PAC207_GAIN_KNEE 20 56#define PAC207_GAIN_KNEE 20
57 57
58#define PAC207_AUTOGAIN_DEADZONE 30 58#define PAC207_AUTOGAIN_DEADZONE 30
59/* We calculating the autogain at the end of the transfer of a frame, at this
60 moment a frame with the old settings is being transmitted, and a frame is
61 being captured with the old settings. So if we adjust the autogain we must
62 ignore atleast the 2 next frames for the new settings to come into effect
63 before doing any other adjustments */
64#define PAC207_AUTOGAIN_IGNORE_FRAMES 3
65 59
66/* specific webcam descriptor */ 60/* specific webcam descriptor */
67struct sd { 61struct sd {
@@ -338,6 +332,9 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
338 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */ 332 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
339} 333}
340 334
335/* Include pac common sof detection functions */
336#include "pac_common.h"
337
341static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) 338static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
342{ 339{
343 struct sd *sd = (struct sd *) gspca_dev; 340 struct sd *sd = (struct sd *) gspca_dev;
@@ -351,12 +348,9 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
351 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, 348 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
352 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE, 349 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
353 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) 350 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
354 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES; 351 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
355} 352}
356 353
357/* Include pac common sof detection functions */
358#include "pac_common.h"
359
360static void sd_pkt_scan(struct gspca_dev *gspca_dev, 354static void sd_pkt_scan(struct gspca_dev *gspca_dev,
361 struct gspca_frame *frame, 355 struct gspca_frame *frame,
362 __u8 *data, 356 __u8 *data,
@@ -500,7 +494,7 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
500 sd->gain = PAC207_GAIN_DEFAULT; 494 sd->gain = PAC207_GAIN_DEFAULT;
501 if (gspca_dev->streaming) { 495 if (gspca_dev->streaming) {
502 sd->autogain_ignore_frames = 496 sd->autogain_ignore_frames =
503 PAC207_AUTOGAIN_IGNORE_FRAMES; 497 PAC_AUTOGAIN_IGNORE_FRAMES;
504 setexposure(gspca_dev); 498 setexposure(gspca_dev);
505 setgain(gspca_dev); 499 setgain(gspca_dev);
506 } 500 }
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
index e22ca610334f..14b98111cd9d 100644
--- a/drivers/media/video/gspca/pac7311.c
+++ b/drivers/media/video/gspca/pac7311.c
@@ -44,6 +44,9 @@
44 0x10/- Master gain 0-31 44 0x10/- Master gain 0-31
45 -/0x10 Another gain 0-15, limited influence (1-2x gain I guess) 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 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.
47*/ 50*/
48 51
49#define MODULE_NAME "pac7311" 52#define MODULE_NAME "pac7311"
@@ -61,6 +64,8 @@ struct sd {
61 unsigned char brightness; 64 unsigned char brightness;
62 unsigned char contrast; 65 unsigned char contrast;
63 unsigned char colors; 66 unsigned char colors;
67 unsigned char gain;
68 unsigned char exposure;
64 unsigned char autogain; 69 unsigned char autogain;
65 __u8 hflip; 70 __u8 hflip;
66 __u8 vflip; 71 __u8 vflip;
@@ -88,8 +93,14 @@ static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val); 93static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val); 94static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getvflip(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);
91 100
92static struct ctrl sd_ctrls[] = { 101static struct ctrl sd_ctrls[] = {
102/* This control is pac7302 only */
103#define BRIGHTNESS_IDX 0
93 { 104 {
94 { 105 {
95 .id = V4L2_CID_BRIGHTNESS, 106 .id = V4L2_CID_BRIGHTNESS,
@@ -105,6 +116,7 @@ static struct ctrl sd_ctrls[] = {
105 .set = sd_setbrightness, 116 .set = sd_setbrightness,
106 .get = sd_getbrightness, 117 .get = sd_getbrightness,
107 }, 118 },
119/* This control is for both the 7302 and the 7311 */
108 { 120 {
109 { 121 {
110 .id = V4L2_CID_CONTRAST, 122 .id = V4L2_CID_CONTRAST,
@@ -120,6 +132,8 @@ static struct ctrl sd_ctrls[] = {
120 .set = sd_setcontrast, 132 .set = sd_setcontrast,
121 .get = sd_getcontrast, 133 .get = sd_getcontrast,
122 }, 134 },
135/* This control is pac7302 only */
136#define SATURATION_IDX 2
123 { 137 {
124 { 138 {
125 .id = V4L2_CID_SATURATION, 139 .id = V4L2_CID_SATURATION,
@@ -135,6 +149,39 @@ static struct ctrl sd_ctrls[] = {
135 .set = sd_setcolors, 149 .set = sd_setcolors,
136 .get = sd_getcolors, 150 .get = sd_getcolors,
137 }, 151 },
152/* All controls below are for both the 7302 and the 7311 */
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 /* Gain seems to cause little noise on the pac73xx */
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 /* 32 ms / 30 fps */
179#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
180 .default_value = EXPOSURE_DEF,
181 },
182 .set = sd_setexposure,
183 .get = sd_getexposure,
184 },
138 { 185 {
139 { 186 {
140 .id = V4L2_CID_AUTOGAIN, 187 .id = V4L2_CID_AUTOGAIN,
@@ -149,8 +196,6 @@ static struct ctrl sd_ctrls[] = {
149 .set = sd_setautogain, 196 .set = sd_setautogain,
150 .get = sd_getautogain, 197 .get = sd_getautogain,
151 }, 198 },
152/* next controls work with pac7302 only */
153#define HFLIP_IDX 4
154 { 199 {
155 { 200 {
156 .id = V4L2_CID_HFLIP, 201 .id = V4L2_CID_HFLIP,
@@ -165,7 +210,6 @@ static struct ctrl sd_ctrls[] = {
165 .set = sd_sethflip, 210 .set = sd_sethflip,
166 .get = sd_gethflip, 211 .get = sd_gethflip,
167 }, 212 },
168#define VFLIP_IDX 5
169 { 213 {
170 { 214 {
171 .id = V4L2_CID_VFLIP, 215 .id = V4L2_CID_VFLIP,
@@ -345,7 +389,7 @@ static const __u8 page4_7311[] = {
345 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62, 389 0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
346 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 390 0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa, 391 0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
348 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01, 392 0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x68,
349 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00, 393 0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
350 0x23, 0x28, 0x04, 0x11, 0x00, 0x00 394 0x23, 0x28, 0x04, 0x11, 0x00, 0x00
351}; 395};
@@ -374,7 +418,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
374 usb_sndctrlpipe(gspca_dev->dev, 0), 418 usb_sndctrlpipe(gspca_dev->dev, 0),
375 0, /* request */ 419 0, /* request */
376 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 420 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
377 value, index, gspca_dev->usb_buf, 1, 421 0, index, gspca_dev->usb_buf, 1,
378 500); 422 500);
379} 423}
380 424
@@ -469,20 +513,22 @@ static int sd_config(struct gspca_dev *gspca_dev,
469 513
470 cam->cam_mode = vga_mode; 514 cam->cam_mode = vga_mode;
471 cam->nmodes = ARRAY_SIZE(vga_mode); 515 cam->nmodes = ARRAY_SIZE(vga_mode);
472 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) 516 gspca_dev->ctrl_dis = (1 << BRIGHTNESS_IDX)
473 | (1 << VFLIP_IDX); 517 | (1 << SATURATION_IDX);
474 } 518 }
475 519
476 sd->brightness = BRIGHTNESS_DEF; 520 sd->brightness = BRIGHTNESS_DEF;
477 sd->contrast = CONTRAST_DEF; 521 sd->contrast = CONTRAST_DEF;
478 sd->colors = COLOR_DEF; 522 sd->colors = COLOR_DEF;
523 sd->gain = GAIN_DEF;
524 sd->exposure = EXPOSURE_DEF;
479 sd->autogain = AUTOGAIN_DEF; 525 sd->autogain = AUTOGAIN_DEF;
480 sd->hflip = HFLIP_DEF; 526 sd->hflip = HFLIP_DEF;
481 sd->vflip = VFLIP_DEF; 527 sd->vflip = VFLIP_DEF;
482 return 0; 528 return 0;
483} 529}
484 530
485/* rev 12a only */ 531/* This function is used by pac7302 only */
486static void setbrightcont(struct gspca_dev *gspca_dev) 532static void setbrightcont(struct gspca_dev *gspca_dev)
487{ 533{
488 struct sd *sd = (struct sd *) gspca_dev; 534 struct sd *sd = (struct sd *) gspca_dev;
@@ -509,67 +555,95 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
509 reg_w(gspca_dev, 0xdc, 0x01); 555 reg_w(gspca_dev, 0xdc, 0x01);
510} 556}
511 557
512/* This function is used by pac7302 only */ 558/* This function is used by pac7311 only */
513static void setbrightness(struct gspca_dev *gspca_dev) 559static void setcontrast(struct gspca_dev *gspca_dev)
514{ 560{
515 struct sd *sd = (struct sd *) gspca_dev; 561 struct sd *sd = (struct sd *) gspca_dev;
516 int brightness;
517
518 if (sd->sensor == SENSOR_PAC7302) {
519 setbrightcont(gspca_dev);
520 return;
521 }
522/* HDG: this is not brightness but gain, I'll add gain and exposure controls
523 in a next patch */
524 return;
525 562
526 brightness = BRIGHTNESS_MAX - sd->brightness;
527 reg_w(gspca_dev, 0xff, 0x04); 563 reg_w(gspca_dev, 0xff, 0x04);
528 reg_w(gspca_dev, 0x0e, 0x00); 564 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
529 reg_w(gspca_dev, 0x0f, brightness);
530 /* load registers to sensor (Bit 0, auto clear) */ 565 /* load registers to sensor (Bit 0, auto clear) */
531 reg_w(gspca_dev, 0x11, 0x01); 566 reg_w(gspca_dev, 0x11, 0x01);
532 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
533} 567}
534 568
535static void setcontrast(struct gspca_dev *gspca_dev) 569/* This function is used by pac7302 only */
570static void setcolors(struct gspca_dev *gspca_dev)
571{
572 struct sd *sd = (struct sd *) gspca_dev;
573 int i, v;
574 static const int a[9] =
575 {217, -212, 0, -101, 170, -67, -38, -315, 355};
576 static const int b[9] =
577 {19, 106, 0, 19, 106, 1, 19, 106, 1};
578
579 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
580 reg_w(gspca_dev, 0x11, 0x01);
581 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
582 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
583 for (i = 0; i < 9; i++) {
584 v = a[i] * sd->colors / COLOR_MAX + b[i];
585 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
586 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
587 }
588 reg_w(gspca_dev, 0xdc, 0x01);
589 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
590}
591
592static void setgain(struct gspca_dev *gspca_dev)
536{ 593{
537 struct sd *sd = (struct sd *) gspca_dev; 594 struct sd *sd = (struct sd *) gspca_dev;
538 595
539 if (sd->sensor == SENSOR_PAC7302) { 596 if (sd->sensor == SENSOR_PAC7302) {
540 setbrightcont(gspca_dev); 597 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
541 return; 598 reg_w(gspca_dev, 0x10, sd->gain >> 3);
599 } else {
600 int gain = GAIN_MAX - sd->gain;
601 if (gain < 1)
602 gain = 1;
603 else if (gain > 245)
604 gain = 245;
605 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
606 reg_w(gspca_dev, 0x0e, 0x00);
607 reg_w(gspca_dev, 0x0f, gain);
542 } 608 }
543 reg_w(gspca_dev, 0xff, 0x04);
544 reg_w(gspca_dev, 0x10, sd->contrast >> 4);
545 /* load registers to sensor (Bit 0, auto clear) */ 609 /* load registers to sensor (Bit 0, auto clear) */
546 reg_w(gspca_dev, 0x11, 0x01); 610 reg_w(gspca_dev, 0x11, 0x01);
547} 611}
548 612
549/* This function is used by pac7302 only */ 613static void setexposure(struct gspca_dev *gspca_dev)
550static void setcolors(struct gspca_dev *gspca_dev)
551{ 614{
552 struct sd *sd = (struct sd *) gspca_dev; 615 struct sd *sd = (struct sd *) gspca_dev;
616 __u8 reg;
617
618 /* register 2 of frame 3/4 contains the clock divider configuring the
619 no fps according to the formula: 60 / reg. sd->exposure is the
620 desired exposure time in ms. */
621 reg = 120 * sd->exposure / 1000;
622 if (reg < 2)
623 reg = 2;
624 else if (reg > 63)
625 reg = 63;
553 626
554 if (sd->sensor == SENSOR_PAC7302) { 627 if (sd->sensor == SENSOR_PAC7302) {
555 int i, v; 628 /* On the pac7302 reg2 MUST be a multiple of 3, so round it to
556 static const int a[9] = 629 the nearest multiple of 3 */
557 {217, -212, 0, -101, 170, -67, -38, -315, 355}; 630 reg = ((reg + 1) / 3) * 3;
558 static const int b[9] = 631 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
559 {19, 106, 0, 19, 106, 1, 19, 106, 1}; 632 reg_w(gspca_dev, 0x02, reg);
560 633 } else {
561 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 634 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
562 reg_w(gspca_dev, 0x11, 0x01); 635 reg_w(gspca_dev, 0x02, reg);
563 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 636 /* Page 1 register 8 must always be 0x08 except when not in
564 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */ 637 640x480 mode and Page3/4 reg 2 <= 3 then it must be 9 */
565 for (i = 0; i < 9; i++) { 638 reg_w(gspca_dev, 0xff, 0x01);
566 v = a[i] * sd->colors / COLOR_MAX + b[i]; 639 if (gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv &&
567 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07); 640 reg <= 3)
568 reg_w(gspca_dev, 0x0f + 2 * i + 1, v); 641 reg_w(gspca_dev, 0x08, 0x09);
569 } 642 else
570 reg_w(gspca_dev, 0xdc, 0x01); 643 reg_w(gspca_dev, 0x08, 0x08);
571 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
572 } 644 }
645 /* load registers to sensor (Bit 0, auto clear) */
646 reg_w(gspca_dev, 0x11, 0x01);
573} 647}
574 648
575static void sethvflip(struct gspca_dev *gspca_dev) 649static void sethvflip(struct gspca_dev *gspca_dev)
@@ -579,14 +653,15 @@ static void sethvflip(struct gspca_dev *gspca_dev)
579 653
580 if (sd->sensor == SENSOR_PAC7302) { 654 if (sd->sensor == SENSOR_PAC7302) {
581 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */ 655 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
582 data = (sd->hflip ? 0x00 : 0x08) 656 data = (sd->hflip ? 0x08 : 0x00)
583 | (sd->vflip ? 0x04 : 0x00); 657 | (sd->vflip ? 0x04 : 0x00);
584 } else { 658 } else {
585 reg_w(gspca_dev, 0xff, 0x04); /* page 3 */ 659 reg_w(gspca_dev, 0xff, 0x04); /* page 4 */
586 data = (sd->hflip ? 0x04 : 0x00) 660 data = (sd->hflip ? 0x04 : 0x00)
587 | (sd->vflip ? 0x08 : 0x00); 661 | (sd->vflip ? 0x08 : 0x00);
588 } 662 }
589 reg_w(gspca_dev, 0x21, data); 663 reg_w(gspca_dev, 0x21, data);
664 /* load registers to sensor (Bit 0, auto clear) */
590 reg_w(gspca_dev, 0x11, 0x01); 665 reg_w(gspca_dev, 0x11, 0x01);
591} 666}
592 667
@@ -602,61 +677,49 @@ static void sd_start(struct gspca_dev *gspca_dev)
602 677
603 sd->sof_read = 0; 678 sd->sof_read = 0;
604 679
605 if (sd->sensor == SENSOR_PAC7302) 680 if (sd->sensor == SENSOR_PAC7302) {
606 reg_w_var(gspca_dev, start_7302); 681 reg_w_var(gspca_dev, start_7302);
607 else 682 setbrightcont(gspca_dev);
683 setcolors(gspca_dev);
684 } else {
608 reg_w_var(gspca_dev, start_7311); 685 reg_w_var(gspca_dev, start_7311);
609 686 setcontrast(gspca_dev);
610 setcontrast(gspca_dev); 687 }
611 setbrightness(gspca_dev); 688 setgain(gspca_dev);
612 setcolors(gspca_dev); 689 setexposure(gspca_dev);
690 sethvflip(gspca_dev);
613 691
614 /* set correct resolution */ 692 /* set correct resolution */
615 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) { 693 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
616 case 2: /* 160x120 pac7311 */ 694 case 2: /* 160x120 pac7311 */
617 reg_w(gspca_dev, 0xff, 0x04);
618 reg_w(gspca_dev, 0x02, 0x03);
619 reg_w(gspca_dev, 0xff, 0x01); 695 reg_w(gspca_dev, 0xff, 0x01);
620 reg_w(gspca_dev, 0x08, 0x09);
621 reg_w(gspca_dev, 0x17, 0x20); 696 reg_w(gspca_dev, 0x17, 0x20);
622 reg_w(gspca_dev, 0x1b, 0x00);
623 reg_w(gspca_dev, 0x87, 0x10); 697 reg_w(gspca_dev, 0x87, 0x10);
624 break; 698 break;
625 case 1: /* 320x240 pac7311 */ 699 case 1: /* 320x240 pac7311 */
626 reg_w(gspca_dev, 0xff, 0x04);
627 reg_w(gspca_dev, 0x02, 0x03);
628 reg_w(gspca_dev, 0xff, 0x01); 700 reg_w(gspca_dev, 0xff, 0x01);
629 reg_w(gspca_dev, 0x08, 0x09);
630 reg_w(gspca_dev, 0x17, 0x30); 701 reg_w(gspca_dev, 0x17, 0x30);
631 reg_w(gspca_dev, 0x87, 0x11); 702 reg_w(gspca_dev, 0x87, 0x11);
632 break; 703 break;
633 case 0: /* 640x480 */ 704 case 0: /* 640x480 */
634 if (sd->sensor == SENSOR_PAC7302) 705 if (sd->sensor == SENSOR_PAC7302)
635 break; 706 break;
636 reg_w(gspca_dev, 0xff, 0x04);
637 reg_w(gspca_dev, 0x02, 0x07);
638 reg_w(gspca_dev, 0xff, 0x01); 707 reg_w(gspca_dev, 0xff, 0x01);
639 reg_w(gspca_dev, 0x08, 0x08);
640 reg_w(gspca_dev, 0x17, 0x00); 708 reg_w(gspca_dev, 0x17, 0x00);
641 reg_w(gspca_dev, 0x87, 0x12); 709 reg_w(gspca_dev, 0x87, 0x12);
642 break; 710 break;
643 } 711 }
644 712
645 /* start stream */
646 reg_w(gspca_dev, 0xff, 0x01);
647 if (sd->sensor == SENSOR_PAC7302) {
648 sethvflip(gspca_dev);
649 reg_w(gspca_dev, 0x78, 0x01);
650 reg_w(gspca_dev, 0xff, 0x01);
651 reg_w(gspca_dev, 0x78, 0x01);
652 } else {
653 reg_w(gspca_dev, 0x78, 0x44);
654 reg_w(gspca_dev, 0x78, 0x45);
655 }
656
657 sd->sof_read = 0; 713 sd->sof_read = 0;
658 sd->autogain_ignore_frames = 0; 714 sd->autogain_ignore_frames = 0;
659 atomic_set(&sd->avg_lum, -1); 715 atomic_set(&sd->avg_lum, -1);
716
717 /* start stream */
718 reg_w(gspca_dev, 0xff, 0x01);
719 if (sd->sensor == SENSOR_PAC7302)
720 reg_w(gspca_dev, 0x78, 0x01);
721 else
722 reg_w(gspca_dev, 0x78, 0x05);
660} 723}
661 724
662static void sd_stopN(struct gspca_dev *gspca_dev) 725static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -691,8 +754,28 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
691 } 754 }
692} 755}
693 756
757/* Include pac common sof detection functions */
758#include "pac_common.h"
759
694static void do_autogain(struct gspca_dev *gspca_dev) 760static void do_autogain(struct gspca_dev *gspca_dev)
695{ 761{
762 struct sd *sd = (struct sd *) gspca_dev;
763 int avg_lum = atomic_read(&sd->avg_lum);
764 int desired_lum;
765
766 if (avg_lum == -1)
767 return;
768
769 if (sd->sensor == SENSOR_PAC7302)
770 desired_lum = 70 + sd->brightness * 2;
771 else
772 desired_lum = 200;
773
774 if (sd->autogain_ignore_frames > 0)
775 sd->autogain_ignore_frames--;
776 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
777 10, GAIN_KNEE, EXPOSURE_KNEE))
778 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
696} 779}
697 780
698static const unsigned char pac7311_jpeg_header1[] = { 781static const unsigned char pac7311_jpeg_header1[] = {
@@ -704,9 +787,6 @@ static const unsigned char pac7311_jpeg_header2[] = {
704 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00 787 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
705}; 788};
706 789
707/* Include pac common sof detection functions */
708#include "pac_common.h"
709
710/* this function is run at interrupt level */ 790/* this function is run at interrupt level */
711static void sd_pkt_scan(struct gspca_dev *gspca_dev, 791static void sd_pkt_scan(struct gspca_dev *gspca_dev,
712 struct gspca_frame *frame, /* target */ 792 struct gspca_frame *frame, /* target */
@@ -790,7 +870,7 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
790 870
791 sd->brightness = val; 871 sd->brightness = val;
792 if (gspca_dev->streaming) 872 if (gspca_dev->streaming)
793 setbrightness(gspca_dev); 873 setbrightcont(gspca_dev);
794 return 0; 874 return 0;
795} 875}
796 876
@@ -807,8 +887,12 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
807 struct sd *sd = (struct sd *) gspca_dev; 887 struct sd *sd = (struct sd *) gspca_dev;
808 888
809 sd->contrast = val; 889 sd->contrast = val;
810 if (gspca_dev->streaming) 890 if (gspca_dev->streaming) {
811 setcontrast(gspca_dev); 891 if (sd->sensor == SENSOR_PAC7302)
892 setbrightcont(gspca_dev);
893 else
894 setcontrast(gspca_dev);
895 }
812 return 0; 896 return 0;
813} 897}
814 898
@@ -838,11 +922,61 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
838 return 0; 922 return 0;
839} 923}
840 924
925static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
926{
927 struct sd *sd = (struct sd *) gspca_dev;
928
929 sd->gain = val;
930 if (gspca_dev->streaming)
931 setgain(gspca_dev);
932 return 0;
933}
934
935static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
936{
937 struct sd *sd = (struct sd *) gspca_dev;
938
939 *val = sd->gain;
940 return 0;
941}
942
943static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 sd->exposure = val;
948 if (gspca_dev->streaming)
949 setexposure(gspca_dev);
950 return 0;
951}
952
953static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
956
957 *val = sd->exposure;
958 return 0;
959}
960
841static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) 961static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
842{ 962{
843 struct sd *sd = (struct sd *) gspca_dev; 963 struct sd *sd = (struct sd *) gspca_dev;
844 964
845 sd->autogain = val; 965 sd->autogain = val;
966 /* when switching to autogain set defaults to make sure
967 we are on a valid point of the autogain gain /
968 exposure knee graph, and give this change time to
969 take effect before doing autogain. */
970 if (sd->autogain) {
971 sd->exposure = EXPOSURE_DEF;
972 sd->gain = GAIN_DEF;
973 if (gspca_dev->streaming) {
974 sd->autogain_ignore_frames =
975 PAC_AUTOGAIN_IGNORE_FRAMES;
976 setexposure(gspca_dev);
977 setgain(gspca_dev);
978 }
979 }
846 980
847 return 0; 981 return 0;
848} 982}
@@ -914,6 +1048,7 @@ static __devinitdata struct usb_device_id device_table[] = {
914 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311}, 1048 {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
915 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311}, 1049 {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
916 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302}, 1050 {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
1051 {USB_DEVICE(0x093a, 0x2624), .driver_info = SENSOR_PAC7302},
917 {} 1052 {}
918}; 1053};
919MODULE_DEVICE_TABLE(usb, device_table); 1054MODULE_DEVICE_TABLE(usb, device_table);
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
index a19b5d44c009..34d4b1494cd5 100644
--- a/drivers/media/video/gspca/pac_common.h
+++ b/drivers/media/video/gspca/pac_common.h
@@ -23,6 +23,13 @@
23 * 23 *
24 */ 24 */
25 25
26/* We calculate the autogain at the end of the transfer of a frame, at this
27 moment a frame with the old settings is being transmitted, and a frame is
28 being captured with the old settings. So if we adjust the autogain we must
29 ignore atleast the 2 next frames for the new settings to come into effect
30 before doing any other adjustments */
31#define PAC_AUTOGAIN_IGNORE_FRAMES 3
32
26static const unsigned char pac_sof_marker[5] = 33static const unsigned char pac_sof_marker[5] =
27 { 0xff, 0xff, 0x00, 0xff, 0x96 }; 34 { 0xff, 0xff, 0x00, 0xff, 0x96 };
28 35
@@ -37,7 +44,7 @@ static unsigned char *pac_find_sof(struct gspca_dev *gspca_dev,
37 if (m[i] == pac_sof_marker[sd->sof_read]) { 44 if (m[i] == pac_sof_marker[sd->sof_read]) {
38 sd->sof_read++; 45 sd->sof_read++;
39 if (sd->sof_read == sizeof(pac_sof_marker)) { 46 if (sd->sof_read == sizeof(pac_sof_marker)) {
40 PDEBUG(D_STREAM, 47 PDEBUG(D_FRAM,
41 "SOF found, bytes to analyze: %u." 48 "SOF found, bytes to analyze: %u."
42 " Frame starts at byte #%u", 49 " Frame starts at byte #%u",
43 len, i + 1); 50 len, i + 1);