blob: 7fa280d731a35062cf8f28abf48b42cda86a30ce [file] [log] [blame]
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001/*
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
Jean-Francois Moine100f7f22008-07-17 09:41:03 -030027#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030029
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030038 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030039 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 char qindex;
47 char bridge;
48#define BRIDGE_SPCA504 0
49#define BRIDGE_SPCA504B 1
50#define BRIDGE_SPCA504C 2
51#define BRIDGE_SPCA533 3
52#define BRIDGE_SPCA536 4
53 char subtype;
54#define AiptekMiniPenCam13 1
55#define LogitechClickSmart420 2
56#define LogitechClickSmart820 3
57#define MegapixV4 4
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[] = {
71#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 0xff,
79 .step = 1,
80 .default_value = 0,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85#define SD_CONTRAST 1
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 0xff,
93 .step = 1,
94 .default_value = 0x20,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99#define SD_COLOR 2
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 0xff,
107 .step = 1,
108 .default_value = 0x1a,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113#define SD_AUTOGAIN 3
114 {
115 {
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Auto Gain",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 1,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300129static struct v4l2_pix_format vga_mode[] = {
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},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300140};
141
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300142static struct v4l2_pix_format custom_mode[] = {
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},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300153};
154
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300155static struct v4l2_pix_format vga_mode2[] = {
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},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300176};
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 */
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186/* Frame packet header offsets for the spca536 */
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190/* Initialisation data for the Creative PC-CAM 600 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300191static const __u16 spca504_pccam600_init_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300192/* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {}
216};
217
218/* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
220 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300221static const __u16 spca504_pccam600_open_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
226 {}
227};
228
229/* Initialisation data for the logitech clicksmart 420 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300230static const __u16 spca504A_clicksmart420_init_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300231/* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
245
246
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
256
257 {}
258};
259
260/* clicksmart 420 open data ? */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300261static const __u16 spca504A_clicksmart420_open_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267/* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
284
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
301
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
318
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
335
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
352
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
369
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
386
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
403
404 {0xa0, 0x0000, 0x0503},
405 {}
406};
407
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300408static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 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};
428
429/* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
431 * NWG: 18/05/2003.
432 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300433static const __u8 qtable_spca504_default[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 },
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 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};
454
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300455static void reg_r(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300456 __u16 req,
457 __u16 index,
458 __u8 *buffer, __u16 length)
459{
460 usb_control_msg(dev,
461 usb_rcvctrlpipe(dev, 0),
462 req,
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
464 0, /* value */
465 index, buffer, length,
466 500);
467}
468
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300469static void reg_w(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300470 __u16 req,
471 __u16 value,
472 __u16 index,
473 __u8 *buffer, __u16 length)
474{
475 usb_control_msg(dev,
476 usb_sndctrlpipe(dev, 0),
477 req,
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
480 500);
481}
482
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300483/* write req / index / value */
484static int reg_w_riv(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300485 __u16 req, __u16 index, __u16 value)
486{
487 int ret;
488
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
491 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493 value, index, NULL, 0, 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300495 req, index, value, ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300496 if (ret < 0)
497 PDEBUG(D_ERR, "reg write: error %d", ret);
498 return ret;
499}
500
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300501/* read 1 byte */
502static int reg_r_1(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503 __u16 value) /* wValue */
504{
505 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300509 0x20, /* request */
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value,
512 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300513 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514 500); /* timeout */
515 if (ret < 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517 return 0;
518 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300519 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300520}
521
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300522/* read 1 or 2 bytes - returns < 0 if error */
523static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
527{
528 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300529
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300533 req,
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
535 0, /* value */
536 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300537 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300538 500);
539 if (ret < 0) {
540 PDEBUG(D_ERR, "reg_read err %d", ret);
541 return -1;
542 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300544}
545
546static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300547 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300548{
549 struct usb_device *dev = gspca_dev->dev;
550 int ret, i = 0;
551
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300553 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300554 if (ret < 0) {
555 PDEBUG(D_ERR,
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
558 return ret;
559 }
560 i++;
561 }
562 return 0;
563}
564
565static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
567 unsigned int ybase,
568 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300569 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300570{
571 struct usb_device *dev = gspca_dev->dev;
572 int i, err;
573
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300576 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300577 if (err < 0)
578 return err;
579 }
580
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300583 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300584 if (err < 0)
585 return err;
586 }
587 return 0;
588}
589
590static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
592{
593 struct usb_device *dev = gspca_dev->dev;
594 __u8 notdone;
595
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300596 reg_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300599
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
601
602 msleep(200);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300603 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
605}
606
607static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
608 __u16 req,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
610{
611 struct usb_device *dev = gspca_dev->dev;
612 __u8 status;
613 __u8 endcode;
614
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300615 reg_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300617 endcode = stat;
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 if (!count)
620 return;
621 count = 200;
622 while (--count > 0) {
623 msleep(10);
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300625/* reg_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
630 break;
631 }
632 }
633}
634
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300635static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300636{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300637 int count = 10;
638
639 while (--count > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300642 break;
643 msleep(10);
644 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300645 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300646}
647
648static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
649{
650 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300651 int count = 50;
652
653 while (--count > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300660 break;
661 }
662 msleep(10);
663 }
664}
665
666static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
667{
668 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300669 __u8 *data;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
677 kfree(data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300678}
679
680static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
684 __u8 Size;
685 __u8 Type;
686 int rc;
687
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300689 Type = 0;
690 switch (sd->bridge) {
691 case BRIDGE_SPCA533:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300692 reg_w(dev, 0x31, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300693 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300694 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300695 spca50x_GetFirmware(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300699
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704
705 /* Init the cam width height with some values get on init ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300706 reg_w(dev, 0x31, 0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300707 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300708 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300709 break;
710 default:
711/* case BRIDGE_SPCA504B: */
712/* case BRIDGE_SPCA536: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300716 Type = 6;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300721 break;
722 case BRIDGE_SPCA504:
723 Size += 3;
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
727 0x08, Size, 0,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
730 1, 3, 0, 0x9f, 0);
731 } else {
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
733 }
734 break;
735 case BRIDGE_SPCA504C:
736 /* capture mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300739 break;
740 }
741}
742
743static void spca504_wait_status(struct gspca_dev *gspca_dev)
744{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300745 int cnt;
746
747 cnt = 256;
748 while (--cnt > 0) {
749 /* With this we get the status, when return 0 it's all ok */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300751 return;
752 msleep(10);
753 }
754}
755
756static void spca504B_setQtable(struct gspca_dev *gspca_dev)
757{
758 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300759
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300764}
765
766static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
770 int pollreg = 1;
771
772 switch (sd->bridge) {
773 case BRIDGE_SPCA504:
774 case BRIDGE_SPCA504C:
775 pollreg = 0;
776 /* fall thru */
777 default:
778/* case BRIDGE_SPCA533: */
779/* case BRIDGE_SPCA504B: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300780 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300786 break;
787 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300794 break;
795 }
796 if (pollreg)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300797 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300798}
799
800/* this function is called at probe time */
801static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
806 struct cam *cam;
807 __u16 vendor;
808 __u16 product;
809 __u8 fw;
810
811 vendor = id->idVendor;
812 product = id->idProduct;
813 switch (vendor) {
814 case 0x041e: /* Creative cameras */
815/* switch (product) { */
816/* case 0x400b: */
817/* case 0x4012: */
818/* case 0x4013: */
819/* sd->bridge = BRIDGE_SPCA504C; */
820/* break; */
821/* } */
822 break;
823 case 0x0458: /* Genius KYE cameras */
824/* switch (product) { */
825/* case 0x7006: */
826 sd->bridge = BRIDGE_SPCA504B;
827/* break; */
828/* } */
829 break;
Jean-Francois Moine100f7f22008-07-17 09:41:03 -0300830 case 0x0461: /* MicroInnovation */
831/* switch (product) { */
832/* case 0x0821: */
833 sd->bridge = BRIDGE_SPCA533;
834/* break; */
835/* } */
836 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300837 case 0x046d: /* Logitech Labtec */
838 switch (product) {
839 case 0x0905:
840 sd->subtype = LogitechClickSmart820;
841 sd->bridge = BRIDGE_SPCA533;
842 break;
843 case 0x0960:
844 sd->subtype = LogitechClickSmart420;
845 sd->bridge = BRIDGE_SPCA504C;
846 break;
847 }
848 break;
849 case 0x0471: /* Philips */
850/* switch (product) { */
851/* case 0x0322: */
852 sd->bridge = BRIDGE_SPCA504B;
853/* break; */
854/* } */
855 break;
856 case 0x04a5: /* Benq */
857 switch (product) {
858 case 0x3003:
859 sd->bridge = BRIDGE_SPCA504B;
860 break;
861 case 0x3008:
862 case 0x300a:
863 sd->bridge = BRIDGE_SPCA533;
864 break;
865 }
866 break;
867 case 0x04f1: /* JVC */
868/* switch (product) { */
869/* case 0x1001: */
870 sd->bridge = BRIDGE_SPCA504B;
871/* break; */
872/* } */
873 break;
874 case 0x04fc: /* SunPlus */
875 switch (product) {
876 case 0x500c:
877 sd->bridge = BRIDGE_SPCA504B;
878 break;
879 case 0x504a:
880/* try to get the firmware as some cam answer 2.0.1.2.2
881 * and should be a spca504b then overwrite that setting */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300882 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
883 fw = gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300884 if (fw == 1) {
885 sd->subtype = AiptekMiniPenCam13;
886 sd->bridge = BRIDGE_SPCA504;
887 } else if (fw == 2) {
888 sd->bridge = BRIDGE_SPCA504B;
889 } else
890 return -ENODEV;
891 break;
892 case 0x504b:
893 sd->bridge = BRIDGE_SPCA504B;
894 break;
895 case 0x5330:
896 sd->bridge = BRIDGE_SPCA533;
897 break;
898 case 0x5360:
899 sd->bridge = BRIDGE_SPCA536;
900 break;
901 case 0xffff:
902 sd->bridge = BRIDGE_SPCA504B;
903 break;
904 }
905 break;
906 case 0x052b: /* ?? Megapix */
907/* switch (product) { */
908/* case 0x1513: */
909 sd->subtype = MegapixV4;
910 sd->bridge = BRIDGE_SPCA533;
911/* break; */
912/* } */
913 break;
914 case 0x0546: /* Polaroid */
915 switch (product) {
916 case 0x3155:
917 sd->bridge = BRIDGE_SPCA533;
918 break;
919 case 0x3191:
920 case 0x3273:
921 sd->bridge = BRIDGE_SPCA504B;
922 break;
923 }
924 break;
925 case 0x055f: /* Mustek cameras */
926 switch (product) {
927 case 0xc211:
928 sd->bridge = BRIDGE_SPCA536;
929 break;
930 case 0xc230:
931 case 0xc232:
932 sd->bridge = BRIDGE_SPCA533;
933 break;
934 case 0xc360:
935 sd->bridge = BRIDGE_SPCA536;
936 break;
937 case 0xc420:
938 sd->bridge = BRIDGE_SPCA504;
939 break;
940 case 0xc430:
941 case 0xc440:
942 sd->bridge = BRIDGE_SPCA533;
943 break;
944 case 0xc520:
945 sd->bridge = BRIDGE_SPCA504;
946 break;
947 case 0xc530:
948 case 0xc540:
949 case 0xc630:
950 case 0xc650:
951 sd->bridge = BRIDGE_SPCA533;
952 break;
953 }
954 break;
955 case 0x05da: /* Digital Dream cameras */
956/* switch (product) { */
957/* case 0x1018: */
958 sd->bridge = BRIDGE_SPCA504B;
959/* break; */
960/* } */
961 break;
962 case 0x06d6: /* Trust */
963/* switch (product) { */
964/* case 0x0031: */
965 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
966/* break; */
967/* } */
968 break;
969 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
970 switch (product) {
971 case 0x1311:
972 case 0x1314:
973 case 0x2211:
974 case 0x2221:
975 sd->bridge = BRIDGE_SPCA533;
976 break;
977 case 0x3261:
978 case 0x3281:
979 sd->bridge = BRIDGE_SPCA536;
980 break;
981 }
982 break;
983 case 0x08ca: /* Aiptek */
984 switch (product) {
985 case 0x0104:
986 case 0x0106:
987 sd->bridge = BRIDGE_SPCA533;
988 break;
989 case 0x2008:
990 sd->bridge = BRIDGE_SPCA504B;
991 break;
992 case 0x2010:
993 sd->bridge = BRIDGE_SPCA533;
994 break;
995 case 0x2016:
996 case 0x2018:
997 sd->bridge = BRIDGE_SPCA504B;
998 break;
999 case 0x2020:
1000 case 0x2022:
1001 sd->bridge = BRIDGE_SPCA533;
1002 break;
1003 case 0x2024:
1004 sd->bridge = BRIDGE_SPCA536;
1005 break;
1006 case 0x2028:
1007 sd->bridge = BRIDGE_SPCA533;
1008 break;
1009 case 0x2040:
1010 case 0x2042:
1011 case 0x2060:
1012 sd->bridge = BRIDGE_SPCA536;
1013 break;
1014 }
1015 break;
1016 case 0x0d64: /* SunPlus */
1017/* switch (product) { */
1018/* case 0x0303: */
1019 sd->bridge = BRIDGE_SPCA536;
1020/* break; */
1021/* } */
1022 break;
1023 }
1024
1025 cam = &gspca_dev->cam;
1026 cam->dev_name = (char *) id->driver_info;
1027 cam->epaddr = 0x01;
1028
1029 switch (sd->bridge) {
1030 default:
1031/* case BRIDGE_SPCA504B: */
1032/* case BRIDGE_SPCA504: */
1033/* case BRIDGE_SPCA536: */
1034 cam->cam_mode = vga_mode;
1035 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1036 break;
1037 case BRIDGE_SPCA533:
1038 cam->cam_mode = custom_mode;
1039 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1040 break;
1041 case BRIDGE_SPCA504C:
1042 cam->cam_mode = vga_mode2;
1043 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1044 break;
1045 }
1046 sd->qindex = 5; /* set the quantization table */
1047 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1048 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1049 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1050 return 0;
1051}
1052
1053/* this function is called at open time */
1054static int sd_open(struct gspca_dev *gspca_dev)
1055{
1056 struct sd *sd = (struct sd *) gspca_dev;
1057 struct usb_device *dev = gspca_dev->dev;
1058 int rc;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001059 __u8 i;
1060 __u8 info[6];
1061 int err_code;
1062
1063 switch (sd->bridge) {
1064 case BRIDGE_SPCA504B:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001065 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1066 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1067 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1068 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1069 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1070 reg_w(dev, 0, 0, 0x2306, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001071 /* fall thru */
1072 case BRIDGE_SPCA533:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001073 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001074 spca50x_GetFirmware(gspca_dev);
1075 break;
1076 case BRIDGE_SPCA536:
1077 spca50x_GetFirmware(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001078 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1079 gspca_dev->usb_buf[0] = 0;
1080 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1081 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1082 rc = spca504B_PollingDataReady(gspca_dev);
1083 reg_w(dev, 0x34, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001084 spca504B_WaitCmdStatus(gspca_dev);
1085 break;
1086 case BRIDGE_SPCA504C: /* pccam600 */
1087 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001088 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1089 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001090 spca504_wait_status(gspca_dev);
1091 if (sd->subtype == LogitechClickSmart420)
1092 write_vector(gspca_dev,
1093 spca504A_clicksmart420_open_data);
1094 else
1095 write_vector(gspca_dev, spca504_pccam600_open_data);
1096 err_code = spca50x_setup_qtable(gspca_dev,
1097 0x00, 0x2800,
1098 0x2840, qtable_creative_pccam);
1099 if (err_code < 0) {
1100 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1101 return err_code;
1102 }
1103 break;
1104 default:
1105/* case BRIDGE_SPCA504: */
1106 PDEBUG(D_STREAM, "Opening SPCA504");
1107 if (sd->subtype == AiptekMiniPenCam13) {
1108 /*****************************/
1109 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001110 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001111 PDEBUG(D_STREAM,
1112 "Read info: %d %d %d %d %d %d."
1113 " Should be 1,0,2,2,0,0",
1114 info[0], info[1], info[2],
1115 info[3], info[4], info[5]);
1116 /* spca504a aiptek */
1117 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1118 spca504A_acknowledged_command(gspca_dev, 0x24,
1119 8, 3, 0x9e, 1);
1120 /* Twice sequencial need status 0xff->0x9e->0x9d */
1121 spca504A_acknowledged_command(gspca_dev, 0x24,
1122 8, 3, 0x9e, 0);
1123
1124 spca504A_acknowledged_command(gspca_dev, 0x24,
1125 0, 0, 0x9d, 1);
1126 /******************************/
1127 /* spca504a aiptek */
1128 spca504A_acknowledged_command(gspca_dev, 0x08,
1129 6, 0, 0x86, 1);
1130/* reg_write (dev, 0, 0x2000, 0); */
1131/* reg_write (dev, 0, 0x2883, 1); */
1132/* spca504A_acknowledged_command (gspca_dev, 0x08,
1133 6, 0, 0x86, 1); */
1134/* spca504A_acknowledged_command (gspca_dev, 0x24,
1135 0, 0, 0x9D, 1); */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001136 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1137 reg_w_riv(dev, 0x0, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001138 spca504A_acknowledged_command(gspca_dev, 0x01,
1139 0x0f, 0, 0xff, 0);
1140 }
1141 /* setup qtable */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001142 reg_w_riv(dev, 0, 0x2000, 0);
1143 reg_w_riv(dev, 0, 0x2883, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001144 err_code = spca50x_setup_qtable(gspca_dev,
1145 0x00, 0x2800,
1146 0x2840,
1147 qtable_spca504_default);
1148 if (err_code < 0) {
1149 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1150 return err_code;
1151 }
1152 break;
1153 }
1154 return 0;
1155}
1156
1157static void sd_start(struct gspca_dev *gspca_dev)
1158{
1159 struct sd *sd = (struct sd *) gspca_dev;
1160 struct usb_device *dev = gspca_dev->dev;
1161 int rc;
1162 int enable;
1163 __u8 i;
1164 __u8 info[6];
1165
1166 if (sd->bridge == BRIDGE_SPCA504B)
1167 spca504B_setQtable(gspca_dev);
1168 spca504B_SetSizeType(gspca_dev);
1169 switch (sd->bridge) {
1170 default:
1171/* case BRIDGE_SPCA504B: */
1172/* case BRIDGE_SPCA533: */
1173/* case BRIDGE_SPCA536: */
1174 if (sd->subtype == MegapixV4 ||
1175 sd->subtype == LogitechClickSmart820) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001176 reg_w(dev, 0xf0, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001177 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001178 reg_r(dev, 0xf0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001179 spca504B_WaitCmdStatus(gspca_dev);
1180 } else {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001181 reg_w(dev, 0x31, 0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001183 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001184 }
1185 break;
1186 case BRIDGE_SPCA504:
1187 if (sd->subtype == AiptekMiniPenCam13) {
1188 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001189 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001190 PDEBUG(D_STREAM,
1191 "Read info: %d %d %d %d %d %d."
1192 " Should be 1,0,2,2,0,0",
1193 info[0], info[1], info[2],
1194 info[3], info[4], info[5]);
1195 /* spca504a aiptek */
1196 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1197 spca504A_acknowledged_command(gspca_dev, 0x24,
1198 8, 3, 0x9e, 1);
1199 /* Twice sequencial need status 0xff->0x9e->0x9d */
1200 spca504A_acknowledged_command(gspca_dev, 0x24,
1201 8, 3, 0x9e, 0);
1202 spca504A_acknowledged_command(gspca_dev, 0x24,
1203 0, 0, 0x9d, 1);
1204 } else {
1205 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1206 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001207 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001208 PDEBUG(D_STREAM,
1209 "Read info: %d %d %d %d %d %d."
1210 " Should be 1,0,2,2,0,0",
1211 info[0], info[1], info[2],
1212 info[3], info[4], info[5]);
1213 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1214 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1215 }
1216 spca504B_SetSizeType(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001217 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1218 reg_w_riv(dev, 0x0, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001219 break;
1220 case BRIDGE_SPCA504C:
1221 if (sd->subtype == LogitechClickSmart420) {
1222 write_vector(gspca_dev,
1223 spca504A_clicksmart420_init_data);
1224 } else {
1225 write_vector(gspca_dev, spca504_pccam600_init_data);
1226 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001227 enable = (sd->autogain ? 0x04 : 0x01);
1228 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1229 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001230
1231 /* set default exposure compensation and whiteness balance */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001232 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1233 reg_w_riv(dev, 0x30, 0x0002, 1600);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001234 spca504B_SetSizeType(gspca_dev);
1235 break;
1236 }
1237 sp5xx_initContBrigHueRegisters(gspca_dev);
1238}
1239
1240static void sd_stopN(struct gspca_dev *gspca_dev)
1241{
1242 struct sd *sd = (struct sd *) gspca_dev;
1243 struct usb_device *dev = gspca_dev->dev;
1244
1245 switch (sd->bridge) {
1246 default:
1247/* case BRIDGE_SPCA533: */
1248/* case BRIDGE_SPCA536: */
1249/* case BRIDGE_SPCA504B: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001250 reg_w(dev, 0x31, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001251 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001252 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001253 break;
1254 case BRIDGE_SPCA504:
1255 case BRIDGE_SPCA504C:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001256 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001257
1258 if (sd->subtype == AiptekMiniPenCam13) {
1259 /* spca504a aiptek */
1260/* spca504A_acknowledged_command(gspca_dev, 0x08,
1261 6, 0, 0x86, 1); */
1262 spca504A_acknowledged_command(gspca_dev, 0x24,
1263 0x00, 0x00, 0x9d, 1);
1264 spca504A_acknowledged_command(gspca_dev, 0x01,
1265 0x0f, 0x00, 0xff, 1);
1266 } else {
1267 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001268 reg_w_riv(dev, 0x01, 0x000f, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001269 }
1270 break;
1271 }
1272}
1273
1274static void sd_stop0(struct gspca_dev *gspca_dev)
1275{
1276}
1277
1278static void sd_close(struct gspca_dev *gspca_dev)
1279{
1280}
1281
1282static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1283 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001284 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001285 int len) /* iso packet length */
1286{
1287 struct sd *sd = (struct sd *) gspca_dev;
1288 int i, sof = 0;
1289 unsigned char *s, *d;
1290 static unsigned char ffd9[] = {0xff, 0xd9};
1291
1292/* frames are jpeg 4.1.1 without 0xff escape */
1293 switch (sd->bridge) {
1294 case BRIDGE_SPCA533:
1295 if (data[0] == 0xff) {
1296 if (data[1] != 0x01) { /* drop packet */
1297/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1298 return;
1299 }
1300 sof = 1;
1301 data += SPCA533_OFFSET_DATA;
1302 len -= SPCA533_OFFSET_DATA;
1303 } else {
1304 data += 1;
1305 len -= 1;
1306 }
1307 break;
1308 case BRIDGE_SPCA536:
1309 if (data[0] == 0xff) {
1310 sof = 1;
1311 data += SPCA536_OFFSET_DATA;
1312 len -= SPCA536_OFFSET_DATA;
1313 } else {
1314 data += 2;
1315 len -= 2;
1316 }
1317 break;
1318 default:
1319/* case BRIDGE_SPCA504: */
1320/* case BRIDGE_SPCA504B: */
1321 switch (data[0]) {
1322 case 0xfe: /* start of frame */
1323 sof = 1;
1324 data += SPCA50X_OFFSET_DATA;
1325 len -= SPCA50X_OFFSET_DATA;
1326 break;
1327 case 0xff: /* drop packet */
1328/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1329 return;
1330 default:
1331 data += 1;
1332 len -= 1;
1333 break;
1334 }
1335 break;
1336 case BRIDGE_SPCA504C:
1337 switch (data[0]) {
1338 case 0xfe: /* start of frame */
1339 sof = 1;
1340 data += SPCA504_PCCAM600_OFFSET_DATA;
1341 len -= SPCA504_PCCAM600_OFFSET_DATA;
1342 break;
1343 case 0xff: /* drop packet */
1344/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1345 return;
1346 default:
1347 data += 1;
1348 len -= 1;
1349 break;
1350 }
1351 break;
1352 }
1353 if (sof) { /* start of frame */
1354 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1355 ffd9, 2);
1356
1357 /* put the JPEG header in the new frame */
1358 jpeg_put_header(gspca_dev, frame,
1359 ((struct sd *) gspca_dev)->qindex,
1360 0x22);
1361 }
1362
1363 /* add 0x00 after 0xff */
1364 for (i = len; --i >= 0; )
1365 if (data[i] == 0xff)
1366 break;
1367 if (i < 0) { /* no 0xff */
1368 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1369 return;
1370 }
1371 s = data;
1372 d = sd->packet;
1373 for (i = 0; i < len; i++) {
1374 *d++ = *s++;
1375 if (s[-1] == 0xff)
1376 *d++ = 0x00;
1377 }
1378 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1379 sd->packet, d - sd->packet);
1380}
1381
1382static void setbrightness(struct gspca_dev *gspca_dev)
1383{
1384 struct sd *sd = (struct sd *) gspca_dev;
1385 struct usb_device *dev = gspca_dev->dev;
1386
1387 switch (sd->bridge) {
1388 default:
1389/* case BRIDGE_SPCA533: */
1390/* case BRIDGE_SPCA504B: */
1391/* case BRIDGE_SPCA504: */
1392/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001393 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001394 break;
1395 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001396 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001397 break;
1398 }
1399}
1400
1401static void getbrightness(struct gspca_dev *gspca_dev)
1402{
1403 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001404 __u16 brightness = 0;
1405
1406 switch (sd->bridge) {
1407 default:
1408/* case BRIDGE_SPCA533: */
1409/* case BRIDGE_SPCA504B: */
1410/* case BRIDGE_SPCA504: */
1411/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001412 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001413 break;
1414 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001415 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001416 break;
1417 }
1418 sd->brightness = ((brightness & 0xff) - 128) % 255;
1419}
1420
1421static void setcontrast(struct gspca_dev *gspca_dev)
1422{
1423 struct sd *sd = (struct sd *) gspca_dev;
1424 struct usb_device *dev = gspca_dev->dev;
1425
1426 switch (sd->bridge) {
1427 default:
1428/* case BRIDGE_SPCA533: */
1429/* case BRIDGE_SPCA504B: */
1430/* case BRIDGE_SPCA504: */
1431/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001432 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001433 break;
1434 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001435 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001436 break;
1437 }
1438}
1439
1440static void getcontrast(struct gspca_dev *gspca_dev)
1441{
1442 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001443
1444 switch (sd->bridge) {
1445 default:
1446/* case BRIDGE_SPCA533: */
1447/* case BRIDGE_SPCA504B: */
1448/* case BRIDGE_SPCA504: */
1449/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001450 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001451 break;
1452 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001453 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001454 break;
1455 }
1456}
1457
1458static void setcolors(struct gspca_dev *gspca_dev)
1459{
1460 struct sd *sd = (struct sd *) gspca_dev;
1461 struct usb_device *dev = gspca_dev->dev;
1462
1463 switch (sd->bridge) {
1464 default:
1465/* case BRIDGE_SPCA533: */
1466/* case BRIDGE_SPCA504B: */
1467/* case BRIDGE_SPCA504: */
1468/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001469 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001470 break;
1471 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001472 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001473 break;
1474 }
1475}
1476
1477static void getcolors(struct gspca_dev *gspca_dev)
1478{
1479 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001480
1481 switch (sd->bridge) {
1482 default:
1483/* case BRIDGE_SPCA533: */
1484/* case BRIDGE_SPCA504B: */
1485/* case BRIDGE_SPCA504: */
1486/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001487 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001488 break;
1489 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001490 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001491 break;
1492 }
1493}
1494
1495static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1496{
1497 struct sd *sd = (struct sd *) gspca_dev;
1498
1499 sd->brightness = val;
1500 if (gspca_dev->streaming)
1501 setbrightness(gspca_dev);
1502 return 0;
1503}
1504
1505static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1506{
1507 struct sd *sd = (struct sd *) gspca_dev;
1508
1509 getbrightness(gspca_dev);
1510 *val = sd->brightness;
1511 return 0;
1512}
1513
1514static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1515{
1516 struct sd *sd = (struct sd *) gspca_dev;
1517
1518 sd->contrast = val;
1519 if (gspca_dev->streaming)
1520 setcontrast(gspca_dev);
1521 return 0;
1522}
1523
1524static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1525{
1526 struct sd *sd = (struct sd *) gspca_dev;
1527
1528 getcontrast(gspca_dev);
1529 *val = sd->contrast;
1530 return 0;
1531}
1532
1533static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 sd->colors = val;
1538 if (gspca_dev->streaming)
1539 setcolors(gspca_dev);
1540 return 0;
1541}
1542
1543static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1544{
1545 struct sd *sd = (struct sd *) gspca_dev;
1546
1547 getcolors(gspca_dev);
1548 *val = sd->colors;
1549 return 0;
1550}
1551
1552static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 sd->autogain = val;
1557 return 0;
1558}
1559
1560static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 *val = sd->autogain;
1565 return 0;
1566}
1567
1568/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001569static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001570 .name = MODULE_NAME,
1571 .ctrls = sd_ctrls,
1572 .nctrls = ARRAY_SIZE(sd_ctrls),
1573 .config = sd_config,
1574 .open = sd_open,
1575 .start = sd_start,
1576 .stopN = sd_stopN,
1577 .stop0 = sd_stop0,
1578 .close = sd_close,
1579 .pkt_scan = sd_pkt_scan,
1580};
1581
1582/* -- module initialisation -- */
1583#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001584static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001585 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1586 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1587 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1588 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
Jean-Francois Moine100f7f22008-07-17 09:41:03 -03001589 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001590 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1591 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1592 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1593 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1594 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1595 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1596 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1597 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1598 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1599 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1600 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1601 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1602 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1603 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1604 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1605 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1606 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1607 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1608 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1609 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1610 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1611 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1612 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1613 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1614 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1615 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1616 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1617 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1618 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1619 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1620 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1621 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1622 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1623 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1624 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1625 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1626 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1627 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1628 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1629 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1630 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1631 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1632 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1633 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1634 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1635 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1636 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1637 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1638 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1639 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1640 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1641 {}
1642};
1643MODULE_DEVICE_TABLE(usb, device_table);
1644
1645/* -- device connect -- */
1646static int sd_probe(struct usb_interface *intf,
1647 const struct usb_device_id *id)
1648{
1649 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1650 THIS_MODULE);
1651}
1652
1653static struct usb_driver sd_driver = {
1654 .name = MODULE_NAME,
1655 .id_table = device_table,
1656 .probe = sd_probe,
1657 .disconnect = gspca_disconnect,
1658};
1659
1660/* -- module insert / remove -- */
1661static int __init sd_mod_init(void)
1662{
1663 if (usb_register(&sd_driver) < 0)
1664 return -1;
1665 PDEBUG(D_PROBE, "v%s registered", version);
1666 return 0;
1667}
1668static void __exit sd_mod_exit(void)
1669{
1670 usb_deregister(&sd_driver);
1671 PDEBUG(D_PROBE, "deregistered");
1672}
1673
1674module_init(sd_mod_init);
1675module_exit(sd_mod_exit);