• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *		Sunplus spca504(abc) spca533 spca536 library
3  *		Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
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 "sunplus"
23 
24 #include "gspca.h"
25 #include "jpeg.h"
26 
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
29 MODULE_LICENSE("GPL");
30 
31 /* specific webcam descriptor */
32 struct sd {
33 	struct gspca_dev gspca_dev;	/* !! must be the first item */
34 
35 	__u8 packet[ISO_MAX_SIZE + 128];
36 				/* !! no more than 128 ff in an ISO packet */
37 
38 	unsigned char brightness;
39 	unsigned char contrast;
40 	unsigned char colors;
41 	unsigned char autogain;
42 
43 	char qindex;
44 	char bridge;
45 #define BRIDGE_SPCA504 0
46 #define BRIDGE_SPCA504B 1
47 #define BRIDGE_SPCA504C 2
48 #define BRIDGE_SPCA533 3
49 #define BRIDGE_SPCA536 4
50 	char subtype;
51 #define AiptekMiniPenCam13 1
52 #define LogitechClickSmart420 2
53 #define LogitechClickSmart820 3
54 #define MegapixV4 4
55 };
56 
57 /* V4L2 controls supported by the driver */
58 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
66 
67 static struct ctrl sd_ctrls[] = {
68 #define SD_BRIGHTNESS 0
69 	{
70 	    {
71 		.id      = V4L2_CID_BRIGHTNESS,
72 		.type    = V4L2_CTRL_TYPE_INTEGER,
73 		.name    = "Brightness",
74 		.minimum = 0,
75 		.maximum = 0xff,
76 		.step    = 1,
77 		.default_value = 0,
78 	    },
79 	    .set = sd_setbrightness,
80 	    .get = sd_getbrightness,
81 	},
82 #define SD_CONTRAST 1
83 	{
84 	    {
85 		.id      = V4L2_CID_CONTRAST,
86 		.type    = V4L2_CTRL_TYPE_INTEGER,
87 		.name    = "Contrast",
88 		.minimum = 0,
89 		.maximum = 0xff,
90 		.step    = 1,
91 		.default_value = 0x20,
92 	    },
93 	    .set = sd_setcontrast,
94 	    .get = sd_getcontrast,
95 	},
96 #define SD_COLOR 2
97 	{
98 	    {
99 		.id      = V4L2_CID_SATURATION,
100 		.type    = V4L2_CTRL_TYPE_INTEGER,
101 		.name    = "Color",
102 		.minimum = 0,
103 		.maximum = 0xff,
104 		.step    = 1,
105 		.default_value = 0x1a,
106 	    },
107 	    .set = sd_setcolors,
108 	    .get = sd_getcolors,
109 	},
110 #define SD_AUTOGAIN 3
111 	{
112 	    {
113 		.id      = V4L2_CID_AUTOGAIN,
114 		.type    = V4L2_CTRL_TYPE_BOOLEAN,
115 		.name    = "Auto Gain",
116 		.minimum = 0,
117 		.maximum = 1,
118 		.step    = 1,
119 		.default_value = 1,
120 	    },
121 	    .set = sd_setautogain,
122 	    .get = sd_getautogain,
123 	},
124 };
125 
126 static const struct v4l2_pix_format vga_mode[] = {
127 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
128 		.bytesperline = 320,
129 		.sizeimage = 320 * 240 * 3 / 8 + 590,
130 		.colorspace = V4L2_COLORSPACE_JPEG,
131 		.priv = 2},
132 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 		.bytesperline = 640,
134 		.sizeimage = 640 * 480 * 3 / 8 + 590,
135 		.colorspace = V4L2_COLORSPACE_JPEG,
136 		.priv = 1},
137 };
138 
139 static const struct v4l2_pix_format custom_mode[] = {
140 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 		.bytesperline = 320,
142 		.sizeimage = 320 * 240 * 3 / 8 + 590,
143 		.colorspace = V4L2_COLORSPACE_JPEG,
144 		.priv = 2},
145 	{464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 		.bytesperline = 464,
147 		.sizeimage = 464 * 480 * 3 / 8 + 590,
148 		.colorspace = V4L2_COLORSPACE_JPEG,
149 		.priv = 1},
150 };
151 
152 static const struct v4l2_pix_format vga_mode2[] = {
153 	{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
154 		.bytesperline = 176,
155 		.sizeimage = 176 * 144 * 3 / 8 + 590,
156 		.colorspace = V4L2_COLORSPACE_JPEG,
157 		.priv = 4},
158 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
159 		.bytesperline = 320,
160 		.sizeimage = 320 * 240 * 3 / 8 + 590,
161 		.colorspace = V4L2_COLORSPACE_JPEG,
162 		.priv = 3},
163 	{352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
164 		.bytesperline = 352,
165 		.sizeimage = 352 * 288 * 3 / 8 + 590,
166 		.colorspace = V4L2_COLORSPACE_JPEG,
167 		.priv = 2},
168 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
169 		.bytesperline = 640,
170 		.sizeimage = 640 * 480 * 3 / 8 + 590,
171 		.colorspace = V4L2_COLORSPACE_JPEG,
172 		.priv = 1},
173 };
174 
175 #define SPCA50X_OFFSET_DATA 10
176 #define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
177 #define SPCA504_PCCAM600_OFFSET_COMPRESS 4
178 #define SPCA504_PCCAM600_OFFSET_MODE	 5
179 #define SPCA504_PCCAM600_OFFSET_DATA	 14
180  /* Frame packet header offsets for the spca533 */
181 #define SPCA533_OFFSET_DATA      16
182 #define SPCA533_OFFSET_FRAMSEQ	15
183 /* Frame packet header offsets for the spca536 */
184 #define SPCA536_OFFSET_DATA      4
185 #define SPCA536_OFFSET_FRAMSEQ	 1
186 
187 /* Initialisation data for the Creative PC-CAM 600 */
188 static const __u16 spca504_pccam600_init_data[][3] = {
189 /*	{0xa0, 0x0000, 0x0503},  * capture mode */
190 	{0x00, 0x0000, 0x2000},
191 	{0x00, 0x0013, 0x2301},
192 	{0x00, 0x0003, 0x2000},
193 	{0x00, 0x0001, 0x21ac},
194 	{0x00, 0x0001, 0x21a6},
195 	{0x00, 0x0000, 0x21a7},	/* brightness */
196 	{0x00, 0x0020, 0x21a8},	/* contrast */
197 	{0x00, 0x0001, 0x21ac},	/* sat/hue */
198 	{0x00, 0x0000, 0x21ad},	/* hue */
199 	{0x00, 0x001a, 0x21ae},	/* saturation */
200 	{0x00, 0x0002, 0x21a3},	/* gamma */
201 	{0x30, 0x0154, 0x0008},
202 	{0x30, 0x0004, 0x0006},
203 	{0x30, 0x0258, 0x0009},
204 	{0x30, 0x0004, 0x0000},
205 	{0x30, 0x0093, 0x0004},
206 	{0x30, 0x0066, 0x0005},
207 	{0x00, 0x0000, 0x2000},
208 	{0x00, 0x0013, 0x2301},
209 	{0x00, 0x0003, 0x2000},
210 	{0x00, 0x0013, 0x2301},
211 	{0x00, 0x0003, 0x2000},
212 	{}
213 };
214 
215 /* Creative PC-CAM 600 specific open data, sent before using the
216  * generic initialisation data from spca504_open_data.
217  */
218 static const __u16 spca504_pccam600_open_data[][3] = {
219 	{0x00, 0x0001, 0x2501},
220 	{0x20, 0x0500, 0x0001},	/* snapshot mode */
221 	{0x00, 0x0003, 0x2880},
222 	{0x00, 0x0001, 0x2881},
223 	{}
224 };
225 
226 /* Initialisation data for the logitech clicksmart 420 */
227 static const __u16 spca504A_clicksmart420_init_data[][3] = {
228 /*	{0xa0, 0x0000, 0x0503},  * capture mode */
229 	{0x00, 0x0000, 0x2000},
230 	{0x00, 0x0013, 0x2301},
231 	{0x00, 0x0003, 0x2000},
232 	{0x00, 0x0001, 0x21ac},
233 	{0x00, 0x0001, 0x21a6},
234 	{0x00, 0x0000, 0x21a7},	/* brightness */
235 	{0x00, 0x0020, 0x21a8},	/* contrast */
236 	{0x00, 0x0001, 0x21ac},	/* sat/hue */
237 	{0x00, 0x0000, 0x21ad},	/* hue */
238 	{0x00, 0x001a, 0x21ae},	/* saturation */
239 	{0x00, 0x0002, 0x21a3},	/* gamma */
240 	{0x30, 0x0004, 0x000a},
241 	{0xb0, 0x0001, 0x0000},
242 
243 
244 	{0x0a1, 0x0080, 0x0001},
245 	{0x30, 0x0049, 0x0000},
246 	{0x30, 0x0060, 0x0005},
247 	{0x0c, 0x0004, 0x0000},
248 	{0x00, 0x0000, 0x0000},
249 	{0x00, 0x0000, 0x2000},
250 	{0x00, 0x0013, 0x2301},
251 	{0x00, 0x0003, 0x2000},
252 	{0x00, 0x0000, 0x2000},
253 
254 	{}
255 };
256 
257 /* clicksmart 420 open data ? */
258 static const __u16 spca504A_clicksmart420_open_data[][3] = {
259 	{0x00, 0x0001, 0x2501},
260 	{0x20, 0x0502, 0x0000},
261 	{0x06, 0x0000, 0x0000},
262 	{0x00, 0x0004, 0x2880},
263 	{0x00, 0x0001, 0x2881},
264 /* look like setting a qTable */
265 	{0x00, 0x0006, 0x2800},
266 	{0x00, 0x0004, 0x2801},
267 	{0x00, 0x0004, 0x2802},
268 	{0x00, 0x0006, 0x2803},
269 	{0x00, 0x000a, 0x2804},
270 	{0x00, 0x0010, 0x2805},
271 	{0x00, 0x0014, 0x2806},
272 	{0x00, 0x0018, 0x2807},
273 	{0x00, 0x0005, 0x2808},
274 	{0x00, 0x0005, 0x2809},
275 	{0x00, 0x0006, 0x280a},
276 	{0x00, 0x0008, 0x280b},
277 	{0x00, 0x000a, 0x280c},
278 	{0x00, 0x0017, 0x280d},
279 	{0x00, 0x0018, 0x280e},
280 	{0x00, 0x0016, 0x280f},
281 
282 	{0x00, 0x0006, 0x2810},
283 	{0x00, 0x0005, 0x2811},
284 	{0x00, 0x0006, 0x2812},
285 	{0x00, 0x000a, 0x2813},
286 	{0x00, 0x0010, 0x2814},
287 	{0x00, 0x0017, 0x2815},
288 	{0x00, 0x001c, 0x2816},
289 	{0x00, 0x0016, 0x2817},
290 	{0x00, 0x0006, 0x2818},
291 	{0x00, 0x0007, 0x2819},
292 	{0x00, 0x0009, 0x281a},
293 	{0x00, 0x000c, 0x281b},
294 	{0x00, 0x0014, 0x281c},
295 	{0x00, 0x0023, 0x281d},
296 	{0x00, 0x0020, 0x281e},
297 	{0x00, 0x0019, 0x281f},
298 
299 	{0x00, 0x0007, 0x2820},
300 	{0x00, 0x0009, 0x2821},
301 	{0x00, 0x000f, 0x2822},
302 	{0x00, 0x0016, 0x2823},
303 	{0x00, 0x001b, 0x2824},
304 	{0x00, 0x002c, 0x2825},
305 	{0x00, 0x0029, 0x2826},
306 	{0x00, 0x001f, 0x2827},
307 	{0x00, 0x000a, 0x2828},
308 	{0x00, 0x000e, 0x2829},
309 	{0x00, 0x0016, 0x282a},
310 	{0x00, 0x001a, 0x282b},
311 	{0x00, 0x0020, 0x282c},
312 	{0x00, 0x002a, 0x282d},
313 	{0x00, 0x002d, 0x282e},
314 	{0x00, 0x0025, 0x282f},
315 
316 	{0x00, 0x0014, 0x2830},
317 	{0x00, 0x001a, 0x2831},
318 	{0x00, 0x001f, 0x2832},
319 	{0x00, 0x0023, 0x2833},
320 	{0x00, 0x0029, 0x2834},
321 	{0x00, 0x0030, 0x2835},
322 	{0x00, 0x0030, 0x2836},
323 	{0x00, 0x0028, 0x2837},
324 	{0x00, 0x001d, 0x2838},
325 	{0x00, 0x0025, 0x2839},
326 	{0x00, 0x0026, 0x283a},
327 	{0x00, 0x0027, 0x283b},
328 	{0x00, 0x002d, 0x283c},
329 	{0x00, 0x0028, 0x283d},
330 	{0x00, 0x0029, 0x283e},
331 	{0x00, 0x0028, 0x283f},
332 
333 	{0x00, 0x0007, 0x2840},
334 	{0x00, 0x0007, 0x2841},
335 	{0x00, 0x000a, 0x2842},
336 	{0x00, 0x0013, 0x2843},
337 	{0x00, 0x0028, 0x2844},
338 	{0x00, 0x0028, 0x2845},
339 	{0x00, 0x0028, 0x2846},
340 	{0x00, 0x0028, 0x2847},
341 	{0x00, 0x0007, 0x2848},
342 	{0x00, 0x0008, 0x2849},
343 	{0x00, 0x000a, 0x284a},
344 	{0x00, 0x001a, 0x284b},
345 	{0x00, 0x0028, 0x284c},
346 	{0x00, 0x0028, 0x284d},
347 	{0x00, 0x0028, 0x284e},
348 	{0x00, 0x0028, 0x284f},
349 
350 	{0x00, 0x000a, 0x2850},
351 	{0x00, 0x000a, 0x2851},
352 	{0x00, 0x0016, 0x2852},
353 	{0x00, 0x0028, 0x2853},
354 	{0x00, 0x0028, 0x2854},
355 	{0x00, 0x0028, 0x2855},
356 	{0x00, 0x0028, 0x2856},
357 	{0x00, 0x0028, 0x2857},
358 	{0x00, 0x0013, 0x2858},
359 	{0x00, 0x001a, 0x2859},
360 	{0x00, 0x0028, 0x285a},
361 	{0x00, 0x0028, 0x285b},
362 	{0x00, 0x0028, 0x285c},
363 	{0x00, 0x0028, 0x285d},
364 	{0x00, 0x0028, 0x285e},
365 	{0x00, 0x0028, 0x285f},
366 
367 	{0x00, 0x0028, 0x2860},
368 	{0x00, 0x0028, 0x2861},
369 	{0x00, 0x0028, 0x2862},
370 	{0x00, 0x0028, 0x2863},
371 	{0x00, 0x0028, 0x2864},
372 	{0x00, 0x0028, 0x2865},
373 	{0x00, 0x0028, 0x2866},
374 	{0x00, 0x0028, 0x2867},
375 	{0x00, 0x0028, 0x2868},
376 	{0x00, 0x0028, 0x2869},
377 	{0x00, 0x0028, 0x286a},
378 	{0x00, 0x0028, 0x286b},
379 	{0x00, 0x0028, 0x286c},
380 	{0x00, 0x0028, 0x286d},
381 	{0x00, 0x0028, 0x286e},
382 	{0x00, 0x0028, 0x286f},
383 
384 	{0x00, 0x0028, 0x2870},
385 	{0x00, 0x0028, 0x2871},
386 	{0x00, 0x0028, 0x2872},
387 	{0x00, 0x0028, 0x2873},
388 	{0x00, 0x0028, 0x2874},
389 	{0x00, 0x0028, 0x2875},
390 	{0x00, 0x0028, 0x2876},
391 	{0x00, 0x0028, 0x2877},
392 	{0x00, 0x0028, 0x2878},
393 	{0x00, 0x0028, 0x2879},
394 	{0x00, 0x0028, 0x287a},
395 	{0x00, 0x0028, 0x287b},
396 	{0x00, 0x0028, 0x287c},
397 	{0x00, 0x0028, 0x287d},
398 	{0x00, 0x0028, 0x287e},
399 	{0x00, 0x0028, 0x287f},
400 
401 	{0xa0, 0x0000, 0x0503},
402 	{}
403 };
404 
405 static const __u8 qtable_creative_pccam[2][64] = {
406 	{				/* Q-table Y-components */
407 	 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
408 	 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
409 	 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
410 	 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
411 	 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
412 	 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
413 	 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
414 	 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
415 	{				/* Q-table C-components */
416 	 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
417 	 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
418 	 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
419 	 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
420 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
421 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
424 };
425 
426 /* FIXME: This Q-table is identical to the Creative PC-CAM one,
427  *		except for one byte. Possibly a typo?
428  *		NWG: 18/05/2003.
429  */
430 static const __u8 qtable_spca504_default[2][64] = {
431 	{				/* Q-table Y-components */
432 	 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
433 	 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
434 	 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
435 	 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
436 	 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
437 	 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
438 	 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
439 	 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
440 	 },
441 	{				/* Q-table C-components */
442 	 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
443 	 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
444 	 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
445 	 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
446 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
447 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 	 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
450 };
451 
452 /* read <len> bytes to gspca_dev->usb_buf */
reg_r(struct gspca_dev * gspca_dev,__u16 req,__u16 index,__u16 len)453 static void reg_r(struct gspca_dev *gspca_dev,
454 		  __u16 req,
455 		  __u16 index,
456 		  __u16 len)
457 {
458 #ifdef GSPCA_DEBUG
459 	if (len > USB_BUF_SZ) {
460 		err("reg_r: buffer overflow");
461 		return;
462 	}
463 #endif
464 	usb_control_msg(gspca_dev->dev,
465 			usb_rcvctrlpipe(gspca_dev->dev, 0),
466 			req,
467 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
468 			0,		/* value */
469 			index,
470 			len ? gspca_dev->usb_buf : NULL, len,
471 			500);
472 }
473 
474 /* write <len> bytes from gspca_dev->usb_buf */
reg_w(struct gspca_dev * gspca_dev,__u16 req,__u16 value,__u16 index,__u16 len)475 static void reg_w(struct gspca_dev *gspca_dev,
476 		   __u16 req,
477 		   __u16 value,
478 		   __u16 index,
479 		   __u16 len)
480 {
481 #ifdef GSPCA_DEBUG
482 	if (len > USB_BUF_SZ) {
483 		err("reg_w: buffer overflow");
484 		return;
485 	}
486 #endif
487 	usb_control_msg(gspca_dev->dev,
488 			usb_sndctrlpipe(gspca_dev->dev, 0),
489 			req,
490 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
491 			value, index,
492 			len ? gspca_dev->usb_buf : NULL, len,
493 			500);
494 }
495 
496 /* write req / index / value */
reg_w_riv(struct usb_device * dev,__u16 req,__u16 index,__u16 value)497 static int reg_w_riv(struct usb_device *dev,
498 		     __u16 req, __u16 index, __u16 value)
499 {
500 	int ret;
501 
502 	ret = usb_control_msg(dev,
503 			usb_sndctrlpipe(dev, 0),
504 			req,
505 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
506 			value, index, NULL, 0, 500);
507 	PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
508 		req, index, value, ret);
509 	if (ret < 0)
510 		PDEBUG(D_ERR, "reg write: error %d", ret);
511 	return ret;
512 }
513 
514 /* read 1 byte */
reg_r_1(struct gspca_dev * gspca_dev,__u16 value)515 static int reg_r_1(struct gspca_dev *gspca_dev,
516 			__u16 value)	/* wValue */
517 {
518 	int ret;
519 
520 	ret = usb_control_msg(gspca_dev->dev,
521 			usb_rcvctrlpipe(gspca_dev->dev, 0),
522 			0x20,			/* request */
523 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
524 			value,
525 			0,			/* index */
526 			gspca_dev->usb_buf, 1,
527 			500);			/* timeout */
528 	if (ret < 0) {
529 		PDEBUG(D_ERR, "reg_r_1 err %d", ret);
530 		return 0;
531 	}
532 	return gspca_dev->usb_buf[0];
533 }
534 
535 /* read 1 or 2 bytes - returns < 0 if error */
reg_r_12(struct gspca_dev * gspca_dev,__u16 req,__u16 index,__u16 length)536 static int reg_r_12(struct gspca_dev *gspca_dev,
537 			__u16 req,	/* bRequest */
538 			__u16 index,	/* wIndex */
539 			__u16 length)	/* wLength (1 or 2 only) */
540 {
541 	int ret;
542 
543 	gspca_dev->usb_buf[1] = 0;
544 	ret = usb_control_msg(gspca_dev->dev,
545 			usb_rcvctrlpipe(gspca_dev->dev, 0),
546 			req,
547 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
548 			0,		/* value */
549 			index,
550 			gspca_dev->usb_buf, length,
551 			500);
552 	if (ret < 0) {
553 		PDEBUG(D_ERR, "reg_read err %d", ret);
554 		return -1;
555 	}
556 	return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
557 }
558 
write_vector(struct gspca_dev * gspca_dev,const __u16 data[][3])559 static int write_vector(struct gspca_dev *gspca_dev,
560 			const __u16 data[][3])
561 {
562 	struct usb_device *dev = gspca_dev->dev;
563 	int ret, i = 0;
564 
565 	while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
566 		ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
567 		if (ret < 0) {
568 			PDEBUG(D_ERR,
569 				"Register write failed for 0x%x,0x%x,0x%x",
570 				data[i][0], data[i][1], data[i][2]);
571 			return ret;
572 		}
573 		i++;
574 	}
575 	return 0;
576 }
577 
spca50x_setup_qtable(struct gspca_dev * gspca_dev,unsigned int request,unsigned int ybase,unsigned int cbase,const __u8 qtable[2][64])578 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
579 				unsigned int request,
580 				unsigned int ybase,
581 				unsigned int cbase,
582 				const __u8 qtable[2][64])
583 {
584 	struct usb_device *dev = gspca_dev->dev;
585 	int i, err;
586 
587 	/* loop over y components */
588 	for (i = 0; i < 64; i++) {
589 		err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
590 		if (err < 0)
591 			return err;
592 	}
593 
594 	/* loop over c components */
595 	for (i = 0; i < 64; i++) {
596 		err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
597 		if (err < 0)
598 			return err;
599 	}
600 	return 0;
601 }
602 
spca504_acknowledged_command(struct gspca_dev * gspca_dev,__u16 req,__u16 idx,__u16 val)603 static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
604 			     __u16 req, __u16 idx, __u16 val)
605 {
606 	struct usb_device *dev = gspca_dev->dev;
607 	__u8 notdone;
608 
609 	reg_w_riv(dev, req, idx, val);
610 	notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
611 	reg_w_riv(dev, req, idx, val);
612 
613 	PDEBUG(D_FRAM, "before wait 0x%x", notdone);
614 
615 	msleep(200);
616 	notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
617 	PDEBUG(D_FRAM, "after wait 0x%x", notdone);
618 }
619 
spca504A_acknowledged_command(struct gspca_dev * gspca_dev,__u16 req,__u16 idx,__u16 val,__u8 stat,__u8 count)620 static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
621 			__u16 req,
622 			__u16 idx, __u16 val, __u8 stat, __u8 count)
623 {
624 	struct usb_device *dev = gspca_dev->dev;
625 	__u8 status;
626 	__u8 endcode;
627 
628 	reg_w_riv(dev, req, idx, val);
629 	status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
630 	endcode = stat;
631 	PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
632 	if (!count)
633 		return;
634 	count = 200;
635 	while (--count > 0) {
636 		msleep(10);
637 		/* gsmart mini2 write a each wait setting 1 ms is enought */
638 /*		reg_w_riv(dev, req, idx, val); */
639 		status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
640 		if (status == endcode) {
641 			PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
642 				status, 200 - count);
643 				break;
644 		}
645 	}
646 }
647 
spca504B_PollingDataReady(struct gspca_dev * gspca_dev)648 static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
649 {
650 	int count = 10;
651 
652 	while (--count > 0) {
653 		reg_r(gspca_dev, 0x21, 0, 1);
654 		if ((gspca_dev->usb_buf[0] & 0x01) == 0)
655 			break;
656 		msleep(10);
657 	}
658 	return gspca_dev->usb_buf[0];
659 }
660 
spca504B_WaitCmdStatus(struct gspca_dev * gspca_dev)661 static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
662 {
663 	int count = 50;
664 
665 	while (--count > 0) {
666 		reg_r(gspca_dev, 0x21, 1, 1);
667 		if (gspca_dev->usb_buf[0] != 0) {
668 			gspca_dev->usb_buf[0] = 0;
669 			reg_w(gspca_dev, 0x21, 0, 1, 1);
670 			reg_r(gspca_dev, 0x21, 1, 1);
671 			spca504B_PollingDataReady(gspca_dev);
672 			break;
673 		}
674 		msleep(10);
675 	}
676 }
677 
spca50x_GetFirmware(struct gspca_dev * gspca_dev)678 static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
679 {
680 	__u8 *data;
681 
682 	data = gspca_dev->usb_buf;
683 	reg_r(gspca_dev, 0x20, 0, 5);
684 	PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
685 		data[0], data[1], data[2], data[3], data[4]);
686 	reg_r(gspca_dev, 0x23, 0, 64);
687 	reg_r(gspca_dev, 0x23, 1, 64);
688 }
689 
spca504B_SetSizeType(struct gspca_dev * gspca_dev)690 static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
691 {
692 	struct sd *sd = (struct sd *) gspca_dev;
693 	struct usb_device *dev = gspca_dev->dev;
694 	__u8 Size;
695 	__u8 Type;
696 	int rc;
697 
698 	Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
699 	Type = 0;
700 	switch (sd->bridge) {
701 	case BRIDGE_SPCA533:
702 		reg_w(gspca_dev, 0x31, 0, 0, 0);
703 		spca504B_WaitCmdStatus(gspca_dev);
704 		rc = spca504B_PollingDataReady(gspca_dev);
705 		spca50x_GetFirmware(gspca_dev);
706 		gspca_dev->usb_buf[0] = 2;			/* type */
707 		reg_w(gspca_dev, 0x24, 0, 8, 1);
708 		reg_r(gspca_dev, 0x24, 8, 1);
709 
710 		gspca_dev->usb_buf[0] = Size;
711 		reg_w(gspca_dev, 0x25, 0, 4, 1);
712 		reg_r(gspca_dev, 0x25, 4, 1);			/* size */
713 		rc = spca504B_PollingDataReady(gspca_dev);
714 
715 		/* Init the cam width height with some values get on init ? */
716 		reg_w(gspca_dev, 0x31, 0, 4, 0);
717 		spca504B_WaitCmdStatus(gspca_dev);
718 		rc = spca504B_PollingDataReady(gspca_dev);
719 		break;
720 	default:
721 /* case BRIDGE_SPCA504B: */
722 /* case BRIDGE_SPCA536: */
723 		gspca_dev->usb_buf[0] = Size;
724 		reg_w(gspca_dev, 0x25, 0, 4, 1);
725 		reg_r(gspca_dev, 0x25, 4, 1);			/* size */
726 		Type = 6;
727 		gspca_dev->usb_buf[0] = Type;
728 		reg_w(gspca_dev, 0x27, 0, 0, 1);
729 		reg_r(gspca_dev, 0x27, 0, 1);			/* type */
730 		rc = spca504B_PollingDataReady(gspca_dev);
731 		break;
732 	case BRIDGE_SPCA504:
733 		Size += 3;
734 		if (sd->subtype == AiptekMiniPenCam13) {
735 			/* spca504a aiptek */
736 			spca504A_acknowledged_command(gspca_dev,
737 						0x08, Size, 0,
738 						0x80 | (Size & 0x0f), 1);
739 			spca504A_acknowledged_command(gspca_dev,
740 							1, 3, 0, 0x9f, 0);
741 		} else {
742 			spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
743 		}
744 		break;
745 	case BRIDGE_SPCA504C:
746 		/* capture mode */
747 		reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
748 		reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
749 		break;
750 	}
751 }
752 
spca504_wait_status(struct gspca_dev * gspca_dev)753 static void spca504_wait_status(struct gspca_dev *gspca_dev)
754 {
755 	int cnt;
756 
757 	cnt = 256;
758 	while (--cnt > 0) {
759 		/* With this we get the status, when return 0 it's all ok */
760 		if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
761 			return;
762 		msleep(10);
763 	}
764 }
765 
spca504B_setQtable(struct gspca_dev * gspca_dev)766 static void spca504B_setQtable(struct gspca_dev *gspca_dev)
767 {
768 	gspca_dev->usb_buf[0] = 3;
769 	reg_w(gspca_dev, 0x26, 0, 0, 1);
770 	reg_r(gspca_dev, 0x26, 0, 1);
771 	spca504B_PollingDataReady(gspca_dev);
772 }
773 
sp5xx_initContBrigHueRegisters(struct gspca_dev * gspca_dev)774 static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
775 {
776 	struct sd *sd = (struct sd *) gspca_dev;
777 	int pollreg = 1;
778 
779 	switch (sd->bridge) {
780 	case BRIDGE_SPCA504:
781 	case BRIDGE_SPCA504C:
782 		pollreg = 0;
783 		/* fall thru */
784 	default:
785 /*	case BRIDGE_SPCA533: */
786 /*	case BRIDGE_SPCA504B: */
787 		reg_w(gspca_dev, 0, 0, 0x21a7, 0);	/* brightness */
788 		reg_w(gspca_dev, 0, 0x20, 0x21a8, 0);	/* contrast */
789 		reg_w(gspca_dev, 0, 0, 0x21ad, 0);	/* hue */
790 		reg_w(gspca_dev, 0, 1, 0x21ac, 0);	/* sat/hue */
791 		reg_w(gspca_dev, 0, 0x20, 0x21ae, 0);	/* saturation */
792 		reg_w(gspca_dev, 0, 0, 0x21a3, 0);	/* gamma */
793 		break;
794 	case BRIDGE_SPCA536:
795 		reg_w(gspca_dev, 0, 0, 0x20f0, 0);
796 		reg_w(gspca_dev, 0, 0x21, 0x20f1, 0);
797 		reg_w(gspca_dev, 0, 0x40, 0x20f5, 0);
798 		reg_w(gspca_dev, 0, 1, 0x20f4, 0);
799 		reg_w(gspca_dev, 0, 0x40, 0x20f6, 0);
800 		reg_w(gspca_dev, 0, 0, 0x2089, 0);
801 		break;
802 	}
803 	if (pollreg)
804 		spca504B_PollingDataReady(gspca_dev);
805 }
806 
807 /* this function is called at probe time */
sd_config(struct gspca_dev * gspca_dev,const struct usb_device_id * id)808 static int sd_config(struct gspca_dev *gspca_dev,
809 			const struct usb_device_id *id)
810 {
811 	struct sd *sd = (struct sd *) gspca_dev;
812 	struct cam *cam;
813 
814 	cam = &gspca_dev->cam;
815 	cam->epaddr = 0x01;
816 
817 	sd->bridge = id->driver_info >> 8;
818 	sd->subtype = id->driver_info;
819 
820 	if (sd->subtype == AiptekMiniPenCam13) {
821 /* try to get the firmware as some cam answer 2.0.1.2.2
822  * and should be a spca504b then overwrite that setting */
823 		reg_r(gspca_dev, 0x20, 0, 1);
824 		switch (gspca_dev->usb_buf[0]) {
825 		case 1:
826 			break;		/* (right bridge/subtype) */
827 		case 2:
828 			sd->bridge = BRIDGE_SPCA504B;
829 			sd->subtype = 0;
830 			break;
831 		default:
832 			return -ENODEV;
833 		}
834 	}
835 
836 	switch (sd->bridge) {
837 	default:
838 /*	case BRIDGE_SPCA504B: */
839 /*	case BRIDGE_SPCA504: */
840 /*	case BRIDGE_SPCA536: */
841 		cam->cam_mode = vga_mode;
842 		cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
843 		break;
844 	case BRIDGE_SPCA533:
845 		cam->cam_mode = custom_mode;
846 		cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
847 		break;
848 	case BRIDGE_SPCA504C:
849 		cam->cam_mode = vga_mode2;
850 		cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
851 		break;
852 	}
853 	sd->qindex = 5;			/* set the quantization table */
854 	sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
855 	sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
856 	sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
857 	return 0;
858 }
859 
860 /* this function is called at probe and resume time */
sd_init(struct gspca_dev * gspca_dev)861 static int sd_init(struct gspca_dev *gspca_dev)
862 {
863 	struct sd *sd = (struct sd *) gspca_dev;
864 	struct usb_device *dev = gspca_dev->dev;
865 	int rc;
866 	__u8 i;
867 	__u8 info[6];
868 	int err_code;
869 
870 	switch (sd->bridge) {
871 	case BRIDGE_SPCA504B:
872 		reg_w(gspca_dev, 0x1d, 0, 0, 0);
873 		reg_w(gspca_dev, 0, 1, 0x2306, 0);
874 		reg_w(gspca_dev, 0, 0, 0x0d04, 0);
875 		reg_w(gspca_dev, 0, 0, 0x2000, 0);
876 		reg_w(gspca_dev, 0, 0x13, 0x2301, 0);
877 		reg_w(gspca_dev, 0, 0, 0x2306, 0);
878 		/* fall thru */
879 	case BRIDGE_SPCA533:
880 		rc = spca504B_PollingDataReady(gspca_dev);
881 		spca50x_GetFirmware(gspca_dev);
882 		break;
883 	case BRIDGE_SPCA536:
884 		spca50x_GetFirmware(gspca_dev);
885 		reg_r(gspca_dev, 0x00, 0x5002, 1);
886 		gspca_dev->usb_buf[0] = 0;
887 		reg_w(gspca_dev, 0x24, 0, 0, 1);
888 		reg_r(gspca_dev, 0x24, 0, 1);
889 		rc = spca504B_PollingDataReady(gspca_dev);
890 		reg_w(gspca_dev, 0x34, 0, 0, 0);
891 		spca504B_WaitCmdStatus(gspca_dev);
892 		break;
893 	case BRIDGE_SPCA504C:	/* pccam600 */
894 		PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
895 		reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
896 		reg_w_riv(dev, 0xe0, 0x0000, 0x0001);	/* reset */
897 		spca504_wait_status(gspca_dev);
898 		if (sd->subtype == LogitechClickSmart420)
899 			write_vector(gspca_dev,
900 					spca504A_clicksmart420_open_data);
901 		else
902 			write_vector(gspca_dev, spca504_pccam600_open_data);
903 		err_code = spca50x_setup_qtable(gspca_dev,
904 						0x00, 0x2800,
905 						0x2840, qtable_creative_pccam);
906 		if (err_code < 0) {
907 			PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
908 			return err_code;
909 		}
910 		break;
911 	default:
912 /*	case BRIDGE_SPCA504: */
913 		PDEBUG(D_STREAM, "Opening SPCA504");
914 		if (sd->subtype == AiptekMiniPenCam13) {
915 			/*****************************/
916 			for (i = 0; i < 6; i++)
917 				info[i] = reg_r_1(gspca_dev, i);
918 			PDEBUG(D_STREAM,
919 				"Read info: %d %d %d %d %d %d."
920 				" Should be 1,0,2,2,0,0",
921 				info[0], info[1], info[2],
922 				info[3], info[4], info[5]);
923 			/* spca504a aiptek */
924 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
925 			spca504A_acknowledged_command(gspca_dev, 0x24,
926 							8, 3, 0x9e, 1);
927 			/* Twice sequencial need status 0xff->0x9e->0x9d */
928 			spca504A_acknowledged_command(gspca_dev, 0x24,
929 							8, 3, 0x9e, 0);
930 
931 			spca504A_acknowledged_command(gspca_dev, 0x24,
932 							0, 0, 0x9d, 1);
933 			/******************************/
934 			/* spca504a aiptek */
935 			spca504A_acknowledged_command(gspca_dev, 0x08,
936 							6, 0, 0x86, 1);
937 /*			reg_write (dev, 0, 0x2000, 0); */
938 /*			reg_write (dev, 0, 0x2883, 1); */
939 /*			spca504A_acknowledged_command (gspca_dev, 0x08,
940 							6, 0, 0x86, 1); */
941 /*			spca504A_acknowledged_command (gspca_dev, 0x24,
942 							0, 0, 0x9D, 1); */
943 			reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
944 			reg_w_riv(dev, 0x0, 0x2310, 0x05);
945 			spca504A_acknowledged_command(gspca_dev, 0x01,
946 							0x0f, 0, 0xff, 0);
947 		}
948 		/* setup qtable */
949 		reg_w_riv(dev, 0, 0x2000, 0);
950 		reg_w_riv(dev, 0, 0x2883, 1);
951 		err_code = spca50x_setup_qtable(gspca_dev,
952 						0x00, 0x2800,
953 						0x2840,
954 						qtable_spca504_default);
955 		if (err_code < 0) {
956 			PDEBUG(D_ERR, "spca50x_setup_qtable failed");
957 			return err_code;
958 		}
959 		break;
960 	}
961 	return 0;
962 }
963 
sd_start(struct gspca_dev * gspca_dev)964 static int sd_start(struct gspca_dev *gspca_dev)
965 {
966 	struct sd *sd = (struct sd *) gspca_dev;
967 	struct usb_device *dev = gspca_dev->dev;
968 	int rc;
969 	int enable;
970 	__u8 i;
971 	__u8 info[6];
972 
973 	if (sd->bridge == BRIDGE_SPCA504B)
974 		spca504B_setQtable(gspca_dev);
975 	spca504B_SetSizeType(gspca_dev);
976 	switch (sd->bridge) {
977 	default:
978 /*	case BRIDGE_SPCA504B: */
979 /*	case BRIDGE_SPCA533: */
980 /*	case BRIDGE_SPCA536: */
981 		if (sd->subtype == MegapixV4 ||
982 		    sd->subtype == LogitechClickSmart820) {
983 			reg_w(gspca_dev, 0xf0, 0, 0, 0);
984 			spca504B_WaitCmdStatus(gspca_dev);
985 			reg_r(gspca_dev, 0xf0, 4, 0);
986 			spca504B_WaitCmdStatus(gspca_dev);
987 		} else {
988 			reg_w(gspca_dev, 0x31, 0, 4, 0);
989 			spca504B_WaitCmdStatus(gspca_dev);
990 			rc = spca504B_PollingDataReady(gspca_dev);
991 		}
992 		break;
993 	case BRIDGE_SPCA504:
994 		if (sd->subtype == AiptekMiniPenCam13) {
995 			for (i = 0; i < 6; i++)
996 				info[i] = reg_r_1(gspca_dev, i);
997 			PDEBUG(D_STREAM,
998 				"Read info: %d %d %d %d %d %d."
999 				" Should be 1,0,2,2,0,0",
1000 				info[0], info[1], info[2],
1001 				info[3], info[4], info[5]);
1002 			/* spca504a aiptek */
1003 			/* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1004 			spca504A_acknowledged_command(gspca_dev, 0x24,
1005 							8, 3, 0x9e, 1);
1006 			/* Twice sequencial need status 0xff->0x9e->0x9d */
1007 			spca504A_acknowledged_command(gspca_dev, 0x24,
1008 							8, 3, 0x9e, 0);
1009 			spca504A_acknowledged_command(gspca_dev, 0x24,
1010 							0, 0, 0x9d, 1);
1011 		} else {
1012 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1013 			for (i = 0; i < 6; i++)
1014 				info[i] = reg_r_1(gspca_dev, i);
1015 			PDEBUG(D_STREAM,
1016 				"Read info: %d %d %d %d %d %d."
1017 				" Should be 1,0,2,2,0,0",
1018 				info[0], info[1], info[2],
1019 				info[3], info[4], info[5]);
1020 			spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1021 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1022 		}
1023 		spca504B_SetSizeType(gspca_dev);
1024 		reg_w_riv(dev, 0x0, 0x270c, 0x05);	/* L92 sno1t.txt */
1025 		reg_w_riv(dev, 0x0, 0x2310, 0x05);
1026 		break;
1027 	case BRIDGE_SPCA504C:
1028 		if (sd->subtype == LogitechClickSmart420) {
1029 			write_vector(gspca_dev,
1030 					spca504A_clicksmart420_init_data);
1031 		} else {
1032 			write_vector(gspca_dev, spca504_pccam600_init_data);
1033 		}
1034 		enable = (sd->autogain ? 0x04 : 0x01);
1035 		reg_w_riv(dev, 0x0c, 0x0000, enable);	/* auto exposure */
1036 		reg_w_riv(dev, 0xb0, 0x0000, enable);	/* auto whiteness */
1037 
1038 		/* set default exposure compensation and whiteness balance */
1039 		reg_w_riv(dev, 0x30, 0x0001, 800);	/* ~ 20 fps */
1040 		reg_w_riv(dev, 0x30, 0x0002, 1600);
1041 		spca504B_SetSizeType(gspca_dev);
1042 		break;
1043 	}
1044 	sp5xx_initContBrigHueRegisters(gspca_dev);
1045 	return 0;
1046 }
1047 
sd_stopN(struct gspca_dev * gspca_dev)1048 static void sd_stopN(struct gspca_dev *gspca_dev)
1049 {
1050 	struct sd *sd = (struct sd *) gspca_dev;
1051 	struct usb_device *dev = gspca_dev->dev;
1052 
1053 	switch (sd->bridge) {
1054 	default:
1055 /*	case BRIDGE_SPCA533: */
1056 /*	case BRIDGE_SPCA536: */
1057 /*	case BRIDGE_SPCA504B: */
1058 		reg_w(gspca_dev, 0x31, 0, 0, 0);
1059 		spca504B_WaitCmdStatus(gspca_dev);
1060 		spca504B_PollingDataReady(gspca_dev);
1061 		break;
1062 	case BRIDGE_SPCA504:
1063 	case BRIDGE_SPCA504C:
1064 		reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1065 
1066 		if (sd->subtype == AiptekMiniPenCam13) {
1067 			/* spca504a aiptek */
1068 /*			spca504A_acknowledged_command(gspca_dev, 0x08,
1069 							 6, 0, 0x86, 1); */
1070 			spca504A_acknowledged_command(gspca_dev, 0x24,
1071 							0x00, 0x00, 0x9d, 1);
1072 			spca504A_acknowledged_command(gspca_dev, 0x01,
1073 							0x0f, 0x00, 0xff, 1);
1074 		} else {
1075 			spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1076 			reg_w_riv(dev, 0x01, 0x000f, 0x00);
1077 		}
1078 		break;
1079 	}
1080 }
1081 
sd_pkt_scan(struct gspca_dev * gspca_dev,struct gspca_frame * frame,__u8 * data,int len)1082 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1083 			struct gspca_frame *frame,	/* target */
1084 			__u8 *data,			/* isoc packet */
1085 			int len)			/* iso packet length */
1086 {
1087 	struct sd *sd = (struct sd *) gspca_dev;
1088 	int i, sof = 0;
1089 	unsigned char *s, *d;
1090 	static unsigned char ffd9[] = {0xff, 0xd9};
1091 
1092 /* frames are jpeg 4.1.1 without 0xff escape */
1093 	switch (sd->bridge) {
1094 	case BRIDGE_SPCA533:
1095 		if (data[0] == 0xff) {
1096 			if (data[1] != 0x01) {	/* drop packet */
1097 /*				gspca_dev->last_packet_type = DISCARD_PACKET; */
1098 				return;
1099 			}
1100 			sof = 1;
1101 			data += SPCA533_OFFSET_DATA;
1102 			len -= SPCA533_OFFSET_DATA;
1103 		} else {
1104 			data += 1;
1105 			len -= 1;
1106 		}
1107 		break;
1108 	case BRIDGE_SPCA536:
1109 		if (data[0] == 0xff) {
1110 			sof = 1;
1111 			data += SPCA536_OFFSET_DATA;
1112 			len -= SPCA536_OFFSET_DATA;
1113 		} else {
1114 			data += 2;
1115 			len -= 2;
1116 		}
1117 		break;
1118 	default:
1119 /*	case BRIDGE_SPCA504: */
1120 /*	case BRIDGE_SPCA504B: */
1121 		switch (data[0]) {
1122 		case 0xfe:			/* start of frame */
1123 			sof = 1;
1124 			data += SPCA50X_OFFSET_DATA;
1125 			len -= SPCA50X_OFFSET_DATA;
1126 			break;
1127 		case 0xff:			/* drop packet */
1128 /*			gspca_dev->last_packet_type = DISCARD_PACKET; */
1129 			return;
1130 		default:
1131 			data += 1;
1132 			len -= 1;
1133 			break;
1134 		}
1135 		break;
1136 	case BRIDGE_SPCA504C:
1137 		switch (data[0]) {
1138 		case 0xfe:			/* start of frame */
1139 			sof = 1;
1140 			data += SPCA504_PCCAM600_OFFSET_DATA;
1141 			len -= SPCA504_PCCAM600_OFFSET_DATA;
1142 			break;
1143 		case 0xff:			/* drop packet */
1144 /*			gspca_dev->last_packet_type = DISCARD_PACKET; */
1145 			return;
1146 		default:
1147 			data += 1;
1148 			len -= 1;
1149 			break;
1150 		}
1151 		break;
1152 	}
1153 	if (sof) {		/* start of frame */
1154 		frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1155 					ffd9, 2);
1156 
1157 		/* put the JPEG header in the new frame */
1158 		jpeg_put_header(gspca_dev, frame,
1159 				((struct sd *) gspca_dev)->qindex,
1160 				0x22);
1161 	}
1162 
1163 	/* add 0x00 after 0xff */
1164 	for (i = len; --i >= 0; )
1165 		if (data[i] == 0xff)
1166 			break;
1167 	if (i < 0) {			/* no 0xff */
1168 		gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1169 		return;
1170 	}
1171 	s = data;
1172 	d = sd->packet;
1173 	for (i = 0; i < len; i++) {
1174 		*d++ = *s++;
1175 		if (s[-1] == 0xff)
1176 			*d++ = 0x00;
1177 	}
1178 	gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1179 			sd->packet, d - sd->packet);
1180 }
1181 
setbrightness(struct gspca_dev * gspca_dev)1182 static void setbrightness(struct gspca_dev *gspca_dev)
1183 {
1184 	struct sd *sd = (struct sd *) gspca_dev;
1185 	struct usb_device *dev = gspca_dev->dev;
1186 
1187 	switch (sd->bridge) {
1188 	default:
1189 /*	case BRIDGE_SPCA533: */
1190 /*	case BRIDGE_SPCA504B: */
1191 /*	case BRIDGE_SPCA504: */
1192 /*	case BRIDGE_SPCA504C: */
1193 		reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1194 		break;
1195 	case BRIDGE_SPCA536:
1196 		reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1197 		break;
1198 	}
1199 }
1200 
getbrightness(struct gspca_dev * gspca_dev)1201 static void getbrightness(struct gspca_dev *gspca_dev)
1202 {
1203 	struct sd *sd = (struct sd *) gspca_dev;
1204 	__u16 brightness = 0;
1205 
1206 	switch (sd->bridge) {
1207 	default:
1208 /*	case BRIDGE_SPCA533: */
1209 /*	case BRIDGE_SPCA504B: */
1210 /*	case BRIDGE_SPCA504: */
1211 /*	case BRIDGE_SPCA504C: */
1212 		brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1213 		break;
1214 	case BRIDGE_SPCA536:
1215 		brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1216 		break;
1217 	}
1218 	sd->brightness = ((brightness & 0xff) - 128) % 255;
1219 }
1220 
setcontrast(struct gspca_dev * gspca_dev)1221 static void setcontrast(struct gspca_dev *gspca_dev)
1222 {
1223 	struct sd *sd = (struct sd *) gspca_dev;
1224 	struct usb_device *dev = gspca_dev->dev;
1225 
1226 	switch (sd->bridge) {
1227 	default:
1228 /*	case BRIDGE_SPCA533: */
1229 /*	case BRIDGE_SPCA504B: */
1230 /*	case BRIDGE_SPCA504: */
1231 /*	case BRIDGE_SPCA504C: */
1232 		reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1233 		break;
1234 	case BRIDGE_SPCA536:
1235 		reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1236 		break;
1237 	}
1238 }
1239 
getcontrast(struct gspca_dev * gspca_dev)1240 static void getcontrast(struct gspca_dev *gspca_dev)
1241 {
1242 	struct sd *sd = (struct sd *) gspca_dev;
1243 
1244 	switch (sd->bridge) {
1245 	default:
1246 /*	case BRIDGE_SPCA533: */
1247 /*	case BRIDGE_SPCA504B: */
1248 /*	case BRIDGE_SPCA504: */
1249 /*	case BRIDGE_SPCA504C: */
1250 		sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1251 		break;
1252 	case BRIDGE_SPCA536:
1253 		sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1254 		break;
1255 	}
1256 }
1257 
setcolors(struct gspca_dev * gspca_dev)1258 static void setcolors(struct gspca_dev *gspca_dev)
1259 {
1260 	struct sd *sd = (struct sd *) gspca_dev;
1261 	struct usb_device *dev = gspca_dev->dev;
1262 
1263 	switch (sd->bridge) {
1264 	default:
1265 /*	case BRIDGE_SPCA533: */
1266 /*	case BRIDGE_SPCA504B: */
1267 /*	case BRIDGE_SPCA504: */
1268 /*	case BRIDGE_SPCA504C: */
1269 		reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1270 		break;
1271 	case BRIDGE_SPCA536:
1272 		reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1273 		break;
1274 	}
1275 }
1276 
getcolors(struct gspca_dev * gspca_dev)1277 static void getcolors(struct gspca_dev *gspca_dev)
1278 {
1279 	struct sd *sd = (struct sd *) gspca_dev;
1280 
1281 	switch (sd->bridge) {
1282 	default:
1283 /*	case BRIDGE_SPCA533: */
1284 /*	case BRIDGE_SPCA504B: */
1285 /*	case BRIDGE_SPCA504: */
1286 /*	case BRIDGE_SPCA504C: */
1287 		sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1288 		break;
1289 	case BRIDGE_SPCA536:
1290 		sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1291 		break;
1292 	}
1293 }
1294 
sd_setbrightness(struct gspca_dev * gspca_dev,__s32 val)1295 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1296 {
1297 	struct sd *sd = (struct sd *) gspca_dev;
1298 
1299 	sd->brightness = val;
1300 	if (gspca_dev->streaming)
1301 		setbrightness(gspca_dev);
1302 	return 0;
1303 }
1304 
sd_getbrightness(struct gspca_dev * gspca_dev,__s32 * val)1305 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1306 {
1307 	struct sd *sd = (struct sd *) gspca_dev;
1308 
1309 	getbrightness(gspca_dev);
1310 	*val = sd->brightness;
1311 	return 0;
1312 }
1313 
sd_setcontrast(struct gspca_dev * gspca_dev,__s32 val)1314 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1315 {
1316 	struct sd *sd = (struct sd *) gspca_dev;
1317 
1318 	sd->contrast = val;
1319 	if (gspca_dev->streaming)
1320 		setcontrast(gspca_dev);
1321 	return 0;
1322 }
1323 
sd_getcontrast(struct gspca_dev * gspca_dev,__s32 * val)1324 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1325 {
1326 	struct sd *sd = (struct sd *) gspca_dev;
1327 
1328 	getcontrast(gspca_dev);
1329 	*val = sd->contrast;
1330 	return 0;
1331 }
1332 
sd_setcolors(struct gspca_dev * gspca_dev,__s32 val)1333 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1334 {
1335 	struct sd *sd = (struct sd *) gspca_dev;
1336 
1337 	sd->colors = val;
1338 	if (gspca_dev->streaming)
1339 		setcolors(gspca_dev);
1340 	return 0;
1341 }
1342 
sd_getcolors(struct gspca_dev * gspca_dev,__s32 * val)1343 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1344 {
1345 	struct sd *sd = (struct sd *) gspca_dev;
1346 
1347 	getcolors(gspca_dev);
1348 	*val = sd->colors;
1349 	return 0;
1350 }
1351 
sd_setautogain(struct gspca_dev * gspca_dev,__s32 val)1352 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1353 {
1354 	struct sd *sd = (struct sd *) gspca_dev;
1355 
1356 	sd->autogain = val;
1357 	return 0;
1358 }
1359 
sd_getautogain(struct gspca_dev * gspca_dev,__s32 * val)1360 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1361 {
1362 	struct sd *sd = (struct sd *) gspca_dev;
1363 
1364 	*val = sd->autogain;
1365 	return 0;
1366 }
1367 
1368 /* sub-driver description */
1369 static const struct sd_desc sd_desc = {
1370 	.name = MODULE_NAME,
1371 	.ctrls = sd_ctrls,
1372 	.nctrls = ARRAY_SIZE(sd_ctrls),
1373 	.config = sd_config,
1374 	.init = sd_init,
1375 	.start = sd_start,
1376 	.stopN = sd_stopN,
1377 	.pkt_scan = sd_pkt_scan,
1378 };
1379 
1380 /* -- module initialisation -- */
1381 #define BS(bridge, subtype) \
1382 	.driver_info = (BRIDGE_ ## bridge << 8) \
1383 			| (subtype)
1384 static const __devinitdata struct usb_device_id device_table[] = {
1385 	{USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1386 	{USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1387 	{USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1388 	{USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1389 	{USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1390 	{USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1391 	{USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1392 	{USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1393 	{USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1394 	{USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1395 	{USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1396 	{USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1397 	{USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1398 	{USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1399 	{USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1400 	{USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1401 	{USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1402 	{USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1403 	{USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
1404 	{USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1405 	{USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1406 	{USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1407 	{USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1408 	{USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1409 	{USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1410 	{USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1411 	{USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1412 	{USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1413 	{USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1414 	{USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1415 	{USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1416 	{USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1417 	{USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1418 	{USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1419 	{USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1420 	{USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1421 	{USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1422 	{USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1423 	{USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1424 	{USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1425 	{USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1426 	{USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1427 	{USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1428 	{USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1429 	{USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1430 	{USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1431 	{USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1432 	{USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1433 	{USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1434 	{USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1435 	{USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1436 	{USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1437 	{USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1438 	{USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1439 	{USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1440 	{USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1441 	{USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
1442 	{}
1443 };
1444 MODULE_DEVICE_TABLE(usb, device_table);
1445 
1446 /* -- device connect -- */
sd_probe(struct usb_interface * intf,const struct usb_device_id * id)1447 static int sd_probe(struct usb_interface *intf,
1448 			const struct usb_device_id *id)
1449 {
1450 	return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1451 				THIS_MODULE);
1452 }
1453 
1454 static struct usb_driver sd_driver = {
1455 	.name = MODULE_NAME,
1456 	.id_table = device_table,
1457 	.probe = sd_probe,
1458 	.disconnect = gspca_disconnect,
1459 #ifdef CONFIG_PM
1460 	.suspend = gspca_suspend,
1461 	.resume = gspca_resume,
1462 #endif
1463 };
1464 
1465 /* -- module insert / remove -- */
sd_mod_init(void)1466 static int __init sd_mod_init(void)
1467 {
1468 	if (usb_register(&sd_driver) < 0)
1469 		return -1;
1470 	PDEBUG(D_PROBE, "registered");
1471 	return 0;
1472 }
sd_mod_exit(void)1473 static void __exit sd_mod_exit(void)
1474 {
1475 	usb_deregister(&sd_driver);
1476 	PDEBUG(D_PROBE, "deregistered");
1477 }
1478 
1479 module_init(sd_mod_init);
1480 module_exit(sd_mod_exit);
1481