]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/media/video/gspca/pac7311.c
V4L/DVB (8675): gspca: Pixmap PJPG (Pixart 73xx JPEG) added, generated by pac7311.
[linux-2.6-omap-h63xx.git] / drivers / media / video / gspca / pac7311.c
1 /*
2  *              Pixart PAC7311 library
3  *              Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
4  *
5  * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
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  * 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
22 #define MODULE_NAME "pac7311"
23
24 #include "gspca.h"
25 #include "jpeg.h"
26
27 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
28 MODULE_DESCRIPTION("Pixart PAC7311");
29 MODULE_LICENSE("GPL");
30
31 /* specific webcam descriptor */
32 struct sd {
33         struct gspca_dev gspca_dev;             /* !! must be the first item */
34
35         int lum_sum;
36         atomic_t avg_lum;
37         atomic_t do_gain;
38
39         unsigned char brightness;
40         unsigned char contrast;
41         unsigned char colors;
42         unsigned char autogain;
43
44         char tosof;     /* number of bytes before next start of frame */
45         signed char ag_cnt;
46 #define AG_CNT_START 13
47
48         __u8 sensor;
49 #define SENSOR_PAC7302 0
50 #define SENSOR_PAC7311 1
51 };
52
53 /* V4L2 controls supported by the driver */
54 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
55 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
56 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
57 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
58 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
62
63 static struct ctrl sd_ctrls[] = {
64         {
65             {
66                 .id      = V4L2_CID_BRIGHTNESS,
67                 .type    = V4L2_CTRL_TYPE_INTEGER,
68                 .name    = "Brightness",
69                 .minimum = 0,
70 #define BRIGHTNESS_MAX 0x20
71                 .maximum = BRIGHTNESS_MAX,
72                 .step    = 1,
73 #define BRIGHTNESS_DEF 0x10
74                 .default_value = BRIGHTNESS_DEF,
75             },
76             .set = sd_setbrightness,
77             .get = sd_getbrightness,
78         },
79         {
80             {
81                 .id      = V4L2_CID_CONTRAST,
82                 .type    = V4L2_CTRL_TYPE_INTEGER,
83                 .name    = "Contrast",
84                 .minimum = 0,
85                 .maximum = 255,
86                 .step    = 1,
87 #define CONTRAST_DEF 127
88                 .default_value = CONTRAST_DEF,
89             },
90             .set = sd_setcontrast,
91             .get = sd_getcontrast,
92         },
93         {
94             {
95                 .id      = V4L2_CID_SATURATION,
96                 .type    = V4L2_CTRL_TYPE_INTEGER,
97                 .name    = "Color",
98                 .minimum = 0,
99                 .maximum = 255,
100                 .step    = 1,
101 #define COLOR_DEF 127
102                 .default_value = COLOR_DEF,
103             },
104             .set = sd_setcolors,
105             .get = sd_getcolors,
106         },
107         {
108             {
109                 .id      = V4L2_CID_AUTOGAIN,
110                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
111                 .name    = "Auto Gain",
112                 .minimum = 0,
113                 .maximum = 1,
114                 .step    = 1,
115 #define AUTOGAIN_DEF 1
116                 .default_value = AUTOGAIN_DEF,
117             },
118             .set = sd_setautogain,
119             .get = sd_getautogain,
120         },
121 };
122
123 static struct v4l2_pix_format vga_mode[] = {
124         {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
125                 .bytesperline = 160,
126                 .sizeimage = 160 * 120 * 3 / 8 + 590,
127                 .colorspace = V4L2_COLORSPACE_JPEG,
128                 .priv = 2},
129         {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
130                 .bytesperline = 320,
131                 .sizeimage = 320 * 240 * 3 / 8 + 590,
132                 .colorspace = V4L2_COLORSPACE_JPEG,
133                 .priv = 1},
134         {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
135                 .bytesperline = 640,
136                 .sizeimage = 640 * 480 * 3 / 8 + 590,
137                 .colorspace = V4L2_COLORSPACE_JPEG,
138                 .priv = 0},
139 };
140
141 /* pac 7302 */
142 static const __u8 probe_7302[] = {
143 /*      index,value */
144         0xff, 0x01,             /* page 1 */
145         0x78, 0x00,             /* deactivate */
146         0xff, 0x01,
147         0x78, 0x40,             /* led off */
148 };
149 static const __u8 start_7302[] = {
150 /*      index, len, [value]* */
151         0xff, 1,        0x00,           /* page 0 */
152         0x00, 12,       0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
153                         0x00, 0x00, 0x00, 0x00,
154         0x0d, 24,       0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
155                         0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
156                         0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
157         0x26, 2,        0xaa, 0xaa,
158         0x2e, 1,        0x31,
159         0x38, 1,        0x01,
160         0x3a, 3,        0x14, 0xff, 0x5a,
161         0x43, 11,       0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
162                         0x00, 0x54, 0x11,
163         0x55, 1,        0x00,
164         0x62, 4,        0x10, 0x1e, 0x1e, 0x18,
165         0x6b, 1,        0x00,
166         0x6e, 3,        0x08, 0x06, 0x00,
167         0x72, 3,        0x00, 0xff, 0x00,
168         0x7d, 23,       0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
169                         0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
170                         0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
171         0xa2, 10,       0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
172                         0xd2, 0xeb,
173         0xaf, 1,        0x02,
174         0xb5, 2,        0x08, 0x08,
175         0xb8, 2,        0x08, 0x88,
176         0xc4, 4,        0xae, 0x01, 0x04, 0x01,
177         0xcc, 1,        0x00,
178         0xd1, 11,       0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
179                         0xc1, 0xd7, 0xec,
180         0xdc, 1,        0x01,
181         0xff, 1,        0x01,           /* page 1 */
182         0x12, 3,        0x02, 0x00, 0x01,
183         0x3e, 2,        0x00, 0x00,
184         0x76, 5,        0x01, 0x20, 0x40, 0x00, 0xf2,
185         0x7c, 1,        0x00,
186         0x7f, 10,       0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
187                         0x02, 0x00,
188         0x96, 5,        0x01, 0x10, 0x04, 0x01, 0x04,
189         0xc8, 14,       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
190                         0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
191         0xd8, 1,        0x01,
192         0xdb, 2,        0x00, 0x01,
193         0xde, 7,        0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
194         0xe6, 4,        0x00, 0x00, 0x00, 0x01,
195         0xeb, 1,        0x00,
196         0xff, 1,        0x02,           /* page 2 */
197         0x22, 1,        0x00,
198         0xff, 1,        0x03,           /* page 3 */
199         0x00, 255,                      /* load the page 3 */
200         0x11, 1,        0x01,
201         0xff, 1,        0x02,           /* page 2 */
202         0x13, 1,        0x00,
203         0x22, 4,        0x1f, 0xa4, 0xf0, 0x96,
204         0x27, 2,        0x14, 0x0c,
205         0x2a, 5,        0xc8, 0x00, 0x18, 0x12, 0x22,
206         0x64, 8,        0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
207         0x6e, 1,        0x08,
208         0xff, 1,        0x03,           /* page 1 */
209         0x78, 1,        0x00,
210         0, 0                            /* end of sequence */
211 };
212
213 /* page 3 - the value 0xaa says skip the index - see reg_w_page() */
214 static const __u8 page3_7302[] = {
215         0x90, 0x40, 0x03, 0x50, 0xc2, 0x01, 0x14, 0x16,
216         0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
217         0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218         0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
219         0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
220         0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
221         0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
222         0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223         0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
224         0x00, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
225         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226         0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
227         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228         0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
229         0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
230         0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
231         0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
232         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233         0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
234         0x00
235 };
236
237 /* pac 7311 */
238 static const __u8 probe_7311[] = {
239         0x78, 0x40,     /* Bit_0=start stream, Bit_7=LED */
240         0x78, 0x40,     /* Bit_0=start stream, Bit_7=LED */
241         0x78, 0x44,     /* Bit_0=start stream, Bit_7=LED */
242         0xff, 0x04,
243         0x27, 0x80,
244         0x28, 0xca,
245         0x29, 0x53,
246         0x2a, 0x0e,
247         0xff, 0x01,
248         0x3e, 0x20,
249 };
250
251 static const __u8 start_7311[] = {
252 /*      index, len, [value]* */
253         0xff, 1,        0x01,           /* page 1 */
254         0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
255                         0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
256                         0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
257                         0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
258                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259                         0x00, 0x00, 0x00,
260         0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
261                         0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
262                         0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
263                         0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
264                         0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
265                         0xd0, 0xff,
266         0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
267         0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
268                         0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
269                         0x18, 0x20,
270         0x96, 3,        0x01, 0x08, 0x04,
271         0xa0, 4,        0x44, 0x44, 0x44, 0x04,
272         0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
273                         0x3f, 0x00, 0x0a, 0x01, 0x00,
274         0xff, 1,        0x04,           /* page 4 */
275         0x00, 254,                      /* load the page 4 */
276         0x11, 1,        0x01,
277         0, 0                            /* end of sequence */
278 };
279
280 /* page 4 - the value 0xaa says skip the index - see reg_w_page() */
281 static const __u8 page4_7311[] = {
282         0xaa, 0xaa, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
283         0x09, 0x00, 0xaa, 0xaa, 0x07, 0x00, 0x00, 0x62,
284         0x08, 0xaa, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
285         0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, 0xaa,
286         0xaa, 0x00, 0x08, 0xaa, 0x03, 0xaa, 0x00, 0x01,
287         0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
288         0x23, 0x28, 0x04, 0x11, 0x00, 0x00
289 };
290
291 static void reg_w_buf(struct gspca_dev *gspca_dev,
292                   __u8 index,
293                   const char *buffer, int len)
294 {
295         memcpy(gspca_dev->usb_buf, buffer, len);
296         usb_control_msg(gspca_dev->dev,
297                         usb_sndctrlpipe(gspca_dev->dev, 0),
298                         1,              /* request */
299                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
300                         0,              /* value */
301                         index, gspca_dev->usb_buf, len,
302                         500);
303 }
304
305 static __u8 reg_r(struct gspca_dev *gspca_dev,
306                              __u8 index)
307 {
308         usb_control_msg(gspca_dev->dev,
309                         usb_rcvctrlpipe(gspca_dev->dev, 0),
310                         0,                      /* request */
311                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
312                         0,                      /* value */
313                         index, gspca_dev->usb_buf, 1,
314                         500);
315         return gspca_dev->usb_buf[0];
316 }
317
318 static void reg_w(struct gspca_dev *gspca_dev,
319                   __u8 index,
320                   __u8 value)
321 {
322         gspca_dev->usb_buf[0] = value;
323         usb_control_msg(gspca_dev->dev,
324                         usb_sndctrlpipe(gspca_dev->dev, 0),
325                         0,                      /* request */
326                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
327                         value, index, gspca_dev->usb_buf, 1,
328                         500);
329 }
330
331 static void reg_w_seq(struct gspca_dev *gspca_dev,
332                 const __u8 *seq, int len)
333 {
334         while (--len >= 0) {
335                 reg_w(gspca_dev, seq[0], seq[1]);
336                 seq += 2;
337         }
338 }
339
340 /* load the beginning of a page */
341 static void reg_w_page(struct gspca_dev *gspca_dev,
342                         const __u8 *page, int len)
343 {
344         int index;
345
346         for (index = 0; index < len; index++) {
347                 if (page[index] == 0xaa)                /* skip this index */
348                         continue;
349                 gspca_dev->usb_buf[0] = page[index];
350                 usb_control_msg(gspca_dev->dev,
351                                 usb_sndctrlpipe(gspca_dev->dev, 0),
352                                 0,                      /* request */
353                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
354                                 0, index, gspca_dev->usb_buf, 1,
355                                 500);
356         }
357 }
358
359 /* output a variable sequence */
360 static void reg_w_var(struct gspca_dev *gspca_dev,
361                         const __u8 *seq)
362 {
363         int index, len;
364
365         for (;;) {
366                 index = *seq++;
367                 len = *seq++;
368                 switch (len) {
369                 case 0:
370                         return;
371                 case 254:
372                         reg_w_page(gspca_dev, page4_7311, sizeof page4_7311);
373                         break;
374                 case 255:
375                         reg_w_page(gspca_dev, page3_7302, sizeof page3_7302);
376                         break;
377                 default:
378                         if (len > 32) {
379                                 PDEBUG(D_ERR|D_STREAM,
380                                         "Incorrect variable sequence");
381                                 return;
382                         }
383                         while (len > 0) {
384                                 if (len < 8) {
385                                         reg_w_buf(gspca_dev, index, seq, len);
386                                         seq += len;
387                                         break;
388                                 }
389                                 reg_w_buf(gspca_dev, index, seq, 8);
390                                 seq += 8;
391                                 index += 8;
392                                 len -= 8;
393                         }
394                 }
395         }
396         /* not reached */
397 }
398
399 /* this function is called at probe time */
400 static int sd_config(struct gspca_dev *gspca_dev,
401                         const struct usb_device_id *id)
402 {
403         struct sd *sd = (struct sd *) gspca_dev;
404         struct cam *cam;
405
406         cam = &gspca_dev->cam;
407         cam->epaddr = 0x05;
408
409         sd->sensor = id->driver_info;
410         if (sd->sensor == SENSOR_PAC7302) {
411                 PDEBUG(D_CONF, "Find Sensor PAC7302");
412                 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
413
414                 cam->cam_mode = &vga_mode[2];   /* only 640x480 */
415                 cam->nmodes = 1;
416         } else {
417                 PDEBUG(D_CONF, "Find Sensor PAC7311");
418                 reg_w_seq(gspca_dev, probe_7302, sizeof probe_7302);
419
420                 cam->cam_mode = vga_mode;
421                 cam->nmodes = ARRAY_SIZE(vga_mode);
422         }
423
424         sd->brightness = BRIGHTNESS_DEF;
425         sd->contrast = CONTRAST_DEF;
426         sd->colors = COLOR_DEF;
427         sd->autogain = AUTOGAIN_DEF;
428         sd->ag_cnt = -1;
429         return 0;
430 }
431
432 static void setbrightness(struct gspca_dev *gspca_dev)
433 {
434         struct sd *sd = (struct sd *) gspca_dev;
435         int brightness;
436
437         if (sd->sensor == SENSOR_PAC7302)
438                 return;
439 /*jfm: inverted?*/
440         brightness = BRIGHTNESS_MAX - sd->brightness;
441         reg_w(gspca_dev, 0xff, 0x04);
442         reg_w(gspca_dev, 0x0f, brightness);
443         /* load registers to sensor (Bit 0, auto clear) */
444         reg_w(gspca_dev, 0x11, 0x01);
445         PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
446 }
447
448 static void setcontrast(struct gspca_dev *gspca_dev)
449 {
450         struct sd *sd = (struct sd *) gspca_dev;
451
452         if (sd->sensor == SENSOR_PAC7302)
453                 return;
454         reg_w(gspca_dev, 0xff, 0x01);
455         reg_w(gspca_dev, 0x80, sd->contrast);
456         /* load registers to sensor (Bit 0, auto clear) */
457         reg_w(gspca_dev, 0x11, 0x01);
458         PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
459 }
460
461 static void setcolors(struct gspca_dev *gspca_dev)
462 {
463         struct sd *sd = (struct sd *) gspca_dev;
464
465         if (sd->sensor == SENSOR_PAC7302)
466                 return;
467         reg_w(gspca_dev, 0xff, 0x01);
468         reg_w(gspca_dev, 0x10, sd->colors);
469         /* load registers to sensor (Bit 0, auto clear) */
470         reg_w(gspca_dev, 0x11, 0x01);
471         PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
472 }
473
474 static void setautogain(struct gspca_dev *gspca_dev)
475 {
476         struct sd *sd = (struct sd *) gspca_dev;
477
478         if (sd->autogain) {
479                 sd->lum_sum = 0;
480                 sd->ag_cnt = AG_CNT_START;
481         } else {
482                 sd->ag_cnt = -1;
483         }
484 }
485
486 /* this function is called at open time */
487 static int sd_open(struct gspca_dev *gspca_dev)
488 {
489         reg_w(gspca_dev, 0x78, 0x00);   /* Turn on LED */
490         return 0;
491 }
492
493 static void sd_start(struct gspca_dev *gspca_dev)
494 {
495         struct sd *sd = (struct sd *) gspca_dev;
496
497         sd->tosof = 0;
498
499         if (sd->sensor == SENSOR_PAC7302)
500                 reg_w_var(gspca_dev, start_7302);
501         else
502                 reg_w_var(gspca_dev, start_7311);
503
504         setcontrast(gspca_dev);
505         setbrightness(gspca_dev);
506         setcolors(gspca_dev);
507         setautogain(gspca_dev);
508
509         /* set correct resolution */
510         switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
511         case 2:                                 /* 160x120 pac7311 */
512                 reg_w(gspca_dev, 0xff, 0x04);
513                 reg_w(gspca_dev, 0x02, 0x03);
514                 reg_w(gspca_dev, 0xff, 0x01);
515                 reg_w(gspca_dev, 0x08, 0x09);
516                 reg_w(gspca_dev, 0x17, 0x20);
517                 reg_w(gspca_dev, 0x1b, 0x00);
518 /*              reg_w(gspca_dev, 0x80, 0x69); */
519                 reg_w(gspca_dev, 0x87, 0x10);
520                 break;
521         case 1:                                 /* 320x240 pac7311 */
522                 reg_w(gspca_dev, 0xff, 0x04);
523                 reg_w(gspca_dev, 0x02, 0x03);
524                 reg_w(gspca_dev, 0xff, 0x01);
525                 reg_w(gspca_dev, 0x08, 0x09);
526                 reg_w(gspca_dev, 0x17, 0x30);
527 /*              reg_w(gspca_dev, 0x80, 0x3f); */
528                 reg_w(gspca_dev, 0x87, 0x11);
529                 break;
530         case 0:                                 /* 640x480 */
531                 if (sd->sensor == SENSOR_PAC7302)
532                         break;
533                 reg_w(gspca_dev, 0xff, 0x04);
534                 reg_w(gspca_dev, 0x02, 0x03);
535                 reg_w(gspca_dev, 0xff, 0x01);
536                 reg_w(gspca_dev, 0x08, 0x08);
537                 reg_w(gspca_dev, 0x17, 0x00);
538 /*              reg_w(gspca_dev, 0x80, 0x1c); */
539                 reg_w(gspca_dev, 0x87, 0x12);
540                 break;
541         }
542
543         /* start stream */
544         reg_w(gspca_dev, 0xff, 0x01);
545         if (sd->sensor == SENSOR_PAC7302) {
546                 reg_w(gspca_dev, 0x78, 0x01);
547                 reg_w(gspca_dev, 0xff, 0x01);
548                 reg_w(gspca_dev, 0x78, 0x01);
549         } else {
550                 reg_w(gspca_dev, 0x78, 0x04);
551                 reg_w(gspca_dev, 0x78, 0x05);
552         }
553 }
554
555 static void sd_stopN(struct gspca_dev *gspca_dev)
556 {
557         struct sd *sd = (struct sd *) gspca_dev;
558
559         if (sd->sensor == SENSOR_PAC7302) {
560                 reg_w(gspca_dev, 0x78, 0x00);
561                 reg_w(gspca_dev, 0x78, 0x00);
562                 return;
563         }
564         reg_w(gspca_dev, 0xff, 0x04);
565         reg_w(gspca_dev, 0x27, 0x80);
566         reg_w(gspca_dev, 0x28, 0xca);
567         reg_w(gspca_dev, 0x29, 0x53);
568         reg_w(gspca_dev, 0x2a, 0x0e);
569         reg_w(gspca_dev, 0xff, 0x01);
570         reg_w(gspca_dev, 0x3e, 0x20);
571         reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
572         reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
573         reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
574 }
575
576 static void sd_stop0(struct gspca_dev *gspca_dev)
577 {
578         struct sd *sd = (struct sd *) gspca_dev;
579
580         if (sd->sensor == SENSOR_PAC7302) {
581                 reg_w(gspca_dev, 0xff, 0x01);
582                 reg_w(gspca_dev, 0x78, 0x40);
583         }
584 }
585
586 /* this function is called at close time */
587 static void sd_close(struct gspca_dev *gspca_dev)
588 {
589 }
590
591 static void do_autogain(struct gspca_dev *gspca_dev)
592 {
593         struct sd *sd = (struct sd *) gspca_dev;
594         int luma;
595         int luma_mean = 128;
596         int luma_delta = 20;
597         __u8 spring = 5;
598         int Gbright;
599
600         if (!atomic_read(&sd->do_gain))
601                 return;
602         atomic_set(&sd->do_gain, 0);
603
604         luma = atomic_read(&sd->avg_lum);
605         Gbright = reg_r(gspca_dev, 0x02);
606         PDEBUG(D_FRAM, "luma mean %d", luma);
607         if (luma < luma_mean - luma_delta ||
608             luma > luma_mean + luma_delta) {
609                 Gbright += (luma_mean - luma) >> spring;
610                 if (Gbright > 0x1a)
611                         Gbright = 0x1a;
612                 else if (Gbright < 4)
613                         Gbright = 4;
614                 PDEBUG(D_FRAM, "gbright %d", Gbright);
615                 if (sd->sensor == SENSOR_PAC7302) {
616                         reg_w(gspca_dev, 0xff, 0x03);
617                         reg_w(gspca_dev, 0x10, Gbright);
618                         /* load registers to sensor (Bit 0, auto clear) */
619                         reg_w(gspca_dev, 0x11, 0x01);
620                 } else {
621                         reg_w(gspca_dev, 0xff, 0x04);
622                         reg_w(gspca_dev, 0x0f, Gbright);
623                         /* load registers to sensor (Bit 0, auto clear) */
624                         reg_w(gspca_dev, 0x11, 0x01);
625                 }
626         }
627 }
628
629 /* this function is run at interrupt level */
630 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
631                         struct gspca_frame *frame,      /* target */
632                         __u8 *data,                     /* isoc packet */
633                         int len)                        /* iso packet length */
634 {
635         struct sd *sd = (struct sd *) gspca_dev;
636         int i;
637
638 #define INTER_FRAME 0x53        /* eof + inter frame + sof */
639 #define LUM_OFFSET 0x1e         /* reverse offset / start of frame */
640
641         /*
642          * inside a frame, there may be:
643          *      escaped ff ('ff 00')
644          *      sequences'ff ff ff xx' to remove
645          *      end of frame ('ff d9')
646          * at the end of frame, there are:
647          *      ff d9                   end of frame
648          *      0x33 bytes
649          *      one byte luminosity
650          *      0x16 bytes
651          *      ff ff 00 ff 96 62 44    start of frame
652          */
653
654         if (sd->tosof != 0) {   /* if outside a frame */
655
656                 /* get the luminosity and go to the start of frame */
657                 data += sd->tosof;
658                 len -= sd->tosof;
659                 if (sd->tosof > LUM_OFFSET)
660                         sd->lum_sum += data[-LUM_OFFSET];
661                 sd->tosof = 0;
662                 jpeg_put_header(gspca_dev, frame, 1, 0x21);
663         }
664
665         for (i = 0; i < len; i++) {
666                 if (data[i] != 0xff)
667                         continue;
668                 switch (data[i + 1]) {
669                 case 0xd9:              /* 'ff d9' end of frame */
670                         frame = gspca_frame_add(gspca_dev,
671                                                 LAST_PACKET,
672                                                 frame, data, i + 2);
673                         data += i + INTER_FRAME;
674                         len -= i + INTER_FRAME;
675                         i = 0;
676                         if (len > -LUM_OFFSET)
677                                 sd->lum_sum += data[-LUM_OFFSET];
678                         if (len < 0) {
679                                 sd->tosof = -len;
680                                 break;
681                         }
682                         jpeg_put_header(gspca_dev, frame, 1, 0x21);
683                         break;
684                 }
685         }
686         gspca_frame_add(gspca_dev, INTER_PACKET,
687                         frame, data, i);
688 }
689
690 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
691 {
692         struct sd *sd = (struct sd *) gspca_dev;
693
694         sd->brightness = val;
695         if (gspca_dev->streaming)
696                 setbrightness(gspca_dev);
697         return 0;
698 }
699
700 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
701 {
702         struct sd *sd = (struct sd *) gspca_dev;
703
704         *val = sd->brightness;
705         return 0;
706 }
707
708 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
709 {
710         struct sd *sd = (struct sd *) gspca_dev;
711
712         sd->contrast = val;
713         if (gspca_dev->streaming)
714                 setcontrast(gspca_dev);
715         return 0;
716 }
717
718 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
719 {
720         struct sd *sd = (struct sd *) gspca_dev;
721
722         *val = sd->contrast;
723         return 0;
724 }
725
726 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
727 {
728         struct sd *sd = (struct sd *) gspca_dev;
729
730         sd->colors = val;
731         if (gspca_dev->streaming)
732                 setcolors(gspca_dev);
733         return 0;
734 }
735
736 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
737 {
738         struct sd *sd = (struct sd *) gspca_dev;
739
740         *val = sd->colors;
741         return 0;
742 }
743
744 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
745 {
746         struct sd *sd = (struct sd *) gspca_dev;
747
748         sd->autogain = val;
749         if (gspca_dev->streaming)
750                 setautogain(gspca_dev);
751         return 0;
752 }
753
754 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
755 {
756         struct sd *sd = (struct sd *) gspca_dev;
757
758         *val = sd->autogain;
759         return 0;
760 }
761
762 /* sub-driver description */
763 static struct sd_desc sd_desc = {
764         .name = MODULE_NAME,
765         .ctrls = sd_ctrls,
766         .nctrls = ARRAY_SIZE(sd_ctrls),
767         .config = sd_config,
768         .open = sd_open,
769         .start = sd_start,
770         .stopN = sd_stopN,
771         .stop0 = sd_stop0,
772         .close = sd_close,
773         .pkt_scan = sd_pkt_scan,
774         .dq_callback = do_autogain,
775 };
776
777 /* -- module initialisation -- */
778 static __devinitdata struct usb_device_id device_table[] = {
779         {USB_DEVICE(0x093a, 0x2600), .driver_info = SENSOR_PAC7311},
780         {USB_DEVICE(0x093a, 0x2601), .driver_info = SENSOR_PAC7311},
781         {USB_DEVICE(0x093a, 0x2603), .driver_info = SENSOR_PAC7311},
782         {USB_DEVICE(0x093a, 0x2608), .driver_info = SENSOR_PAC7311},
783         {USB_DEVICE(0x093a, 0x260e), .driver_info = SENSOR_PAC7311},
784         {USB_DEVICE(0x093a, 0x260f), .driver_info = SENSOR_PAC7311},
785         {USB_DEVICE(0x093a, 0x2621), .driver_info = SENSOR_PAC7302},
786         {}
787 };
788 MODULE_DEVICE_TABLE(usb, device_table);
789
790 /* -- device connect -- */
791 static int sd_probe(struct usb_interface *intf,
792                         const struct usb_device_id *id)
793 {
794         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
795                                 THIS_MODULE);
796 }
797
798 static struct usb_driver sd_driver = {
799         .name = MODULE_NAME,
800         .id_table = device_table,
801         .probe = sd_probe,
802         .disconnect = gspca_disconnect,
803 };
804
805 /* -- module insert / remove -- */
806 static int __init sd_mod_init(void)
807 {
808         if (usb_register(&sd_driver) < 0)
809                 return -1;
810         PDEBUG(D_PROBE, "registered");
811         return 0;
812 }
813 static void __exit sd_mod_exit(void)
814 {
815         usb_deregister(&sd_driver);
816         PDEBUG(D_PROBE, "deregistered");
817 }
818
819 module_init(sd_mod_init);
820 module_exit(sd_mod_exit);