V4L/DVB (11695): gspca - stv06xx-vv6410: Set analog gain at init
[safe/jmp/linux-2.6] / drivers / media / video / gspca / stv06xx / stv06xx_pb0100.c
1 /*
2  * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
3  *                    Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
4  * Copyright (c) 2002, 2003 Tuukka Toivonen
5  * Copyright (c) 2008 Erik AndrĂ©n
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * P/N 861037:      Sensor HDCS1000        ASIC STV0600
22  * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
23  * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
24  * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
25  * P/N 861075-0040: Sensor HDCS1000        ASIC
26  * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
27  * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
28  */
29
30 /*
31  * The spec file for the PB-0100 suggests the following for best quality
32  * images after the sensor has been reset :
33  *
34  * PB_ADCGAINL      = R60 = 0x03 (3 dec)      : sets low reference of ADC
35                                                 to produce good black level
36  * PB_PREADCTRL     = R32 = 0x1400 (5120 dec) : Enables global gain changes
37                                                 through R53
38  * PB_ADCMINGAIN    = R52 = 0x10 (16 dec)     : Sets the minimum gain for
39                                                 auto-exposure
40  * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec)     : Sets the global gain
41  * PB_EXPGAIN       = R14 = 0x11 (17 dec)     : Sets the auto-exposure value
42  * PB_UPDATEINT     = R23 = 0x02 (2 dec)      : Sets the speed on
43                                                 auto-exposure routine
44  * PB_CFILLIN       = R5  = 0x0E (14 dec)     : Sets the frame rate
45  */
46
47 #include "stv06xx_pb0100.h"
48
49 static const struct ctrl pb0100_ctrl[] = {
50 #define GAIN_IDX 0
51         {
52                 {
53                         .id             = V4L2_CID_GAIN,
54                         .type           = V4L2_CTRL_TYPE_INTEGER,
55                         .name           = "Gain",
56                         .minimum        = 0,
57                         .maximum        = 255,
58                         .step           = 1,
59                         .default_value  = 128
60                 },
61                 .set = pb0100_set_gain,
62                 .get = pb0100_get_gain
63         },
64 #define RED_BALANCE_IDX 1
65         {
66                 {
67                         .id             = V4L2_CID_RED_BALANCE,
68                         .type           = V4L2_CTRL_TYPE_INTEGER,
69                         .name           = "Red Balance",
70                         .minimum        = -255,
71                         .maximum        = 255,
72                         .step           = 1,
73                         .default_value  = 0
74                 },
75                 .set = pb0100_set_red_balance,
76                 .get = pb0100_get_red_balance
77         },
78 #define BLUE_BALANCE_IDX 2
79         {
80                 {
81                         .id             = V4L2_CID_BLUE_BALANCE,
82                         .type           = V4L2_CTRL_TYPE_INTEGER,
83                         .name           = "Blue Balance",
84                         .minimum        = -255,
85                         .maximum        = 255,
86                         .step           = 1,
87                         .default_value  = 0
88                 },
89                 .set = pb0100_set_blue_balance,
90                 .get = pb0100_get_blue_balance
91         },
92 #define EXPOSURE_IDX 3
93         {
94                 {
95                         .id             = V4L2_CID_EXPOSURE,
96                         .type           = V4L2_CTRL_TYPE_INTEGER,
97                         .name           = "Exposure",
98                         .minimum        = 0,
99                         .maximum        = 511,
100                         .step           = 1,
101                         .default_value  = 12
102                 },
103                 .set = pb0100_set_exposure,
104                 .get = pb0100_get_exposure
105         },
106 #define AUTOGAIN_IDX 4
107         {
108                 {
109                         .id             = V4L2_CID_AUTOGAIN,
110                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
111                         .name           = "Automatic Gain and Exposure",
112                         .minimum        = 0,
113                         .maximum        = 1,
114                         .step           = 1,
115                         .default_value  = 1
116                 },
117                 .set = pb0100_set_autogain,
118                 .get = pb0100_get_autogain
119         },
120 #define AUTOGAIN_TARGET_IDX 5
121         {
122                 {
123                         .id             = V4L2_CTRL_CLASS_USER + 0x1000,
124                         .type           = V4L2_CTRL_TYPE_INTEGER,
125                         .name           = "Automatic Gain Target",
126                         .minimum        = 0,
127                         .maximum        = 255,
128                         .step           = 1,
129                         .default_value  = 128
130                 },
131                 .set = pb0100_set_autogain_target,
132                 .get = pb0100_get_autogain_target
133         },
134 #define NATURAL_IDX 6
135         {
136                 {
137                         .id             = V4L2_CTRL_CLASS_USER + 0x1001,
138                         .type           = V4L2_CTRL_TYPE_BOOLEAN,
139                         .name           = "Natural Light Source",
140                         .minimum        = 0,
141                         .maximum        = 1,
142                         .step           = 1,
143                         .default_value  = 1
144                 },
145                 .set = pb0100_set_natural,
146                 .get = pb0100_get_natural
147         }
148 };
149
150 static struct v4l2_pix_format pb0100_mode[] = {
151 /* low res / subsample modes disabled as they are only half res horizontal,
152    halving the vertical resolution does not seem to work */
153         {
154                 320,
155                 240,
156                 V4L2_PIX_FMT_SGRBG8,
157                 V4L2_FIELD_NONE,
158                 .sizeimage = 320 * 240,
159                 .bytesperline = 320,
160                 .colorspace = V4L2_COLORSPACE_SRGB,
161                 .priv = PB0100_CROP_TO_VGA
162         },
163         {
164                 352,
165                 288,
166                 V4L2_PIX_FMT_SGRBG8,
167                 V4L2_FIELD_NONE,
168                 .sizeimage = 352 * 288,
169                 .bytesperline = 352,
170                 .colorspace = V4L2_COLORSPACE_SRGB,
171                 .priv = 0
172         }
173 };
174
175 static int pb0100_probe(struct sd *sd)
176 {
177         u16 sensor;
178         int i, err;
179         s32 *sensor_settings;
180
181         err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
182
183         if (err < 0)
184                 return -ENODEV;
185
186         if ((sensor >> 8) == 0x64) {
187                 sensor_settings = kmalloc(
188                                 ARRAY_SIZE(pb0100_ctrl) * sizeof(s32),
189                                 GFP_KERNEL);
190                 if (!sensor_settings)
191                         return -ENOMEM;
192
193                 info("Photobit pb0100 sensor detected");
194
195                 sd->gspca_dev.cam.cam_mode = pb0100_mode;
196                 sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
197                 sd->desc.ctrls = pb0100_ctrl;
198                 sd->desc.nctrls = ARRAY_SIZE(pb0100_ctrl);
199                 for (i = 0; i < sd->desc.nctrls; i++)
200                         sensor_settings[i] = pb0100_ctrl[i].qctrl.default_value;
201                 sd->sensor_priv = sensor_settings;
202
203                 return 0;
204         }
205
206         return -ENODEV;
207 }
208
209 static int pb0100_start(struct sd *sd)
210 {
211         int err;
212         struct cam *cam = &sd->gspca_dev.cam;
213         s32 *sensor_settings = sd->sensor_priv;
214         u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
215
216         /* Setup sensor window */
217         if (mode & PB0100_CROP_TO_VGA) {
218                 stv06xx_write_sensor(sd, PB_RSTART, 30);
219                 stv06xx_write_sensor(sd, PB_CSTART, 20);
220                 stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
221                 stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
222         } else {
223                 stv06xx_write_sensor(sd, PB_RSTART, 8);
224                 stv06xx_write_sensor(sd, PB_CSTART, 4);
225                 stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
226                 stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
227         }
228
229         if (mode & PB0100_SUBSAMPLE) {
230                 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
231                 stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
232
233                 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
234         } else {
235                 stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
236                 stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
237                 /* larger -> slower */
238                 stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
239         }
240
241         /* set_gain also sets red and blue balance */
242         pb0100_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
243         pb0100_set_exposure(&sd->gspca_dev, sensor_settings[EXPOSURE_IDX]);
244         pb0100_set_autogain_target(&sd->gspca_dev,
245                                    sensor_settings[AUTOGAIN_TARGET_IDX]);
246         pb0100_set_autogain(&sd->gspca_dev, sensor_settings[AUTOGAIN_IDX]);
247
248         err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
249         PDEBUG(D_STREAM, "Started stream, status: %d", err);
250
251         return (err < 0) ? err : 0;
252 }
253
254 static int pb0100_stop(struct sd *sd)
255 {
256         int err;
257
258         err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
259
260         if (err < 0)
261                 goto out;
262
263         /* Set bit 1 to zero */
264         err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
265
266         PDEBUG(D_STREAM, "Halting stream");
267 out:
268         return (err < 0) ? err : 0;
269 }
270
271 static void pb0100_disconnect(struct sd *sd)
272 {
273         sd->sensor = NULL;
274         kfree(sd->sensor_priv);
275 }
276
277 /* FIXME: Sort the init commands out and put them into tables,
278           this is only for getting the camera to work */
279 /* FIXME: No error handling for now,
280           add this once the init has been converted to proper tables */
281 static int pb0100_init(struct sd *sd)
282 {
283         stv06xx_write_bridge(sd, STV_REG00, 1);
284         stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
285
286         /* Reset sensor */
287         stv06xx_write_sensor(sd, PB_RESET, 1);
288         stv06xx_write_sensor(sd, PB_RESET, 0);
289
290         /* Disable chip */
291         stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
292
293         /* Gain stuff...*/
294         stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
295         stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
296
297         /* Set up auto-exposure */
298         /* ADC VREF_HI new setting for a transition
299           from the Expose1 to the Expose2 setting */
300         stv06xx_write_sensor(sd, PB_R28, 12);
301         /* gain max for autoexposure */
302         stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
303         /* gain min for autoexposure  */
304         stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
305         /* Maximum frame integration time (programmed into R8)
306            allowed for auto-exposure routine */
307         stv06xx_write_sensor(sd, PB_R54, 3);
308         /* Minimum frame integration time (programmed into R8)
309            allowed for auto-exposure routine */
310         stv06xx_write_sensor(sd, PB_R55, 0);
311         stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
312         /* R15  Expose0 (maximum that auto-exposure may use) */
313         stv06xx_write_sensor(sd, PB_R15, 800);
314         /* R17  Expose2 (minimum that auto-exposure may use) */
315         stv06xx_write_sensor(sd, PB_R17, 10);
316
317         stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
318
319         /* 0x14 */
320         stv06xx_write_sensor(sd, PB_VOFFSET, 0);
321         /* 0x0D */
322         stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
323         /* Set black level (important!) */
324         stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
325
326         /* ??? */
327         stv06xx_write_bridge(sd, STV_REG00, 0x11);
328         stv06xx_write_bridge(sd, STV_REG03, 0x45);
329         stv06xx_write_bridge(sd, STV_REG04, 0x07);
330
331         /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */
332         stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847);
333
334         /* Scan/timing for the sensor */
335         stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
336         stv06xx_write_sensor(sd, PB_CFILLIN, 14);
337         stv06xx_write_sensor(sd, PB_VBL, 0);
338         stv06xx_write_sensor(sd, PB_FINTTIME, 0);
339         stv06xx_write_sensor(sd, PB_RINTTIME, 123);
340
341         stv06xx_write_bridge(sd, STV_REG01, 0xc2);
342         stv06xx_write_bridge(sd, STV_REG02, 0xb0);
343         return 0;
344 }
345
346 static int pb0100_dump(struct sd *sd)
347 {
348         return 0;
349 }
350
351 static int pb0100_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
352 {
353         struct sd *sd = (struct sd *) gspca_dev;
354         s32 *sensor_settings = sd->sensor_priv;
355
356         *val = sensor_settings[GAIN_IDX];
357
358         return 0;
359 }
360
361 static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
362 {
363         int err;
364         struct sd *sd = (struct sd *) gspca_dev;
365         s32 *sensor_settings = sd->sensor_priv;
366
367         if (sensor_settings[AUTOGAIN_IDX])
368                 return -EBUSY;
369
370         sensor_settings[GAIN_IDX] = val;
371         err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
372         if (!err)
373                 err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
374         PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
375
376         if (!err)
377                 err = pb0100_set_red_balance(gspca_dev,
378                                              sensor_settings[RED_BALANCE_IDX]);
379         if (!err)
380                 err = pb0100_set_blue_balance(gspca_dev,
381                                             sensor_settings[BLUE_BALANCE_IDX]);
382
383         return err;
384 }
385
386 static int pb0100_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
387 {
388         struct sd *sd = (struct sd *) gspca_dev;
389         s32 *sensor_settings = sd->sensor_priv;
390
391         *val = sensor_settings[RED_BALANCE_IDX];
392
393         return 0;
394 }
395
396 static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
397 {
398         int err;
399         struct sd *sd = (struct sd *) gspca_dev;
400         s32 *sensor_settings = sd->sensor_priv;
401
402         if (sensor_settings[AUTOGAIN_IDX])
403                 return -EBUSY;
404
405         sensor_settings[RED_BALANCE_IDX] = val;
406         val += sensor_settings[GAIN_IDX];
407         if (val < 0)
408                 val = 0;
409         else if (val > 255)
410                 val = 255;
411
412         err = stv06xx_write_sensor(sd, PB_RGAIN, val);
413         PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
414
415         return err;
416 }
417
418 static int pb0100_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
419 {
420         struct sd *sd = (struct sd *) gspca_dev;
421         s32 *sensor_settings = sd->sensor_priv;
422
423         *val = sensor_settings[BLUE_BALANCE_IDX];
424
425         return 0;
426 }
427
428 static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
429 {
430         int err;
431         struct sd *sd = (struct sd *) gspca_dev;
432         s32 *sensor_settings = sd->sensor_priv;
433
434         if (sensor_settings[AUTOGAIN_IDX])
435                 return -EBUSY;
436
437         sensor_settings[BLUE_BALANCE_IDX] = val;
438         val += sensor_settings[GAIN_IDX];
439         if (val < 0)
440                 val = 0;
441         else if (val > 255)
442                 val = 255;
443
444         err = stv06xx_write_sensor(sd, PB_BGAIN, val);
445         PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
446
447         return err;
448 }
449
450 static int pb0100_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
451 {
452         struct sd *sd = (struct sd *) gspca_dev;
453         s32 *sensor_settings = sd->sensor_priv;
454
455         *val = sensor_settings[EXPOSURE_IDX];
456
457         return 0;
458 }
459
460 static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
461 {
462         int err;
463         struct sd *sd = (struct sd *) gspca_dev;
464         s32 *sensor_settings = sd->sensor_priv;
465
466         if (sensor_settings[AUTOGAIN_IDX])
467                 return -EBUSY;
468
469         sensor_settings[EXPOSURE_IDX] = val;
470         err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
471         PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
472
473         return err;
474 }
475
476 static int pb0100_get_autogain(struct gspca_dev *gspca_dev, __s32 *val)
477 {
478         struct sd *sd = (struct sd *) gspca_dev;
479         s32 *sensor_settings = sd->sensor_priv;
480
481         *val = sensor_settings[AUTOGAIN_IDX];
482
483         return 0;
484 }
485
486 static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
487 {
488         int err;
489         struct sd *sd = (struct sd *) gspca_dev;
490         s32 *sensor_settings = sd->sensor_priv;
491
492         sensor_settings[AUTOGAIN_IDX] = val;
493         if (sensor_settings[AUTOGAIN_IDX]) {
494                 if (sensor_settings[NATURAL_IDX])
495                         val = BIT(6)|BIT(4)|BIT(0);
496                 else
497                         val = BIT(4)|BIT(0);
498         } else
499                 val = 0;
500
501         err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
502         PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
503                sensor_settings[AUTOGAIN_IDX], sensor_settings[NATURAL_IDX],
504                err);
505
506         return err;
507 }
508
509 static int pb0100_get_autogain_target(struct gspca_dev *gspca_dev, __s32 *val)
510 {
511         struct sd *sd = (struct sd *) gspca_dev;
512         s32 *sensor_settings = sd->sensor_priv;
513
514         *val = sensor_settings[AUTOGAIN_TARGET_IDX];
515
516         return 0;
517 }
518
519 static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
520 {
521         int err, totalpixels, brightpixels, darkpixels;
522         struct sd *sd = (struct sd *) gspca_dev;
523         s32 *sensor_settings = sd->sensor_priv;
524
525         sensor_settings[AUTOGAIN_TARGET_IDX] = val;
526
527         /* Number of pixels counted by the sensor when subsampling the pixels.
528          * Slightly larger than the real value to avoid oscillation */
529         totalpixels = gspca_dev->width * gspca_dev->height;
530         totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
531
532         brightpixels = (totalpixels * val) >> 8;
533         darkpixels   = totalpixels - brightpixels;
534         err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
535         if (!err)
536                 err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
537
538         PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
539
540         return err;
541 }
542
543 static int pb0100_get_natural(struct gspca_dev *gspca_dev, __s32 *val)
544 {
545         struct sd *sd = (struct sd *) gspca_dev;
546         s32 *sensor_settings = sd->sensor_priv;
547
548         *val = sensor_settings[NATURAL_IDX];
549
550         return 0;
551 }
552
553 static int pb0100_set_natural(struct gspca_dev *gspca_dev, __s32 val)
554 {
555         struct sd *sd = (struct sd *) gspca_dev;
556         s32 *sensor_settings = sd->sensor_priv;
557
558         sensor_settings[NATURAL_IDX] = val;
559
560         return pb0100_set_autogain(gspca_dev, sensor_settings[AUTOGAIN_IDX]);
561 }