2 * SPCA500 chip based cameras initialization data
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20 #define MODULE_NAME "spca500"
25 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26 MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
27 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev
; /* !! must be the first item */
37 #define AiptekPocketDV 1
39 #define CreativePCCam300 3
42 #define IntelPocketPCCamera 6
44 #define LogitechClickSmart310 8
45 #define LogitechClickSmart510 9
46 #define LogitechTraveler 10
47 #define MustekGsmart300 11
49 #define PalmPixDC85 13
50 #define ToptroIndus 14
52 u8 jpeg_hdr
[JPEG_HDR_SZ
];
55 static const struct v4l2_pix_format vga_mode
[] = {
56 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
58 .sizeimage
= 320 * 240 * 3 / 8 + 590,
59 .colorspace
= V4L2_COLORSPACE_JPEG
,
61 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
63 .sizeimage
= 640 * 480 * 3 / 8 + 590,
64 .colorspace
= V4L2_COLORSPACE_JPEG
,
68 static const struct v4l2_pix_format sif_mode
[] = {
69 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
71 .sizeimage
= 176 * 144 * 3 / 8 + 590,
72 .colorspace
= V4L2_COLORSPACE_JPEG
,
74 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
76 .sizeimage
= 352 * 288 * 3 / 8 + 590,
77 .colorspace
= V4L2_COLORSPACE_JPEG
,
81 /* Frame packet header offsets for the spca500 */
82 #define SPCA500_OFFSET_PADDINGLB 2
83 #define SPCA500_OFFSET_PADDINGHB 3
84 #define SPCA500_OFFSET_MODE 4
85 #define SPCA500_OFFSET_IMGWIDTH 5
86 #define SPCA500_OFFSET_IMGHEIGHT 6
87 #define SPCA500_OFFSET_IMGMODE 7
88 #define SPCA500_OFFSET_QTBLINDEX 8
89 #define SPCA500_OFFSET_FRAMSEQ 9
90 #define SPCA500_OFFSET_CDSPINFO 10
91 #define SPCA500_OFFSET_GPIO 11
92 #define SPCA500_OFFSET_AUGPIO 12
93 #define SPCA500_OFFSET_DATA 16
96 static const __u16 spca500_visual_defaults
[][3] = {
97 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
99 * saturation/hue enable,
100 * brightness/contrast enable.
102 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
103 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
104 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
105 * hue (H byte) = 0, saturation/hue enable,
106 * brightness/contrast enable.
107 * was 0x0003, now 0x0000.
109 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
110 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
111 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
112 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
113 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
114 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
115 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
116 {0x0c, 0x0004, 0x0000},
120 static const __u16 Clicksmart510_defaults
[][3] = {
121 {0x00, 0x00, 0x8211},
122 {0x00, 0x01, 0x82c0},
123 {0x00, 0x10, 0x82cb},
124 {0x00, 0x0f, 0x800d},
125 {0x00, 0x82, 0x8225},
126 {0x00, 0x21, 0x8228},
127 {0x00, 0x00, 0x8203},
128 {0x00, 0x00, 0x8204},
129 {0x00, 0x08, 0x8205},
130 {0x00, 0xf8, 0x8206},
131 {0x00, 0x28, 0x8207},
132 {0x00, 0xa0, 0x8208},
133 {0x00, 0x08, 0x824a},
134 {0x00, 0x08, 0x8214},
135 {0x00, 0x80, 0x82c1},
136 {0x00, 0x00, 0x82c2},
137 {0x00, 0x00, 0x82ca},
138 {0x00, 0x80, 0x82c1},
139 {0x00, 0x04, 0x82c2},
140 {0x00, 0x00, 0x82ca},
141 {0x00, 0xfc, 0x8100},
142 {0x00, 0xfc, 0x8105},
143 {0x00, 0x30, 0x8101},
144 {0x00, 0x00, 0x8102},
145 {0x00, 0x00, 0x8103},
146 {0x00, 0x66, 0x8107},
147 {0x00, 0x00, 0x816b},
148 {0x00, 0x00, 0x8155},
149 {0x00, 0x01, 0x8156},
150 {0x00, 0x60, 0x8157},
151 {0x00, 0x40, 0x8158},
152 {0x00, 0x0a, 0x8159},
153 {0x00, 0x06, 0x815a},
154 {0x00, 0x00, 0x813f},
155 {0x00, 0x00, 0x8200},
156 {0x00, 0x19, 0x8201},
157 {0x00, 0x00, 0x82c1},
158 {0x00, 0xa0, 0x82c2},
159 {0x00, 0x00, 0x82ca},
160 {0x00, 0x00, 0x8117},
161 {0x00, 0x00, 0x8118},
162 {0x00, 0x65, 0x8119},
163 {0x00, 0x00, 0x811a},
164 {0x00, 0x00, 0x811b},
165 {0x00, 0x55, 0x811c},
166 {0x00, 0x65, 0x811d},
167 {0x00, 0x55, 0x811e},
168 {0x00, 0x16, 0x811f},
169 {0x00, 0x19, 0x8120},
170 {0x00, 0x80, 0x8103},
171 {0x00, 0x83, 0x816b},
172 {0x00, 0x25, 0x8168},
173 {0x00, 0x01, 0x820f},
174 {0x00, 0xff, 0x8115},
175 {0x00, 0x48, 0x8116},
176 {0x00, 0x50, 0x8151},
177 {0x00, 0x40, 0x8152},
178 {0x00, 0x78, 0x8153},
179 {0x00, 0x40, 0x8154},
180 {0x00, 0x00, 0x8167},
181 {0x00, 0x20, 0x8168},
182 {0x00, 0x00, 0x816a},
183 {0x00, 0x03, 0x816b},
184 {0x00, 0x20, 0x8169},
185 {0x00, 0x60, 0x8157},
186 {0x00, 0x00, 0x8190},
187 {0x00, 0x00, 0x81a1},
188 {0x00, 0x00, 0x81b2},
189 {0x00, 0x27, 0x8191},
190 {0x00, 0x27, 0x81a2},
191 {0x00, 0x27, 0x81b3},
192 {0x00, 0x4b, 0x8192},
193 {0x00, 0x4b, 0x81a3},
194 {0x00, 0x4b, 0x81b4},
195 {0x00, 0x66, 0x8193},
196 {0x00, 0x66, 0x81a4},
197 {0x00, 0x66, 0x81b5},
198 {0x00, 0x79, 0x8194},
199 {0x00, 0x79, 0x81a5},
200 {0x00, 0x79, 0x81b6},
201 {0x00, 0x8a, 0x8195},
202 {0x00, 0x8a, 0x81a6},
203 {0x00, 0x8a, 0x81b7},
204 {0x00, 0x9b, 0x8196},
205 {0x00, 0x9b, 0x81a7},
206 {0x00, 0x9b, 0x81b8},
207 {0x00, 0xa6, 0x8197},
208 {0x00, 0xa6, 0x81a8},
209 {0x00, 0xa6, 0x81b9},
210 {0x00, 0xb2, 0x8198},
211 {0x00, 0xb2, 0x81a9},
212 {0x00, 0xb2, 0x81ba},
213 {0x00, 0xbe, 0x8199},
214 {0x00, 0xbe, 0x81aa},
215 {0x00, 0xbe, 0x81bb},
216 {0x00, 0xc8, 0x819a},
217 {0x00, 0xc8, 0x81ab},
218 {0x00, 0xc8, 0x81bc},
219 {0x00, 0xd2, 0x819b},
220 {0x00, 0xd2, 0x81ac},
221 {0x00, 0xd2, 0x81bd},
222 {0x00, 0xdb, 0x819c},
223 {0x00, 0xdb, 0x81ad},
224 {0x00, 0xdb, 0x81be},
225 {0x00, 0xe4, 0x819d},
226 {0x00, 0xe4, 0x81ae},
227 {0x00, 0xe4, 0x81bf},
228 {0x00, 0xed, 0x819e},
229 {0x00, 0xed, 0x81af},
230 {0x00, 0xed, 0x81c0},
231 {0x00, 0xf7, 0x819f},
232 {0x00, 0xf7, 0x81b0},
233 {0x00, 0xf7, 0x81c1},
234 {0x00, 0xff, 0x81a0},
235 {0x00, 0xff, 0x81b1},
236 {0x00, 0xff, 0x81c2},
237 {0x00, 0x03, 0x8156},
238 {0x00, 0x00, 0x8211},
239 {0x00, 0x20, 0x8168},
240 {0x00, 0x01, 0x8202},
241 {0x00, 0x30, 0x8101},
242 {0x00, 0x00, 0x8111},
243 {0x00, 0x00, 0x8112},
244 {0x00, 0x00, 0x8113},
245 {0x00, 0x00, 0x8114},
249 static const __u8 qtable_creative_pccam
[2][64] = {
250 { /* Q-table Y-components */
251 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
252 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
253 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
254 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
255 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
256 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
257 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
258 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
259 { /* Q-table C-components */
260 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
261 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
262 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
263 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
264 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
265 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
266 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
267 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
270 static const __u8 qtable_kodak_ez200
[2][64] = {
271 { /* Q-table Y-components */
272 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
273 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
274 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
275 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
276 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
277 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
278 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
279 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
280 { /* Q-table C-components */
281 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
282 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
283 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
284 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
285 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
286 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
287 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
288 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
291 static const __u8 qtable_pocketdv
[2][64] = {
292 { /* Q-table Y-components start registers 0x8800 */
293 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
294 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
295 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
296 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
297 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
298 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
299 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
300 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
302 { /* Q-table C-components start registers 0x8840 */
303 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
304 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
305 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
306 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
307 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
308 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
309 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
310 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
313 /* read 'len' bytes to gspca_dev->usb_buf */
314 static void reg_r(struct gspca_dev
*gspca_dev
,
318 usb_control_msg(gspca_dev
->dev
,
319 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
321 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
323 index
, gspca_dev
->usb_buf
, length
, 500);
326 static int reg_w(struct gspca_dev
*gspca_dev
,
327 __u16 req
, __u16 index
, __u16 value
)
331 gspca_dbg(gspca_dev
, D_USBO
, "reg write: [0x%02x] = 0x%02x\n",
333 ret
= usb_control_msg(gspca_dev
->dev
,
334 usb_sndctrlpipe(gspca_dev
->dev
, 0),
336 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
337 value
, index
, NULL
, 0, 500);
339 pr_err("reg write: error %d\n", ret
);
343 /* returns: negative is error, pos or zero is data */
344 static int reg_r_12(struct gspca_dev
*gspca_dev
,
345 __u16 req
, /* bRequest */
346 __u16 index
, /* wIndex */
347 __u16 length
) /* wLength (1 or 2 only) */
351 gspca_dev
->usb_buf
[1] = 0;
352 ret
= usb_control_msg(gspca_dev
->dev
,
353 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
355 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
358 gspca_dev
->usb_buf
, length
,
361 pr_err("reg_r_12 err %d\n", ret
);
364 return (gspca_dev
->usb_buf
[1] << 8) + gspca_dev
->usb_buf
[0];
368 * Simple function to wait for a given 8-bit value to be returned from
370 * Returns: negative is error or timeout, zero is success.
372 static int reg_r_wait(struct gspca_dev
*gspca_dev
,
373 __u16 reg
, __u16 index
, __u16 value
)
378 ret
= reg_r_12(gspca_dev
, reg
, index
, 1);
386 static int write_vector(struct gspca_dev
*gspca_dev
,
387 const __u16 data
[][3])
391 while (data
[i
][0] != 0 || data
[i
][1] != 0 || data
[i
][2] != 0) {
392 ret
= reg_w(gspca_dev
, data
[i
][0], data
[i
][2], data
[i
][1]);
400 static int spca50x_setup_qtable(struct gspca_dev
*gspca_dev
,
401 unsigned int request
,
404 const __u8 qtable
[2][64])
408 /* loop over y components */
409 for (i
= 0; i
< 64; i
++) {
410 err
= reg_w(gspca_dev
, request
, ybase
+ i
, qtable
[0][i
]);
415 /* loop over c components */
416 for (i
= 0; i
< 64; i
++) {
417 err
= reg_w(gspca_dev
, request
, cbase
+ i
, qtable
[1][i
]);
424 static void spca500_ping310(struct gspca_dev
*gspca_dev
)
426 reg_r(gspca_dev
, 0x0d04, 2);
427 gspca_dbg(gspca_dev
, D_STREAM
, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x\n",
428 gspca_dev
->usb_buf
[0], gspca_dev
->usb_buf
[1]);
431 static void spca500_clksmart310_init(struct gspca_dev
*gspca_dev
)
433 reg_r(gspca_dev
, 0x0d05, 2);
434 gspca_dbg(gspca_dev
, D_STREAM
, "ClickSmart310 init 0x0d05 0x%02x 0x%02x\n",
435 gspca_dev
->usb_buf
[0], gspca_dev
->usb_buf
[1]);
436 reg_w(gspca_dev
, 0x00, 0x8167, 0x5a);
437 spca500_ping310(gspca_dev
);
439 reg_w(gspca_dev
, 0x00, 0x8168, 0x22);
440 reg_w(gspca_dev
, 0x00, 0x816a, 0xc0);
441 reg_w(gspca_dev
, 0x00, 0x816b, 0x0b);
442 reg_w(gspca_dev
, 0x00, 0x8169, 0x25);
443 reg_w(gspca_dev
, 0x00, 0x8157, 0x5b);
444 reg_w(gspca_dev
, 0x00, 0x8158, 0x5b);
445 reg_w(gspca_dev
, 0x00, 0x813f, 0x03);
446 reg_w(gspca_dev
, 0x00, 0x8151, 0x4a);
447 reg_w(gspca_dev
, 0x00, 0x8153, 0x78);
448 reg_w(gspca_dev
, 0x00, 0x0d01, 0x04);
449 /* 00 for adjust shutter */
450 reg_w(gspca_dev
, 0x00, 0x0d02, 0x01);
451 reg_w(gspca_dev
, 0x00, 0x8169, 0x25);
452 reg_w(gspca_dev
, 0x00, 0x0d01, 0x02);
455 static void spca500_setmode(struct gspca_dev
*gspca_dev
,
456 __u8 xmult
, __u8 ymult
)
460 /* set x multiplier */
461 reg_w(gspca_dev
, 0, 0x8001, xmult
);
463 /* set y multiplier */
464 reg_w(gspca_dev
, 0, 0x8002, ymult
);
466 /* use compressed mode, VGA, with mode specific subsample */
467 mode
= gspca_dev
->cam
.cam_mode
[(int) gspca_dev
->curr_mode
].priv
;
468 reg_w(gspca_dev
, 0, 0x8003, mode
<< 4);
471 static int spca500_full_reset(struct gspca_dev
*gspca_dev
)
475 /* send the reset command */
476 err
= reg_w(gspca_dev
, 0xe0, 0x0001, 0x0000);
480 /* wait for the reset to complete */
481 err
= reg_r_wait(gspca_dev
, 0x06, 0x0000, 0x0000);
484 err
= reg_w(gspca_dev
, 0xe0, 0x0000, 0x0000);
487 err
= reg_r_wait(gspca_dev
, 0x06, 0, 0);
489 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
496 /* Synchro the Bridge with sensor */
497 /* Maybe that will work on all spca500 chip */
498 /* because i only own a clicksmart310 try for that chip */
499 /* using spca50x_set_packet_size() cause an Ooops here */
500 /* usb_set_interface from kernel 2.6.x clear all the urb stuff */
501 /* up-port the same feature as in 2.4.x kernel */
502 static int spca500_synch310(struct gspca_dev
*gspca_dev
)
504 if (usb_set_interface(gspca_dev
->dev
, gspca_dev
->iface
, 0) < 0) {
505 gspca_err(gspca_dev
, "Set packet size: set interface error\n");
508 spca500_ping310(gspca_dev
);
510 reg_r(gspca_dev
, 0x0d00, 1);
512 /* need alt setting here */
513 gspca_dbg(gspca_dev
, D_PACK
, "ClickSmart310 sync alt: %d\n",
516 /* Windoze use pipe with altsetting 6 why 7 here */
517 if (usb_set_interface(gspca_dev
->dev
,
519 gspca_dev
->alt
) < 0) {
520 gspca_err(gspca_dev
, "Set packet size: set interface error\n");
528 static void spca500_reinit(struct gspca_dev
*gspca_dev
)
533 /* some unknown command from Aiptek pocket dv and family300 */
535 reg_w(gspca_dev
, 0x00, 0x0d01, 0x01);
536 reg_w(gspca_dev
, 0x00, 0x0d03, 0x00);
537 reg_w(gspca_dev
, 0x00, 0x0d02, 0x01);
539 /* enable drop packet */
540 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
542 err
= spca50x_setup_qtable(gspca_dev
, 0x00, 0x8800, 0x8840,
545 gspca_err(gspca_dev
, "spca50x_setup_qtable failed on init\n");
547 /* set qtable index */
548 reg_w(gspca_dev
, 0x00, 0x8880, 2);
549 /* family cam Quicksmart stuff */
550 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
551 /* Set agc transfer: synced between frames */
552 reg_w(gspca_dev
, 0x00, 0x820f, 0x01);
553 /* Init SDRAM - needed for SDRAM access */
554 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
555 /*Start init sequence or stream */
556 reg_w(gspca_dev
, 0, 0x8003, 0x00);
557 /* switch to video camera mode */
558 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
560 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0) {
561 reg_r(gspca_dev
, 0x816b, 1);
562 Data
= gspca_dev
->usb_buf
[0];
563 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
567 /* this function is called at probe time */
568 static int sd_config(struct gspca_dev
*gspca_dev
,
569 const struct usb_device_id
*id
)
571 struct sd
*sd
= (struct sd
*) gspca_dev
;
574 cam
= &gspca_dev
->cam
;
575 sd
->subtype
= id
->driver_info
;
576 if (sd
->subtype
!= LogitechClickSmart310
) {
577 cam
->cam_mode
= vga_mode
;
578 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
580 cam
->cam_mode
= sif_mode
;
581 cam
->nmodes
= ARRAY_SIZE(sif_mode
);
586 /* this function is called at probe and resume time */
587 static int sd_init(struct gspca_dev
*gspca_dev
)
589 struct sd
*sd
= (struct sd
*) gspca_dev
;
591 /* initialisation of spca500 based cameras is deferred */
592 gspca_dbg(gspca_dev
, D_STREAM
, "SPCA500 init\n");
593 if (sd
->subtype
== LogitechClickSmart310
)
594 spca500_clksmart310_init(gspca_dev
);
596 spca500_initialise(gspca_dev); */
597 gspca_dbg(gspca_dev
, D_STREAM
, "SPCA500 init done\n");
601 static int sd_start(struct gspca_dev
*gspca_dev
)
603 struct sd
*sd
= (struct sd
*) gspca_dev
;
608 /* create the JPEG header */
609 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->pixfmt
.height
,
610 gspca_dev
->pixfmt
.width
,
611 0x22); /* JPEG 411 */
612 jpeg_set_qual(sd
->jpeg_hdr
, QUALITY
);
614 if (sd
->subtype
== LogitechClickSmart310
) {
622 /* is there a sensor here ? */
623 reg_r(gspca_dev
, 0x8a04, 1);
624 gspca_dbg(gspca_dev
, D_STREAM
, "Spca500 Sensor Address 0x%02x\n",
625 gspca_dev
->usb_buf
[0]);
626 gspca_dbg(gspca_dev
, D_STREAM
, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
627 gspca_dev
->curr_mode
, xmult
, ymult
);
630 switch (sd
->subtype
) {
631 case LogitechClickSmart310
:
632 spca500_setmode(gspca_dev
, xmult
, ymult
);
634 /* enable drop packet */
635 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
636 reg_w(gspca_dev
, 0x00, 0x8880, 3);
637 err
= spca50x_setup_qtable(gspca_dev
,
638 0x00, 0x8800, 0x8840,
639 qtable_creative_pccam
);
641 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
642 /* Init SDRAM - needed for SDRAM access */
643 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
645 /* switch to video camera mode */
646 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
648 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
649 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
651 reg_r(gspca_dev
, 0x816b, 1);
652 Data
= gspca_dev
->usb_buf
[0];
653 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
655 spca500_synch310(gspca_dev
);
657 write_vector(gspca_dev
, spca500_visual_defaults
);
658 spca500_setmode(gspca_dev
, xmult
, ymult
);
659 /* enable drop packet */
660 err
= reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
662 gspca_err(gspca_dev
, "failed to enable drop packet\n");
663 reg_w(gspca_dev
, 0x00, 0x8880, 3);
664 err
= spca50x_setup_qtable(gspca_dev
,
665 0x00, 0x8800, 0x8840,
666 qtable_creative_pccam
);
668 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
670 /* Init SDRAM - needed for SDRAM access */
671 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
673 /* switch to video camera mode */
674 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
676 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
677 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
679 reg_r(gspca_dev
, 0x816b, 1);
680 Data
= gspca_dev
->usb_buf
[0];
681 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
683 case CreativePCCam300
: /* Creative PC-CAM 300 640x480 CCD */
684 case IntelPocketPCCamera
: /* FIXME: Temporary fix for
685 * Intel Pocket PC Camera
686 * - NWG (Sat 29th March 2003) */
688 /* do a full reset */
689 err
= spca500_full_reset(gspca_dev
);
691 gspca_err(gspca_dev
, "spca500_full_reset failed\n");
693 /* enable drop packet */
694 err
= reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
696 gspca_err(gspca_dev
, "failed to enable drop packet\n");
697 reg_w(gspca_dev
, 0x00, 0x8880, 3);
698 err
= spca50x_setup_qtable(gspca_dev
,
699 0x00, 0x8800, 0x8840,
700 qtable_creative_pccam
);
702 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
704 spca500_setmode(gspca_dev
, xmult
, ymult
);
705 reg_w(gspca_dev
, 0x20, 0x0001, 0x0004);
707 /* switch to video camera mode */
708 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
710 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
711 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
713 reg_r(gspca_dev
, 0x816b, 1);
714 Data
= gspca_dev
->usb_buf
[0];
715 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
717 /* write_vector(gspca_dev, spca500_visual_defaults); */
719 case KodakEZ200
: /* Kodak EZ200 */
721 /* do a full reset */
722 err
= spca500_full_reset(gspca_dev
);
724 gspca_err(gspca_dev
, "spca500_full_reset failed\n");
725 /* enable drop packet */
726 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
727 reg_w(gspca_dev
, 0x00, 0x8880, 0);
728 err
= spca50x_setup_qtable(gspca_dev
,
729 0x00, 0x8800, 0x8840,
732 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
733 spca500_setmode(gspca_dev
, xmult
, ymult
);
735 reg_w(gspca_dev
, 0x20, 0x0001, 0x0004);
737 /* switch to video camera mode */
738 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
740 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
741 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
743 reg_r(gspca_dev
, 0x816b, 1);
744 Data
= gspca_dev
->usb_buf
[0];
745 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
747 /* write_vector(gspca_dev, spca500_visual_defaults); */
751 case DLinkDSC350
: /* FamilyCam 300 */
752 case AiptekPocketDV
: /* Aiptek PocketDV */
753 case Gsmartmini
: /*Mustek Gsmart Mini */
754 case MustekGsmart300
: /* Mustek Gsmart 300 */
759 spca500_reinit(gspca_dev
);
760 reg_w(gspca_dev
, 0x00, 0x0d01, 0x01);
761 /* enable drop packet */
762 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
764 err
= spca50x_setup_qtable(gspca_dev
,
765 0x00, 0x8800, 0x8840, qtable_pocketdv
);
767 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
768 reg_w(gspca_dev
, 0x00, 0x8880, 2);
770 /* familycam Quicksmart pocketDV stuff */
771 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
772 /* Set agc transfer: synced between frames */
773 reg_w(gspca_dev
, 0x00, 0x820f, 0x01);
774 /* Init SDRAM - needed for SDRAM access */
775 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
777 spca500_setmode(gspca_dev
, xmult
, ymult
);
778 /* switch to video camera mode */
779 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
781 reg_r_wait(gspca_dev
, 0, 0x8000, 0x44);
783 reg_r(gspca_dev
, 0x816b, 1);
784 Data
= gspca_dev
->usb_buf
[0];
785 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
787 case LogitechTraveler
:
788 case LogitechClickSmart510
:
789 reg_w(gspca_dev
, 0x02, 0x00, 0x00);
790 /* enable drop packet */
791 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
793 err
= spca50x_setup_qtable(gspca_dev
,
795 0x8840, qtable_creative_pccam
);
797 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
798 reg_w(gspca_dev
, 0x00, 0x8880, 3);
799 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
800 /* Init SDRAM - needed for SDRAM access */
801 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
803 spca500_setmode(gspca_dev
, xmult
, ymult
);
805 /* switch to video camera mode */
806 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
807 reg_r_wait(gspca_dev
, 0, 0x8000, 0x44);
809 reg_r(gspca_dev
, 0x816b, 1);
810 Data
= gspca_dev
->usb_buf
[0];
811 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
812 write_vector(gspca_dev
, Clicksmart510_defaults
);
818 static void sd_stopN(struct gspca_dev
*gspca_dev
)
820 reg_w(gspca_dev
, 0, 0x8003, 0x00);
822 /* switch to video camera mode */
823 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
824 reg_r(gspca_dev
, 0x8000, 1);
825 gspca_dbg(gspca_dev
, D_STREAM
, "stop SPCA500 done reg8000: 0x%2x\n",
826 gspca_dev
->usb_buf
[0]);
829 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
830 u8
*data
, /* isoc packet */
831 int len
) /* iso packet length */
833 struct sd
*sd
= (struct sd
*) gspca_dev
;
835 static __u8 ffd9
[] = {0xff, 0xd9};
837 /* frames are jpeg 4.1.1 without 0xff escape */
838 if (data
[0] == 0xff) {
839 if (data
[1] != 0x01) { /* drop packet */
840 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
843 gspca_frame_add(gspca_dev
, LAST_PACKET
,
846 /* put the JPEG header in the new frame */
847 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
848 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
850 data
+= SPCA500_OFFSET_DATA
;
851 len
-= SPCA500_OFFSET_DATA
;
857 /* add 0x00 after 0xff */
860 if (data
[i
] == 0xff) {
861 gspca_frame_add(gspca_dev
, INTER_PACKET
,
870 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
873 static void setbrightness(struct gspca_dev
*gspca_dev
, s32 val
)
875 reg_w(gspca_dev
, 0x00, 0x8167,
879 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
881 reg_w(gspca_dev
, 0x00, 0x8168, val
);
884 static void setcolors(struct gspca_dev
*gspca_dev
, s32 val
)
886 reg_w(gspca_dev
, 0x00, 0x8169, val
);
889 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
891 struct gspca_dev
*gspca_dev
=
892 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
894 gspca_dev
->usb_err
= 0;
896 if (!gspca_dev
->streaming
)
900 case V4L2_CID_BRIGHTNESS
:
901 setbrightness(gspca_dev
, ctrl
->val
);
903 case V4L2_CID_CONTRAST
:
904 setcontrast(gspca_dev
, ctrl
->val
);
906 case V4L2_CID_SATURATION
:
907 setcolors(gspca_dev
, ctrl
->val
);
910 return gspca_dev
->usb_err
;
913 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
917 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
919 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
921 gspca_dev
->vdev
.ctrl_handler
= hdl
;
922 v4l2_ctrl_handler_init(hdl
, 3);
923 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
924 V4L2_CID_BRIGHTNESS
, 0, 255, 1, 127);
925 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
926 V4L2_CID_CONTRAST
, 0, 63, 1, 31);
927 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
928 V4L2_CID_SATURATION
, 0, 63, 1, 31);
931 pr_err("Could not initialize controls\n");
937 /* sub-driver description */
938 static const struct sd_desc sd_desc
= {
942 .init_controls
= sd_init_controls
,
945 .pkt_scan
= sd_pkt_scan
,
948 /* -- module initialisation -- */
949 static const struct usb_device_id device_table
[] = {
950 {USB_DEVICE(0x040a, 0x0300), .driver_info
= KodakEZ200
},
951 {USB_DEVICE(0x041e, 0x400a), .driver_info
= CreativePCCam300
},
952 {USB_DEVICE(0x046d, 0x0890), .driver_info
= LogitechTraveler
},
953 {USB_DEVICE(0x046d, 0x0900), .driver_info
= LogitechClickSmart310
},
954 {USB_DEVICE(0x046d, 0x0901), .driver_info
= LogitechClickSmart510
},
955 {USB_DEVICE(0x04a5, 0x300c), .driver_info
= BenqDC1016
},
956 {USB_DEVICE(0x04fc, 0x7333), .driver_info
= PalmPixDC85
},
957 {USB_DEVICE(0x055f, 0xc200), .driver_info
= MustekGsmart300
},
958 {USB_DEVICE(0x055f, 0xc220), .driver_info
= Gsmartmini
},
959 {USB_DEVICE(0x06bd, 0x0404), .driver_info
= AgfaCl20
},
960 {USB_DEVICE(0x06be, 0x0800), .driver_info
= Optimedia
},
961 {USB_DEVICE(0x084d, 0x0003), .driver_info
= DLinkDSC350
},
962 {USB_DEVICE(0x08ca, 0x0103), .driver_info
= AiptekPocketDV
},
963 {USB_DEVICE(0x2899, 0x012c), .driver_info
= ToptroIndus
},
964 {USB_DEVICE(0x8086, 0x0630), .driver_info
= IntelPocketPCCamera
},
967 MODULE_DEVICE_TABLE(usb
, device_table
);
969 /* -- device connect -- */
970 static int sd_probe(struct usb_interface
*intf
,
971 const struct usb_device_id
*id
)
973 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
977 static struct usb_driver sd_driver
= {
979 .id_table
= device_table
,
981 .disconnect
= gspca_disconnect
,
983 .suspend
= gspca_suspend
,
984 .resume
= gspca_resume
,
985 .reset_resume
= gspca_resume
,
989 module_usb_driver(sd_driver
);