blob: 53e20275f26db728c77ccb964ba88e7f66c72cff [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 Moine6a7eba22008-06-30 15:50:11 -030027MODULE_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
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -030035 __u8 packet[ISO_MAX_SIZE + 128];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -030036 /* !! no more than 128 ff in an ISO packet */
37
38 unsigned char brightness;
39 unsigned char contrast;
40 unsigned char colors;
41 unsigned char autogain;
42
43 char qindex;
44 char bridge;
45#define BRIDGE_SPCA504 0
46#define BRIDGE_SPCA504B 1
47#define BRIDGE_SPCA504C 2
48#define BRIDGE_SPCA533 3
49#define BRIDGE_SPCA536 4
50 char subtype;
51#define AiptekMiniPenCam13 1
52#define LogitechClickSmart420 2
53#define LogitechClickSmart820 3
54#define MegapixV4 4
55};
56
57/* V4L2 controls supported by the driver */
58static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
60static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
61static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
62static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
63static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
64static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
65static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
66
67static struct ctrl sd_ctrls[] = {
68#define SD_BRIGHTNESS 0
69 {
70 {
71 .id = V4L2_CID_BRIGHTNESS,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Brightness",
74 .minimum = 0,
75 .maximum = 0xff,
76 .step = 1,
77 .default_value = 0,
78 },
79 .set = sd_setbrightness,
80 .get = sd_getbrightness,
81 },
82#define SD_CONTRAST 1
83 {
84 {
85 .id = V4L2_CID_CONTRAST,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Contrast",
88 .minimum = 0,
89 .maximum = 0xff,
90 .step = 1,
91 .default_value = 0x20,
92 },
93 .set = sd_setcontrast,
94 .get = sd_getcontrast,
95 },
96#define SD_COLOR 2
97 {
98 {
99 .id = V4L2_CID_SATURATION,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Color",
102 .minimum = 0,
103 .maximum = 0xff,
104 .step = 1,
105 .default_value = 0x1a,
106 },
107 .set = sd_setcolors,
108 .get = sd_getcolors,
109 },
110#define SD_AUTOGAIN 3
111 {
112 {
113 .id = V4L2_CID_AUTOGAIN,
114 .type = V4L2_CTRL_TYPE_BOOLEAN,
115 .name = "Auto Gain",
116 .minimum = 0,
117 .maximum = 1,
118 .step = 1,
119 .default_value = 1,
120 },
121 .set = sd_setautogain,
122 .get = sd_getautogain,
123 },
124};
125
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300126static struct v4l2_pix_format vga_mode[] = {
127 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
128 .bytesperline = 320,
129 .sizeimage = 320 * 240 * 3 / 8 + 590,
130 .colorspace = V4L2_COLORSPACE_JPEG,
131 .priv = 2},
132 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
133 .bytesperline = 640,
134 .sizeimage = 640 * 480 * 3 / 8 + 590,
135 .colorspace = V4L2_COLORSPACE_JPEG,
136 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300137};
138
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300139static struct v4l2_pix_format custom_mode[] = {
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 .bytesperline = 320,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
144 .priv = 2},
145 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 464,
147 .sizeimage = 464 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300150};
151
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300152static struct v4l2_pix_format vga_mode2[] = {
153 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
154 .bytesperline = 176,
155 .sizeimage = 176 * 144 * 3 / 8 + 590,
156 .colorspace = V4L2_COLORSPACE_JPEG,
157 .priv = 4},
158 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
159 .bytesperline = 320,
160 .sizeimage = 320 * 240 * 3 / 8 + 590,
161 .colorspace = V4L2_COLORSPACE_JPEG,
162 .priv = 3},
163 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
164 .bytesperline = 352,
165 .sizeimage = 352 * 288 * 3 / 8 + 590,
166 .colorspace = V4L2_COLORSPACE_JPEG,
167 .priv = 2},
168 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
169 .bytesperline = 640,
170 .sizeimage = 640 * 480 * 3 / 8 + 590,
171 .colorspace = V4L2_COLORSPACE_JPEG,
172 .priv = 1},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300173};
174
175#define SPCA50X_OFFSET_DATA 10
176#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
177#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
178#define SPCA504_PCCAM600_OFFSET_MODE 5
179#define SPCA504_PCCAM600_OFFSET_DATA 14
180 /* Frame packet header offsets for the spca533 */
181#define SPCA533_OFFSET_DATA 16
182#define SPCA533_OFFSET_FRAMSEQ 15
183/* Frame packet header offsets for the spca536 */
184#define SPCA536_OFFSET_DATA 4
185#define SPCA536_OFFSET_FRAMSEQ 1
186
187/* Initialisation data for the Creative PC-CAM 600 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300188static const __u16 spca504_pccam600_init_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300189/* {0xa0, 0x0000, 0x0503}, * capture mode */
190 {0x00, 0x0000, 0x2000},
191 {0x00, 0x0013, 0x2301},
192 {0x00, 0x0003, 0x2000},
193 {0x00, 0x0001, 0x21ac},
194 {0x00, 0x0001, 0x21a6},
195 {0x00, 0x0000, 0x21a7}, /* brightness */
196 {0x00, 0x0020, 0x21a8}, /* contrast */
197 {0x00, 0x0001, 0x21ac}, /* sat/hue */
198 {0x00, 0x0000, 0x21ad}, /* hue */
199 {0x00, 0x001a, 0x21ae}, /* saturation */
200 {0x00, 0x0002, 0x21a3}, /* gamma */
201 {0x30, 0x0154, 0x0008},
202 {0x30, 0x0004, 0x0006},
203 {0x30, 0x0258, 0x0009},
204 {0x30, 0x0004, 0x0000},
205 {0x30, 0x0093, 0x0004},
206 {0x30, 0x0066, 0x0005},
207 {0x00, 0x0000, 0x2000},
208 {0x00, 0x0013, 0x2301},
209 {0x00, 0x0003, 0x2000},
210 {0x00, 0x0013, 0x2301},
211 {0x00, 0x0003, 0x2000},
212 {}
213};
214
215/* Creative PC-CAM 600 specific open data, sent before using the
216 * generic initialisation data from spca504_open_data.
217 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300218static const __u16 spca504_pccam600_open_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300219 {0x00, 0x0001, 0x2501},
220 {0x20, 0x0500, 0x0001}, /* snapshot mode */
221 {0x00, 0x0003, 0x2880},
222 {0x00, 0x0001, 0x2881},
223 {}
224};
225
226/* Initialisation data for the logitech clicksmart 420 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300227static const __u16 spca504A_clicksmart420_init_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300228/* {0xa0, 0x0000, 0x0503}, * capture mode */
229 {0x00, 0x0000, 0x2000},
230 {0x00, 0x0013, 0x2301},
231 {0x00, 0x0003, 0x2000},
232 {0x00, 0x0001, 0x21ac},
233 {0x00, 0x0001, 0x21a6},
234 {0x00, 0x0000, 0x21a7}, /* brightness */
235 {0x00, 0x0020, 0x21a8}, /* contrast */
236 {0x00, 0x0001, 0x21ac}, /* sat/hue */
237 {0x00, 0x0000, 0x21ad}, /* hue */
238 {0x00, 0x001a, 0x21ae}, /* saturation */
239 {0x00, 0x0002, 0x21a3}, /* gamma */
240 {0x30, 0x0004, 0x000a},
241 {0xb0, 0x0001, 0x0000},
242
243
244 {0x0a1, 0x0080, 0x0001},
245 {0x30, 0x0049, 0x0000},
246 {0x30, 0x0060, 0x0005},
247 {0x0c, 0x0004, 0x0000},
248 {0x00, 0x0000, 0x0000},
249 {0x00, 0x0000, 0x2000},
250 {0x00, 0x0013, 0x2301},
251 {0x00, 0x0003, 0x2000},
252 {0x00, 0x0000, 0x2000},
253
254 {}
255};
256
257/* clicksmart 420 open data ? */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300258static const __u16 spca504A_clicksmart420_open_data[][3] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300259 {0x00, 0x0001, 0x2501},
260 {0x20, 0x0502, 0x0000},
261 {0x06, 0x0000, 0x0000},
262 {0x00, 0x0004, 0x2880},
263 {0x00, 0x0001, 0x2881},
264/* look like setting a qTable */
265 {0x00, 0x0006, 0x2800},
266 {0x00, 0x0004, 0x2801},
267 {0x00, 0x0004, 0x2802},
268 {0x00, 0x0006, 0x2803},
269 {0x00, 0x000a, 0x2804},
270 {0x00, 0x0010, 0x2805},
271 {0x00, 0x0014, 0x2806},
272 {0x00, 0x0018, 0x2807},
273 {0x00, 0x0005, 0x2808},
274 {0x00, 0x0005, 0x2809},
275 {0x00, 0x0006, 0x280a},
276 {0x00, 0x0008, 0x280b},
277 {0x00, 0x000a, 0x280c},
278 {0x00, 0x0017, 0x280d},
279 {0x00, 0x0018, 0x280e},
280 {0x00, 0x0016, 0x280f},
281
282 {0x00, 0x0006, 0x2810},
283 {0x00, 0x0005, 0x2811},
284 {0x00, 0x0006, 0x2812},
285 {0x00, 0x000a, 0x2813},
286 {0x00, 0x0010, 0x2814},
287 {0x00, 0x0017, 0x2815},
288 {0x00, 0x001c, 0x2816},
289 {0x00, 0x0016, 0x2817},
290 {0x00, 0x0006, 0x2818},
291 {0x00, 0x0007, 0x2819},
292 {0x00, 0x0009, 0x281a},
293 {0x00, 0x000c, 0x281b},
294 {0x00, 0x0014, 0x281c},
295 {0x00, 0x0023, 0x281d},
296 {0x00, 0x0020, 0x281e},
297 {0x00, 0x0019, 0x281f},
298
299 {0x00, 0x0007, 0x2820},
300 {0x00, 0x0009, 0x2821},
301 {0x00, 0x000f, 0x2822},
302 {0x00, 0x0016, 0x2823},
303 {0x00, 0x001b, 0x2824},
304 {0x00, 0x002c, 0x2825},
305 {0x00, 0x0029, 0x2826},
306 {0x00, 0x001f, 0x2827},
307 {0x00, 0x000a, 0x2828},
308 {0x00, 0x000e, 0x2829},
309 {0x00, 0x0016, 0x282a},
310 {0x00, 0x001a, 0x282b},
311 {0x00, 0x0020, 0x282c},
312 {0x00, 0x002a, 0x282d},
313 {0x00, 0x002d, 0x282e},
314 {0x00, 0x0025, 0x282f},
315
316 {0x00, 0x0014, 0x2830},
317 {0x00, 0x001a, 0x2831},
318 {0x00, 0x001f, 0x2832},
319 {0x00, 0x0023, 0x2833},
320 {0x00, 0x0029, 0x2834},
321 {0x00, 0x0030, 0x2835},
322 {0x00, 0x0030, 0x2836},
323 {0x00, 0x0028, 0x2837},
324 {0x00, 0x001d, 0x2838},
325 {0x00, 0x0025, 0x2839},
326 {0x00, 0x0026, 0x283a},
327 {0x00, 0x0027, 0x283b},
328 {0x00, 0x002d, 0x283c},
329 {0x00, 0x0028, 0x283d},
330 {0x00, 0x0029, 0x283e},
331 {0x00, 0x0028, 0x283f},
332
333 {0x00, 0x0007, 0x2840},
334 {0x00, 0x0007, 0x2841},
335 {0x00, 0x000a, 0x2842},
336 {0x00, 0x0013, 0x2843},
337 {0x00, 0x0028, 0x2844},
338 {0x00, 0x0028, 0x2845},
339 {0x00, 0x0028, 0x2846},
340 {0x00, 0x0028, 0x2847},
341 {0x00, 0x0007, 0x2848},
342 {0x00, 0x0008, 0x2849},
343 {0x00, 0x000a, 0x284a},
344 {0x00, 0x001a, 0x284b},
345 {0x00, 0x0028, 0x284c},
346 {0x00, 0x0028, 0x284d},
347 {0x00, 0x0028, 0x284e},
348 {0x00, 0x0028, 0x284f},
349
350 {0x00, 0x000a, 0x2850},
351 {0x00, 0x000a, 0x2851},
352 {0x00, 0x0016, 0x2852},
353 {0x00, 0x0028, 0x2853},
354 {0x00, 0x0028, 0x2854},
355 {0x00, 0x0028, 0x2855},
356 {0x00, 0x0028, 0x2856},
357 {0x00, 0x0028, 0x2857},
358 {0x00, 0x0013, 0x2858},
359 {0x00, 0x001a, 0x2859},
360 {0x00, 0x0028, 0x285a},
361 {0x00, 0x0028, 0x285b},
362 {0x00, 0x0028, 0x285c},
363 {0x00, 0x0028, 0x285d},
364 {0x00, 0x0028, 0x285e},
365 {0x00, 0x0028, 0x285f},
366
367 {0x00, 0x0028, 0x2860},
368 {0x00, 0x0028, 0x2861},
369 {0x00, 0x0028, 0x2862},
370 {0x00, 0x0028, 0x2863},
371 {0x00, 0x0028, 0x2864},
372 {0x00, 0x0028, 0x2865},
373 {0x00, 0x0028, 0x2866},
374 {0x00, 0x0028, 0x2867},
375 {0x00, 0x0028, 0x2868},
376 {0x00, 0x0028, 0x2869},
377 {0x00, 0x0028, 0x286a},
378 {0x00, 0x0028, 0x286b},
379 {0x00, 0x0028, 0x286c},
380 {0x00, 0x0028, 0x286d},
381 {0x00, 0x0028, 0x286e},
382 {0x00, 0x0028, 0x286f},
383
384 {0x00, 0x0028, 0x2870},
385 {0x00, 0x0028, 0x2871},
386 {0x00, 0x0028, 0x2872},
387 {0x00, 0x0028, 0x2873},
388 {0x00, 0x0028, 0x2874},
389 {0x00, 0x0028, 0x2875},
390 {0x00, 0x0028, 0x2876},
391 {0x00, 0x0028, 0x2877},
392 {0x00, 0x0028, 0x2878},
393 {0x00, 0x0028, 0x2879},
394 {0x00, 0x0028, 0x287a},
395 {0x00, 0x0028, 0x287b},
396 {0x00, 0x0028, 0x287c},
397 {0x00, 0x0028, 0x287d},
398 {0x00, 0x0028, 0x287e},
399 {0x00, 0x0028, 0x287f},
400
401 {0xa0, 0x0000, 0x0503},
402 {}
403};
404
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300405static const __u8 qtable_creative_pccam[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300406 { /* Q-table Y-components */
407 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
408 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
409 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
410 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
411 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
412 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
413 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
414 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
415 { /* Q-table C-components */
416 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
417 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
418 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
419 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
424};
425
426/* FIXME: This Q-table is identical to the Creative PC-CAM one,
427 * except for one byte. Possibly a typo?
428 * NWG: 18/05/2003.
429 */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300430static const __u8 qtable_spca504_default[2][64] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300431 { /* Q-table Y-components */
432 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
433 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
434 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
435 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
436 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
437 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
438 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
439 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
440 },
441 { /* Q-table C-components */
442 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
443 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
444 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
445 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
450};
451
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300452static void reg_r(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300453 __u16 req,
454 __u16 index,
455 __u8 *buffer, __u16 length)
456{
457 usb_control_msg(dev,
458 usb_rcvctrlpipe(dev, 0),
459 req,
460 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
461 0, /* value */
462 index, buffer, length,
463 500);
464}
465
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300466static void reg_w(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300467 __u16 req,
468 __u16 value,
469 __u16 index,
470 __u8 *buffer, __u16 length)
471{
472 usb_control_msg(dev,
473 usb_sndctrlpipe(dev, 0),
474 req,
475 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
476 value, index, buffer, length,
477 500);
478}
479
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300480/* write req / index / value */
481static int reg_w_riv(struct usb_device *dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300482 __u16 req, __u16 index, __u16 value)
483{
484 int ret;
485
486 ret = usb_control_msg(dev,
487 usb_sndctrlpipe(dev, 0),
488 req,
Jean-Francois Moinebf7f0b92008-07-03 11:09:12 -0300489 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300490 value, index, NULL, 0, 500);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300491 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
Jean-Francois Moine956e42d2008-07-01 10:03:42 -0300492 req, index, value, ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300493 if (ret < 0)
494 PDEBUG(D_ERR, "reg write: error %d", ret);
495 return ret;
496}
497
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300498/* read 1 byte */
499static int reg_r_1(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300500 __u16 value) /* wValue */
501{
502 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300503
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300504 ret = usb_control_msg(gspca_dev->dev,
505 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300506 0x20, /* request */
507 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
508 value,
509 0, /* index */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300510 gspca_dev->usb_buf, 1,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300511 500); /* timeout */
512 if (ret < 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300513 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300514 return 0;
515 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300516 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300517}
518
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300519/* read 1 or 2 bytes - returns < 0 if error */
520static int reg_r_12(struct gspca_dev *gspca_dev,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300521 __u16 req, /* bRequest */
522 __u16 index, /* wIndex */
523 __u16 length) /* wLength (1 or 2 only) */
524{
525 int ret;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300526
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300527 gspca_dev->usb_buf[1] = 0;
528 ret = usb_control_msg(gspca_dev->dev,
529 usb_rcvctrlpipe(gspca_dev->dev, 0),
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300530 req,
531 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
532 0, /* value */
533 index,
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300534 gspca_dev->usb_buf, length,
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300535 500);
536 if (ret < 0) {
537 PDEBUG(D_ERR, "reg_read err %d", ret);
538 return -1;
539 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300540 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300541}
542
543static int write_vector(struct gspca_dev *gspca_dev,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300544 const __u16 data[][3])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300545{
546 struct usb_device *dev = gspca_dev->dev;
547 int ret, i = 0;
548
549 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300550 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300551 if (ret < 0) {
552 PDEBUG(D_ERR,
553 "Register write failed for 0x%x,0x%x,0x%x",
554 data[i][0], data[i][1], data[i][2]);
555 return ret;
556 }
557 i++;
558 }
559 return 0;
560}
561
562static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
563 unsigned int request,
564 unsigned int ybase,
565 unsigned int cbase,
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -0300566 const __u8 qtable[2][64])
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300567{
568 struct usb_device *dev = gspca_dev->dev;
569 int i, err;
570
571 /* loop over y components */
572 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300573 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300574 if (err < 0)
575 return err;
576 }
577
578 /* loop over c components */
579 for (i = 0; i < 64; i++) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300580 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300581 if (err < 0)
582 return err;
583 }
584 return 0;
585}
586
587static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
588 __u16 req, __u16 idx, __u16 val)
589{
590 struct usb_device *dev = gspca_dev->dev;
591 __u8 notdone;
592
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300593 reg_w_riv(dev, req, idx, val);
594 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
595 reg_w_riv(dev, req, idx, val);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300596
597 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
598
599 msleep(200);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300600 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300601 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
602}
603
604static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
605 __u16 req,
606 __u16 idx, __u16 val, __u8 stat, __u8 count)
607{
608 struct usb_device *dev = gspca_dev->dev;
609 __u8 status;
610 __u8 endcode;
611
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300612 reg_w_riv(dev, req, idx, val);
613 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300614 endcode = stat;
615 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
616 if (!count)
617 return;
618 count = 200;
619 while (--count > 0) {
620 msleep(10);
621 /* gsmart mini2 write a each wait setting 1 ms is enought */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300622/* reg_w_riv(dev, req, idx, val); */
623 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300624 if (status == endcode) {
625 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
626 status, 200 - count);
627 break;
628 }
629 }
630}
631
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300632static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300633{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300634 int count = 10;
635
636 while (--count > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300637 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
638 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300639 break;
640 msleep(10);
641 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300642 return gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300643}
644
645static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
646{
647 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300648 int count = 50;
649
650 while (--count > 0) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300651 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
652 if (gspca_dev->usb_buf[0] != 0) {
653 gspca_dev->usb_buf[0] = 0;
654 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
655 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
656 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300657 break;
658 }
659 msleep(10);
660 }
661}
662
663static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
664{
665 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300666 __u8 *data;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300667
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300668 data = kmalloc(64, GFP_KERNEL);
669 reg_r(dev, 0x20, 0, data, 5);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300670 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300671 data[0], data[1], data[2], data[3], data[4]);
672 reg_r(dev, 0x23, 0, data, 64);
673 reg_r(dev, 0x23, 1, data, 64);
674 kfree(data);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300675}
676
677static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
678{
679 struct sd *sd = (struct sd *) gspca_dev;
680 struct usb_device *dev = gspca_dev->dev;
681 __u8 Size;
682 __u8 Type;
683 int rc;
684
Jean-Francois Moinec2446b32008-07-05 11:49:20 -0300685 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300686 Type = 0;
687 switch (sd->bridge) {
688 case BRIDGE_SPCA533:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300689 reg_w(dev, 0x31, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300690 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300691 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300692 spca50x_GetFirmware(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300693 gspca_dev->usb_buf[0] = 2; /* type */
694 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
695 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300696
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300697 gspca_dev->usb_buf[0] = Size;
698 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
699 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
700 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300701
702 /* Init the cam width height with some values get on init ? */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300703 reg_w(dev, 0x31, 0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300704 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300705 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300706 break;
707 default:
708/* case BRIDGE_SPCA504B: */
709/* case BRIDGE_SPCA536: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300710 gspca_dev->usb_buf[0] = Size;
711 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
712 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300713 Type = 6;
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300714 gspca_dev->usb_buf[0] = Type;
715 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
716 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
717 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300718 break;
719 case BRIDGE_SPCA504:
720 Size += 3;
721 if (sd->subtype == AiptekMiniPenCam13) {
722 /* spca504a aiptek */
723 spca504A_acknowledged_command(gspca_dev,
724 0x08, Size, 0,
725 0x80 | (Size & 0x0f), 1);
726 spca504A_acknowledged_command(gspca_dev,
727 1, 3, 0, 0x9f, 0);
728 } else {
729 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
730 }
731 break;
732 case BRIDGE_SPCA504C:
733 /* capture mode */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300734 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
735 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300736 break;
737 }
738}
739
740static void spca504_wait_status(struct gspca_dev *gspca_dev)
741{
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300742 int cnt;
743
744 cnt = 256;
745 while (--cnt > 0) {
746 /* With this we get the status, when return 0 it's all ok */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300747 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300748 return;
749 msleep(10);
750 }
751}
752
753static void spca504B_setQtable(struct gspca_dev *gspca_dev)
754{
755 struct usb_device *dev = gspca_dev->dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300756
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300757 gspca_dev->usb_buf[0] = 3;
758 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
759 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
760 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300761}
762
763static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
764{
765 struct sd *sd = (struct sd *) gspca_dev;
766 struct usb_device *dev = gspca_dev->dev;
767 int pollreg = 1;
768
769 switch (sd->bridge) {
770 case BRIDGE_SPCA504:
771 case BRIDGE_SPCA504C:
772 pollreg = 0;
773 /* fall thru */
774 default:
775/* case BRIDGE_SPCA533: */
776/* case BRIDGE_SPCA504B: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300777 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
778 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
779 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
780 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
781 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
782 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300783 break;
784 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300785 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
786 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
787 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
788 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
789 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
790 reg_w(dev, 0, 0, 0x2089, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300791 break;
792 }
793 if (pollreg)
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300794 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300795}
796
797/* this function is called at probe time */
798static int sd_config(struct gspca_dev *gspca_dev,
799 const struct usb_device_id *id)
800{
801 struct sd *sd = (struct sd *) gspca_dev;
802 struct usb_device *dev = gspca_dev->dev;
803 struct cam *cam;
804 __u16 vendor;
805 __u16 product;
806 __u8 fw;
807
808 vendor = id->idVendor;
809 product = id->idProduct;
810 switch (vendor) {
811 case 0x041e: /* Creative cameras */
812/* switch (product) { */
813/* case 0x400b: */
814/* case 0x4012: */
815/* case 0x4013: */
816/* sd->bridge = BRIDGE_SPCA504C; */
817/* break; */
818/* } */
819 break;
820 case 0x0458: /* Genius KYE cameras */
821/* switch (product) { */
822/* case 0x7006: */
823 sd->bridge = BRIDGE_SPCA504B;
824/* break; */
825/* } */
826 break;
Jean-Francois Moine100f7f22008-07-17 09:41:03 -0300827 case 0x0461: /* MicroInnovation */
828/* switch (product) { */
829/* case 0x0821: */
830 sd->bridge = BRIDGE_SPCA533;
831/* break; */
832/* } */
833 break;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300834 case 0x046d: /* Logitech Labtec */
835 switch (product) {
836 case 0x0905:
837 sd->subtype = LogitechClickSmart820;
838 sd->bridge = BRIDGE_SPCA533;
839 break;
840 case 0x0960:
841 sd->subtype = LogitechClickSmart420;
842 sd->bridge = BRIDGE_SPCA504C;
843 break;
844 }
845 break;
846 case 0x0471: /* Philips */
847/* switch (product) { */
848/* case 0x0322: */
849 sd->bridge = BRIDGE_SPCA504B;
850/* break; */
851/* } */
852 break;
853 case 0x04a5: /* Benq */
854 switch (product) {
855 case 0x3003:
856 sd->bridge = BRIDGE_SPCA504B;
857 break;
858 case 0x3008:
859 case 0x300a:
860 sd->bridge = BRIDGE_SPCA533;
861 break;
862 }
863 break;
864 case 0x04f1: /* JVC */
865/* switch (product) { */
866/* case 0x1001: */
867 sd->bridge = BRIDGE_SPCA504B;
868/* break; */
869/* } */
870 break;
871 case 0x04fc: /* SunPlus */
872 switch (product) {
873 case 0x500c:
874 sd->bridge = BRIDGE_SPCA504B;
875 break;
876 case 0x504a:
877/* try to get the firmware as some cam answer 2.0.1.2.2
878 * and should be a spca504b then overwrite that setting */
Jean-Francois Moine739570b2008-07-14 09:38:29 -0300879 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
880 fw = gspca_dev->usb_buf[0];
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -0300881 if (fw == 1) {
882 sd->subtype = AiptekMiniPenCam13;
883 sd->bridge = BRIDGE_SPCA504;
884 } else if (fw == 2) {
885 sd->bridge = BRIDGE_SPCA504B;
886 } else
887 return -ENODEV;
888 break;
889 case 0x504b:
890 sd->bridge = BRIDGE_SPCA504B;
891 break;
892 case 0x5330:
893 sd->bridge = BRIDGE_SPCA533;
894 break;
895 case 0x5360:
896 sd->bridge = BRIDGE_SPCA536;
897 break;
898 case 0xffff:
899 sd->bridge = BRIDGE_SPCA504B;
900 break;
901 }
902 break;
903 case 0x052b: /* ?? Megapix */
904/* switch (product) { */
905/* case 0x1513: */
906 sd->subtype = MegapixV4;
907 sd->bridge = BRIDGE_SPCA533;
908/* break; */
909/* } */
910 break;
911 case 0x0546: /* Polaroid */
912 switch (product) {
913 case 0x3155:
914 sd->bridge = BRIDGE_SPCA533;
915 break;
916 case 0x3191:
917 case 0x3273:
918 sd->bridge = BRIDGE_SPCA504B;
919 break;
920 }
921 break;
922 case 0x055f: /* Mustek cameras */
923 switch (product) {
924 case 0xc211:
925 sd->bridge = BRIDGE_SPCA536;
926 break;
927 case 0xc230:
928 case 0xc232:
929 sd->bridge = BRIDGE_SPCA533;
930 break;
931 case 0xc360:
932 sd->bridge = BRIDGE_SPCA536;
933 break;
934 case 0xc420:
935 sd->bridge = BRIDGE_SPCA504;
936 break;
937 case 0xc430:
938 case 0xc440:
939 sd->bridge = BRIDGE_SPCA533;
940 break;
941 case 0xc520:
942 sd->bridge = BRIDGE_SPCA504;
943 break;
944 case 0xc530:
945 case 0xc540:
946 case 0xc630:
947 case 0xc650:
948 sd->bridge = BRIDGE_SPCA533;
949 break;
950 }
951 break;
952 case 0x05da: /* Digital Dream cameras */
953/* switch (product) { */
954/* case 0x1018: */
955 sd->bridge = BRIDGE_SPCA504B;
956/* break; */
957/* } */
958 break;
959 case 0x06d6: /* Trust */
960/* switch (product) { */
961/* case 0x0031: */
962 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
963/* break; */
964/* } */
965 break;
966 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
967 switch (product) {
968 case 0x1311:
969 case 0x1314:
970 case 0x2211:
971 case 0x2221:
972 sd->bridge = BRIDGE_SPCA533;
973 break;
974 case 0x3261:
975 case 0x3281:
976 sd->bridge = BRIDGE_SPCA536;
977 break;
978 }
979 break;
980 case 0x08ca: /* Aiptek */
981 switch (product) {
982 case 0x0104:
983 case 0x0106:
984 sd->bridge = BRIDGE_SPCA533;
985 break;
986 case 0x2008:
987 sd->bridge = BRIDGE_SPCA504B;
988 break;
989 case 0x2010:
990 sd->bridge = BRIDGE_SPCA533;
991 break;
992 case 0x2016:
993 case 0x2018:
994 sd->bridge = BRIDGE_SPCA504B;
995 break;
996 case 0x2020:
997 case 0x2022:
998 sd->bridge = BRIDGE_SPCA533;
999 break;
1000 case 0x2024:
1001 sd->bridge = BRIDGE_SPCA536;
1002 break;
1003 case 0x2028:
1004 sd->bridge = BRIDGE_SPCA533;
1005 break;
1006 case 0x2040:
1007 case 0x2042:
Jean-Francois Moinec91256c2008-07-17 10:12:55 -03001008 case 0x2050:
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001009 case 0x2060:
1010 sd->bridge = BRIDGE_SPCA536;
1011 break;
1012 }
1013 break;
1014 case 0x0d64: /* SunPlus */
1015/* switch (product) { */
1016/* case 0x0303: */
1017 sd->bridge = BRIDGE_SPCA536;
1018/* break; */
1019/* } */
1020 break;
1021 }
1022
1023 cam = &gspca_dev->cam;
1024 cam->dev_name = (char *) id->driver_info;
1025 cam->epaddr = 0x01;
1026
1027 switch (sd->bridge) {
1028 default:
1029/* case BRIDGE_SPCA504B: */
1030/* case BRIDGE_SPCA504: */
1031/* case BRIDGE_SPCA536: */
1032 cam->cam_mode = vga_mode;
1033 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1034 break;
1035 case BRIDGE_SPCA533:
1036 cam->cam_mode = custom_mode;
1037 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1038 break;
1039 case BRIDGE_SPCA504C:
1040 cam->cam_mode = vga_mode2;
1041 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1042 break;
1043 }
1044 sd->qindex = 5; /* set the quantization table */
1045 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1046 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1047 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1048 return 0;
1049}
1050
1051/* this function is called at open time */
1052static int sd_open(struct gspca_dev *gspca_dev)
1053{
1054 struct sd *sd = (struct sd *) gspca_dev;
1055 struct usb_device *dev = gspca_dev->dev;
1056 int rc;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001057 __u8 i;
1058 __u8 info[6];
1059 int err_code;
1060
1061 switch (sd->bridge) {
1062 case BRIDGE_SPCA504B:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001063 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1064 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1065 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1066 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1067 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1068 reg_w(dev, 0, 0, 0x2306, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001069 /* fall thru */
1070 case BRIDGE_SPCA533:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001071 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001072 spca50x_GetFirmware(gspca_dev);
1073 break;
1074 case BRIDGE_SPCA536:
1075 spca50x_GetFirmware(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001076 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1077 gspca_dev->usb_buf[0] = 0;
1078 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1079 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1080 rc = spca504B_PollingDataReady(gspca_dev);
1081 reg_w(dev, 0x34, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001082 spca504B_WaitCmdStatus(gspca_dev);
1083 break;
1084 case BRIDGE_SPCA504C: /* pccam600 */
1085 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001086 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1087 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001088 spca504_wait_status(gspca_dev);
1089 if (sd->subtype == LogitechClickSmart420)
1090 write_vector(gspca_dev,
1091 spca504A_clicksmart420_open_data);
1092 else
1093 write_vector(gspca_dev, spca504_pccam600_open_data);
1094 err_code = spca50x_setup_qtable(gspca_dev,
1095 0x00, 0x2800,
1096 0x2840, qtable_creative_pccam);
1097 if (err_code < 0) {
1098 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1099 return err_code;
1100 }
1101 break;
1102 default:
1103/* case BRIDGE_SPCA504: */
1104 PDEBUG(D_STREAM, "Opening SPCA504");
1105 if (sd->subtype == AiptekMiniPenCam13) {
1106 /*****************************/
1107 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001108 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001109 PDEBUG(D_STREAM,
1110 "Read info: %d %d %d %d %d %d."
1111 " Should be 1,0,2,2,0,0",
1112 info[0], info[1], info[2],
1113 info[3], info[4], info[5]);
1114 /* spca504a aiptek */
1115 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1116 spca504A_acknowledged_command(gspca_dev, 0x24,
1117 8, 3, 0x9e, 1);
1118 /* Twice sequencial need status 0xff->0x9e->0x9d */
1119 spca504A_acknowledged_command(gspca_dev, 0x24,
1120 8, 3, 0x9e, 0);
1121
1122 spca504A_acknowledged_command(gspca_dev, 0x24,
1123 0, 0, 0x9d, 1);
1124 /******************************/
1125 /* spca504a aiptek */
1126 spca504A_acknowledged_command(gspca_dev, 0x08,
1127 6, 0, 0x86, 1);
1128/* reg_write (dev, 0, 0x2000, 0); */
1129/* reg_write (dev, 0, 0x2883, 1); */
1130/* spca504A_acknowledged_command (gspca_dev, 0x08,
1131 6, 0, 0x86, 1); */
1132/* spca504A_acknowledged_command (gspca_dev, 0x24,
1133 0, 0, 0x9D, 1); */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001134 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1135 reg_w_riv(dev, 0x0, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001136 spca504A_acknowledged_command(gspca_dev, 0x01,
1137 0x0f, 0, 0xff, 0);
1138 }
1139 /* setup qtable */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001140 reg_w_riv(dev, 0, 0x2000, 0);
1141 reg_w_riv(dev, 0, 0x2883, 1);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001142 err_code = spca50x_setup_qtable(gspca_dev,
1143 0x00, 0x2800,
1144 0x2840,
1145 qtable_spca504_default);
1146 if (err_code < 0) {
1147 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1148 return err_code;
1149 }
1150 break;
1151 }
1152 return 0;
1153}
1154
1155static void sd_start(struct gspca_dev *gspca_dev)
1156{
1157 struct sd *sd = (struct sd *) gspca_dev;
1158 struct usb_device *dev = gspca_dev->dev;
1159 int rc;
1160 int enable;
1161 __u8 i;
1162 __u8 info[6];
1163
1164 if (sd->bridge == BRIDGE_SPCA504B)
1165 spca504B_setQtable(gspca_dev);
1166 spca504B_SetSizeType(gspca_dev);
1167 switch (sd->bridge) {
1168 default:
1169/* case BRIDGE_SPCA504B: */
1170/* case BRIDGE_SPCA533: */
1171/* case BRIDGE_SPCA536: */
1172 if (sd->subtype == MegapixV4 ||
1173 sd->subtype == LogitechClickSmart820) {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001174 reg_w(dev, 0xf0, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001175 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001176 reg_r(dev, 0xf0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001177 spca504B_WaitCmdStatus(gspca_dev);
1178 } else {
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001179 reg_w(dev, 0x31, 0, 4, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001180 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001181 rc = spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001182 }
1183 break;
1184 case BRIDGE_SPCA504:
1185 if (sd->subtype == AiptekMiniPenCam13) {
1186 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001187 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001188 PDEBUG(D_STREAM,
1189 "Read info: %d %d %d %d %d %d."
1190 " Should be 1,0,2,2,0,0",
1191 info[0], info[1], info[2],
1192 info[3], info[4], info[5]);
1193 /* spca504a aiptek */
1194 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1195 spca504A_acknowledged_command(gspca_dev, 0x24,
1196 8, 3, 0x9e, 1);
1197 /* Twice sequencial need status 0xff->0x9e->0x9d */
1198 spca504A_acknowledged_command(gspca_dev, 0x24,
1199 8, 3, 0x9e, 0);
1200 spca504A_acknowledged_command(gspca_dev, 0x24,
1201 0, 0, 0x9d, 1);
1202 } else {
1203 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1204 for (i = 0; i < 6; i++)
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001205 info[i] = reg_r_1(gspca_dev, i);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001206 PDEBUG(D_STREAM,
1207 "Read info: %d %d %d %d %d %d."
1208 " Should be 1,0,2,2,0,0",
1209 info[0], info[1], info[2],
1210 info[3], info[4], info[5]);
1211 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1212 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1213 }
1214 spca504B_SetSizeType(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001215 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1216 reg_w_riv(dev, 0x0, 0x2310, 0x05);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001217 break;
1218 case BRIDGE_SPCA504C:
1219 if (sd->subtype == LogitechClickSmart420) {
1220 write_vector(gspca_dev,
1221 spca504A_clicksmart420_init_data);
1222 } else {
1223 write_vector(gspca_dev, spca504_pccam600_init_data);
1224 }
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001225 enable = (sd->autogain ? 0x04 : 0x01);
1226 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1227 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001228
1229 /* set default exposure compensation and whiteness balance */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001230 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1231 reg_w_riv(dev, 0x30, 0x0002, 1600);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001232 spca504B_SetSizeType(gspca_dev);
1233 break;
1234 }
1235 sp5xx_initContBrigHueRegisters(gspca_dev);
1236}
1237
1238static void sd_stopN(struct gspca_dev *gspca_dev)
1239{
1240 struct sd *sd = (struct sd *) gspca_dev;
1241 struct usb_device *dev = gspca_dev->dev;
1242
1243 switch (sd->bridge) {
1244 default:
1245/* case BRIDGE_SPCA533: */
1246/* case BRIDGE_SPCA536: */
1247/* case BRIDGE_SPCA504B: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001248 reg_w(dev, 0x31, 0, 0, NULL, 0);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001249 spca504B_WaitCmdStatus(gspca_dev);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001250 spca504B_PollingDataReady(gspca_dev);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001251 break;
1252 case BRIDGE_SPCA504:
1253 case BRIDGE_SPCA504C:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001254 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001255
1256 if (sd->subtype == AiptekMiniPenCam13) {
1257 /* spca504a aiptek */
1258/* spca504A_acknowledged_command(gspca_dev, 0x08,
1259 6, 0, 0x86, 1); */
1260 spca504A_acknowledged_command(gspca_dev, 0x24,
1261 0x00, 0x00, 0x9d, 1);
1262 spca504A_acknowledged_command(gspca_dev, 0x01,
1263 0x0f, 0x00, 0xff, 1);
1264 } else {
1265 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001266 reg_w_riv(dev, 0x01, 0x000f, 0x00);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001267 }
1268 break;
1269 }
1270}
1271
1272static void sd_stop0(struct gspca_dev *gspca_dev)
1273{
1274}
1275
1276static void sd_close(struct gspca_dev *gspca_dev)
1277{
1278}
1279
1280static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1281 struct gspca_frame *frame, /* target */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001282 __u8 *data, /* isoc packet */
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001283 int len) /* iso packet length */
1284{
1285 struct sd *sd = (struct sd *) gspca_dev;
1286 int i, sof = 0;
1287 unsigned char *s, *d;
1288 static unsigned char ffd9[] = {0xff, 0xd9};
1289
1290/* frames are jpeg 4.1.1 without 0xff escape */
1291 switch (sd->bridge) {
1292 case BRIDGE_SPCA533:
1293 if (data[0] == 0xff) {
1294 if (data[1] != 0x01) { /* drop packet */
1295/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1296 return;
1297 }
1298 sof = 1;
1299 data += SPCA533_OFFSET_DATA;
1300 len -= SPCA533_OFFSET_DATA;
1301 } else {
1302 data += 1;
1303 len -= 1;
1304 }
1305 break;
1306 case BRIDGE_SPCA536:
1307 if (data[0] == 0xff) {
1308 sof = 1;
1309 data += SPCA536_OFFSET_DATA;
1310 len -= SPCA536_OFFSET_DATA;
1311 } else {
1312 data += 2;
1313 len -= 2;
1314 }
1315 break;
1316 default:
1317/* case BRIDGE_SPCA504: */
1318/* case BRIDGE_SPCA504B: */
1319 switch (data[0]) {
1320 case 0xfe: /* start of frame */
1321 sof = 1;
1322 data += SPCA50X_OFFSET_DATA;
1323 len -= SPCA50X_OFFSET_DATA;
1324 break;
1325 case 0xff: /* drop packet */
1326/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1327 return;
1328 default:
1329 data += 1;
1330 len -= 1;
1331 break;
1332 }
1333 break;
1334 case BRIDGE_SPCA504C:
1335 switch (data[0]) {
1336 case 0xfe: /* start of frame */
1337 sof = 1;
1338 data += SPCA504_PCCAM600_OFFSET_DATA;
1339 len -= SPCA504_PCCAM600_OFFSET_DATA;
1340 break;
1341 case 0xff: /* drop packet */
1342/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1343 return;
1344 default:
1345 data += 1;
1346 len -= 1;
1347 break;
1348 }
1349 break;
1350 }
1351 if (sof) { /* start of frame */
1352 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1353 ffd9, 2);
1354
1355 /* put the JPEG header in the new frame */
1356 jpeg_put_header(gspca_dev, frame,
1357 ((struct sd *) gspca_dev)->qindex,
1358 0x22);
1359 }
1360
1361 /* add 0x00 after 0xff */
1362 for (i = len; --i >= 0; )
1363 if (data[i] == 0xff)
1364 break;
1365 if (i < 0) { /* no 0xff */
1366 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1367 return;
1368 }
1369 s = data;
1370 d = sd->packet;
1371 for (i = 0; i < len; i++) {
1372 *d++ = *s++;
1373 if (s[-1] == 0xff)
1374 *d++ = 0x00;
1375 }
1376 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1377 sd->packet, d - sd->packet);
1378}
1379
1380static void setbrightness(struct gspca_dev *gspca_dev)
1381{
1382 struct sd *sd = (struct sd *) gspca_dev;
1383 struct usb_device *dev = gspca_dev->dev;
1384
1385 switch (sd->bridge) {
1386 default:
1387/* case BRIDGE_SPCA533: */
1388/* case BRIDGE_SPCA504B: */
1389/* case BRIDGE_SPCA504: */
1390/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001391 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001392 break;
1393 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001394 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001395 break;
1396 }
1397}
1398
1399static void getbrightness(struct gspca_dev *gspca_dev)
1400{
1401 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001402 __u16 brightness = 0;
1403
1404 switch (sd->bridge) {
1405 default:
1406/* case BRIDGE_SPCA533: */
1407/* case BRIDGE_SPCA504B: */
1408/* case BRIDGE_SPCA504: */
1409/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001410 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001411 break;
1412 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001413 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001414 break;
1415 }
1416 sd->brightness = ((brightness & 0xff) - 128) % 255;
1417}
1418
1419static void setcontrast(struct gspca_dev *gspca_dev)
1420{
1421 struct sd *sd = (struct sd *) gspca_dev;
1422 struct usb_device *dev = gspca_dev->dev;
1423
1424 switch (sd->bridge) {
1425 default:
1426/* case BRIDGE_SPCA533: */
1427/* case BRIDGE_SPCA504B: */
1428/* case BRIDGE_SPCA504: */
1429/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001430 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001431 break;
1432 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001433 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001434 break;
1435 }
1436}
1437
1438static void getcontrast(struct gspca_dev *gspca_dev)
1439{
1440 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001441
1442 switch (sd->bridge) {
1443 default:
1444/* case BRIDGE_SPCA533: */
1445/* case BRIDGE_SPCA504B: */
1446/* case BRIDGE_SPCA504: */
1447/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001448 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001449 break;
1450 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001451 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001452 break;
1453 }
1454}
1455
1456static void setcolors(struct gspca_dev *gspca_dev)
1457{
1458 struct sd *sd = (struct sd *) gspca_dev;
1459 struct usb_device *dev = gspca_dev->dev;
1460
1461 switch (sd->bridge) {
1462 default:
1463/* case BRIDGE_SPCA533: */
1464/* case BRIDGE_SPCA504B: */
1465/* case BRIDGE_SPCA504: */
1466/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001467 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001468 break;
1469 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001470 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001471 break;
1472 }
1473}
1474
1475static void getcolors(struct gspca_dev *gspca_dev)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001478
1479 switch (sd->bridge) {
1480 default:
1481/* case BRIDGE_SPCA533: */
1482/* case BRIDGE_SPCA504B: */
1483/* case BRIDGE_SPCA504: */
1484/* case BRIDGE_SPCA504C: */
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001485 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001486 break;
1487 case BRIDGE_SPCA536:
Jean-Francois Moine739570b2008-07-14 09:38:29 -03001488 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001489 break;
1490 }
1491}
1492
1493static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1494{
1495 struct sd *sd = (struct sd *) gspca_dev;
1496
1497 sd->brightness = val;
1498 if (gspca_dev->streaming)
1499 setbrightness(gspca_dev);
1500 return 0;
1501}
1502
1503static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1504{
1505 struct sd *sd = (struct sd *) gspca_dev;
1506
1507 getbrightness(gspca_dev);
1508 *val = sd->brightness;
1509 return 0;
1510}
1511
1512static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1513{
1514 struct sd *sd = (struct sd *) gspca_dev;
1515
1516 sd->contrast = val;
1517 if (gspca_dev->streaming)
1518 setcontrast(gspca_dev);
1519 return 0;
1520}
1521
1522static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1523{
1524 struct sd *sd = (struct sd *) gspca_dev;
1525
1526 getcontrast(gspca_dev);
1527 *val = sd->contrast;
1528 return 0;
1529}
1530
1531static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1532{
1533 struct sd *sd = (struct sd *) gspca_dev;
1534
1535 sd->colors = val;
1536 if (gspca_dev->streaming)
1537 setcolors(gspca_dev);
1538 return 0;
1539}
1540
1541static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1542{
1543 struct sd *sd = (struct sd *) gspca_dev;
1544
1545 getcolors(gspca_dev);
1546 *val = sd->colors;
1547 return 0;
1548}
1549
1550static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1551{
1552 struct sd *sd = (struct sd *) gspca_dev;
1553
1554 sd->autogain = val;
1555 return 0;
1556}
1557
1558static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1559{
1560 struct sd *sd = (struct sd *) gspca_dev;
1561
1562 *val = sd->autogain;
1563 return 0;
1564}
1565
1566/* sub-driver description */
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001567static const struct sd_desc sd_desc = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001568 .name = MODULE_NAME,
1569 .ctrls = sd_ctrls,
1570 .nctrls = ARRAY_SIZE(sd_ctrls),
1571 .config = sd_config,
1572 .open = sd_open,
1573 .start = sd_start,
1574 .stopN = sd_stopN,
1575 .stop0 = sd_stop0,
1576 .close = sd_close,
1577 .pkt_scan = sd_pkt_scan,
1578};
1579
1580/* -- module initialisation -- */
1581#define DVNM(name) .driver_info = (kernel_ulong_t) name
Jean-Francois Moinea5ae2062008-07-04 11:16:16 -03001582static const __devinitdata struct usb_device_id device_table[] = {
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001583 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1584 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1585 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1586 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
Jean-Francois Moine100f7f22008-07-17 09:41:03 -03001587 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001588 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1589 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1590 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1591 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1592 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1593 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1594 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1595 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1596 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1597 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1598 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1599 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1600 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1601 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1602 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1603 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1604 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1605 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1606 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1607 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1608 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1609 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1610 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1611 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1612 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1613 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1614 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1615 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1616 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1617 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1618 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1619 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1620 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1621 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1622 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1623 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1624 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1625 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1626 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1627 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1628 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1629 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1630 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1631 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1632 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1633 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1634 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1635 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1636 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
Jean-Francois Moinec91256c2008-07-17 10:12:55 -03001637 {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001638 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1639 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1640 {}
1641};
1642MODULE_DEVICE_TABLE(usb, device_table);
1643
1644/* -- device connect -- */
1645static int sd_probe(struct usb_interface *intf,
1646 const struct usb_device_id *id)
1647{
1648 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1649 THIS_MODULE);
1650}
1651
1652static struct usb_driver sd_driver = {
1653 .name = MODULE_NAME,
1654 .id_table = device_table,
1655 .probe = sd_probe,
1656 .disconnect = gspca_disconnect,
1657};
1658
1659/* -- module insert / remove -- */
1660static int __init sd_mod_init(void)
1661{
1662 if (usb_register(&sd_driver) < 0)
1663 return -1;
Jean-Francois Moine10b0e962008-07-22 05:35:10 -03001664 PDEBUG(D_PROBE, "registered");
Jean-Francois Moine6a7eba22008-06-30 15:50:11 -03001665 return 0;
1666}
1667static void __exit sd_mod_exit(void)
1668{
1669 usb_deregister(&sd_driver);
1670 PDEBUG(D_PROBE, "deregistered");
1671}
1672
1673module_init(sd_mod_init);
1674module_exit(sd_mod_exit);