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