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