V4L/DVB (8180): Source cleanup - compile error with VIDEO_ADV_DEBUG.
[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
26 #define DRIVER_VERSION_NUMBER   KERNEL_VERSION(2, 1, 0)
27 static const char version[] = "2.1.0";
28
29 MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30 MODULE_DESCRIPTION("Pixart PAC7311");
31 MODULE_LICENSE("GPL");
32
33 /* specific webcam descriptor */
34 struct sd {
35         struct gspca_dev gspca_dev;             /* !! must be the first item */
36
37         int avg_lum;
38
39         unsigned char brightness;
40 #define BRIGHTNESS_MAX 0x20
41         unsigned char contrast;
42         unsigned char colors;
43         unsigned char autogain;
44
45         char ffseq;
46         signed char ag_cnt;
47 #define AG_CNT_START 13
48 };
49
50 /* V4L2 controls supported by the driver */
51 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
52 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
53 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
54 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
55 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
56 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
57 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
58 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
59
60 static struct ctrl sd_ctrls[] = {
61 #define SD_BRIGHTNESS 0
62         {
63             {
64                 .id      = V4L2_CID_BRIGHTNESS,
65                 .type    = V4L2_CTRL_TYPE_INTEGER,
66                 .name    = "Brightness",
67                 .minimum = 0,
68                 .maximum = BRIGHTNESS_MAX,
69                 .step    = 1,
70                 .default_value = 0x10,
71             },
72             .set = sd_setbrightness,
73             .get = sd_getbrightness,
74         },
75 #define SD_CONTRAST 1
76         {
77             {
78                 .id      = V4L2_CID_CONTRAST,
79                 .type    = V4L2_CTRL_TYPE_INTEGER,
80                 .name    = "Contrast",
81                 .minimum = 0,
82                 .maximum = 255,
83                 .step    = 1,
84                 .default_value = 127,
85             },
86             .set = sd_setcontrast,
87             .get = sd_getcontrast,
88         },
89 #define SD_COLOR 2
90         {
91             {
92                 .id      = V4L2_CID_SATURATION,
93                 .type    = V4L2_CTRL_TYPE_INTEGER,
94                 .name    = "Color",
95                 .minimum = 0,
96                 .maximum = 255,
97                 .step    = 1,
98                 .default_value = 127,
99             },
100             .set = sd_setcolors,
101             .get = sd_getcolors,
102         },
103 #define SD_AUTOGAIN 3
104         {
105             {
106                 .id      = V4L2_CID_AUTOGAIN,
107                 .type    = V4L2_CTRL_TYPE_BOOLEAN,
108                 .name    = "Auto Gain",
109                 .minimum = 0,
110                 .maximum = 1,
111                 .step    = 1,
112                 .default_value = 1,
113             },
114             .set = sd_setautogain,
115             .get = sd_getautogain,
116         },
117 };
118
119 static struct cam_mode vga_mode[] = {
120         {V4L2_PIX_FMT_JPEG, 160, 120, 2},
121         {V4L2_PIX_FMT_JPEG, 320, 240, 1},
122         {V4L2_PIX_FMT_JPEG, 640, 480, 0},
123 };
124
125 #define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header)   /* (594) */
126
127 const unsigned char pac7311_jpeg_header[] = {
128         0xff, 0xd8,
129         0xff, 0xe0, 0x00, 0x03, 0x20,
130         0xff, 0xc0, 0x00, 0x11, 0x08,
131                 0x01, 0xe0,                     /* 12: height */
132                 0x02, 0x80,                     /* 14: width */
133                 0x03,                           /* 16 */
134                         0x01, 0x21, 0x00,
135                         0x02, 0x11, 0x01,
136                         0x03, 0x11, 0x01,
137         0xff, 0xdb, 0x00, 0x84,
138         0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
139         0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
140         0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
141         0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
142         0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
143         0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
144         0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
145         0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
146         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
147         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
148         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
149         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
150         0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
151         0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
152         0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153         0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
154         0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
155         0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
156         0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
157         0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
158         0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
159         0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
160         0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
161         0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
162         0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
163         0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
164         0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
165         0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
166         0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
167         0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
168         0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
169         0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
170         0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
171         0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
172         0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
173         0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
175         0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
176         0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
177         0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
178         0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
179         0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
180         0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
181         0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
182         0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
183         0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
184         0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
185         0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
186         0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
187         0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
188         0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
189         0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
190         0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
191         0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
192         0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
193         0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
194         0x11, 0x00, 0x3f, 0x00
195 };
196
197 static void reg_w(struct usb_device *dev,
198                             __u16 req,
199                             __u16 value,
200                             __u16 index,
201                             __u8 *buffer, __u16 length)
202 {
203         usb_control_msg(dev,
204                         usb_sndctrlpipe(dev, 0),
205                         req,
206                         USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
207                         value, index, buffer, length,
208                         500);
209 }
210
211 static void pac7311_reg_read(struct usb_device *dev, __u16 index,
212                             __u8 *buffer)
213 {
214         usb_control_msg(dev,
215                         usb_rcvctrlpipe(dev, 0),
216                         0,                      /* request */
217                         USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
218                         0,                      /* value */
219                         index, buffer, 1,
220                         500);
221 }
222
223 static void pac7311_reg_write(struct usb_device *dev,
224                               __u16 index,
225                               __u8 value)
226 {
227         __u8 buf;
228
229         buf = value;
230         reg_w(dev, 0x00, value, index, &buf, 1);
231 }
232
233 /* this function is called at probe time */
234 static int sd_config(struct gspca_dev *gspca_dev,
235                         const struct usb_device_id *id)
236 {
237         struct sd *sd = (struct sd *) gspca_dev;
238         struct usb_device *dev = gspca_dev->dev;
239         struct cam *cam;
240
241         PDEBUG(D_CONF, "Find Sensor PAC7311");
242         pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
243         pac7311_reg_write(dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
244         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
245         pac7311_reg_write(dev, 0xff, 0x04);
246         pac7311_reg_write(dev, 0x27, 0x80);
247         pac7311_reg_write(dev, 0x28, 0xca);
248         pac7311_reg_write(dev, 0x29, 0x53);
249         pac7311_reg_write(dev, 0x2a, 0x0e);
250         pac7311_reg_write(dev, 0xff, 0x01);
251         pac7311_reg_write(dev, 0x3e, 0x20);
252
253         cam = &gspca_dev->cam;
254         cam->dev_name = (char *) id->driver_info;
255         cam->epaddr = 0x05;
256         cam->cam_mode = vga_mode;
257         cam->nmodes = ARRAY_SIZE(vga_mode);
258
259         sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
260         sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
261         sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
262         sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
263         return 0;
264 }
265
266 static void setbrightness(struct gspca_dev *gspca_dev)
267 {
268         struct sd *sd = (struct sd *) gspca_dev;
269         int brightness;
270
271 /*jfm: inverted?*/
272         brightness = BRIGHTNESS_MAX - sd->brightness;
273         pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
274         /* pac7311_reg_write(gspca_dev->dev, 0x0e, 0x00); */
275         pac7311_reg_write(gspca_dev->dev, 0x0f, brightness);
276         /* load registers to sensor (Bit 0, auto clear) */
277         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
278         PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
279 }
280
281 static void setcontrast(struct gspca_dev *gspca_dev)
282 {
283         struct sd *sd = (struct sd *) gspca_dev;
284
285         pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
286         pac7311_reg_write(gspca_dev->dev, 0x80, sd->contrast);
287         /* load registers to sensor (Bit 0, auto clear) */
288         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
289         PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
290 }
291
292 static void setcolors(struct gspca_dev *gspca_dev)
293 {
294         struct sd *sd = (struct sd *) gspca_dev;
295
296         pac7311_reg_write(gspca_dev->dev, 0xff, 0x01);
297         pac7311_reg_write(gspca_dev->dev, 0x10, sd->colors);
298         /* load registers to sensor (Bit 0, auto clear) */
299         pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
300         PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
301 }
302
303 /* this function is called at open time */
304 static int sd_open(struct gspca_dev *gspca_dev)
305 {
306         pac7311_reg_write(gspca_dev->dev, 0x78, 0x00);  /* Turn on LED */
307         return 0;
308 }
309
310 static void sd_start(struct gspca_dev *gspca_dev)
311 {
312         struct usb_device *dev = gspca_dev->dev;
313         struct sd *sd = (struct sd *) gspca_dev;
314
315         pac7311_reg_write(dev, 0xff, 0x01);
316         reg_w(dev, 0x01, 0, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
317         reg_w(dev, 0x01, 0, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
318         reg_w(dev, 0x01, 0, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
319         reg_w(dev, 0x01, 0, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
320         reg_w(dev, 0x01, 0, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
321         reg_w(dev, 0x01, 0, 0x002a, "\x00\x00\x00", 3);
322         reg_w(dev, 0x01, 0, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
323         reg_w(dev, 0x01, 0, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
324         reg_w(dev, 0x01, 0, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
325         reg_w(dev, 0x01, 0, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
326         reg_w(dev, 0x01, 0, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
327         reg_w(dev, 0x01, 0, 0x0066, "\xd0\xff", 2);
328         reg_w(dev, 0x01, 0, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
329         reg_w(dev, 0x01, 0, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
330         reg_w(dev, 0x01, 0, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
331         reg_w(dev, 0x01, 0, 0x008f, "\x18\x20", 2);
332         reg_w(dev, 0x01, 0, 0x0096, "\x01\x08\x04", 3);
333         reg_w(dev, 0x01, 0, 0x00a0, "\x44\x44\x44\x04", 4);
334         reg_w(dev, 0x01, 0, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
335         reg_w(dev, 0x01, 0, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
336
337         pac7311_reg_write(dev, 0xff, 0x04);
338         pac7311_reg_write(dev, 0x02, 0x04);
339         pac7311_reg_write(dev, 0x03, 0x54);
340         pac7311_reg_write(dev, 0x04, 0x07);
341         pac7311_reg_write(dev, 0x05, 0x2b);
342         pac7311_reg_write(dev, 0x06, 0x09);
343         pac7311_reg_write(dev, 0x07, 0x0f);
344         pac7311_reg_write(dev, 0x08, 0x09);
345         pac7311_reg_write(dev, 0x09, 0x00);
346         pac7311_reg_write(dev, 0x0c, 0x07);
347         pac7311_reg_write(dev, 0x0d, 0x00);
348         pac7311_reg_write(dev, 0x0e, 0x00);
349         pac7311_reg_write(dev, 0x0f, 0x62);
350         pac7311_reg_write(dev, 0x10, 0x08);
351         pac7311_reg_write(dev, 0x12, 0x07);
352         pac7311_reg_write(dev, 0x13, 0x00);
353         pac7311_reg_write(dev, 0x14, 0x00);
354         pac7311_reg_write(dev, 0x15, 0x00);
355         pac7311_reg_write(dev, 0x16, 0x00);
356         pac7311_reg_write(dev, 0x17, 0x00);
357         pac7311_reg_write(dev, 0x18, 0x00);
358         pac7311_reg_write(dev, 0x19, 0x00);
359         pac7311_reg_write(dev, 0x1a, 0x00);
360         pac7311_reg_write(dev, 0x1b, 0x03);
361         pac7311_reg_write(dev, 0x1c, 0xa0);
362         pac7311_reg_write(dev, 0x1d, 0x01);
363         pac7311_reg_write(dev, 0x1e, 0xf4);
364         pac7311_reg_write(dev, 0x21, 0x00);
365         pac7311_reg_write(dev, 0x22, 0x08);
366         pac7311_reg_write(dev, 0x24, 0x03);
367         pac7311_reg_write(dev, 0x26, 0x00);
368         pac7311_reg_write(dev, 0x27, 0x01);
369         pac7311_reg_write(dev, 0x28, 0xca);
370         pac7311_reg_write(dev, 0x29, 0x10);
371         pac7311_reg_write(dev, 0x2a, 0x06);
372         pac7311_reg_write(dev, 0x2b, 0x78);
373         pac7311_reg_write(dev, 0x2c, 0x00);
374         pac7311_reg_write(dev, 0x2d, 0x00);
375         pac7311_reg_write(dev, 0x2e, 0x00);
376         pac7311_reg_write(dev, 0x2f, 0x00);
377         pac7311_reg_write(dev, 0x30, 0x23);
378         pac7311_reg_write(dev, 0x31, 0x28);
379         pac7311_reg_write(dev, 0x32, 0x04);
380         pac7311_reg_write(dev, 0x33, 0x11);
381         pac7311_reg_write(dev, 0x34, 0x00);
382         pac7311_reg_write(dev, 0x35, 0x00);
383         pac7311_reg_write(dev, 0x11, 0x01);
384         setcontrast(gspca_dev);
385         setbrightness(gspca_dev);
386         setcolors(gspca_dev);
387
388         /* set correct resolution */
389         switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
390         case 2:                                 /* 160x120 */
391                 pac7311_reg_write(dev, 0xff, 0x04);
392                 pac7311_reg_write(dev, 0x02, 0x03);
393                 pac7311_reg_write(dev, 0xff, 0x01);
394                 pac7311_reg_write(dev, 0x08, 0x09);
395                 pac7311_reg_write(dev, 0x17, 0x20);
396                 pac7311_reg_write(dev, 0x1b, 0x00);
397 /*              pac7311_reg_write(dev, 0x80, 0x69); */
398                 pac7311_reg_write(dev, 0x87, 0x10);
399                 break;
400         case 1:                                 /* 320x240 */
401                 pac7311_reg_write(dev, 0xff, 0x04);
402                 pac7311_reg_write(dev, 0x02, 0x03);
403                 pac7311_reg_write(dev, 0xff, 0x01);
404                 pac7311_reg_write(dev, 0x08, 0x09);
405                 pac7311_reg_write(dev, 0x17, 0x30);
406 /*              pac7311_reg_write(dev, 0x80, 0x3f); */
407                 pac7311_reg_write(dev, 0x87, 0x11);
408                 break;
409         case 0:                                 /* 640x480 */
410                 pac7311_reg_write(dev, 0xff, 0x04);
411                 pac7311_reg_write(dev, 0x02, 0x03);
412                 pac7311_reg_write(dev, 0xff, 0x01);
413                 pac7311_reg_write(dev, 0x08, 0x08);
414                 pac7311_reg_write(dev, 0x17, 0x00);
415 /*              pac7311_reg_write(dev, 0x80, 0x1c); */
416                 pac7311_reg_write(dev, 0x87, 0x12);
417                 break;
418         }
419
420         /* start stream */
421         pac7311_reg_write(dev, 0xff, 0x01);
422         pac7311_reg_write(dev, 0x78, 0x04);
423         pac7311_reg_write(dev, 0x78, 0x05);
424
425         if (sd->autogain) {
426                 sd->ag_cnt = AG_CNT_START;
427                 sd->avg_lum = 0;
428         } else {
429                 sd->ag_cnt = -1;
430         }
431 }
432
433 static void sd_stopN(struct gspca_dev *gspca_dev)
434 {
435         struct usb_device *dev = gspca_dev->dev;
436
437         pac7311_reg_write(dev, 0xff, 0x04);
438         pac7311_reg_write(dev, 0x27, 0x80);
439         pac7311_reg_write(dev, 0x28, 0xca);
440         pac7311_reg_write(dev, 0x29, 0x53);
441         pac7311_reg_write(dev, 0x2a, 0x0e);
442         pac7311_reg_write(dev, 0xff, 0x01);
443         pac7311_reg_write(dev, 0x3e, 0x20);
444         pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
445         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
446         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
447 }
448
449 static void sd_stop0(struct gspca_dev *gspca_dev)
450 {
451 }
452
453 /* this function is called at close time */
454 static void sd_close(struct gspca_dev *gspca_dev)
455 {
456         struct usb_device *dev = gspca_dev->dev;
457
458         pac7311_reg_write(dev, 0xff, 0x04);
459         pac7311_reg_write(dev, 0x27, 0x80);
460         pac7311_reg_write(dev, 0x28, 0xca);
461         pac7311_reg_write(dev, 0x29, 0x53);
462         pac7311_reg_write(dev, 0x2a, 0x0e);
463         pac7311_reg_write(dev, 0xff, 0x01);
464         pac7311_reg_write(dev, 0x3e, 0x20);
465         pac7311_reg_write(dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
466         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
467         pac7311_reg_write(dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
468 }
469
470 static void setautogain(struct gspca_dev *gspca_dev, int luma)
471 {
472         int luma_mean = 128;
473         int luma_delta = 20;
474         __u8 spring = 5;
475         __u8 Pxclk;
476         int Gbright;
477
478         pac7311_reg_read(gspca_dev->dev, 0x02, &Pxclk);
479         Gbright = Pxclk;
480         PDEBUG(D_FRAM, "luma mean %d", luma);
481         if (luma < luma_mean - luma_delta ||
482             luma > luma_mean + luma_delta) {
483                 Gbright += (luma_mean - luma) >> spring;
484                 if (Gbright > 0x1a)
485                         Gbright = 0x1a;
486                 else if (Gbright < 4)
487                         Gbright = 4;
488                 PDEBUG(D_FRAM, "gbright %d", Gbright);
489                 pac7311_reg_write(gspca_dev->dev, 0xff, 0x04);
490                 pac7311_reg_write(gspca_dev->dev, 0x0f, Gbright);
491                 /* load registers to sensor (Bit 0, auto clear) */
492                 pac7311_reg_write(gspca_dev->dev, 0x11, 0x01);
493         }
494 }
495
496 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
497                         struct gspca_frame *frame,      /* target */
498                         unsigned char *data,            /* isoc packet */
499                         int len)                        /* iso packet length */
500 {
501         struct sd *sd = (struct sd *) gspca_dev;
502         unsigned char tmpbuf[4];
503         int i, p, ffseq;
504
505 /*      if (len < 5) { */
506         if (len < 6) {
507 /*              gspca_dev->last_packet_type = DISCARD_PACKET; */
508                 return;
509         }
510
511         ffseq = sd->ffseq;
512
513         for (p = 0; p < len - 6; p++) {
514                 if ((data[0 + p] == 0xff)
515                     && (data[1 + p] == 0xff)
516                     && (data[2 + p] == 0x00)
517                     && (data[3 + p] == 0xff)
518                     && (data[4 + p] == 0x96)) {
519
520                         /* start of frame */
521                         if (sd->ag_cnt >= 0 && p > 28) {
522                                 sd->avg_lum += data[p - 23];
523                                 if (--sd->ag_cnt < 0) {
524                                         sd->ag_cnt = AG_CNT_START;
525                                         setautogain(gspca_dev,
526                                                 sd->avg_lum / AG_CNT_START);
527                                         sd->avg_lum = 0;
528                                 }
529                         }
530
531                         /* copy the end of data to the current frame */
532                         frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
533                                                 data, p);
534
535                         /* put the JPEG header in the new frame */
536                         gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
537                                         (unsigned char *) pac7311_jpeg_header,
538                                         12);
539                         tmpbuf[0] = gspca_dev->height >> 8;
540                         tmpbuf[1] = gspca_dev->height & 0xff;
541                         tmpbuf[2] = gspca_dev->width >> 8;
542                         tmpbuf[3] = gspca_dev->width & 0xff;
543                         gspca_frame_add(gspca_dev, INTER_PACKET, frame,
544                                         tmpbuf, 4);
545                         gspca_frame_add(gspca_dev, INTER_PACKET, frame,
546                                 (unsigned char *) &pac7311_jpeg_header[16],
547                                 PAC7311_JPEG_HEADER_SIZE - 16);
548
549                         data += p + 7;
550                         len -= p + 7;
551                         ffseq = 0;
552                         break;
553                 }
554         }
555
556         /* remove the 'ff ff ff xx' sequences */
557         switch (ffseq) {
558         case 3:
559                 data += 1;
560                 len -= 1;
561                 break;
562         case 2:
563                 if (data[0] == 0xff) {
564                         data += 2;
565                         len -= 2;
566                         frame->data_end -= 2;
567                 }
568                 break;
569         case 1:
570                 if (data[0] == 0xff
571                     && data[1] == 0xff) {
572                         data += 3;
573                         len -= 3;
574                         frame->data_end -= 1;
575                 }
576                 break;
577         }
578         for (i = 0; i < len - 4; i++) {
579                 if (data[i] == 0xff
580                     && data[i + 1] == 0xff
581                     && data[i + 2] == 0xff) {
582                         memmove(&data[i], &data[i + 4], len - i - 4);
583                         len -= 4;
584                 }
585         }
586         ffseq = 0;
587         if (data[len - 4] == 0xff) {
588                 if (data[len - 3] == 0xff
589                     && data[len - 2] == 0xff) {
590                         len -= 4;
591                 }
592         } else if (data[len - 3] == 0xff) {
593                 if (data[len - 2] == 0xff
594                     && data[len - 1] == 0xff)
595                         ffseq = 3;
596         } else if (data[len - 2] == 0xff) {
597                 if (data[len - 1] == 0xff)
598                         ffseq = 2;
599         } else if (data[len - 1] == 0xff)
600                 ffseq = 1;
601         sd->ffseq = ffseq;
602         gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
603 }
604
605 static void getbrightness(struct gspca_dev *gspca_dev)
606 {
607 /*      __u8 brightness = 0;
608
609         pac7311_reg_read(gspca_dev->dev, 0x0008, &brightness);
610         spca50x->brightness = brightness;
611         return spca50x->brightness;     */
612 /*      PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
613 }
614
615
616
617 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
618 {
619         struct sd *sd = (struct sd *) gspca_dev;
620
621         sd->brightness = val;
622         if (gspca_dev->streaming)
623                 setbrightness(gspca_dev);
624         return 0;
625 }
626
627 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
628 {
629         struct sd *sd = (struct sd *) gspca_dev;
630
631         getbrightness(gspca_dev);
632         *val = sd->brightness;
633         return 0;
634 }
635
636 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
637 {
638         struct sd *sd = (struct sd *) gspca_dev;
639
640         sd->contrast = val;
641         if (gspca_dev->streaming)
642                 setcontrast(gspca_dev);
643         return 0;
644 }
645
646 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
647 {
648         struct sd *sd = (struct sd *) gspca_dev;
649
650 /*      getcontrast(gspca_dev); */
651         *val = sd->contrast;
652         return 0;
653 }
654
655 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
656 {
657         struct sd *sd = (struct sd *) gspca_dev;
658
659         sd->colors = val;
660         if (gspca_dev->streaming)
661                 setcolors(gspca_dev);
662         return 0;
663 }
664
665 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
666 {
667         struct sd *sd = (struct sd *) gspca_dev;
668
669 /*      getcolors(gspca_dev); */
670         *val = sd->colors;
671         return 0;
672 }
673
674 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
675 {
676         struct sd *sd = (struct sd *) gspca_dev;
677
678         sd->autogain = val;
679         if (val) {
680                 sd->ag_cnt = AG_CNT_START;
681                 sd->avg_lum = 0;
682         } else {
683                 sd->ag_cnt = -1;
684         }
685         return 0;
686 }
687
688 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
689 {
690         struct sd *sd = (struct sd *) gspca_dev;
691
692         *val = sd->autogain;
693         return 0;
694 }
695
696 /* sub-driver description */
697 static struct sd_desc sd_desc = {
698         .name = MODULE_NAME,
699         .ctrls = sd_ctrls,
700         .nctrls = ARRAY_SIZE(sd_ctrls),
701         .config = sd_config,
702         .open = sd_open,
703         .start = sd_start,
704         .stopN = sd_stopN,
705         .stop0 = sd_stop0,
706         .close = sd_close,
707         .pkt_scan = sd_pkt_scan,
708 };
709
710 /* -- module initialisation -- */
711 #define DVNM(name) .driver_info = (kernel_ulong_t) name
712 static __devinitdata struct usb_device_id device_table[] = {
713         {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
714         {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
715         {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
716         {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
717         {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
718                         /* and also ', Trust WB-3350p, SIGMA cam 2350' */
719         {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
720         {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
721         {}
722 };
723 MODULE_DEVICE_TABLE(usb, device_table);
724
725 /* -- device connect -- */
726 static int sd_probe(struct usb_interface *intf,
727                         const struct usb_device_id *id)
728 {
729         return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
730                                 THIS_MODULE);
731 }
732
733 static struct usb_driver sd_driver = {
734         .name = MODULE_NAME,
735         .id_table = device_table,
736         .probe = sd_probe,
737         .disconnect = gspca_disconnect,
738 };
739
740 /* -- module insert / remove -- */
741 static int __init sd_mod_init(void)
742 {
743         if (usb_register(&sd_driver) < 0)
744                 return -1;
745         PDEBUG(D_PROBE, "v%s registered", version);
746         return 0;
747 }
748 static void __exit sd_mod_exit(void)
749 {
750         usb_deregister(&sd_driver);
751         PDEBUG(D_PROBE, "deregistered");
752 }
753
754 module_init(sd_mod_init);
755 module_exit(sd_mod_exit);