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