]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/media/video/gspca/sunplus.c
tree-wide: fix assorted typos all over the place
[mirror_ubuntu-zesty-kernel.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{
8295d99e
JFM
463#ifdef GSPCA_DEBUG
464 if (len > USB_BUF_SZ) {
465 err("reg_r: buffer overflow");
466 return;
467 }
468#endif
469 usb_control_msg(gspca_dev->dev,
470 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
471 req,
472 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
473 0, /* value */
8295d99e
JFM
474 index,
475 len ? gspca_dev->usb_buf : NULL, len,
6a7eba24
JFM
476 500);
477}
478
2e1794b5
JFM
479/* write one byte */
480static void reg_w_1(struct gspca_dev *gspca_dev,
481 u8 req,
482 u16 value,
483 u16 index,
484 u16 byte)
6a7eba24 485{
2e1794b5 486 gspca_dev->usb_buf[0] = byte;
8295d99e
JFM
487 usb_control_msg(gspca_dev->dev,
488 usb_sndctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
489 req,
490 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
8295d99e 491 value, index,
2e1794b5 492 gspca_dev->usb_buf, 1,
6a7eba24
JFM
493 500);
494}
495
739570bb
JFM
496/* write req / index / value */
497static int reg_w_riv(struct usb_device *dev,
2e1794b5 498 u8 req, u16 index, u16 value)
6a7eba24
JFM
499{
500 int ret;
501
502 ret = usb_control_msg(dev,
503 usb_sndctrlpipe(dev, 0),
504 req,
bf7f0b98 505 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6a7eba24 506 value, index, NULL, 0, 500);
739570bb 507 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
956e42d2 508 req, index, value, ret);
6a7eba24
JFM
509 if (ret < 0)
510 PDEBUG(D_ERR, "reg write: error %d", ret);
511 return ret;
512}
513
739570bb
JFM
514/* read 1 byte */
515static int reg_r_1(struct gspca_dev *gspca_dev,
2e1794b5 516 u16 value) /* wValue */
6a7eba24
JFM
517{
518 int ret;
6a7eba24 519
739570bb
JFM
520 ret = usb_control_msg(gspca_dev->dev,
521 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
522 0x20, /* request */
523 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
524 value,
525 0, /* index */
739570bb 526 gspca_dev->usb_buf, 1,
6a7eba24
JFM
527 500); /* timeout */
528 if (ret < 0) {
739570bb 529 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
6a7eba24
JFM
530 return 0;
531 }
739570bb 532 return gspca_dev->usb_buf[0];
6a7eba24
JFM
533}
534
739570bb
JFM
535/* read 1 or 2 bytes - returns < 0 if error */
536static int reg_r_12(struct gspca_dev *gspca_dev,
2e1794b5
JFM
537 u8 req, /* bRequest */
538 u16 index, /* wIndex */
539 u16 length) /* wLength (1 or 2 only) */
6a7eba24
JFM
540{
541 int ret;
6a7eba24 542
739570bb
JFM
543 gspca_dev->usb_buf[1] = 0;
544 ret = usb_control_msg(gspca_dev->dev,
545 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
546 req,
547 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
548 0, /* value */
549 index,
739570bb 550 gspca_dev->usb_buf, length,
6a7eba24
JFM
551 500);
552 if (ret < 0) {
553 PDEBUG(D_ERR, "reg_read err %d", ret);
554 return -1;
555 }
739570bb 556 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
6a7eba24
JFM
557}
558
559static int write_vector(struct gspca_dev *gspca_dev,
2e1794b5 560 const struct cmd *data, int ncmds)
6a7eba24
JFM
561{
562 struct usb_device *dev = gspca_dev->dev;
2e1794b5 563 int ret;
6a7eba24 564
2e1794b5
JFM
565 while (--ncmds >= 0) {
566 ret = reg_w_riv(dev, data->req, data->idx, data->val);
6a7eba24
JFM
567 if (ret < 0) {
568 PDEBUG(D_ERR,
2e1794b5
JFM
569 "Register write failed for 0x%02x, 0x%04x, 0x%04x",
570 data->req, data->val, data->idx);
6a7eba24
JFM
571 return ret;
572 }
2e1794b5 573 data++;
6a7eba24
JFM
574 }
575 return 0;
576}
577
578static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
2e1794b5 579 const u8 qtable[2][64])
6a7eba24
JFM
580{
581 struct usb_device *dev = gspca_dev->dev;
582 int i, err;
583
584 /* loop over y components */
585 for (i = 0; i < 64; i++) {
2e1794b5 586 err = reg_w_riv(dev, 0x00, 0x2800 + i, qtable[0][i]);
6a7eba24
JFM
587 if (err < 0)
588 return err;
589 }
590
591 /* loop over c components */
592 for (i = 0; i < 64; i++) {
2e1794b5 593 err = reg_w_riv(dev, 0x00, 0x2840 + i, qtable[1][i]);
6a7eba24
JFM
594 if (err < 0)
595 return err;
596 }
597 return 0;
598}
599
600static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
2e1794b5 601 u8 req, u16 idx, u16 val)
6a7eba24
JFM
602{
603 struct usb_device *dev = gspca_dev->dev;
2e1794b5 604 int notdone;
6a7eba24 605
739570bb
JFM
606 reg_w_riv(dev, req, idx, val);
607 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
608 reg_w_riv(dev, req, idx, val);
6a7eba24 609
2e1794b5 610 PDEBUG(D_FRAM, "before wait 0x%04x", notdone);
6a7eba24
JFM
611
612 msleep(200);
739570bb 613 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
2e1794b5 614 PDEBUG(D_FRAM, "after wait 0x%04x", notdone);
6a7eba24
JFM
615}
616
617static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
2e1794b5
JFM
618 u8 req,
619 u16 idx, u16 val, u8 stat, u8 count)
6a7eba24
JFM
620{
621 struct usb_device *dev = gspca_dev->dev;
2e1794b5
JFM
622 int status;
623 u8 endcode;
6a7eba24 624
739570bb
JFM
625 reg_w_riv(dev, req, idx, val);
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
6a7eba24 627 endcode = stat;
2e1794b5 628 PDEBUG(D_FRAM, "Status 0x%x Need 0x%04x", status, stat);
6a7eba24
JFM
629 if (!count)
630 return;
631 count = 200;
632 while (--count > 0) {
633 msleep(10);
af901ca1 634 /* gsmart mini2 write a each wait setting 1 ms is enough */
739570bb
JFM
635/* reg_w_riv(dev, req, idx, val); */
636 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
6a7eba24 637 if (status == endcode) {
2e1794b5 638 PDEBUG(D_FRAM, "status 0x%04x after wait %d",
6a7eba24
JFM
639 status, 200 - count);
640 break;
641 }
642 }
643}
644
739570bb 645static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
6a7eba24 646{
6a7eba24
JFM
647 int count = 10;
648
649 while (--count > 0) {
8295d99e 650 reg_r(gspca_dev, 0x21, 0, 1);
739570bb 651 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
6a7eba24
JFM
652 break;
653 msleep(10);
654 }
739570bb 655 return gspca_dev->usb_buf[0];
6a7eba24
JFM
656}
657
658static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
659{
6a7eba24
JFM
660 int count = 50;
661
662 while (--count > 0) {
8295d99e 663 reg_r(gspca_dev, 0x21, 1, 1);
739570bb 664 if (gspca_dev->usb_buf[0] != 0) {
2e1794b5 665 reg_w_1(gspca_dev, 0x21, 0, 1, 0);
8295d99e 666 reg_r(gspca_dev, 0x21, 1, 1);
739570bb 667 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
668 break;
669 }
670 msleep(10);
671 }
672}
673
674static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
675{
2e1794b5 676 u8 *data;
6a7eba24 677
8295d99e
JFM
678 data = gspca_dev->usb_buf;
679 reg_r(gspca_dev, 0x20, 0, 5);
6a7eba24 680 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
739570bb 681 data[0], data[1], data[2], data[3], data[4]);
8295d99e
JFM
682 reg_r(gspca_dev, 0x23, 0, 64);
683 reg_r(gspca_dev, 0x23, 1, 64);
6a7eba24
JFM
684}
685
686static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
687{
688 struct sd *sd = (struct sd *) gspca_dev;
689 struct usb_device *dev = gspca_dev->dev;
2e1794b5 690 u8 Size;
6a7eba24
JFM
691 int rc;
692
2e1794b5 693 Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
6a7eba24
JFM
694 switch (sd->bridge) {
695 case BRIDGE_SPCA533:
2e1794b5 696 reg_w_riv(dev, 0x31, 0, 0);
6a7eba24 697 spca504B_WaitCmdStatus(gspca_dev);
739570bb 698 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24 699 spca50x_GetFirmware(gspca_dev);
2e1794b5 700 reg_w_1(gspca_dev, 0x24, 0, 8, 2); /* type */
8295d99e 701 reg_r(gspca_dev, 0x24, 8, 1);
6a7eba24 702
2e1794b5 703 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
8295d99e 704 reg_r(gspca_dev, 0x25, 4, 1); /* size */
739570bb 705 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
706
707 /* Init the cam width height with some values get on init ? */
2e1794b5 708 reg_w_riv(dev, 0x31, 0, 0x04);
6a7eba24 709 spca504B_WaitCmdStatus(gspca_dev);
739570bb 710 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
711 break;
712 default:
713/* case BRIDGE_SPCA504B: */
714/* case BRIDGE_SPCA536: */
2e1794b5 715 reg_w_1(gspca_dev, 0x25, 0, 4, Size);
8295d99e 716 reg_r(gspca_dev, 0x25, 4, 1); /* size */
2e1794b5 717 reg_w_1(gspca_dev, 0x27, 0, 0, 6);
8295d99e 718 reg_r(gspca_dev, 0x27, 0, 1); /* type */
739570bb 719 rc = spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
720 break;
721 case BRIDGE_SPCA504:
722 Size += 3;
723 if (sd->subtype == AiptekMiniPenCam13) {
724 /* spca504a aiptek */
725 spca504A_acknowledged_command(gspca_dev,
726 0x08, Size, 0,
727 0x80 | (Size & 0x0f), 1);
728 spca504A_acknowledged_command(gspca_dev,
729 1, 3, 0, 0x9f, 0);
730 } else {
731 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
732 }
733 break;
734 case BRIDGE_SPCA504C:
735 /* capture mode */
739570bb
JFM
736 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
737 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
6a7eba24
JFM
738 break;
739 }
740}
741
742static void spca504_wait_status(struct gspca_dev *gspca_dev)
743{
6a7eba24
JFM
744 int cnt;
745
746 cnt = 256;
747 while (--cnt > 0) {
748 /* With this we get the status, when return 0 it's all ok */
739570bb 749 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
6a7eba24
JFM
750 return;
751 msleep(10);
752 }
753}
754
755static void spca504B_setQtable(struct gspca_dev *gspca_dev)
756{
2e1794b5 757 reg_w_1(gspca_dev, 0x26, 0, 0, 3);
8295d99e 758 reg_r(gspca_dev, 0x26, 0, 1);
739570bb 759 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
760}
761
2e1794b5
JFM
762static void setbrightness(struct gspca_dev *gspca_dev)
763{
764 struct sd *sd = (struct sd *) gspca_dev;
765 struct usb_device *dev = gspca_dev->dev;
766 u16 reg;
767
768 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
769 reg_w_riv(dev, 0x00, reg, sd->brightness);
770}
771
772static void setcontrast(struct gspca_dev *gspca_dev)
6a7eba24
JFM
773{
774 struct sd *sd = (struct sd *) gspca_dev;
2e1794b5
JFM
775 struct usb_device *dev = gspca_dev->dev;
776 u16 reg;
777
778 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
779 reg_w_riv(dev, 0x00, reg, sd->contrast);
780}
781
782static void setcolors(struct gspca_dev *gspca_dev)
783{
784 struct sd *sd = (struct sd *) gspca_dev;
785 struct usb_device *dev = gspca_dev->dev;
786 u16 reg;
787
788 reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
789 reg_w_riv(dev, 0x00, reg, sd->colors);
790}
791
792static void init_ctl_reg(struct gspca_dev *gspca_dev)
793{
794 struct sd *sd = (struct sd *) gspca_dev;
795 struct usb_device *dev = gspca_dev->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: */
2e1794b5
JFM
810 reg_w_riv(dev, 0, 0x00, 0x21ad); /* hue */
811 reg_w_riv(dev, 0, 0x01, 0x21ac); /* sat/hue */
812 reg_w_riv(dev, 0, 0x00, 0x21a3); /* gamma */
6a7eba24
JFM
813 break;
814 case BRIDGE_SPCA536:
2e1794b5
JFM
815 reg_w_riv(dev, 0, 0x40, 0x20f5);
816 reg_w_riv(dev, 0, 0x01, 0x20f4);
817 reg_w_riv(dev, 0, 0x00, 0x2089);
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;
884 struct usb_device *dev = gspca_dev->dev;
2e1794b5
JFM
885 int i, err_code;
886 u8 info[6];
6a7eba24
JFM
887
888 switch (sd->bridge) {
889 case BRIDGE_SPCA504B:
2e1794b5
JFM
890 reg_w_riv(dev, 0x1d, 0x00, 0);
891 reg_w_riv(dev, 0, 0x01, 0x2306);
892 reg_w_riv(dev, 0, 0x00, 0x0d04);
893 reg_w_riv(dev, 0, 0x00, 0x2000);
894 reg_w_riv(dev, 0, 0x13, 0x2301);
895 reg_w_riv(dev, 0, 0x00, 0x2306);
6a7eba24
JFM
896 /* fall thru */
897 case BRIDGE_SPCA533:
2e1794b5 898 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
899 spca50x_GetFirmware(gspca_dev);
900 break;
901 case BRIDGE_SPCA536:
902 spca50x_GetFirmware(gspca_dev);
8295d99e 903 reg_r(gspca_dev, 0x00, 0x5002, 1);
2e1794b5 904 reg_w_1(gspca_dev, 0x24, 0, 0, 0);
8295d99e 905 reg_r(gspca_dev, 0x24, 0, 1);
2e1794b5
JFM
906 spca504B_PollingDataReady(gspca_dev);
907 reg_w_riv(dev, 0x34, 0, 0);
6a7eba24
JFM
908 spca504B_WaitCmdStatus(gspca_dev);
909 break;
910 case BRIDGE_SPCA504C: /* pccam600 */
911 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
739570bb
JFM
912 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
913 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
6a7eba24
JFM
914 spca504_wait_status(gspca_dev);
915 if (sd->subtype == LogitechClickSmart420)
916 write_vector(gspca_dev,
2e1794b5
JFM
917 spca504A_clicksmart420_open_data,
918 ARRAY_SIZE(spca504A_clicksmart420_open_data));
6a7eba24 919 else
2e1794b5
JFM
920 write_vector(gspca_dev, spca504_pccam600_open_data,
921 ARRAY_SIZE(spca504_pccam600_open_data));
6a7eba24 922 err_code = spca50x_setup_qtable(gspca_dev,
2e1794b5 923 qtable_creative_pccam);
6a7eba24
JFM
924 if (err_code < 0) {
925 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
926 return err_code;
927 }
928 break;
929 default:
930/* case BRIDGE_SPCA504: */
931 PDEBUG(D_STREAM, "Opening SPCA504");
932 if (sd->subtype == AiptekMiniPenCam13) {
933 /*****************************/
934 for (i = 0; i < 6; i++)
739570bb 935 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
936 PDEBUG(D_STREAM,
937 "Read info: %d %d %d %d %d %d."
938 " Should be 1,0,2,2,0,0",
939 info[0], info[1], info[2],
940 info[3], info[4], info[5]);
941 /* spca504a aiptek */
942 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
943 spca504A_acknowledged_command(gspca_dev, 0x24,
944 8, 3, 0x9e, 1);
945 /* Twice sequencial need status 0xff->0x9e->0x9d */
946 spca504A_acknowledged_command(gspca_dev, 0x24,
947 8, 3, 0x9e, 0);
948
949 spca504A_acknowledged_command(gspca_dev, 0x24,
950 0, 0, 0x9d, 1);
951 /******************************/
952 /* spca504a aiptek */
953 spca504A_acknowledged_command(gspca_dev, 0x08,
954 6, 0, 0x86, 1);
955/* reg_write (dev, 0, 0x2000, 0); */
956/* reg_write (dev, 0, 0x2883, 1); */
957/* spca504A_acknowledged_command (gspca_dev, 0x08,
958 6, 0, 0x86, 1); */
959/* spca504A_acknowledged_command (gspca_dev, 0x24,
960 0, 0, 0x9D, 1); */
2e1794b5
JFM
961 reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
962 reg_w_riv(dev, 0x00, 0x2310, 0x05);
6a7eba24
JFM
963 spca504A_acknowledged_command(gspca_dev, 0x01,
964 0x0f, 0, 0xff, 0);
965 }
966 /* setup qtable */
739570bb
JFM
967 reg_w_riv(dev, 0, 0x2000, 0);
968 reg_w_riv(dev, 0, 0x2883, 1);
6a7eba24 969 err_code = spca50x_setup_qtable(gspca_dev,
6a7eba24
JFM
970 qtable_spca504_default);
971 if (err_code < 0) {
972 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
973 return err_code;
974 }
975 break;
976 }
977 return 0;
978}
979
72ab97ce 980static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24
JFM
981{
982 struct sd *sd = (struct sd *) gspca_dev;
983 struct usb_device *dev = gspca_dev->dev;
6a7eba24 984 int enable;
2e1794b5
JFM
985 int i;
986 u8 info[6];
6a7eba24 987
71cb2764
JFM
988 /* create the JPEG header */
989 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
3eb0237d
JL
990 if (!sd->jpeg_hdr)
991 return -ENOMEM;
71cb2764
JFM
992 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
993 0x22); /* JPEG 411 */
994 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
995
6a7eba24
JFM
996 if (sd->bridge == BRIDGE_SPCA504B)
997 spca504B_setQtable(gspca_dev);
998 spca504B_SetSizeType(gspca_dev);
999 switch (sd->bridge) {
1000 default:
1001/* case BRIDGE_SPCA504B: */
1002/* case BRIDGE_SPCA533: */
1003/* case BRIDGE_SPCA536: */
2e1794b5
JFM
1004 switch (sd->subtype) {
1005 case MegapixV4:
1006 case LogitechClickSmart820:
1007 case MegaImageVI:
1008 reg_w_riv(dev, 0xf0, 0, 0);
6a7eba24 1009 spca504B_WaitCmdStatus(gspca_dev);
8295d99e 1010 reg_r(gspca_dev, 0xf0, 4, 0);
6a7eba24 1011 spca504B_WaitCmdStatus(gspca_dev);
2e1794b5
JFM
1012 break;
1013 default:
1014 reg_w_riv(dev, 0x31, 0, 0x04);
6a7eba24 1015 spca504B_WaitCmdStatus(gspca_dev);
2e1794b5
JFM
1016 spca504B_PollingDataReady(gspca_dev);
1017 break;
6a7eba24
JFM
1018 }
1019 break;
1020 case BRIDGE_SPCA504:
1021 if (sd->subtype == AiptekMiniPenCam13) {
1022 for (i = 0; i < 6; i++)
739570bb 1023 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
1024 PDEBUG(D_STREAM,
1025 "Read info: %d %d %d %d %d %d."
1026 " Should be 1,0,2,2,0,0",
1027 info[0], info[1], info[2],
1028 info[3], info[4], info[5]);
1029 /* spca504a aiptek */
1030 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1031 spca504A_acknowledged_command(gspca_dev, 0x24,
1032 8, 3, 0x9e, 1);
1033 /* Twice sequencial need status 0xff->0x9e->0x9d */
1034 spca504A_acknowledged_command(gspca_dev, 0x24,
1035 8, 3, 0x9e, 0);
1036 spca504A_acknowledged_command(gspca_dev, 0x24,
1037 0, 0, 0x9d, 1);
1038 } else {
1039 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1040 for (i = 0; i < 6; i++)
739570bb 1041 info[i] = reg_r_1(gspca_dev, i);
6a7eba24
JFM
1042 PDEBUG(D_STREAM,
1043 "Read info: %d %d %d %d %d %d."
1044 " Should be 1,0,2,2,0,0",
1045 info[0], info[1], info[2],
1046 info[3], info[4], info[5]);
1047 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1048 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1049 }
1050 spca504B_SetSizeType(gspca_dev);
2e1794b5
JFM
1051 reg_w_riv(dev, 0x00, 0x270c, 0x05); /* L92 sno1t.txt */
1052 reg_w_riv(dev, 0x00, 0x2310, 0x05);
6a7eba24
JFM
1053 break;
1054 case BRIDGE_SPCA504C:
1055 if (sd->subtype == LogitechClickSmart420) {
1056 write_vector(gspca_dev,
2e1794b5
JFM
1057 spca504A_clicksmart420_init_data,
1058 ARRAY_SIZE(spca504A_clicksmart420_init_data));
6a7eba24 1059 } else {
2e1794b5
JFM
1060 write_vector(gspca_dev, spca504_pccam600_init_data,
1061 ARRAY_SIZE(spca504_pccam600_init_data));
6a7eba24 1062 }
739570bb
JFM
1063 enable = (sd->autogain ? 0x04 : 0x01);
1064 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1065 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
6a7eba24
JFM
1066
1067 /* set default exposure compensation and whiteness balance */
739570bb
JFM
1068 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1069 reg_w_riv(dev, 0x30, 0x0002, 1600);
6a7eba24
JFM
1070 spca504B_SetSizeType(gspca_dev);
1071 break;
1072 }
2e1794b5 1073 init_ctl_reg(gspca_dev);
72ab97ce 1074 return 0;
6a7eba24
JFM
1075}
1076
1077static void sd_stopN(struct gspca_dev *gspca_dev)
1078{
1079 struct sd *sd = (struct sd *) gspca_dev;
1080 struct usb_device *dev = gspca_dev->dev;
1081
1082 switch (sd->bridge) {
1083 default:
1084/* case BRIDGE_SPCA533: */
1085/* case BRIDGE_SPCA536: */
1086/* case BRIDGE_SPCA504B: */
2e1794b5 1087 reg_w_riv(dev, 0x31, 0, 0);
6a7eba24 1088 spca504B_WaitCmdStatus(gspca_dev);
739570bb 1089 spca504B_PollingDataReady(gspca_dev);
6a7eba24
JFM
1090 break;
1091 case BRIDGE_SPCA504:
1092 case BRIDGE_SPCA504C:
739570bb 1093 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
6a7eba24
JFM
1094
1095 if (sd->subtype == AiptekMiniPenCam13) {
1096 /* spca504a aiptek */
1097/* spca504A_acknowledged_command(gspca_dev, 0x08,
1098 6, 0, 0x86, 1); */
1099 spca504A_acknowledged_command(gspca_dev, 0x24,
1100 0x00, 0x00, 0x9d, 1);
1101 spca504A_acknowledged_command(gspca_dev, 0x01,
1102 0x0f, 0x00, 0xff, 1);
1103 } else {
1104 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
2e1794b5 1105 reg_w_riv(dev, 0x01, 0x000f, 0x0000);
6a7eba24
JFM
1106 }
1107 break;
1108 }
1109}
1110
71cb2764
JFM
1111static void sd_stop0(struct gspca_dev *gspca_dev)
1112{
1113 struct sd *sd = (struct sd *) gspca_dev;
1114
1115 kfree(sd->jpeg_hdr);
1116}
1117
6a7eba24
JFM
1118static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1119 struct gspca_frame *frame, /* target */
2e1794b5 1120 u8 *data, /* isoc packet */
6a7eba24
JFM
1121 int len) /* iso packet length */
1122{
1123 struct sd *sd = (struct sd *) gspca_dev;
1124 int i, sof = 0;
2e1794b5 1125 static u8 ffd9[] = {0xff, 0xd9};
6a7eba24
JFM
1126
1127/* frames are jpeg 4.1.1 without 0xff escape */
1128 switch (sd->bridge) {
1129 case BRIDGE_SPCA533:
1130 if (data[0] == 0xff) {
1131 if (data[1] != 0x01) { /* drop packet */
1132/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1133 return;
1134 }
1135 sof = 1;
1136 data += SPCA533_OFFSET_DATA;
1137 len -= SPCA533_OFFSET_DATA;
1138 } else {
1139 data += 1;
1140 len -= 1;
1141 }
1142 break;
1143 case BRIDGE_SPCA536:
1144 if (data[0] == 0xff) {
1145 sof = 1;
1146 data += SPCA536_OFFSET_DATA;
1147 len -= SPCA536_OFFSET_DATA;
1148 } else {
1149 data += 2;
1150 len -= 2;
1151 }
1152 break;
1153 default:
1154/* case BRIDGE_SPCA504: */
1155/* case BRIDGE_SPCA504B: */
1156 switch (data[0]) {
1157 case 0xfe: /* start of frame */
1158 sof = 1;
1159 data += SPCA50X_OFFSET_DATA;
1160 len -= SPCA50X_OFFSET_DATA;
1161 break;
1162 case 0xff: /* drop packet */
1163/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1164 return;
1165 default:
1166 data += 1;
1167 len -= 1;
1168 break;
1169 }
1170 break;
1171 case BRIDGE_SPCA504C:
1172 switch (data[0]) {
1173 case 0xfe: /* start of frame */
1174 sof = 1;
1175 data += SPCA504_PCCAM600_OFFSET_DATA;
1176 len -= SPCA504_PCCAM600_OFFSET_DATA;
1177 break;
1178 case 0xff: /* drop packet */
1179/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1180 return;
1181 default:
1182 data += 1;
1183 len -= 1;
1184 break;
1185 }
1186 break;
1187 }
1188 if (sof) { /* start of frame */
1189 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1190 ffd9, 2);
1191
1192 /* put the JPEG header in the new frame */
71cb2764
JFM
1193 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1194 sd->jpeg_hdr, JPEG_HDR_SZ);
6a7eba24
JFM
1195 }
1196
1197 /* add 0x00 after 0xff */
59746e13
JFM
1198 i = 0;
1199 do {
1200 if (data[i] == 0xff) {
1201 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1202 data, i + 1);
1203 len -= i;
1204 data += i;
1205 *data = 0x00;
1206 i = 0;
1207 }
1208 i++;
1209 } while (i < len);
1210 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
6a7eba24
JFM
1211}
1212
6a7eba24
JFM
1213static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1214{
1215 struct sd *sd = (struct sd *) gspca_dev;
1216
1217 sd->brightness = val;
1218 if (gspca_dev->streaming)
1219 setbrightness(gspca_dev);
1220 return 0;
1221}
1222
1223static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1224{
1225 struct sd *sd = (struct sd *) gspca_dev;
1226
6a7eba24
JFM
1227 *val = sd->brightness;
1228 return 0;
1229}
1230
1231static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1232{
1233 struct sd *sd = (struct sd *) gspca_dev;
1234
1235 sd->contrast = val;
1236 if (gspca_dev->streaming)
1237 setcontrast(gspca_dev);
1238 return 0;
1239}
1240
1241static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1242{
1243 struct sd *sd = (struct sd *) gspca_dev;
1244
6a7eba24
JFM
1245 *val = sd->contrast;
1246 return 0;
1247}
1248
1249static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1250{
1251 struct sd *sd = (struct sd *) gspca_dev;
1252
1253 sd->colors = val;
1254 if (gspca_dev->streaming)
1255 setcolors(gspca_dev);
1256 return 0;
1257}
1258
1259static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1260{
1261 struct sd *sd = (struct sd *) gspca_dev;
1262
6a7eba24
JFM
1263 *val = sd->colors;
1264 return 0;
1265}
1266
1267static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1268{
1269 struct sd *sd = (struct sd *) gspca_dev;
1270
1271 sd->autogain = val;
1272 return 0;
1273}
1274
1275static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1276{
1277 struct sd *sd = (struct sd *) gspca_dev;
1278
1279 *val = sd->autogain;
1280 return 0;
1281}
1282
77ac0baf
JFM
1283static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1284 struct v4l2_jpegcompression *jcomp)
1285{
1286 struct sd *sd = (struct sd *) gspca_dev;
1287
1288 if (jcomp->quality < QUALITY_MIN)
1289 sd->quality = QUALITY_MIN;
1290 else if (jcomp->quality > QUALITY_MAX)
1291 sd->quality = QUALITY_MAX;
1292 else
1293 sd->quality = jcomp->quality;
1294 if (gspca_dev->streaming)
1295 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1296 return 0;
1297}
1298
1299static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1300 struct v4l2_jpegcompression *jcomp)
1301{
1302 struct sd *sd = (struct sd *) gspca_dev;
1303
1304 memset(jcomp, 0, sizeof *jcomp);
1305 jcomp->quality = sd->quality;
1306 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1307 | V4L2_JPEG_MARKER_DQT;
1308 return 0;
1309}
1310
6a7eba24 1311/* sub-driver description */
a5ae2062 1312static const struct sd_desc sd_desc = {
6a7eba24
JFM
1313 .name = MODULE_NAME,
1314 .ctrls = sd_ctrls,
1315 .nctrls = ARRAY_SIZE(sd_ctrls),
1316 .config = sd_config,
012d6b02 1317 .init = sd_init,
6a7eba24
JFM
1318 .start = sd_start,
1319 .stopN = sd_stopN,
71cb2764 1320 .stop0 = sd_stop0,
6a7eba24 1321 .pkt_scan = sd_pkt_scan,
77ac0baf
JFM
1322 .get_jcomp = sd_get_jcomp,
1323 .set_jcomp = sd_set_jcomp,
6a7eba24
JFM
1324};
1325
1326/* -- module initialisation -- */
9d64fdb1
JFM
1327#define BS(bridge, subtype) \
1328 .driver_info = (BRIDGE_ ## bridge << 8) \
1329 | (subtype)
a5ae2062 1330static const __devinitdata struct usb_device_id device_table[] = {
9d64fdb1
JFM
1331 {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
1332 {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
1333 {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
1334 {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
1335 {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
1336 {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
1337 {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
1338 {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
1339 {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
1340 {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
1341 {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
1342 {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
1343 {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
1344 {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
1345 {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
1346 {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
1347 {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
1348 {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
1349 {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
af5f88c8 1350 {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
9d64fdb1
JFM
1351 {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
1352 {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
1353 {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
1354 {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
1355 {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
1356 {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
1357 {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
1358 {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
1359 {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
1360 {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
1361 {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
1362 {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
1363 {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
1364 {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
1365 {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
1366 {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
1367 {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
1368 {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
1369 {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
1370 {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
1371 {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
1372 {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
1373 {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
1374 {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
1375 {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
1376 {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
1377 {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
1378 {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
1379 {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
1380 {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
1381 {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
1382 {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
1383 {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
1384 {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
1385 {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
1386 {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
1387 {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
1388 {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
6a7eba24
JFM
1389 {}
1390};
1391MODULE_DEVICE_TABLE(usb, device_table);
1392
1393/* -- device connect -- */
1394static int sd_probe(struct usb_interface *intf,
1395 const struct usb_device_id *id)
1396{
1397 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1398 THIS_MODULE);
1399}
1400
1401static struct usb_driver sd_driver = {
1402 .name = MODULE_NAME,
1403 .id_table = device_table,
1404 .probe = sd_probe,
1405 .disconnect = gspca_disconnect,
6a709749
JFM
1406#ifdef CONFIG_PM
1407 .suspend = gspca_suspend,
1408 .resume = gspca_resume,
1409#endif
6a7eba24
JFM
1410};
1411
1412/* -- module insert / remove -- */
1413static int __init sd_mod_init(void)
1414{
f69e9529
AK
1415 int ret;
1416 ret = usb_register(&sd_driver);
1417 if (ret < 0)
e6b14849 1418 return ret;
10b0e96e 1419 PDEBUG(D_PROBE, "registered");
6a7eba24
JFM
1420 return 0;
1421}
1422static void __exit sd_mod_exit(void)
1423{
1424 usb_deregister(&sd_driver);
1425 PDEBUG(D_PROBE, "deregistered");
1426}
1427
1428module_init(sd_mod_init);
1429module_exit(sd_mod_exit);