diff options
Diffstat (limited to 'drivers/media/video/gspca/sonixb.c')
-rw-r--r-- | drivers/media/video/gspca/sonixb.c | 451 |
1 files changed, 330 insertions, 121 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index ddff2b5ee5c2..785eeb4c2014 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -42,6 +42,7 @@ Reg Use | |||
42 | 42 | ||
43 | #define MODULE_NAME "sonixb" | 43 | #define MODULE_NAME "sonixb" |
44 | 44 | ||
45 | #include <linux/input.h> | ||
45 | #include "gspca.h" | 46 | #include "gspca.h" |
46 | 47 | ||
47 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | 48 | MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); |
@@ -53,9 +54,11 @@ struct sd { | |||
53 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 54 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
54 | atomic_t avg_lum; | 55 | atomic_t avg_lum; |
55 | int prev_avg_lum; | 56 | int prev_avg_lum; |
57 | int exp_too_low_cnt; | ||
58 | int exp_too_high_cnt; | ||
56 | 59 | ||
60 | unsigned short exposure; | ||
57 | unsigned char gain; | 61 | unsigned char gain; |
58 | unsigned char exposure; | ||
59 | unsigned char brightness; | 62 | unsigned char brightness; |
60 | unsigned char autogain; | 63 | unsigned char autogain; |
61 | unsigned char autogain_ignore_frames; | 64 | unsigned char autogain_ignore_frames; |
@@ -73,8 +76,9 @@ struct sd { | |||
73 | #define SENSOR_OV7630 2 | 76 | #define SENSOR_OV7630 2 |
74 | #define SENSOR_PAS106 3 | 77 | #define SENSOR_PAS106 3 |
75 | #define SENSOR_PAS202 4 | 78 | #define SENSOR_PAS202 4 |
76 | #define SENSOR_TAS5110 5 | 79 | #define SENSOR_TAS5110C 5 |
77 | #define SENSOR_TAS5130CXX 6 | 80 | #define SENSOR_TAS5110D 6 |
81 | #define SENSOR_TAS5130CXX 7 | ||
78 | __u8 reg11; | 82 | __u8 reg11; |
79 | }; | 83 | }; |
80 | 84 | ||
@@ -95,13 +99,15 @@ struct sensor_data { | |||
95 | /* sensor_data flags */ | 99 | /* sensor_data flags */ |
96 | #define F_GAIN 0x01 /* has gain */ | 100 | #define F_GAIN 0x01 /* has gain */ |
97 | #define F_SIF 0x02 /* sif or vga */ | 101 | #define F_SIF 0x02 /* sif or vga */ |
102 | #define F_COARSE_EXPO 0x04 /* exposure control is coarse */ | ||
98 | 103 | ||
99 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ | 104 | /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */ |
100 | #define MODE_RAW 0x10 /* raw bayer mode */ | 105 | #define MODE_RAW 0x10 /* raw bayer mode */ |
101 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ | 106 | #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */ |
102 | 107 | ||
103 | /* ctrl_dis helper macros */ | 108 | /* ctrl_dis helper macros */ |
104 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX)) | 109 | #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \ |
110 | (1 << AUTOGAIN_IDX)) | ||
105 | #define NO_FREQ (1 << FREQ_IDX) | 111 | #define NO_FREQ (1 << FREQ_IDX) |
106 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) | 112 | #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX) |
107 | 113 | ||
@@ -127,11 +133,10 @@ struct sensor_data { | |||
127 | } | 133 | } |
128 | 134 | ||
129 | /* We calculate the autogain at the end of the transfer of a frame, at this | 135 | /* We calculate the autogain at the end of the transfer of a frame, at this |
130 | moment a frame with the old settings is being transmitted, and a frame is | 136 | moment a frame with the old settings is being captured and transmitted. So |
131 | being captured with the old settings. So if we adjust the autogain we must | 137 | if we adjust the gain or exposure we must ignore atleast the next frame for |
132 | ignore atleast the 2 next frames for the new settings to come into effect | 138 | the new settings to come into effect before doing any other adjustments. */ |
133 | before doing any other adjustments */ | 139 | #define AUTOGAIN_IGNORE_FRAMES 1 |
134 | #define AUTOGAIN_IGNORE_FRAMES 3 | ||
135 | 140 | ||
136 | /* V4L2 controls supported by the driver */ | 141 | /* V4L2 controls supported by the driver */ |
137 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | 142 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); |
@@ -145,7 +150,7 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | |||
145 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); | 150 | static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val); |
146 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); | 151 | static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val); |
147 | 152 | ||
148 | static struct ctrl sd_ctrls[] = { | 153 | static const struct ctrl sd_ctrls[] = { |
149 | #define BRIGHTNESS_IDX 0 | 154 | #define BRIGHTNESS_IDX 0 |
150 | { | 155 | { |
151 | { | 156 | { |
@@ -171,7 +176,7 @@ static struct ctrl sd_ctrls[] = { | |||
171 | .maximum = 255, | 176 | .maximum = 255, |
172 | .step = 1, | 177 | .step = 1, |
173 | #define GAIN_DEF 127 | 178 | #define GAIN_DEF 127 |
174 | #define GAIN_KNEE 200 | 179 | #define GAIN_KNEE 230 |
175 | .default_value = GAIN_DEF, | 180 | .default_value = GAIN_DEF, |
176 | }, | 181 | }, |
177 | .set = sd_setgain, | 182 | .set = sd_setgain, |
@@ -183,10 +188,10 @@ static struct ctrl sd_ctrls[] = { | |||
183 | .id = V4L2_CID_EXPOSURE, | 188 | .id = V4L2_CID_EXPOSURE, |
184 | .type = V4L2_CTRL_TYPE_INTEGER, | 189 | .type = V4L2_CTRL_TYPE_INTEGER, |
185 | .name = "Exposure", | 190 | .name = "Exposure", |
186 | #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */ | 191 | #define EXPOSURE_DEF 66 /* 33 ms / 30 fps (except on PASXXX) */ |
187 | #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */ | 192 | #define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */ |
188 | .minimum = 0, | 193 | .minimum = 0, |
189 | .maximum = 255, | 194 | .maximum = 1023, |
190 | .step = 1, | 195 | .step = 1, |
191 | .default_value = EXPOSURE_DEF, | 196 | .default_value = EXPOSURE_DEF, |
192 | .flags = 0, | 197 | .flags = 0, |
@@ -194,7 +199,23 @@ static struct ctrl sd_ctrls[] = { | |||
194 | .set = sd_setexposure, | 199 | .set = sd_setexposure, |
195 | .get = sd_getexposure, | 200 | .get = sd_getexposure, |
196 | }, | 201 | }, |
197 | #define AUTOGAIN_IDX 3 | 202 | #define COARSE_EXPOSURE_IDX 3 |
203 | { | ||
204 | { | ||
205 | .id = V4L2_CID_EXPOSURE, | ||
206 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
207 | .name = "Exposure", | ||
208 | #define COARSE_EXPOSURE_DEF 2 /* 30 fps */ | ||
209 | .minimum = 2, | ||
210 | .maximum = 15, | ||
211 | .step = 1, | ||
212 | .default_value = COARSE_EXPOSURE_DEF, | ||
213 | .flags = 0, | ||
214 | }, | ||
215 | .set = sd_setexposure, | ||
216 | .get = sd_getexposure, | ||
217 | }, | ||
218 | #define AUTOGAIN_IDX 4 | ||
198 | { | 219 | { |
199 | { | 220 | { |
200 | .id = V4L2_CID_AUTOGAIN, | 221 | .id = V4L2_CID_AUTOGAIN, |
@@ -210,7 +231,7 @@ static struct ctrl sd_ctrls[] = { | |||
210 | .set = sd_setautogain, | 231 | .set = sd_setautogain, |
211 | .get = sd_getautogain, | 232 | .get = sd_getautogain, |
212 | }, | 233 | }, |
213 | #define FREQ_IDX 4 | 234 | #define FREQ_IDX 5 |
214 | { | 235 | { |
215 | { | 236 | { |
216 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | 237 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
@@ -219,7 +240,7 @@ static struct ctrl sd_ctrls[] = { | |||
219 | .minimum = 0, | 240 | .minimum = 0, |
220 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ | 241 | .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */ |
221 | .step = 1, | 242 | .step = 1, |
222 | #define FREQ_DEF 1 | 243 | #define FREQ_DEF 0 |
223 | .default_value = FREQ_DEF, | 244 | .default_value = FREQ_DEF, |
224 | }, | 245 | }, |
225 | .set = sd_setfreq, | 246 | .set = sd_setfreq, |
@@ -345,7 +366,7 @@ static const __u8 initOv7630[] = { | |||
345 | }; | 366 | }; |
346 | static const __u8 initOv7630_3[] = { | 367 | static const __u8 initOv7630_3[] = { |
347 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ | 368 | 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */ |
348 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */ | 369 | 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */ |
349 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ | 370 | 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */ |
350 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ | 371 | 0x28, 0x1e, /* H & V sizes r15 .. r16 */ |
351 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ | 372 | 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */ |
@@ -387,6 +408,30 @@ static const __u8 initPas106[] = { | |||
387 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 | 408 | 0x18, 0x10, 0x02, 0x02, 0x09, 0x07 |
388 | }; | 409 | }; |
389 | /* compression 0x86 mckinit1 0x2b */ | 410 | /* compression 0x86 mckinit1 0x2b */ |
411 | |||
412 | /* "Known" PAS106B registers: | ||
413 | 0x02 clock divider | ||
414 | 0x03 Variable framerate bits 4-11 | ||
415 | 0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !! | ||
416 | The variable framerate control must never be set lower then 300, | ||
417 | which sets the framerate at 90 / reg02, otherwise vsync is lost. | ||
418 | 0x05 Shutter Time Line Offset, this can be used as an exposure control: | ||
419 | 0 = use full frame time, 255 = no exposure at all | ||
420 | Note this may never be larger then "var-framerate control" / 2 - 2. | ||
421 | When var-framerate control is < 514, no exposure is reached at the max | ||
422 | allowed value for the framerate control value, rather then at 255. | ||
423 | 0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but | ||
424 | only a very little bit, leave at 0xcd | ||
425 | 0x07 offset sign bit (bit0 1 > negative offset) | ||
426 | 0x08 offset | ||
427 | 0x09 Blue Gain | ||
428 | 0x0a Green1 Gain | ||
429 | 0x0b Green2 Gain | ||
430 | 0x0c Red Gain | ||
431 | 0x0e Global gain | ||
432 | 0x13 Write 1 to commit settings to sensor | ||
433 | */ | ||
434 | |||
390 | static const __u8 pas106_sensor_init[][8] = { | 435 | static const __u8 pas106_sensor_init[][8] = { |
391 | /* Pixel Clock Divider 6 */ | 436 | /* Pixel Clock Divider 6 */ |
392 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, | 437 | { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 }, |
@@ -433,37 +478,55 @@ static const __u8 initPas202[] = { | |||
433 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, | 478 | 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, |
434 | 0x00, 0x00, | 479 | 0x00, 0x00, |
435 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, | 480 | 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a, |
436 | 0x28, 0x1e, 0x28, 0x89, 0x20, | 481 | 0x28, 0x1e, 0x20, 0x89, 0x20, |
437 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c | 482 | 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c |
438 | }; | 483 | }; |
484 | |||
485 | /* "Known" PAS202BCB registers: | ||
486 | 0x02 clock divider | ||
487 | 0x04 Variable framerate bits 6-11 (*) | ||
488 | 0x05 Var framerate bits 0-5, one must leave the 2 msb's at 0 !! | ||
489 | 0x07 Blue Gain | ||
490 | 0x08 Green Gain | ||
491 | 0x09 Red Gain | ||
492 | 0x0b offset sign bit (bit0 1 > negative offset) | ||
493 | 0x0c offset | ||
494 | 0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too, | ||
495 | leave at 1 otherwise we get a jump in our exposure control | ||
496 | 0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all | ||
497 | 0x10 Master gain 0 - 31 | ||
498 | 0x11 write 1 to apply changes | ||
499 | (*) The variable framerate control must never be set lower then 500 | ||
500 | which sets the framerate at 30 / reg02, otherwise vsync is lost. | ||
501 | */ | ||
439 | static const __u8 pas202_sensor_init[][8] = { | 502 | static const __u8 pas202_sensor_init[][8] = { |
440 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}, | 503 | /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like |
504 | to set it lower, but for some reason the bridge starts missing | ||
505 | vsync's then */ | ||
506 | {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, | ||
441 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, | 507 | {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, |
442 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, | 508 | {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, |
443 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10}, | 509 | {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, |
444 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, | 510 | {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, |
445 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, | 511 | {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, |
446 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, | 512 | {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, |
447 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 513 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
448 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, | 514 | {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10}, |
449 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, | 515 | {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10}, |
450 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10}, | ||
451 | {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10}, | ||
452 | |||
453 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
454 | {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15}, | ||
455 | {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16}, | ||
456 | {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16}, | ||
457 | {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16}, | ||
458 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
459 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}, | ||
460 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}, | ||
461 | }; | 516 | }; |
462 | 517 | ||
463 | static const __u8 initTas5110[] = { | 518 | static const __u8 initTas5110c[] = { |
464 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 519 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
465 | 0x00, 0x00, | 520 | 0x00, 0x00, |
466 | 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a, | 521 | 0x00, 0x00, 0x00, 0x45, 0x09, 0x0a, |
522 | 0x16, 0x12, 0x60, 0x86, 0x2b, | ||
523 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | ||
524 | }; | ||
525 | /* Same as above, except a different hstart */ | ||
526 | static const __u8 initTas5110d[] = { | ||
527 | 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | ||
528 | 0x00, 0x00, | ||
529 | 0x00, 0x00, 0x00, 0x41, 0x09, 0x0a, | ||
467 | 0x16, 0x12, 0x60, 0x86, 0x2b, | 530 | 0x16, 0x12, 0x60, 0x86, 0x2b, |
468 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 | 531 | 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07 |
469 | }; | 532 | }; |
@@ -476,7 +539,7 @@ static const __u8 tas5110_sensor_init[][8] = { | |||
476 | static const __u8 initTas5130[] = { | 539 | static const __u8 initTas5130[] = { |
477 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, | 540 | 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00, |
478 | 0x00, 0x00, | 541 | 0x00, 0x00, |
479 | 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a, | 542 | 0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a, |
480 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, | 543 | 0x28, 0x1e, 0x60, COMP, MCK_INIT, |
481 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c | 544 | 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c |
482 | }; | 545 | }; |
@@ -493,12 +556,14 @@ SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), | |||
493 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), | 556 | SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), |
494 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, | 557 | SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, |
495 | F_GAIN, 0, 0x21), | 558 | F_GAIN, 0, 0x21), |
496 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ, | 559 | SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_GAIN|F_SIF, NO_FREQ, |
497 | 0), | 560 | 0), |
498 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0, | 561 | SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, F_GAIN, |
499 | NO_EXPO|NO_FREQ, 0), | 562 | NO_FREQ, 0), |
500 | SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF, | 563 | SENS(initTas5110c, NULL, tas5110_sensor_init, NULL, NULL, |
501 | NO_BRIGHTNESS|NO_FREQ, 0), | 564 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), |
565 | SENS(initTas5110d, NULL, tas5110_sensor_init, NULL, NULL, | ||
566 | F_GAIN|F_SIF|F_COARSE_EXPO, NO_BRIGHTNESS|NO_FREQ, 0), | ||
502 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, | 567 | SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, |
503 | 0), | 568 | 0), |
504 | }; | 569 | }; |
@@ -587,42 +652,28 @@ static void setbrightness(struct gspca_dev *gspca_dev) | |||
587 | goto err; | 652 | goto err; |
588 | break; | 653 | break; |
589 | } | 654 | } |
590 | case SENSOR_PAS106: { | 655 | case SENSOR_PAS106: |
591 | __u8 i2c1[] = | ||
592 | {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
593 | |||
594 | i2c1[3] = sd->brightness >> 3; | ||
595 | i2c1[2] = 0x0e; | ||
596 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
597 | goto err; | ||
598 | i2c1[3] = 0x01; | ||
599 | i2c1[2] = 0x13; | ||
600 | if (i2c_w(gspca_dev, i2c1) < 0) | ||
601 | goto err; | ||
602 | break; | ||
603 | } | ||
604 | case SENSOR_PAS202: { | 656 | case SENSOR_PAS202: { |
605 | /* __u8 i2cpexpo1[] = | 657 | __u8 i2cpbright[] = |
606 | {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */ | 658 | {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16}; |
607 | __u8 i2cpexpo[] = | 659 | __u8 i2cpdoit[] = |
608 | {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16}; | 660 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; |
609 | __u8 i2cp202[] = | 661 | |
610 | {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15}; | 662 | /* PAS106 uses reg 7 and 8 instead of b and c */ |
611 | static __u8 i2cpdoit[] = | 663 | if (sd->sensor == SENSOR_PAS106) { |
612 | {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16}; | 664 | i2cpbright[2] = 7; |
613 | 665 | i2cpdoit[2] = 0x13; | |
614 | /* change reg 0x10 */ | 666 | } |
615 | i2cpexpo[4] = 0xff - sd->brightness; | 667 | |
616 | /* if(i2c_w(gspca_dev,i2cpexpo1) < 0) | 668 | if (sd->brightness < 127) { |
617 | goto err; */ | 669 | /* change reg 0x0b, signreg */ |
618 | /* if(i2c_w(gspca_dev,i2cpdoit) < 0) | 670 | i2cpbright[3] = 0x01; |
619 | goto err; */ | 671 | /* set reg 0x0c, offset */ |
620 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | 672 | i2cpbright[4] = 127 - sd->brightness; |
621 | goto err; | 673 | } else |
622 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 674 | i2cpbright[4] = sd->brightness - 127; |
623 | goto err; | 675 | |
624 | i2cp202[3] = sd->brightness >> 3; | 676 | if (i2c_w(gspca_dev, i2cpbright) < 0) |
625 | if (i2c_w(gspca_dev, i2cp202) < 0) | ||
626 | goto err; | 677 | goto err; |
627 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | 678 | if (i2c_w(gspca_dev, i2cpdoit) < 0) |
628 | goto err; | 679 | goto err; |
@@ -652,7 +703,8 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
652 | 703 | ||
653 | switch (sd->sensor) { | 704 | switch (sd->sensor) { |
654 | 705 | ||
655 | case SENSOR_TAS5110: { | 706 | case SENSOR_TAS5110C: |
707 | case SENSOR_TAS5110D: { | ||
656 | __u8 i2c[] = | 708 | __u8 i2c[] = |
657 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; | 709 | {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10}; |
658 | 710 | ||
@@ -674,6 +726,37 @@ static void setsensorgain(struct gspca_dev *gspca_dev) | |||
674 | goto err; | 726 | goto err; |
675 | break; | 727 | break; |
676 | } | 728 | } |
729 | case SENSOR_PAS106: | ||
730 | case SENSOR_PAS202: { | ||
731 | __u8 i2cpgain[] = | ||
732 | {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
733 | __u8 i2cpcolorgain[] = | ||
734 | {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15}; | ||
735 | __u8 i2cpdoit[] = | ||
736 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
737 | |||
738 | /* PAS106 uses different regs (and has split green gains) */ | ||
739 | if (sd->sensor == SENSOR_PAS106) { | ||
740 | i2cpgain[2] = 0x0e; | ||
741 | i2cpcolorgain[0] = 0xd0; | ||
742 | i2cpcolorgain[2] = 0x09; | ||
743 | i2cpdoit[2] = 0x13; | ||
744 | } | ||
745 | |||
746 | i2cpgain[3] = sd->gain >> 3; | ||
747 | i2cpcolorgain[3] = sd->gain >> 4; | ||
748 | i2cpcolorgain[4] = sd->gain >> 4; | ||
749 | i2cpcolorgain[5] = sd->gain >> 4; | ||
750 | i2cpcolorgain[6] = sd->gain >> 4; | ||
751 | |||
752 | if (i2c_w(gspca_dev, i2cpgain) < 0) | ||
753 | goto err; | ||
754 | if (i2c_w(gspca_dev, i2cpcolorgain) < 0) | ||
755 | goto err; | ||
756 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
757 | goto err; | ||
758 | break; | ||
759 | } | ||
677 | } | 760 | } |
678 | return; | 761 | return; |
679 | err: | 762 | err: |
@@ -684,19 +767,21 @@ static void setgain(struct gspca_dev *gspca_dev) | |||
684 | { | 767 | { |
685 | struct sd *sd = (struct sd *) gspca_dev; | 768 | struct sd *sd = (struct sd *) gspca_dev; |
686 | __u8 gain; | 769 | __u8 gain; |
687 | __u8 rgb_value; | 770 | __u8 buf[2] = { 0, 0 }; |
771 | |||
772 | if (sensor_data[sd->sensor].flags & F_GAIN) { | ||
773 | /* Use the sensor gain to do the actual gain */ | ||
774 | setsensorgain(gspca_dev); | ||
775 | return; | ||
776 | } | ||
688 | 777 | ||
689 | gain = sd->gain >> 4; | 778 | gain = sd->gain >> 4; |
690 | 779 | ||
691 | /* red and blue gain */ | 780 | /* red and blue gain */ |
692 | rgb_value = gain << 4 | gain; | 781 | buf[0] = gain << 4 | gain; |
693 | reg_w(gspca_dev, 0x10, &rgb_value, 1); | ||
694 | /* green gain */ | 782 | /* green gain */ |
695 | rgb_value = gain; | 783 | buf[1] = gain; |
696 | reg_w(gspca_dev, 0x11, &rgb_value, 1); | 784 | reg_w(gspca_dev, 0x10, buf, 2); |
697 | |||
698 | if (sensor_data[sd->sensor].flags & F_GAIN) | ||
699 | setsensorgain(gspca_dev); | ||
700 | } | 785 | } |
701 | 786 | ||
702 | static void setexposure(struct gspca_dev *gspca_dev) | 787 | static void setexposure(struct gspca_dev *gspca_dev) |
@@ -704,17 +789,12 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
704 | struct sd *sd = (struct sd *) gspca_dev; | 789 | struct sd *sd = (struct sd *) gspca_dev; |
705 | 790 | ||
706 | switch (sd->sensor) { | 791 | switch (sd->sensor) { |
707 | case SENSOR_TAS5110: { | 792 | case SENSOR_TAS5110C: |
708 | __u8 reg; | 793 | case SENSOR_TAS5110D: { |
709 | |||
710 | /* register 19's high nibble contains the sn9c10x clock divider | 794 | /* register 19's high nibble contains the sn9c10x clock divider |
711 | The high nibble configures the no fps according to the | 795 | The high nibble configures the no fps according to the |
712 | formula: 60 / high_nibble. With a maximum of 30 fps */ | 796 | formula: 60 / high_nibble. With a maximum of 30 fps */ |
713 | reg = 120 * sd->exposure / 1000; | 797 | __u8 reg = sd->exposure; |
714 | if (reg < 2) | ||
715 | reg = 2; | ||
716 | else if (reg > 15) | ||
717 | reg = 15; | ||
718 | reg = (reg << 4) | 0x0b; | 798 | reg = (reg << 4) | 0x0b; |
719 | reg_w(gspca_dev, 0x19, ®, 1); | 799 | reg_w(gspca_dev, 0x19, ®, 1); |
720 | break; | 800 | break; |
@@ -750,20 +830,21 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
750 | } else | 830 | } else |
751 | reg10_max = 0x41; | 831 | reg10_max = 0x41; |
752 | 832 | ||
753 | reg11 = (60 * sd->exposure + 999) / 1000; | 833 | reg11 = (15 * sd->exposure + 999) / 1000; |
754 | if (reg11 < 1) | 834 | if (reg11 < 1) |
755 | reg11 = 1; | 835 | reg11 = 1; |
756 | else if (reg11 > 16) | 836 | else if (reg11 > 16) |
757 | reg11 = 16; | 837 | reg11 = 16; |
758 | 838 | ||
759 | /* In 640x480, if the reg11 has less than 3, the image is | 839 | /* In 640x480, if the reg11 has less than 4, the image is |
760 | unstable (not enough bandwidth). */ | 840 | unstable (the bridge goes into a higher compression mode |
761 | if (gspca_dev->width == 640 && reg11 < 3) | 841 | which we have not reverse engineered yet). */ |
762 | reg11 = 3; | 842 | if (gspca_dev->width == 640 && reg11 < 4) |
843 | reg11 = 4; | ||
763 | 844 | ||
764 | /* frame exposure time in ms = 1000 * reg11 / 30 -> | 845 | /* frame exposure time in ms = 1000 * reg11 / 30 -> |
765 | reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */ | 846 | reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */ |
766 | reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11); | 847 | reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11); |
767 | 848 | ||
768 | /* Don't allow this to get below 10 when using autogain, the | 849 | /* Don't allow this to get below 10 when using autogain, the |
769 | steps become very large (relatively) when below 10 causing | 850 | steps become very large (relatively) when below 10 causing |
@@ -786,10 +867,85 @@ static void setexposure(struct gspca_dev *gspca_dev) | |||
786 | if (i2c_w(gspca_dev, i2c) == 0) | 867 | if (i2c_w(gspca_dev, i2c) == 0) |
787 | sd->reg11 = reg11; | 868 | sd->reg11 = reg11; |
788 | else | 869 | else |
789 | PDEBUG(D_ERR, "i2c error exposure"); | 870 | goto err; |
871 | break; | ||
872 | } | ||
873 | case SENSOR_PAS202: { | ||
874 | __u8 i2cpframerate[] = | ||
875 | {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
876 | __u8 i2cpexpo[] = | ||
877 | {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16}; | ||
878 | const __u8 i2cpdoit[] = | ||
879 | {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16}; | ||
880 | int framerate_ctrl; | ||
881 | |||
882 | /* The exposure knee for the autogain algorithm is 200 | ||
883 | (100 ms / 10 fps on other sensors), for values below this | ||
884 | use the control for setting the partial frame expose time, | ||
885 | above that use variable framerate. This way we run at max | ||
886 | framerate (640x480@7.5 fps, 320x240@10fps) until the knee | ||
887 | is reached. Using the variable framerate control above 200 | ||
888 | is better then playing around with both clockdiv + partial | ||
889 | frame exposure times (like we are doing with the ov chips), | ||
890 | as that sometimes leads to jumps in the exposure control, | ||
891 | which are bad for auto exposure. */ | ||
892 | if (sd->exposure < 200) { | ||
893 | i2cpexpo[3] = 255 - (sd->exposure * 255) / 200; | ||
894 | framerate_ctrl = 500; | ||
895 | } else { | ||
896 | /* The PAS202's exposure control goes from 0 - 4095, | ||
897 | but anything below 500 causes vsync issues, so scale | ||
898 | our 200-1023 to 500-4095 */ | ||
899 | framerate_ctrl = (sd->exposure - 200) * 1000 / 229 + | ||
900 | 500; | ||
901 | } | ||
902 | |||
903 | i2cpframerate[3] = framerate_ctrl >> 6; | ||
904 | i2cpframerate[4] = framerate_ctrl & 0x3f; | ||
905 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
906 | goto err; | ||
907 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
908 | goto err; | ||
909 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
910 | goto err; | ||
911 | break; | ||
912 | } | ||
913 | case SENSOR_PAS106: { | ||
914 | __u8 i2cpframerate[] = | ||
915 | {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
916 | __u8 i2cpexpo[] = | ||
917 | {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14}; | ||
918 | const __u8 i2cpdoit[] = | ||
919 | {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14}; | ||
920 | int framerate_ctrl; | ||
921 | |||
922 | /* For values below 150 use partial frame exposure, above | ||
923 | that use framerate ctrl */ | ||
924 | if (sd->exposure < 150) { | ||
925 | i2cpexpo[3] = 150 - sd->exposure; | ||
926 | framerate_ctrl = 300; | ||
927 | } else { | ||
928 | /* The PAS106's exposure control goes from 0 - 4095, | ||
929 | but anything below 300 causes vsync issues, so scale | ||
930 | our 150-1023 to 300-4095 */ | ||
931 | framerate_ctrl = (sd->exposure - 150) * 1000 / 230 + | ||
932 | 300; | ||
933 | } | ||
934 | |||
935 | i2cpframerate[3] = framerate_ctrl >> 4; | ||
936 | i2cpframerate[4] = framerate_ctrl & 0x0f; | ||
937 | if (i2c_w(gspca_dev, i2cpframerate) < 0) | ||
938 | goto err; | ||
939 | if (i2c_w(gspca_dev, i2cpexpo) < 0) | ||
940 | goto err; | ||
941 | if (i2c_w(gspca_dev, i2cpdoit) < 0) | ||
942 | goto err; | ||
790 | break; | 943 | break; |
791 | } | 944 | } |
792 | } | 945 | } |
946 | return; | ||
947 | err: | ||
948 | PDEBUG(D_ERR, "i2c error exposure"); | ||
793 | } | 949 | } |
794 | 950 | ||
795 | static void setfreq(struct gspca_dev *gspca_dev) | 951 | static void setfreq(struct gspca_dev *gspca_dev) |
@@ -823,30 +979,43 @@ static void setfreq(struct gspca_dev *gspca_dev) | |||
823 | } | 979 | } |
824 | } | 980 | } |
825 | 981 | ||
982 | #include "coarse_expo_autogain.h" | ||
983 | |||
826 | static void do_autogain(struct gspca_dev *gspca_dev) | 984 | static void do_autogain(struct gspca_dev *gspca_dev) |
827 | { | 985 | { |
828 | int deadzone, desired_avg_lum; | 986 | int deadzone, desired_avg_lum, result; |
829 | struct sd *sd = (struct sd *) gspca_dev; | 987 | struct sd *sd = (struct sd *) gspca_dev; |
830 | int avg_lum = atomic_read(&sd->avg_lum); | 988 | int avg_lum = atomic_read(&sd->avg_lum); |
831 | 989 | ||
832 | if (avg_lum == -1) | 990 | if (avg_lum == -1 || !sd->autogain) |
833 | return; | 991 | return; |
834 | 992 | ||
993 | if (sd->autogain_ignore_frames > 0) { | ||
994 | sd->autogain_ignore_frames--; | ||
995 | return; | ||
996 | } | ||
997 | |||
835 | /* SIF / VGA sensors have a different autoexposure area and thus | 998 | /* SIF / VGA sensors have a different autoexposure area and thus |
836 | different avg_lum values for the same picture brightness */ | 999 | different avg_lum values for the same picture brightness */ |
837 | if (sensor_data[sd->sensor].flags & F_SIF) { | 1000 | if (sensor_data[sd->sensor].flags & F_SIF) { |
838 | deadzone = 1000; | 1001 | deadzone = 500; |
839 | desired_avg_lum = 7000; | 1002 | /* SIF sensors tend to overexpose, so keep this small */ |
1003 | desired_avg_lum = 5000; | ||
840 | } else { | 1004 | } else { |
841 | deadzone = 3000; | 1005 | deadzone = 1500; |
842 | desired_avg_lum = 23000; | 1006 | desired_avg_lum = 18000; |
843 | } | 1007 | } |
844 | 1008 | ||
845 | if (sd->autogain_ignore_frames > 0) | 1009 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) |
846 | sd->autogain_ignore_frames--; | 1010 | result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum, |
847 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | 1011 | sd->brightness * desired_avg_lum / 127, |
848 | sd->brightness * desired_avg_lum / 127, | 1012 | deadzone); |
849 | deadzone, GAIN_KNEE, EXPOSURE_KNEE)) { | 1013 | else |
1014 | result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | ||
1015 | sd->brightness * desired_avg_lum / 127, | ||
1016 | deadzone, GAIN_KNEE, EXPOSURE_KNEE); | ||
1017 | |||
1018 | if (result) { | ||
850 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", | 1019 | PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d", |
851 | (int)sd->gain, (int)sd->exposure); | 1020 | (int)sd->gain, (int)sd->exposure); |
852 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; | 1021 | sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES; |
@@ -881,7 +1050,13 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
881 | 1050 | ||
882 | sd->brightness = BRIGHTNESS_DEF; | 1051 | sd->brightness = BRIGHTNESS_DEF; |
883 | sd->gain = GAIN_DEF; | 1052 | sd->gain = GAIN_DEF; |
884 | sd->exposure = EXPOSURE_DEF; | 1053 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { |
1054 | sd->exposure = COARSE_EXPOSURE_DEF; | ||
1055 | gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX); | ||
1056 | } else { | ||
1057 | sd->exposure = EXPOSURE_DEF; | ||
1058 | gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX); | ||
1059 | } | ||
885 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) | 1060 | if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX)) |
886 | sd->autogain = 0; /* Disable do_autogain callback */ | 1061 | sd->autogain = 0; /* Disable do_autogain callback */ |
887 | else | 1062 | else |
@@ -917,9 +1092,6 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
917 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); | 1092 | reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4); |
918 | /* Special cases where reg 17 and or 19 value depends on mode */ | 1093 | /* Special cases where reg 17 and or 19 value depends on mode */ |
919 | switch (sd->sensor) { | 1094 | switch (sd->sensor) { |
920 | case SENSOR_PAS202: | ||
921 | reg12_19[5] = mode ? 0x24 : 0x20; | ||
922 | break; | ||
923 | case SENSOR_TAS5130CXX: | 1095 | case SENSOR_TAS5130CXX: |
924 | /* probably not mode specific at all most likely the upper | 1096 | /* probably not mode specific at all most likely the upper |
925 | nibble of 0x19 is exposure (clock divider) just as with | 1097 | nibble of 0x19 is exposure (clock divider) just as with |
@@ -955,6 +1127,16 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
955 | sensor_data[sd->sensor].sensor_bridge_init_size[ | 1127 | sensor_data[sd->sensor].sensor_bridge_init_size[ |
956 | sd->bridge]); | 1128 | sd->bridge]); |
957 | 1129 | ||
1130 | /* Mode specific sensor setup */ | ||
1131 | switch (sd->sensor) { | ||
1132 | case SENSOR_PAS202: { | ||
1133 | const __u8 i2cpclockdiv[] = | ||
1134 | {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10}; | ||
1135 | /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */ | ||
1136 | if (mode) | ||
1137 | i2c_w(gspca_dev, i2cpclockdiv); | ||
1138 | } | ||
1139 | } | ||
958 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ | 1140 | /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */ |
959 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); | 1141 | reg_w(gspca_dev, 0x15, ®12_19[3], 2); |
960 | /* compression register */ | 1142 | /* compression register */ |
@@ -985,6 +1167,8 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
985 | 1167 | ||
986 | sd->frames_to_drop = 0; | 1168 | sd->frames_to_drop = 0; |
987 | sd->autogain_ignore_frames = 0; | 1169 | sd->autogain_ignore_frames = 0; |
1170 | sd->exp_too_high_cnt = 0; | ||
1171 | sd->exp_too_low_cnt = 0; | ||
988 | atomic_set(&sd->avg_lum, -1); | 1172 | atomic_set(&sd->avg_lum, -1); |
989 | return 0; | 1173 | return 0; |
990 | } | 1174 | } |
@@ -1143,11 +1327,14 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1143 | struct sd *sd = (struct sd *) gspca_dev; | 1327 | struct sd *sd = (struct sd *) gspca_dev; |
1144 | 1328 | ||
1145 | sd->autogain = val; | 1329 | sd->autogain = val; |
1330 | sd->exp_too_high_cnt = 0; | ||
1331 | sd->exp_too_low_cnt = 0; | ||
1332 | |||
1146 | /* when switching to autogain set defaults to make sure | 1333 | /* when switching to autogain set defaults to make sure |
1147 | we are on a valid point of the autogain gain / | 1334 | we are on a valid point of the autogain gain / |
1148 | exposure knee graph, and give this change time to | 1335 | exposure knee graph, and give this change time to |
1149 | take effect before doing autogain. */ | 1336 | take effect before doing autogain. */ |
1150 | if (sd->autogain) { | 1337 | if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) { |
1151 | sd->exposure = EXPOSURE_DEF; | 1338 | sd->exposure = EXPOSURE_DEF; |
1152 | sd->gain = GAIN_DEF; | 1339 | sd->gain = GAIN_DEF; |
1153 | if (gspca_dev->streaming) { | 1340 | if (gspca_dev->streaming) { |
@@ -1207,6 +1394,25 @@ static int sd_querymenu(struct gspca_dev *gspca_dev, | |||
1207 | return -EINVAL; | 1394 | return -EINVAL; |
1208 | } | 1395 | } |
1209 | 1396 | ||
1397 | #ifdef CONFIG_INPUT | ||
1398 | static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, | ||
1399 | u8 *data, /* interrupt packet data */ | ||
1400 | int len) /* interrupt packet length */ | ||
1401 | { | ||
1402 | int ret = -EINVAL; | ||
1403 | |||
1404 | if (len == 1 && data[0] == 1) { | ||
1405 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1); | ||
1406 | input_sync(gspca_dev->input_dev); | ||
1407 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1408 | input_sync(gspca_dev->input_dev); | ||
1409 | ret = 0; | ||
1410 | } | ||
1411 | |||
1412 | return ret; | ||
1413 | } | ||
1414 | #endif | ||
1415 | |||
1210 | /* sub-driver description */ | 1416 | /* sub-driver description */ |
1211 | static const struct sd_desc sd_desc = { | 1417 | static const struct sd_desc sd_desc = { |
1212 | .name = MODULE_NAME, | 1418 | .name = MODULE_NAME, |
@@ -1219,6 +1425,9 @@ static const struct sd_desc sd_desc = { | |||
1219 | .pkt_scan = sd_pkt_scan, | 1425 | .pkt_scan = sd_pkt_scan, |
1220 | .querymenu = sd_querymenu, | 1426 | .querymenu = sd_querymenu, |
1221 | .dq_callback = do_autogain, | 1427 | .dq_callback = do_autogain, |
1428 | #ifdef CONFIG_INPUT | ||
1429 | .int_pkt_scan = sd_int_pkt_scan, | ||
1430 | #endif | ||
1222 | }; | 1431 | }; |
1223 | 1432 | ||
1224 | /* -- module initialisation -- */ | 1433 | /* -- module initialisation -- */ |
@@ -1227,21 +1436,21 @@ static const struct sd_desc sd_desc = { | |||
1227 | 1436 | ||
1228 | 1437 | ||
1229 | static const struct usb_device_id device_table[] __devinitconst = { | 1438 | static const struct usb_device_id device_table[] __devinitconst = { |
1230 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */ | 1439 | {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ |
1231 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */ | 1440 | {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ |
1232 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1441 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1233 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */ | 1442 | {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ |
1443 | #endif | ||
1234 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, | 1444 | {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, |
1235 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, | 1445 | {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, |
1236 | #endif | ||
1237 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, | 1446 | {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, |
1238 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1447 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |
1239 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, | 1448 | {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)}, |
1240 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, | 1449 | {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)}, |
1241 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, | 1450 | {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)}, |
1451 | #endif | ||
1242 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, | 1452 | {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, |
1243 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, | 1453 | {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, |
1244 | #endif | ||
1245 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, | 1454 | {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, |
1246 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, | 1455 | {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, |
1247 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE | 1456 | #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE |