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