Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[deliverable/linux.git] / drivers / media / video / gspca / pac7302.c
1 /*
2 * Pixart PAC7302 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * Separated from Pixart PAC7311 library by Márton Németh
8 * Camera button input handling by Márton Németh <nm127@freemail.hu>
9 * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26 /* Some documentation about various registers as determined by trial and error.
27
28 Register page 1:
29
30 Address Description
31 0x78 Global control, bit 6 controls the LED (inverted)
32
33 Register page 3:
34
35 Address Description
36 0x02 Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
37 the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
38 0x03 Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
39 0x04 Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
40 63 -> ~27 fps, the 2 msb's must always be 1 !!
41 0x05 Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
42 1 -> ~30 fps, 2 -> ~20 fps
43 0x0e Exposure bits 0-7, 0-448, 0 = use full frame time
44 0x0f Exposure bit 8, 0-448, 448 = no exposure at all
45 0x10 Master gain 0-31
46 0x21 Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
47
48 The registers are accessed in the following functions:
49
50 Page | Register | Function
51 -----+------------+---------------------------------------------------
52 0 | 0x0f..0x20 | setcolors()
53 0 | 0xa2..0xab | setbrightcont()
54 0 | 0xc5 | setredbalance()
55 0 | 0xc6 | setwhitebalance()
56 0 | 0xc7 | setbluebalance()
57 0 | 0xdc | setbrightcont(), setcolors()
58 3 | 0x02 | setexposure()
59 3 | 0x10 | setgain()
60 3 | 0x11 | setcolors(), setgain(), setexposure(), sethvflip()
61 3 | 0x21 | sethvflip()
62 */
63
64 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
65
66 #define MODULE_NAME "pac7302"
67
68 #include <linux/input.h>
69 #include <media/v4l2-chip-ident.h>
70 #include "gspca.h"
71
72 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
73 MODULE_DESCRIPTION("Pixart PAC7302");
74 MODULE_LICENSE("GPL");
75
76 /* specific webcam descriptor for pac7302 */
77 struct sd {
78 struct gspca_dev gspca_dev; /* !! must be the first item */
79
80 unsigned char brightness;
81 unsigned char contrast;
82 unsigned char colors;
83 unsigned char white_balance;
84 unsigned char red_balance;
85 unsigned char blue_balance;
86 unsigned char gain;
87 unsigned char autogain;
88 unsigned short exposure;
89 __u8 hflip;
90 __u8 vflip;
91 u8 flags;
92 #define FL_HFLIP 0x01 /* mirrored by default */
93 #define FL_VFLIP 0x02 /* vertical flipped by default */
94
95 u8 sof_read;
96 u8 autogain_ignore_frames;
97
98 atomic_t avg_lum;
99 };
100
101 /* V4L2 controls supported by the driver */
102 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
103 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
104 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
105 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
106 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
107 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
108 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
109 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
110 static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val);
111 static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val);
112 static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val);
113 static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val);
114 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
115 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
116 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
117 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
118 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
119 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
120 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
121 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
122 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
123 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
124
125 static const struct ctrl sd_ctrls[] = {
126 {
127 {
128 .id = V4L2_CID_BRIGHTNESS,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Brightness",
131 .minimum = 0,
132 #define BRIGHTNESS_MAX 0x20
133 .maximum = BRIGHTNESS_MAX,
134 .step = 1,
135 #define BRIGHTNESS_DEF 0x10
136 .default_value = BRIGHTNESS_DEF,
137 },
138 .set = sd_setbrightness,
139 .get = sd_getbrightness,
140 },
141 {
142 {
143 .id = V4L2_CID_CONTRAST,
144 .type = V4L2_CTRL_TYPE_INTEGER,
145 .name = "Contrast",
146 .minimum = 0,
147 #define CONTRAST_MAX 255
148 .maximum = CONTRAST_MAX,
149 .step = 1,
150 #define CONTRAST_DEF 127
151 .default_value = CONTRAST_DEF,
152 },
153 .set = sd_setcontrast,
154 .get = sd_getcontrast,
155 },
156 {
157 {
158 .id = V4L2_CID_SATURATION,
159 .type = V4L2_CTRL_TYPE_INTEGER,
160 .name = "Saturation",
161 .minimum = 0,
162 #define COLOR_MAX 255
163 .maximum = COLOR_MAX,
164 .step = 1,
165 #define COLOR_DEF 127
166 .default_value = COLOR_DEF,
167 },
168 .set = sd_setcolors,
169 .get = sd_getcolors,
170 },
171 {
172 {
173 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
174 .type = V4L2_CTRL_TYPE_INTEGER,
175 .name = "White Balance",
176 .minimum = 0,
177 .maximum = 255,
178 .step = 1,
179 #define WHITEBALANCE_DEF 4
180 .default_value = WHITEBALANCE_DEF,
181 },
182 .set = sd_setwhitebalance,
183 .get = sd_getwhitebalance,
184 },
185 {
186 {
187 .id = V4L2_CID_RED_BALANCE,
188 .type = V4L2_CTRL_TYPE_INTEGER,
189 .name = "Red",
190 .minimum = 0,
191 .maximum = 3,
192 .step = 1,
193 #define REDBALANCE_DEF 1
194 .default_value = REDBALANCE_DEF,
195 },
196 .set = sd_setredbalance,
197 .get = sd_getredbalance,
198 },
199 {
200 {
201 .id = V4L2_CID_BLUE_BALANCE,
202 .type = V4L2_CTRL_TYPE_INTEGER,
203 .name = "Blue",
204 .minimum = 0,
205 .maximum = 3,
206 .step = 1,
207 #define BLUEBALANCE_DEF 1
208 .default_value = BLUEBALANCE_DEF,
209 },
210 .set = sd_setbluebalance,
211 .get = sd_getbluebalance,
212 },
213 {
214 {
215 .id = V4L2_CID_GAIN,
216 .type = V4L2_CTRL_TYPE_INTEGER,
217 .name = "Gain",
218 .minimum = 0,
219 #define GAIN_MAX 255
220 .maximum = GAIN_MAX,
221 .step = 1,
222 #define GAIN_DEF 127
223 #define GAIN_KNEE 255 /* Gain seems to cause little noise on the pac73xx */
224 .default_value = GAIN_DEF,
225 },
226 .set = sd_setgain,
227 .get = sd_getgain,
228 },
229 {
230 {
231 .id = V4L2_CID_EXPOSURE,
232 .type = V4L2_CTRL_TYPE_INTEGER,
233 .name = "Exposure",
234 .minimum = 0,
235 .maximum = 1023,
236 .step = 1,
237 #define EXPOSURE_DEF 66 /* 33 ms / 30 fps */
238 #define EXPOSURE_KNEE 133 /* 66 ms / 15 fps */
239 .default_value = EXPOSURE_DEF,
240 },
241 .set = sd_setexposure,
242 .get = sd_getexposure,
243 },
244 {
245 {
246 .id = V4L2_CID_AUTOGAIN,
247 .type = V4L2_CTRL_TYPE_BOOLEAN,
248 .name = "Auto Gain",
249 .minimum = 0,
250 .maximum = 1,
251 .step = 1,
252 #define AUTOGAIN_DEF 1
253 .default_value = AUTOGAIN_DEF,
254 },
255 .set = sd_setautogain,
256 .get = sd_getautogain,
257 },
258 {
259 {
260 .id = V4L2_CID_HFLIP,
261 .type = V4L2_CTRL_TYPE_BOOLEAN,
262 .name = "Mirror",
263 .minimum = 0,
264 .maximum = 1,
265 .step = 1,
266 #define HFLIP_DEF 0
267 .default_value = HFLIP_DEF,
268 },
269 .set = sd_sethflip,
270 .get = sd_gethflip,
271 },
272 {
273 {
274 .id = V4L2_CID_VFLIP,
275 .type = V4L2_CTRL_TYPE_BOOLEAN,
276 .name = "Vflip",
277 .minimum = 0,
278 .maximum = 1,
279 .step = 1,
280 #define VFLIP_DEF 0
281 .default_value = VFLIP_DEF,
282 },
283 .set = sd_setvflip,
284 .get = sd_getvflip,
285 },
286 };
287
288 static const struct v4l2_pix_format vga_mode[] = {
289 {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
290 .bytesperline = 640,
291 .sizeimage = 640 * 480 * 3 / 8 + 590,
292 .colorspace = V4L2_COLORSPACE_JPEG,
293 .priv = 0},
294 };
295
296 #define LOAD_PAGE3 255
297 #define END_OF_SEQUENCE 0
298
299 /* pac 7302 */
300 static const __u8 init_7302[] = {
301 /* index,value */
302 0xff, 0x01, /* page 1 */
303 0x78, 0x00, /* deactivate */
304 0xff, 0x01,
305 0x78, 0x40, /* led off */
306 };
307 static const __u8 start_7302[] = {
308 /* index, len, [value]* */
309 0xff, 1, 0x00, /* page 0 */
310 0x00, 12, 0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
311 0x00, 0x00, 0x00, 0x00,
312 0x0d, 24, 0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
313 0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
314 0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
315 0x26, 2, 0xaa, 0xaa,
316 0x2e, 1, 0x31,
317 0x38, 1, 0x01,
318 0x3a, 3, 0x14, 0xff, 0x5a,
319 0x43, 11, 0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
320 0x00, 0x54, 0x11,
321 0x55, 1, 0x00,
322 0x62, 4, 0x10, 0x1e, 0x1e, 0x18,
323 0x6b, 1, 0x00,
324 0x6e, 3, 0x08, 0x06, 0x00,
325 0x72, 3, 0x00, 0xff, 0x00,
326 0x7d, 23, 0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
327 0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
328 0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
329 0xa2, 10, 0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
330 0xd2, 0xeb,
331 0xaf, 1, 0x02,
332 0xb5, 2, 0x08, 0x08,
333 0xb8, 2, 0x08, 0x88,
334 0xc4, 4, 0xae, 0x01, 0x04, 0x01,
335 0xcc, 1, 0x00,
336 0xd1, 11, 0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
337 0xc1, 0xd7, 0xec,
338 0xdc, 1, 0x01,
339 0xff, 1, 0x01, /* page 1 */
340 0x12, 3, 0x02, 0x00, 0x01,
341 0x3e, 2, 0x00, 0x00,
342 0x76, 5, 0x01, 0x20, 0x40, 0x00, 0xf2,
343 0x7c, 1, 0x00,
344 0x7f, 10, 0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
345 0x02, 0x00,
346 0x96, 5, 0x01, 0x10, 0x04, 0x01, 0x04,
347 0xc8, 14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
348 0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
349 0xd8, 1, 0x01,
350 0xdb, 2, 0x00, 0x01,
351 0xde, 7, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
352 0xe6, 4, 0x00, 0x00, 0x00, 0x01,
353 0xeb, 1, 0x00,
354 0xff, 1, 0x02, /* page 2 */
355 0x22, 1, 0x00,
356 0xff, 1, 0x03, /* page 3 */
357 0, LOAD_PAGE3, /* load the page 3 */
358 0x11, 1, 0x01,
359 0xff, 1, 0x02, /* page 2 */
360 0x13, 1, 0x00,
361 0x22, 4, 0x1f, 0xa4, 0xf0, 0x96,
362 0x27, 2, 0x14, 0x0c,
363 0x2a, 5, 0xc8, 0x00, 0x18, 0x12, 0x22,
364 0x64, 8, 0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
365 0x6e, 1, 0x08,
366 0xff, 1, 0x01, /* page 1 */
367 0x78, 1, 0x00,
368 0, END_OF_SEQUENCE /* end of sequence */
369 };
370
371 #define SKIP 0xaa
372 /* page 3 - the value SKIP says skip the index - see reg_w_page() */
373 static const __u8 page3_7302[] = {
374 0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
375 0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
376 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
378 0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
379 0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
380 0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
381 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
383 SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
384 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
388 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
389 0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
390 0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
393 0x00
394 };
395
396 static void reg_w_buf(struct gspca_dev *gspca_dev,
397 __u8 index,
398 const u8 *buffer, int len)
399 {
400 int ret;
401
402 if (gspca_dev->usb_err < 0)
403 return;
404 memcpy(gspca_dev->usb_buf, buffer, len);
405 ret = usb_control_msg(gspca_dev->dev,
406 usb_sndctrlpipe(gspca_dev->dev, 0),
407 0, /* request */
408 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
409 0, /* value */
410 index, gspca_dev->usb_buf, len,
411 500);
412 if (ret < 0) {
413 pr_err("reg_w_buf failed index 0x%02x, error %d\n",
414 index, ret);
415 gspca_dev->usb_err = ret;
416 }
417 }
418
419
420 static void reg_w(struct gspca_dev *gspca_dev,
421 __u8 index,
422 __u8 value)
423 {
424 int ret;
425
426 if (gspca_dev->usb_err < 0)
427 return;
428 gspca_dev->usb_buf[0] = value;
429 ret = usb_control_msg(gspca_dev->dev,
430 usb_sndctrlpipe(gspca_dev->dev, 0),
431 0, /* request */
432 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
433 0, index, gspca_dev->usb_buf, 1,
434 500);
435 if (ret < 0) {
436 pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
437 index, value, ret);
438 gspca_dev->usb_err = ret;
439 }
440 }
441
442 static void reg_w_seq(struct gspca_dev *gspca_dev,
443 const __u8 *seq, int len)
444 {
445 while (--len >= 0) {
446 reg_w(gspca_dev, seq[0], seq[1]);
447 seq += 2;
448 }
449 }
450
451 /* load the beginning of a page */
452 static void reg_w_page(struct gspca_dev *gspca_dev,
453 const __u8 *page, int len)
454 {
455 int index;
456 int ret = 0;
457
458 if (gspca_dev->usb_err < 0)
459 return;
460 for (index = 0; index < len; index++) {
461 if (page[index] == SKIP) /* skip this index */
462 continue;
463 gspca_dev->usb_buf[0] = page[index];
464 ret = usb_control_msg(gspca_dev->dev,
465 usb_sndctrlpipe(gspca_dev->dev, 0),
466 0, /* request */
467 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
468 0, index, gspca_dev->usb_buf, 1,
469 500);
470 if (ret < 0) {
471 pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
472 index, page[index], ret);
473 gspca_dev->usb_err = ret;
474 break;
475 }
476 }
477 }
478
479 /* output a variable sequence */
480 static void reg_w_var(struct gspca_dev *gspca_dev,
481 const __u8 *seq,
482 const __u8 *page3, unsigned int page3_len)
483 {
484 int index, len;
485
486 for (;;) {
487 index = *seq++;
488 len = *seq++;
489 switch (len) {
490 case END_OF_SEQUENCE:
491 return;
492 case LOAD_PAGE3:
493 reg_w_page(gspca_dev, page3, page3_len);
494 break;
495 default:
496 if (len > USB_BUF_SZ) {
497 PDEBUG(D_ERR|D_STREAM,
498 "Incorrect variable sequence");
499 return;
500 }
501 while (len > 0) {
502 if (len < 8) {
503 reg_w_buf(gspca_dev,
504 index, seq, len);
505 seq += len;
506 break;
507 }
508 reg_w_buf(gspca_dev, index, seq, 8);
509 seq += 8;
510 index += 8;
511 len -= 8;
512 }
513 }
514 }
515 /* not reached */
516 }
517
518 /* this function is called at probe time for pac7302 */
519 static int sd_config(struct gspca_dev *gspca_dev,
520 const struct usb_device_id *id)
521 {
522 struct sd *sd = (struct sd *) gspca_dev;
523 struct cam *cam;
524
525 cam = &gspca_dev->cam;
526
527 PDEBUG(D_CONF, "Find Sensor PAC7302");
528 cam->cam_mode = vga_mode; /* only 640x480 */
529 cam->nmodes = ARRAY_SIZE(vga_mode);
530
531 sd->brightness = BRIGHTNESS_DEF;
532 sd->contrast = CONTRAST_DEF;
533 sd->colors = COLOR_DEF;
534 sd->white_balance = WHITEBALANCE_DEF;
535 sd->red_balance = REDBALANCE_DEF;
536 sd->blue_balance = BLUEBALANCE_DEF;
537 sd->gain = GAIN_DEF;
538 sd->exposure = EXPOSURE_DEF;
539 sd->autogain = AUTOGAIN_DEF;
540 sd->hflip = HFLIP_DEF;
541 sd->vflip = VFLIP_DEF;
542 sd->flags = id->driver_info;
543 return 0;
544 }
545
546 /* This function is used by pac7302 only */
547 static void setbrightcont(struct gspca_dev *gspca_dev)
548 {
549 struct sd *sd = (struct sd *) gspca_dev;
550 int i, v;
551 static const __u8 max[10] =
552 {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
553 0xd4, 0xec};
554 static const __u8 delta[10] =
555 {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
556 0x11, 0x0b};
557
558 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
559 for (i = 0; i < 10; i++) {
560 v = max[i];
561 v += (sd->brightness - BRIGHTNESS_MAX)
562 * 150 / BRIGHTNESS_MAX; /* 200 ? */
563 v -= delta[i] * sd->contrast / CONTRAST_MAX;
564 if (v < 0)
565 v = 0;
566 else if (v > 0xff)
567 v = 0xff;
568 reg_w(gspca_dev, 0xa2 + i, v);
569 }
570 reg_w(gspca_dev, 0xdc, 0x01);
571 }
572
573 /* This function is used by pac7302 only */
574 static void setcolors(struct gspca_dev *gspca_dev)
575 {
576 struct sd *sd = (struct sd *) gspca_dev;
577 int i, v;
578 static const int a[9] =
579 {217, -212, 0, -101, 170, -67, -38, -315, 355};
580 static const int b[9] =
581 {19, 106, 0, 19, 106, 1, 19, 106, 1};
582
583 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
584 reg_w(gspca_dev, 0x11, 0x01);
585 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
586 for (i = 0; i < 9; i++) {
587 v = a[i] * sd->colors / COLOR_MAX + b[i];
588 reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
589 reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
590 }
591 reg_w(gspca_dev, 0xdc, 0x01);
592 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
593 }
594
595 static void setwhitebalance(struct gspca_dev *gspca_dev)
596 {
597 struct sd *sd = (struct sd *) gspca_dev;
598
599 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
600 reg_w(gspca_dev, 0xc6, sd->white_balance);
601
602 reg_w(gspca_dev, 0xdc, 0x01);
603 PDEBUG(D_CONF|D_STREAM, "white_balance: %i", sd->white_balance);
604 }
605
606 static void setredbalance(struct gspca_dev *gspca_dev)
607 {
608 struct sd *sd = (struct sd *) gspca_dev;
609
610 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
611 reg_w(gspca_dev, 0xc5, sd->red_balance);
612
613 reg_w(gspca_dev, 0xdc, 0x01);
614 PDEBUG(D_CONF|D_STREAM, "red_balance: %i", sd->red_balance);
615 }
616
617 static void setbluebalance(struct gspca_dev *gspca_dev)
618 {
619 struct sd *sd = (struct sd *) gspca_dev;
620
621 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
622 reg_w(gspca_dev, 0xc7, sd->blue_balance);
623
624 reg_w(gspca_dev, 0xdc, 0x01);
625 PDEBUG(D_CONF|D_STREAM, "blue_balance: %i", sd->blue_balance);
626 }
627
628 static void setgain(struct gspca_dev *gspca_dev)
629 {
630 struct sd *sd = (struct sd *) gspca_dev;
631
632 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
633 reg_w(gspca_dev, 0x10, sd->gain >> 3);
634
635 /* load registers to sensor (Bit 0, auto clear) */
636 reg_w(gspca_dev, 0x11, 0x01);
637 }
638
639 static void setexposure(struct gspca_dev *gspca_dev)
640 {
641 struct sd *sd = (struct sd *) gspca_dev;
642 __u8 clockdiv;
643 __u16 exposure;
644
645 /* register 2 of frame 3 contains the clock divider configuring the
646 no fps according to the formula: 90 / reg. sd->exposure is the
647 desired exposure time in 0.5 ms. */
648 clockdiv = (90 * sd->exposure + 1999) / 2000;
649
650 /* Note clockdiv = 3 also works, but when running at 30 fps, depending
651 on the scene being recorded, the camera switches to another
652 quantization table for certain JPEG blocks, and we don't know how
653 to decompress these blocks. So we cap the framerate at 15 fps */
654 if (clockdiv < 6)
655 clockdiv = 6;
656 else if (clockdiv > 63)
657 clockdiv = 63;
658
659 /* reg2 MUST be a multiple of 3, except when between 6 and 12?
660 Always round up, otherwise we cannot get the desired frametime
661 using the partial frame time exposure control */
662 if (clockdiv < 6 || clockdiv > 12)
663 clockdiv = ((clockdiv + 2) / 3) * 3;
664
665 /* frame exposure time in ms = 1000 * clockdiv / 90 ->
666 exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90) */
667 exposure = (sd->exposure * 45 * 448) / (1000 * clockdiv);
668 /* 0 = use full frametime, 448 = no exposure, reverse it */
669 exposure = 448 - exposure;
670
671 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
672 reg_w(gspca_dev, 0x02, clockdiv);
673 reg_w(gspca_dev, 0x0e, exposure & 0xff);
674 reg_w(gspca_dev, 0x0f, exposure >> 8);
675
676 /* load registers to sensor (Bit 0, auto clear) */
677 reg_w(gspca_dev, 0x11, 0x01);
678 }
679
680 static void sethvflip(struct gspca_dev *gspca_dev)
681 {
682 struct sd *sd = (struct sd *) gspca_dev;
683 u8 data, hflip, vflip;
684
685 hflip = sd->hflip;
686 if (sd->flags & FL_HFLIP)
687 hflip = !hflip;
688 vflip = sd->vflip;
689 if (sd->flags & FL_VFLIP)
690 vflip = !vflip;
691
692 reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
693 data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
694 reg_w(gspca_dev, 0x21, data);
695
696 /* load registers to sensor (Bit 0, auto clear) */
697 reg_w(gspca_dev, 0x11, 0x01);
698 }
699
700 /* this function is called at probe and resume time for pac7302 */
701 static int sd_init(struct gspca_dev *gspca_dev)
702 {
703 reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
704 return gspca_dev->usb_err;
705 }
706
707 static int sd_start(struct gspca_dev *gspca_dev)
708 {
709 struct sd *sd = (struct sd *) gspca_dev;
710
711 sd->sof_read = 0;
712
713 reg_w_var(gspca_dev, start_7302,
714 page3_7302, sizeof(page3_7302));
715 setbrightcont(gspca_dev);
716 setcolors(gspca_dev);
717 setwhitebalance(gspca_dev);
718 setredbalance(gspca_dev);
719 setbluebalance(gspca_dev);
720 setgain(gspca_dev);
721 setexposure(gspca_dev);
722 sethvflip(gspca_dev);
723
724 /* only resolution 640x480 is supported for pac7302 */
725
726 sd->sof_read = 0;
727 sd->autogain_ignore_frames = 0;
728 atomic_set(&sd->avg_lum, -1);
729
730 /* start stream */
731 reg_w(gspca_dev, 0xff, 0x01);
732 reg_w(gspca_dev, 0x78, 0x01);
733
734 return gspca_dev->usb_err;
735 }
736
737 static void sd_stopN(struct gspca_dev *gspca_dev)
738 {
739
740 /* stop stream */
741 reg_w(gspca_dev, 0xff, 0x01);
742 reg_w(gspca_dev, 0x78, 0x00);
743 }
744
745 /* called on streamoff with alt 0 and on disconnect for pac7302 */
746 static void sd_stop0(struct gspca_dev *gspca_dev)
747 {
748 if (!gspca_dev->present)
749 return;
750 reg_w(gspca_dev, 0xff, 0x01);
751 reg_w(gspca_dev, 0x78, 0x40);
752 }
753
754 /* Include pac common sof detection functions */
755 #include "pac_common.h"
756
757 static void do_autogain(struct gspca_dev *gspca_dev)
758 {
759 struct sd *sd = (struct sd *) gspca_dev;
760 int avg_lum = atomic_read(&sd->avg_lum);
761 int desired_lum;
762 const int deadzone = 30;
763
764 if (avg_lum == -1)
765 return;
766
767 desired_lum = 270 + sd->brightness;
768
769 if (sd->autogain_ignore_frames > 0)
770 sd->autogain_ignore_frames--;
771 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, desired_lum,
772 deadzone, GAIN_KNEE, EXPOSURE_KNEE))
773 sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
774 }
775
776 /* JPEG header, part 1 */
777 static const unsigned char pac_jpeg_header1[] = {
778 0xff, 0xd8, /* SOI: Start of Image */
779
780 0xff, 0xc0, /* SOF0: Start of Frame (Baseline DCT) */
781 0x00, 0x11, /* length = 17 bytes (including this length field) */
782 0x08 /* Precision: 8 */
783 /* 2 bytes is placed here: number of image lines */
784 /* 2 bytes is placed here: samples per line */
785 };
786
787 /* JPEG header, continued */
788 static const unsigned char pac_jpeg_header2[] = {
789 0x03, /* Number of image components: 3 */
790 0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
791 0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
792 0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
793
794 0xff, 0xda, /* SOS: Start Of Scan */
795 0x00, 0x0c, /* length = 12 bytes (including this length field) */
796 0x03, /* number of components: 3 */
797 0x01, 0x00, /* selector 1, table 0x00 */
798 0x02, 0x11, /* selector 2, table 0x11 */
799 0x03, 0x11, /* selector 3, table 0x11 */
800 0x00, 0x3f, /* Spectral selection: 0 .. 63 */
801 0x00 /* Successive approximation: 0 */
802 };
803
804 static void pac_start_frame(struct gspca_dev *gspca_dev,
805 __u16 lines, __u16 samples_per_line)
806 {
807 unsigned char tmpbuf[4];
808
809 gspca_frame_add(gspca_dev, FIRST_PACKET,
810 pac_jpeg_header1, sizeof(pac_jpeg_header1));
811
812 tmpbuf[0] = lines >> 8;
813 tmpbuf[1] = lines & 0xff;
814 tmpbuf[2] = samples_per_line >> 8;
815 tmpbuf[3] = samples_per_line & 0xff;
816
817 gspca_frame_add(gspca_dev, INTER_PACKET,
818 tmpbuf, sizeof(tmpbuf));
819 gspca_frame_add(gspca_dev, INTER_PACKET,
820 pac_jpeg_header2, sizeof(pac_jpeg_header2));
821 }
822
823 /* this function is run at interrupt level */
824 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
825 u8 *data, /* isoc packet */
826 int len) /* iso packet length */
827 {
828 struct sd *sd = (struct sd *) gspca_dev;
829 u8 *image;
830 unsigned char *sof;
831
832 sof = pac_find_sof(&sd->sof_read, data, len);
833 if (sof) {
834 int n, lum_offset, footer_length;
835
836 /* 6 bytes after the FF D9 EOF marker a number of lumination
837 bytes are send corresponding to different parts of the
838 image, the 14th and 15th byte after the EOF seem to
839 correspond to the center of the image */
840 lum_offset = 61 + sizeof pac_sof_marker;
841 footer_length = 74;
842
843 /* Finish decoding current frame */
844 n = (sof - data) - (footer_length + sizeof pac_sof_marker);
845 if (n < 0) {
846 gspca_dev->image_len += n;
847 n = 0;
848 } else {
849 gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
850 }
851
852 image = gspca_dev->image;
853 if (image != NULL
854 && image[gspca_dev->image_len - 2] == 0xff
855 && image[gspca_dev->image_len - 1] == 0xd9)
856 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
857
858 n = sof - data;
859 len -= n;
860 data = sof;
861
862 /* Get average lumination */
863 if (gspca_dev->last_packet_type == LAST_PACKET &&
864 n >= lum_offset)
865 atomic_set(&sd->avg_lum, data[-lum_offset] +
866 data[-lum_offset + 1]);
867 else
868 atomic_set(&sd->avg_lum, -1);
869
870 /* Start the new frame with the jpeg header */
871 /* The PAC7302 has the image rotated 90 degrees */
872 pac_start_frame(gspca_dev,
873 gspca_dev->width, gspca_dev->height);
874 }
875 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
876 }
877
878 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
879 {
880 struct sd *sd = (struct sd *) gspca_dev;
881
882 sd->brightness = val;
883 if (gspca_dev->streaming)
884 setbrightcont(gspca_dev);
885 return gspca_dev->usb_err;
886 }
887
888 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
889 {
890 struct sd *sd = (struct sd *) gspca_dev;
891
892 *val = sd->brightness;
893 return 0;
894 }
895
896 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
897 {
898 struct sd *sd = (struct sd *) gspca_dev;
899
900 sd->contrast = val;
901 if (gspca_dev->streaming)
902 setbrightcont(gspca_dev);
903 return gspca_dev->usb_err;
904 }
905
906 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
907 {
908 struct sd *sd = (struct sd *) gspca_dev;
909
910 *val = sd->contrast;
911 return 0;
912 }
913
914 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
915 {
916 struct sd *sd = (struct sd *) gspca_dev;
917
918 sd->colors = val;
919 if (gspca_dev->streaming)
920 setcolors(gspca_dev);
921 return gspca_dev->usb_err;
922 }
923
924 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
925 {
926 struct sd *sd = (struct sd *) gspca_dev;
927
928 *val = sd->colors;
929 return 0;
930 }
931
932 static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
933 {
934 struct sd *sd = (struct sd *) gspca_dev;
935
936 sd->white_balance = val;
937 if (gspca_dev->streaming)
938 setwhitebalance(gspca_dev);
939 return gspca_dev->usb_err;
940 }
941
942 static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
943 {
944 struct sd *sd = (struct sd *) gspca_dev;
945
946 *val = sd->white_balance;
947 return 0;
948 }
949
950 static int sd_setredbalance(struct gspca_dev *gspca_dev, __s32 val)
951 {
952 struct sd *sd = (struct sd *) gspca_dev;
953
954 sd->red_balance = val;
955 if (gspca_dev->streaming)
956 setredbalance(gspca_dev);
957 return gspca_dev->usb_err;
958 }
959
960 static int sd_getredbalance(struct gspca_dev *gspca_dev, __s32 *val)
961 {
962 struct sd *sd = (struct sd *) gspca_dev;
963
964 *val = sd->red_balance;
965 return 0;
966 }
967
968 static int sd_setbluebalance(struct gspca_dev *gspca_dev, __s32 val)
969 {
970 struct sd *sd = (struct sd *) gspca_dev;
971
972 sd->blue_balance = val;
973 if (gspca_dev->streaming)
974 setbluebalance(gspca_dev);
975 return gspca_dev->usb_err;
976 }
977
978 static int sd_getbluebalance(struct gspca_dev *gspca_dev, __s32 *val)
979 {
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 *val = sd->blue_balance;
983 return 0;
984 }
985
986 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
987 {
988 struct sd *sd = (struct sd *) gspca_dev;
989
990 sd->gain = val;
991 if (gspca_dev->streaming)
992 setgain(gspca_dev);
993 return gspca_dev->usb_err;
994 }
995
996 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
997 {
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 *val = sd->gain;
1001 return 0;
1002 }
1003
1004 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1005 {
1006 struct sd *sd = (struct sd *) gspca_dev;
1007
1008 sd->exposure = val;
1009 if (gspca_dev->streaming)
1010 setexposure(gspca_dev);
1011 return gspca_dev->usb_err;
1012 }
1013
1014 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1015 {
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 *val = sd->exposure;
1019 return 0;
1020 }
1021
1022 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1023 {
1024 struct sd *sd = (struct sd *) gspca_dev;
1025
1026 sd->autogain = val;
1027 /* when switching to autogain set defaults to make sure
1028 we are on a valid point of the autogain gain /
1029 exposure knee graph, and give this change time to
1030 take effect before doing autogain. */
1031 if (sd->autogain) {
1032 sd->exposure = EXPOSURE_DEF;
1033 sd->gain = GAIN_DEF;
1034 if (gspca_dev->streaming) {
1035 sd->autogain_ignore_frames =
1036 PAC_AUTOGAIN_IGNORE_FRAMES;
1037 setexposure(gspca_dev);
1038 setgain(gspca_dev);
1039 }
1040 }
1041
1042 return gspca_dev->usb_err;
1043 }
1044
1045 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1046 {
1047 struct sd *sd = (struct sd *) gspca_dev;
1048
1049 *val = sd->autogain;
1050 return 0;
1051 }
1052
1053 static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
1054 {
1055 struct sd *sd = (struct sd *) gspca_dev;
1056
1057 sd->hflip = val;
1058 if (gspca_dev->streaming)
1059 sethvflip(gspca_dev);
1060 return gspca_dev->usb_err;
1061 }
1062
1063 static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
1064 {
1065 struct sd *sd = (struct sd *) gspca_dev;
1066
1067 *val = sd->hflip;
1068 return 0;
1069 }
1070
1071 static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1072 {
1073 struct sd *sd = (struct sd *) gspca_dev;
1074
1075 sd->vflip = val;
1076 if (gspca_dev->streaming)
1077 sethvflip(gspca_dev);
1078 return gspca_dev->usb_err;
1079 }
1080
1081 static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1082 {
1083 struct sd *sd = (struct sd *) gspca_dev;
1084
1085 *val = sd->vflip;
1086 return 0;
1087 }
1088
1089 #ifdef CONFIG_VIDEO_ADV_DEBUG
1090 static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
1091 struct v4l2_dbg_register *reg)
1092 {
1093 __u8 index;
1094 __u8 value;
1095
1096 /* reg->reg: bit0..15: reserved for register index (wIndex is 16bit
1097 long on the USB bus)
1098 */
1099 if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
1100 reg->match.addr == 0 &&
1101 (reg->reg < 0x000000ff) &&
1102 (reg->val <= 0x000000ff)
1103 ) {
1104 /* Currently writing to page 0 is only supported. */
1105 /* reg_w() only supports 8bit index */
1106 index = reg->reg & 0x000000ff;
1107 value = reg->val & 0x000000ff;
1108
1109 /* Note that there shall be no access to other page
1110 by any other function between the page swith and
1111 the actual register write */
1112 reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
1113 reg_w(gspca_dev, index, value);
1114
1115 reg_w(gspca_dev, 0xdc, 0x01);
1116 }
1117 return gspca_dev->usb_err;
1118 }
1119
1120 static int sd_chip_ident(struct gspca_dev *gspca_dev,
1121 struct v4l2_dbg_chip_ident *chip)
1122 {
1123 int ret = -EINVAL;
1124
1125 if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
1126 chip->match.addr == 0) {
1127 chip->revision = 0;
1128 chip->ident = V4L2_IDENT_UNKNOWN;
1129 ret = 0;
1130 }
1131 return ret;
1132 }
1133 #endif
1134
1135 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1136 static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
1137 u8 *data, /* interrupt packet data */
1138 int len) /* interrput packet length */
1139 {
1140 int ret = -EINVAL;
1141 u8 data0, data1;
1142
1143 if (len == 2) {
1144 data0 = data[0];
1145 data1 = data[1];
1146 if ((data0 == 0x00 && data1 == 0x11) ||
1147 (data0 == 0x22 && data1 == 0x33) ||
1148 (data0 == 0x44 && data1 == 0x55) ||
1149 (data0 == 0x66 && data1 == 0x77) ||
1150 (data0 == 0x88 && data1 == 0x99) ||
1151 (data0 == 0xaa && data1 == 0xbb) ||
1152 (data0 == 0xcc && data1 == 0xdd) ||
1153 (data0 == 0xee && data1 == 0xff)) {
1154 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
1155 input_sync(gspca_dev->input_dev);
1156 input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
1157 input_sync(gspca_dev->input_dev);
1158 ret = 0;
1159 }
1160 }
1161
1162 return ret;
1163 }
1164 #endif
1165
1166 /* sub-driver description for pac7302 */
1167 static const struct sd_desc sd_desc = {
1168 .name = MODULE_NAME,
1169 .ctrls = sd_ctrls,
1170 .nctrls = ARRAY_SIZE(sd_ctrls),
1171 .config = sd_config,
1172 .init = sd_init,
1173 .start = sd_start,
1174 .stopN = sd_stopN,
1175 .stop0 = sd_stop0,
1176 .pkt_scan = sd_pkt_scan,
1177 .dq_callback = do_autogain,
1178 #ifdef CONFIG_VIDEO_ADV_DEBUG
1179 .set_register = sd_dbg_s_register,
1180 .get_chip_ident = sd_chip_ident,
1181 #endif
1182 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
1183 .int_pkt_scan = sd_int_pkt_scan,
1184 #endif
1185 };
1186
1187 /* -- module initialisation -- */
1188 static const struct usb_device_id device_table[] = {
1189 {USB_DEVICE(0x06f8, 0x3009)},
1190 {USB_DEVICE(0x093a, 0x2620)},
1191 {USB_DEVICE(0x093a, 0x2621)},
1192 {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
1193 {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
1194 {USB_DEVICE(0x093a, 0x2625)},
1195 {USB_DEVICE(0x093a, 0x2626)},
1196 {USB_DEVICE(0x093a, 0x2628)},
1197 {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
1198 {USB_DEVICE(0x093a, 0x262a)},
1199 {USB_DEVICE(0x093a, 0x262c)},
1200 {USB_DEVICE(0x145f, 0x013c)},
1201 {}
1202 };
1203 MODULE_DEVICE_TABLE(usb, device_table);
1204
1205 /* -- device connect -- */
1206 static int sd_probe(struct usb_interface *intf,
1207 const struct usb_device_id *id)
1208 {
1209 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1210 THIS_MODULE);
1211 }
1212
1213 static struct usb_driver sd_driver = {
1214 .name = MODULE_NAME,
1215 .id_table = device_table,
1216 .probe = sd_probe,
1217 .disconnect = gspca_disconnect,
1218 #ifdef CONFIG_PM
1219 .suspend = gspca_suspend,
1220 .resume = gspca_resume,
1221 #endif
1222 };
1223
1224 module_usb_driver(sd_driver);
This page took 0.076129 seconds and 5 git commands to generate.