aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/spca561.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/spca561.c')
-rw-r--r--drivers/media/video/gspca/spca561.c522
1 files changed, 241 insertions, 281 deletions
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
index c3de4e44123d..3c9288019e96 100644
--- a/drivers/media/video/gspca/spca561.c
+++ b/drivers/media/video/gspca/spca561.c
@@ -32,22 +32,22 @@ MODULE_LICENSE("GPL");
32struct sd { 32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */ 33 struct gspca_dev gspca_dev; /* !! must be the first item */
34 34
35 __u16 contrast; /* rev72a only */
36#define CONTRAST_MIN 0x0000
37#define CONTRAST_DEF 0x2000
38#define CONTRAST_MAX 0x3fff
39
40 __u16 exposure; /* rev12a only */ 35 __u16 exposure; /* rev12a only */
41#define EXPOSURE_MIN 1 36#define EXPOSURE_MIN 1
42#define EXPOSURE_DEF 200 37#define EXPOSURE_DEF 200
43#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */ 38#define EXPOSURE_MAX (4095 - 900) /* see set_exposure */
44 39
40 __u8 contrast; /* rev72a only */
41#define CONTRAST_MIN 0x00
42#define CONTRAST_DEF 0x20
43#define CONTRAST_MAX 0x3f
44
45 __u8 brightness; /* rev72a only */ 45 __u8 brightness; /* rev72a only */
46#define BRIGHTNESS_MIN 0 46#define BRIGHTNESS_MIN 0
47#define BRIGHTNESS_DEF 32 47#define BRIGHTNESS_DEF 0x20
48#define BRIGHTNESS_MAX 63 48#define BRIGHTNESS_MAX 0x3f
49 49
50 __u8 white; /* rev12a only */ 50 __u8 white;
51#define WHITE_MIN 1 51#define WHITE_MIN 1
52#define WHITE_DEF 0x40 52#define WHITE_DEF 0x40
53#define WHITE_MAX 0x7f 53#define WHITE_MAX 0x7f
@@ -73,7 +73,7 @@ struct sd {
73#define AG_CNT_START 13 73#define AG_CNT_START 13
74}; 74};
75 75
76static struct v4l2_pix_format sif_012a_mode[] = { 76static const struct v4l2_pix_format sif_012a_mode[] = {
77 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 77 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
78 .bytesperline = 160, 78 .bytesperline = 160,
79 .sizeimage = 160 * 120, 79 .sizeimage = 160 * 120,
@@ -96,7 +96,7 @@ static struct v4l2_pix_format sif_012a_mode[] = {
96 .priv = 0}, 96 .priv = 0},
97}; 97};
98 98
99static struct v4l2_pix_format sif_072a_mode[] = { 99static const struct v4l2_pix_format sif_072a_mode[] = {
100 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE, 100 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
101 .bytesperline = 160, 101 .bytesperline = 160,
102 .sizeimage = 160 * 120, 102 .sizeimage = 160 * 120,
@@ -146,98 +146,7 @@ static struct v4l2_pix_format sif_072a_mode[] = {
146#define SPCA561_SNAPBIT 0x20 146#define SPCA561_SNAPBIT 0x20
147#define SPCA561_SNAPCTRL 0x40 147#define SPCA561_SNAPCTRL 0x40
148 148
149static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value) 149static const __u16 rev72a_init_data1[][2] = {
150{
151 int ret;
152
153 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
154 0, /* request */
155 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
156 value, index, NULL, 0, 500);
157 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
158 if (ret < 0)
159 PDEBUG(D_ERR, "reg write: error %d", ret);
160}
161
162static void write_vector(struct gspca_dev *gspca_dev,
163 const __u16 data[][2])
164{
165 struct usb_device *dev = gspca_dev->dev;
166 int i;
167
168 i = 0;
169 while (data[i][1] != 0) {
170 reg_w_val(dev, data[i][1], data[i][0]);
171 i++;
172 }
173}
174
175/* read 'len' bytes to gspca_dev->usb_buf */
176static void reg_r(struct gspca_dev *gspca_dev,
177 __u16 index, __u16 length)
178{
179 usb_control_msg(gspca_dev->dev,
180 usb_rcvctrlpipe(gspca_dev->dev, 0),
181 0, /* request */
182 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
183 0, /* value */
184 index, gspca_dev->usb_buf, length, 500);
185}
186
187static void reg_w_buf(struct gspca_dev *gspca_dev,
188 __u16 index, const __u8 *buffer, __u16 len)
189{
190 memcpy(gspca_dev->usb_buf, buffer, len);
191 usb_control_msg(gspca_dev->dev,
192 usb_sndctrlpipe(gspca_dev->dev, 0),
193 0, /* request */
194 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
195 0, /* value */
196 index, gspca_dev->usb_buf, len, 500);
197}
198
199static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
200{
201 int retry = 60;
202 __u8 DataLow;
203 __u8 DataHight;
204
205 DataLow = valeur;
206 DataHight = valeur >> 8;
207 reg_w_val(gspca_dev->dev, 0x8801, reg);
208 reg_w_val(gspca_dev->dev, 0x8805, DataLow);
209 reg_w_val(gspca_dev->dev, 0x8800, DataHight);
210 while (retry--) {
211 reg_r(gspca_dev, 0x8803, 1);
212 if (!gspca_dev->usb_buf[0])
213 break;
214 }
215}
216
217static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
218{
219 int retry = 60;
220 __u8 value;
221 __u8 vallsb;
222
223 reg_w_val(gspca_dev->dev, 0x8804, 0x92);
224 reg_w_val(gspca_dev->dev, 0x8801, reg);
225 reg_w_val(gspca_dev->dev, 0x8802, (mode | 0x01));
226 do {
227 reg_r(gspca_dev, 0x8803, 1);
228 if (!gspca_dev->usb_buf[0])
229 break;
230 } while (--retry);
231 if (retry == 0)
232 return -1;
233 reg_r(gspca_dev, 0x8800, 1);
234 value = gspca_dev->usb_buf[0];
235 reg_r(gspca_dev, 0x8805, 1);
236 vallsb = gspca_dev->usb_buf[0];
237 return ((int) value << 8) | vallsb;
238}
239
240static const __u16 spca561_init_data[][2] = {
241 {0x0000, 0x8114}, /* Software GPIO output data */ 150 {0x0000, 0x8114}, /* Software GPIO output data */
242 {0x0001, 0x8114}, /* Software GPIO output data */ 151 {0x0001, 0x8114}, /* Software GPIO output data */
243 {0x0000, 0x8112}, /* Some kind of reset */ 152 {0x0000, 0x8112}, /* Some kind of reset */
@@ -247,44 +156,26 @@ static const __u16 spca561_init_data[][2] = {
247 {0x0001, 0x8118}, /* Conf sensor */ 156 {0x0001, 0x8118}, /* Conf sensor */
248 {0x0092, 0x8804}, /* I know nothing about these */ 157 {0x0092, 0x8804}, /* I know nothing about these */
249 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */ 158 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
250 /***************/
251 {0x000d, 0x8805}, /* sensor default setting */ 159 {0x000d, 0x8805}, /* sensor default setting */
252 {0x0001, 0x8801}, /* 1 <- 0x0d */ 160 {}
253 {0x0000, 0x8800}, 161};
254 {0x0018, 0x8805}, 162static const __u16 rev72a_init_sensor1[][2] = {
255 {0x0002, 0x8801}, /* 2 <- 0x18 */ 163 /* ms-win values */
256 {0x0000, 0x8800}, 164 {0x0001, 0x0018}, /* 0x01 <- 0x0d */
257 {0x0065, 0x8805}, 165 {0x0002, 0x0065}, /* 0x02 <- 0x18 */
258 {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */ 166 {0x0004, 0x0121}, /* 0x04 <- 0x0165 */
259 {0x0001, 0x8800}, 167 {0x0005, 0x00aa}, /* 0x05 <- 0x21 */
260 {0x0021, 0x8805}, 168 {0x0007, 0x0004}, /* 0x07 <- 0xaa */
261 {0x0005, 0x8801}, /* 5 <- 0x21 */ 169 {0x0020, 0x1502}, /* 0x20 <- 0x1504 */
262 {0x0000, 0x8800}, 170 {0x0039, 0x0010}, /* 0x39 <- 0x02 */
263 {0x00aa, 0x8805}, 171 {0x0035, 0x0049}, /* 0x35 <- 0x10 */
264 {0x0007, 0x8801}, /* 7 <- 0xaa */ 172 {0x0009, 0x100b}, /* 0x09 <- 0x1049 */
265 {0x0000, 0x8800}, 173 {0x0028, 0x000f}, /* 0x28 <- 0x0b */
266 {0x0004, 0x8805}, 174 {0x003b, 0x003c}, /* 0x3b <- 0x0f */
267 {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */ 175 {0x003c, 0x0000}, /* 0x3c <- 0x00 */
268 {0x0015, 0x8800}, 176 {}
269 {0x0002, 0x8805}, 177};
270 {0x0039, 0x8801}, /* 0x39 <- 0x02 */ 178static const __u16 rev72a_init_data2[][2] = {
271 {0x0000, 0x8800},
272 {0x0010, 0x8805},
273 {0x0035, 0x8801}, /* 0x35 <- 0x10 */
274 {0x0000, 0x8800},
275 {0x0049, 0x8805},
276 {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */
277 {0x0010, 0x8800},
278 {0x000b, 0x8805},
279 {0x0028, 0x8801}, /* 0x28 <- 0x0b */
280 {0x0000, 0x8800},
281 {0x000f, 0x8805},
282 {0x003b, 0x8801}, /* 0x3b <- 0x0f */
283 {0x0000, 0x8800},
284 {0x0000, 0x8805},
285 {0x003c, 0x8801}, /* 0x3c <- 0x00 */
286 {0x0000, 0x8800},
287 /***************/
288 {0x0018, 0x8601}, /* Pixel/line selection for color separation */ 179 {0x0018, 0x8601}, /* Pixel/line selection for color separation */
289 {0x0000, 0x8602}, /* Optical black level for user setting */ 180 {0x0000, 0x8602}, /* Optical black level for user setting */
290 {0x0060, 0x8604}, /* Optical black horizontal offset */ 181 {0x0060, 0x8604}, /* Optical black horizontal offset */
@@ -309,10 +200,11 @@ static const __u16 spca561_init_data[][2] = {
309 {0x0004, 0x8612}, /* Gr offset for white balance */ 200 {0x0004, 0x8612}, /* Gr offset for white balance */
310 {0x0007, 0x8613}, /* B offset for white balance */ 201 {0x0007, 0x8613}, /* B offset for white balance */
311 {0x0000, 0x8614}, /* Gb offset for white balance */ 202 {0x0000, 0x8614}, /* Gb offset for white balance */
312 {0x008c, 0x8651}, /* R gain for white balance */ 203/* from ms-win */
313 {0x008c, 0x8652}, /* Gr gain for white balance */ 204 {0x0035, 0x8651}, /* R gain for white balance */
314 {0x00b5, 0x8653}, /* B gain for white balance */ 205 {0x0040, 0x8652}, /* Gr gain for white balance */
315 {0x008c, 0x8654}, /* Gb gain for white balance */ 206 {0x005f, 0x8653}, /* B gain for white balance */
207 {0x0040, 0x8654}, /* Gb gain for white balance */
316 {0x0002, 0x8502}, /* Maximum average bit rate stuff */ 208 {0x0002, 0x8502}, /* Maximum average bit rate stuff */
317 209
318 {0x0011, 0x8802}, 210 {0x0011, 0x8802},
@@ -324,29 +216,22 @@ static const __u16 spca561_init_data[][2] = {
324 216
325 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */ 217 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
326 {0x0003, 0x865c}, /* Vertical offset for valid lines */ 218 {0x0003, 0x865c}, /* Vertical offset for valid lines */
327 /***************//* sensor active */ 219 {}
328 {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */ 220};
329 {0x0021, 0x8805}, 221static const __u16 rev72a_init_sensor2[][2] = {
330 {0x0001, 0x8800}, 222 /* ms-win values */
331 {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */ 223 {0x0003, 0x0121}, /* 0x03 <- 0x01 0x21 //289 */
332 {0x0065, 0x8805}, 224 {0x0004, 0x0165}, /* 0x04 <- 0x01 0x65 //357 */
333 {0x0001, 0x8800}, 225 {0x0005, 0x002f}, /* 0x05 <- 0x2f */
334 {0x0005, 0x8801}, /* 0x05 <- 0x2f */ 226 {0x0006, 0x0000}, /* 0x06 <- 0 */
335 {0x002f, 0x8805}, 227 {0x000a, 0x0002}, /* 0x0a <- 2 */
336 {0x0000, 0x8800}, 228 {0x0009, 0x1061}, /* 0x09 <- 0x1061 */
337 {0x0006, 0x8801}, /* 0x06 <- 0 */ 229 {0x0035, 0x0014}, /* 0x35 <- 0x14 */
338 {0x0000, 0x8805}, 230 {}
339 {0x0000, 0x8800}, 231};
340 {0x000a, 0x8801}, /* 0x0a <- 2 */ 232static const __u16 rev72a_init_data3[][2] = {
341 {0x0002, 0x8805},
342 {0x0000, 0x8800},
343 {0x0009, 0x8801}, /* 0x09 <- 0x1061 */
344 {0x0061, 0x8805},
345 {0x0010, 0x8800},
346 {0x0035, 0x8801}, /* 0x35 <-0x14 */
347 {0x0014, 0x8805},
348 {0x0000, 0x8800},
349 {0x0030, 0x8112}, /* ISO and drop packet enable */ 233 {0x0030, 0x8112}, /* ISO and drop packet enable */
234/*fixme: should stop here*/
350 {0x0000, 0x8112}, /* Some kind of reset ???? */ 235 {0x0000, 0x8112}, /* Some kind of reset ???? */
351 {0x0009, 0x8118}, /* Enable sensor and set standby */ 236 {0x0009, 0x8118}, /* Enable sensor and set standby */
352 {0x0000, 0x8114}, /* Software GPIO output data */ 237 {0x0000, 0x8114}, /* Software GPIO output data */
@@ -434,7 +319,6 @@ static const __u16 spca561_init_data[][2] = {
434 {} 319 {}
435}; 320};
436 321
437
438/******************** QC Express etch2 stuff ********************/ 322/******************** QC Express etch2 stuff ********************/
439static const __u16 Pb100_1map8300[][2] = { 323static const __u16 Pb100_1map8300[][2] = {
440 /* reg, value */ 324 /* reg, value */
@@ -515,22 +399,112 @@ static const __u16 spca561_161rev12A_data2[][2] = {
515 {} 399 {}
516}; 400};
517 401
518static void sensor_mapwrite(struct gspca_dev *gspca_dev, 402static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
519 const __u16 sensormap[][2]) 403{
404 int ret;
405
406 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
407 0, /* request */
408 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
409 value, index, NULL, 0, 500);
410 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
411 if (ret < 0)
412 PDEBUG(D_ERR, "reg write: error %d", ret);
413}
414
415static void write_vector(struct gspca_dev *gspca_dev,
416 const __u16 data[][2])
520{ 417{
521 int i = 0; 418 struct usb_device *dev = gspca_dev->dev;
522 __u8 usbval[2]; 419 int i;
523 420
524 while (sensormap[i][0]) { 421 i = 0;
525 usbval[0] = sensormap[i][1]; 422 while (data[i][1] != 0) {
526 usbval[1] = sensormap[i][1] >> 8; 423 reg_w_val(dev, data[i][1], data[i][0]);
527 reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2);
528 i++; 424 i++;
529 } 425 }
530} 426}
427
428/* read 'len' bytes to gspca_dev->usb_buf */
429static void reg_r(struct gspca_dev *gspca_dev,
430 __u16 index, __u16 length)
431{
432 usb_control_msg(gspca_dev->dev,
433 usb_rcvctrlpipe(gspca_dev->dev, 0),
434 0, /* request */
435 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
436 0, /* value */
437 index, gspca_dev->usb_buf, length, 500);
438}
439
440/* write 'len' bytes from gspca_dev->usb_buf */
441static void reg_w_buf(struct gspca_dev *gspca_dev,
442 __u16 index, __u16 len)
443{
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, /* value */
449 index, gspca_dev->usb_buf, len, 500);
450}
451
452static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
453{
454 int retry = 60;
455
456 reg_w_val(gspca_dev->dev, 0x8801, reg);
457 reg_w_val(gspca_dev->dev, 0x8805, value);
458 reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
459 do {
460 reg_r(gspca_dev, 0x8803, 1);
461 if (!gspca_dev->usb_buf[0])
462 return;
463 } while (--retry);
464}
465
466static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
467{
468 int retry = 60;
469 __u8 value;
470
471 reg_w_val(gspca_dev->dev, 0x8804, 0x92);
472 reg_w_val(gspca_dev->dev, 0x8801, reg);
473 reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
474 do {
475 reg_r(gspca_dev, 0x8803, 1);
476 if (!gspca_dev->usb_buf[0]) {
477 reg_r(gspca_dev, 0x8800, 1);
478 value = gspca_dev->usb_buf[0];
479 reg_r(gspca_dev, 0x8805, 1);
480 return ((int) value << 8) | gspca_dev->usb_buf[0];
481 }
482 } while (--retry);
483 return -1;
484}
485
486static void sensor_mapwrite(struct gspca_dev *gspca_dev,
487 const __u16 (*sensormap)[2])
488{
489 while ((*sensormap)[0]) {
490 gspca_dev->usb_buf[0] = (*sensormap)[1];
491 gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
492 reg_w_buf(gspca_dev, (*sensormap)[0], 2);
493 sensormap++;
494 }
495}
496
497static void write_sensor_72a(struct gspca_dev *gspca_dev,
498 const __u16 (*sensor)[2])
499{
500 while ((*sensor)[0]) {
501 i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
502 sensor++;
503 }
504}
505
531static void init_161rev12A(struct gspca_dev *gspca_dev) 506static void init_161rev12A(struct gspca_dev *gspca_dev)
532{ 507{
533/* sensor_reset(gspca_dev); (not in win) */
534 write_vector(gspca_dev, spca561_161rev12A_data1); 508 write_vector(gspca_dev, spca561_161rev12A_data1);
535 sensor_mapwrite(gspca_dev, Pb100_1map8300); 509 sensor_mapwrite(gspca_dev, Pb100_1map8300);
536/*fixme: should be in sd_start*/ 510/*fixme: should be in sd_start*/
@@ -598,49 +572,68 @@ static int sd_init_12a(struct gspca_dev *gspca_dev)
598static int sd_init_72a(struct gspca_dev *gspca_dev) 572static int sd_init_72a(struct gspca_dev *gspca_dev)
599{ 573{
600 PDEBUG(D_STREAM, "Chip revision: 072a"); 574 PDEBUG(D_STREAM, "Chip revision: 072a");
601 write_vector(gspca_dev, spca561_init_data); 575 write_vector(gspca_dev, rev72a_init_data1);
576 write_sensor_72a(gspca_dev, rev72a_init_sensor1);
577 write_vector(gspca_dev, rev72a_init_data2);
578 write_sensor_72a(gspca_dev, rev72a_init_sensor2);
579 write_vector(gspca_dev, rev72a_init_data3);
602 return 0; 580 return 0;
603} 581}
604 582
605static void setcontrast(struct gspca_dev *gspca_dev) 583/* rev 72a only */
584static void setbrightness(struct gspca_dev *gspca_dev)
606{ 585{
607 struct sd *sd = (struct sd *) gspca_dev; 586 struct sd *sd = (struct sd *) gspca_dev;
608 struct usb_device *dev = gspca_dev->dev; 587 struct usb_device *dev = gspca_dev->dev;
609 __u8 lowb; 588 __u8 value;
610 589
611 switch (sd->chip_revision) { 590 value = sd->brightness;
612 case Rev072A:
613 lowb = sd->contrast >> 8;
614 reg_w_val(dev, 0x8651, lowb);
615 reg_w_val(dev, 0x8652, lowb);
616 reg_w_val(dev, 0x8653, lowb);
617 reg_w_val(dev, 0x8654, lowb);
618 break;
619 default: {
620/* case Rev012A: { */
621 static const __u8 Reg8391[] =
622 { 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
623 591
624 reg_w_buf(gspca_dev, 0x8391, Reg8391, 8); 592 /* offsets for white balance */
625 reg_w_buf(gspca_dev, 0x8390, Reg8391, 8); 593 reg_w_val(dev, 0x8611, value); /* R */
626 break; 594 reg_w_val(dev, 0x8612, value); /* Gr */
627 } 595 reg_w_val(dev, 0x8613, value); /* B */
628 } 596 reg_w_val(dev, 0x8614, value); /* Gb */
629} 597}
630 598
631/* rev12a only */
632static void setwhite(struct gspca_dev *gspca_dev) 599static void setwhite(struct gspca_dev *gspca_dev)
633{ 600{
634 struct sd *sd = (struct sd *) gspca_dev; 601 struct sd *sd = (struct sd *) gspca_dev;
635 __u16 white; 602 __u16 white;
636 __u8 reg8614, reg8616; 603 __u8 blue, red;
604 __u16 reg;
637 605
638 white = sd->white;
639 /* try to emulate MS-win as possible */ 606 /* try to emulate MS-win as possible */
640 reg8616 = 0x90 - white * 5 / 8; 607 white = sd->white;
641 reg_w_val(gspca_dev->dev, 0x8616, reg8616); 608 red = 0x20 + white * 3 / 8;
642 reg8614 = 0x20 + white * 3 / 8; 609 blue = 0x90 - white * 5 / 8;
643 reg_w_val(gspca_dev->dev, 0x8614, reg8614); 610 if (sd->chip_revision == Rev012A) {
611 reg = 0x8614;
612 } else {
613 reg = 0x8651;
614 red += sd->contrast - 0x20;
615 blue += sd->contrast - 0x20;
616 }
617 reg_w_val(gspca_dev->dev, reg, red);
618 reg_w_val(gspca_dev->dev, reg + 2, blue);
619}
620
621static void setcontrast(struct gspca_dev *gspca_dev)
622{
623 struct sd *sd = (struct sd *) gspca_dev;
624 struct usb_device *dev = gspca_dev->dev;
625 __u8 value;
626
627 if (sd->chip_revision != Rev072A)
628 return;
629 value = sd->contrast + 0x20;
630
631 /* gains for white balance */
632 setwhite(gspca_dev);
633/* reg_w_val(dev, 0x8651, value); * R - done by setwhite */
634 reg_w_val(dev, 0x8652, value); /* Gr */
635/* reg_w_val(dev, 0x8653, value); * B - done by setwhite */
636 reg_w_val(dev, 0x8654, value); /* Gb */
644} 637}
645 638
646/* rev 12a only */ 639/* rev 12a only */
@@ -649,7 +642,6 @@ static void setexposure(struct gspca_dev *gspca_dev)
649 struct sd *sd = (struct sd *) gspca_dev; 642 struct sd *sd = (struct sd *) gspca_dev;
650 int expo; 643 int expo;
651 int clock_divider; 644 int clock_divider;
652 __u8 data[2];
653 645
654 /* Register 0x8309 controls exposure for the spca561, 646 /* Register 0x8309 controls exposure for the spca561,
655 the basic exposure setting goes from 1-2047, where 1 is completely 647 the basic exposure setting goes from 1-2047, where 1 is completely
@@ -673,20 +665,19 @@ static void setexposure(struct gspca_dev *gspca_dev)
673 clock_divider = 3; 665 clock_divider = 3;
674 } 666 }
675 expo |= clock_divider << 11; 667 expo |= clock_divider << 11;
676 data[0] = expo; 668 gspca_dev->usb_buf[0] = expo;
677 data[1] = expo >> 8; 669 gspca_dev->usb_buf[1] = expo >> 8;
678 reg_w_buf(gspca_dev, 0x8309, data, 2); 670 reg_w_buf(gspca_dev, 0x8309, 2);
679} 671}
680 672
681/* rev 12a only */ 673/* rev 12a only */
682static void setgain(struct gspca_dev *gspca_dev) 674static void setgain(struct gspca_dev *gspca_dev)
683{ 675{
684 struct sd *sd = (struct sd *) gspca_dev; 676 struct sd *sd = (struct sd *) gspca_dev;
685 __u8 data[2];
686 677
687 data[0] = sd->gain; 678 gspca_dev->usb_buf[0] = sd->gain;
688 data[1] = 0; 679 gspca_dev->usb_buf[1] = 0;
689 reg_w_buf(gspca_dev, 0x8335, data, 2); 680 reg_w_buf(gspca_dev, 0x8335, 2);
690} 681}
691 682
692static void setautogain(struct gspca_dev *gspca_dev) 683static void setautogain(struct gspca_dev *gspca_dev)
@@ -702,9 +693,9 @@ static void setautogain(struct gspca_dev *gspca_dev)
702static int sd_start_12a(struct gspca_dev *gspca_dev) 693static int sd_start_12a(struct gspca_dev *gspca_dev)
703{ 694{
704 struct usb_device *dev = gspca_dev->dev; 695 struct usb_device *dev = gspca_dev->dev;
705 int Clck = 0x8a; /* lower 0x8X values lead to fps > 30 */
706 __u8 Reg8307[] = { 0xaa, 0x00 };
707 int mode; 696 int mode;
697 static const __u8 Reg8391[8] =
698 {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
708 699
709 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; 700 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
710 if (mode <= 1) { 701 if (mode <= 1) {
@@ -716,14 +707,21 @@ static int sd_start_12a(struct gspca_dev *gspca_dev)
716 * is sufficient to push raw frames at ~20fps */ 707 * is sufficient to push raw frames at ~20fps */
717 reg_w_val(dev, 0x8500, mode); 708 reg_w_val(dev, 0x8500, mode);
718 } /* -- qq@kuku.eu.org */ 709 } /* -- qq@kuku.eu.org */
719 reg_w_buf(gspca_dev, 0x8307, Reg8307, 2); 710
720 reg_w_val(gspca_dev->dev, 0x8700, Clck); 711 gspca_dev->usb_buf[0] = 0xaa;
712 gspca_dev->usb_buf[1] = 0x00;
713 reg_w_buf(gspca_dev, 0x8307, 2);
714 /* clock - lower 0x8X values lead to fps > 30 */
715 reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
721 /* 0x8f 0x85 0x27 clock */ 716 /* 0x8f 0x85 0x27 clock */
722 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20); 717 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
723 reg_w_val(gspca_dev->dev, 0x850b, 0x03); 718 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
724 setcontrast(gspca_dev); 719 memcpy(gspca_dev->usb_buf, Reg8391, 8);
720 reg_w_buf(gspca_dev, 0x8391, 8);
721 reg_w_buf(gspca_dev, 0x8390, 8);
725 setwhite(gspca_dev); 722 setwhite(gspca_dev);
726 setautogain(gspca_dev); 723 setautogain(gspca_dev);
724/* setgain(gspca_dev); */
727 setexposure(gspca_dev); 725 setexposure(gspca_dev);
728 return 0; 726 return 0;
729} 727}
@@ -750,6 +748,9 @@ static int sd_start_72a(struct gspca_dev *gspca_dev)
750 reg_w_val(dev, 0x8500, mode); /* mode */ 748 reg_w_val(dev, 0x8500, mode); /* mode */
751 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */ 749 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
752 reg_w_val(dev, 0x8112, 0x10 | 0x20); 750 reg_w_val(dev, 0x8112, 0x10 | 0x20);
751 setcontrast(gspca_dev);
752/* setbrightness(gspca_dev); * fixme: bad values */
753 setwhite(gspca_dev);
753 setautogain(gspca_dev); 754 setautogain(gspca_dev);
754 return 0; 755 return 0;
755} 756}
@@ -791,7 +792,6 @@ static void do_autogain(struct gspca_dev *gspca_dev)
791 __u8 luma_mean = 110; 792 __u8 luma_mean = 110;
792 __u8 luma_delta = 20; 793 __u8 luma_delta = 20;
793 __u8 spring = 4; 794 __u8 spring = 4;
794 __u8 reg8339[2];
795 795
796 if (sd->ag_cnt < 0) 796 if (sd->ag_cnt < 0)
797 return; 797 return;
@@ -834,13 +834,13 @@ static void do_autogain(struct gspca_dev *gspca_dev)
834 834
835 if (gainG > 0x3f) 835 if (gainG > 0x3f)
836 gainG = 0x3f; 836 gainG = 0x3f;
837 else if (gainG < 4) 837 else if (gainG < 3)
838 gainG = 3; 838 gainG = 3;
839 i2c_write(gspca_dev, gainG, 0x35); 839 i2c_write(gspca_dev, gainG, 0x35);
840 840
841 if (expotimes >= 0x0256) 841 if (expotimes > 0x0256)
842 expotimes = 0x0256; 842 expotimes = 0x0256;
843 else if (expotimes < 4) 843 else if (expotimes < 3)
844 expotimes = 3; 844 expotimes = 3;
845 i2c_write(gspca_dev, expotimes | pixelclk, 0x09); 845 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
846 } 846 }
@@ -848,13 +848,13 @@ static void do_autogain(struct gspca_dev *gspca_dev)
848 case Rev012A: 848 case Rev012A:
849 reg_r(gspca_dev, 0x8330, 2); 849 reg_r(gspca_dev, 0x8330, 2);
850 if (gspca_dev->usb_buf[1] > 0x08) { 850 if (gspca_dev->usb_buf[1] > 0x08) {
851 reg8339[0] = ++sd->expo12a; 851 gspca_dev->usb_buf[0] = ++sd->expo12a;
852 reg8339[1] = 0; 852 gspca_dev->usb_buf[1] = 0;
853 reg_w_buf(gspca_dev, 0x8339, reg8339, 2); 853 reg_w_buf(gspca_dev, 0x8339, 2);
854 } else if (gspca_dev->usb_buf[1] < 0x02) { 854 } else if (gspca_dev->usb_buf[1] < 0x02) {
855 reg8339[0] = --sd->expo12a; 855 gspca_dev->usb_buf[0] = --sd->expo12a;
856 reg8339[1] = 0; 856 gspca_dev->usb_buf[1] = 0;
857 reg_w_buf(gspca_dev, 0x8339, reg8339, 2); 857 reg_w_buf(gspca_dev, 0x8339, 2);
858 } 858 }
859 break; 859 break;
860 } 860 }
@@ -867,8 +867,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
867{ 867{
868 struct sd *sd = (struct sd *) gspca_dev; 868 struct sd *sd = (struct sd *) gspca_dev;
869 869
870 switch (data[0]) { 870 switch (data[0]) { /* sequence number */
871 case 0: /* start of frame */ 871 case 0: /* start of frame */
872 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 872 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
873 data, 0); 873 data, 0);
874 data += SPCA561_OFFSET_DATA; 874 data += SPCA561_OFFSET_DATA;
@@ -890,8 +890,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
890 frame, data, len); 890 frame, data, len);
891 } 891 }
892 return; 892 return;
893 case 0xff: /* drop */ 893 case 0xff: /* drop (empty mpackets) */
894/* gspca_dev->last_packet_type = DISCARD_PACKET; */
895 return; 894 return;
896 } 895 }
897 data++; 896 data++;
@@ -900,55 +899,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
900} 899}
901 900
902/* rev 72a only */ 901/* rev 72a only */
903static void setbrightness(struct gspca_dev *gspca_dev)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906 __u8 value;
907
908 value = sd->brightness;
909 reg_w_val(gspca_dev->dev, 0x8611, value);
910 reg_w_val(gspca_dev->dev, 0x8612, value);
911 reg_w_val(gspca_dev->dev, 0x8613, value);
912 reg_w_val(gspca_dev->dev, 0x8614, value);
913}
914
915static void getbrightness(struct gspca_dev *gspca_dev)
916{
917 struct sd *sd = (struct sd *) gspca_dev;
918 __u16 tot;
919
920 tot = 0;
921 reg_r(gspca_dev, 0x8611, 1);
922 tot += gspca_dev->usb_buf[0];
923 reg_r(gspca_dev, 0x8612, 1);
924 tot += gspca_dev->usb_buf[0];
925 reg_r(gspca_dev, 0x8613, 1);
926 tot += gspca_dev->usb_buf[0];
927 reg_r(gspca_dev, 0x8614, 1);
928 tot += gspca_dev->usb_buf[0];
929 sd->brightness = tot >> 2;
930}
931
932/* rev72a only */
933static void getcontrast(struct gspca_dev *gspca_dev)
934{
935 struct sd *sd = (struct sd *) gspca_dev;
936 __u16 tot;
937
938 tot = 0;
939 reg_r(gspca_dev, 0x8651, 1);
940 tot += gspca_dev->usb_buf[0];
941 reg_r(gspca_dev, 0x8652, 1);
942 tot += gspca_dev->usb_buf[0];
943 reg_r(gspca_dev, 0x8653, 1);
944 tot += gspca_dev->usb_buf[0];
945 reg_r(gspca_dev, 0x8654, 1);
946 tot += gspca_dev->usb_buf[0];
947 sd->contrast = tot << 6;
948 PDEBUG(D_CONF, "get contrast %d", sd->contrast);
949}
950
951/* rev 72a only */
952static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 902static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
953{ 903{
954 struct sd *sd = (struct sd *) gspca_dev; 904 struct sd *sd = (struct sd *) gspca_dev;
@@ -963,7 +913,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
963{ 913{
964 struct sd *sd = (struct sd *) gspca_dev; 914 struct sd *sd = (struct sd *) gspca_dev;
965 915
966 getbrightness(gspca_dev);
967 *val = sd->brightness; 916 *val = sd->brightness;
968 return 0; 917 return 0;
969} 918}
@@ -983,7 +932,6 @@ static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
983{ 932{
984 struct sd *sd = (struct sd *) gspca_dev; 933 struct sd *sd = (struct sd *) gspca_dev;
985 934
986 getcontrast(gspca_dev);
987 *val = sd->contrast; 935 *val = sd->contrast;
988 return 0; 936 return 0;
989} 937}
@@ -1006,7 +954,6 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1006 return 0; 954 return 0;
1007} 955}
1008 956
1009/* rev12a only */
1010static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val) 957static int sd_setwhite(struct gspca_dev *gspca_dev, __s32 val)
1011{ 958{
1012 struct sd *sd = (struct sd *) gspca_dev; 959 struct sd *sd = (struct sd *) gspca_dev;
@@ -1121,6 +1068,19 @@ static struct ctrl sd_ctrls_12a[] = {
1121 1068
1122static struct ctrl sd_ctrls_72a[] = { 1069static struct ctrl sd_ctrls_72a[] = {
1123 { 1070 {
1071 {
1072 .id = V4L2_CID_DO_WHITE_BALANCE,
1073 .type = V4L2_CTRL_TYPE_INTEGER,
1074 .name = "White Balance",
1075 .minimum = WHITE_MIN,
1076 .maximum = WHITE_MAX,
1077 .step = 1,
1078 .default_value = WHITE_DEF,
1079 },
1080 .set = sd_setwhite,
1081 .get = sd_getwhite,
1082 },
1083 {
1124 { 1084 {
1125 .id = V4L2_CID_BRIGHTNESS, 1085 .id = V4L2_CID_BRIGHTNESS,
1126 .type = V4L2_CTRL_TYPE_INTEGER, 1086 .type = V4L2_CTRL_TYPE_INTEGER,