1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SPCA500 chip based cameras initialization data
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #define MODULE_NAME "spca500"
15 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
16 MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
17 MODULE_LICENSE("GPL");
21 /* specific webcam descriptor */
23 struct gspca_dev gspca_dev
; /* !! must be the first item */
27 #define AiptekPocketDV 1
29 #define CreativePCCam300 3
32 #define IntelPocketPCCamera 6
34 #define LogitechClickSmart310 8
35 #define LogitechClickSmart510 9
36 #define LogitechTraveler 10
37 #define MustekGsmart300 11
39 #define PalmPixDC85 13
40 #define ToptroIndus 14
42 u8 jpeg_hdr
[JPEG_HDR_SZ
];
45 static const struct v4l2_pix_format vga_mode
[] = {
46 {320, 240, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
48 .sizeimage
= 320 * 240 * 3 / 8 + 590,
49 .colorspace
= V4L2_COLORSPACE_JPEG
,
51 {640, 480, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
53 .sizeimage
= 640 * 480 * 3 / 8 + 590,
54 .colorspace
= V4L2_COLORSPACE_JPEG
,
58 static const struct v4l2_pix_format sif_mode
[] = {
59 {176, 144, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
61 .sizeimage
= 176 * 144 * 3 / 8 + 590,
62 .colorspace
= V4L2_COLORSPACE_JPEG
,
64 {352, 288, V4L2_PIX_FMT_JPEG
, V4L2_FIELD_NONE
,
66 .sizeimage
= 352 * 288 * 3 / 8 + 590,
67 .colorspace
= V4L2_COLORSPACE_JPEG
,
71 /* Frame packet header offsets for the spca500 */
72 #define SPCA500_OFFSET_PADDINGLB 2
73 #define SPCA500_OFFSET_PADDINGHB 3
74 #define SPCA500_OFFSET_MODE 4
75 #define SPCA500_OFFSET_IMGWIDTH 5
76 #define SPCA500_OFFSET_IMGHEIGHT 6
77 #define SPCA500_OFFSET_IMGMODE 7
78 #define SPCA500_OFFSET_QTBLINDEX 8
79 #define SPCA500_OFFSET_FRAMSEQ 9
80 #define SPCA500_OFFSET_CDSPINFO 10
81 #define SPCA500_OFFSET_GPIO 11
82 #define SPCA500_OFFSET_AUGPIO 12
83 #define SPCA500_OFFSET_DATA 16
86 static const __u16 spca500_visual_defaults
[][3] = {
87 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
89 * saturation/hue enable,
90 * brightness/contrast enable.
92 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
93 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
94 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
95 * hue (H byte) = 0, saturation/hue enable,
96 * brightness/contrast enable.
97 * was 0x0003, now 0x0000.
99 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
100 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
101 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
102 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
103 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
104 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
105 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
106 {0x0c, 0x0004, 0x0000},
110 static const __u16 Clicksmart510_defaults
[][3] = {
111 {0x00, 0x00, 0x8211},
112 {0x00, 0x01, 0x82c0},
113 {0x00, 0x10, 0x82cb},
114 {0x00, 0x0f, 0x800d},
115 {0x00, 0x82, 0x8225},
116 {0x00, 0x21, 0x8228},
117 {0x00, 0x00, 0x8203},
118 {0x00, 0x00, 0x8204},
119 {0x00, 0x08, 0x8205},
120 {0x00, 0xf8, 0x8206},
121 {0x00, 0x28, 0x8207},
122 {0x00, 0xa0, 0x8208},
123 {0x00, 0x08, 0x824a},
124 {0x00, 0x08, 0x8214},
125 {0x00, 0x80, 0x82c1},
126 {0x00, 0x00, 0x82c2},
127 {0x00, 0x00, 0x82ca},
128 {0x00, 0x80, 0x82c1},
129 {0x00, 0x04, 0x82c2},
130 {0x00, 0x00, 0x82ca},
131 {0x00, 0xfc, 0x8100},
132 {0x00, 0xfc, 0x8105},
133 {0x00, 0x30, 0x8101},
134 {0x00, 0x00, 0x8102},
135 {0x00, 0x00, 0x8103},
136 {0x00, 0x66, 0x8107},
137 {0x00, 0x00, 0x816b},
138 {0x00, 0x00, 0x8155},
139 {0x00, 0x01, 0x8156},
140 {0x00, 0x60, 0x8157},
141 {0x00, 0x40, 0x8158},
142 {0x00, 0x0a, 0x8159},
143 {0x00, 0x06, 0x815a},
144 {0x00, 0x00, 0x813f},
145 {0x00, 0x00, 0x8200},
146 {0x00, 0x19, 0x8201},
147 {0x00, 0x00, 0x82c1},
148 {0x00, 0xa0, 0x82c2},
149 {0x00, 0x00, 0x82ca},
150 {0x00, 0x00, 0x8117},
151 {0x00, 0x00, 0x8118},
152 {0x00, 0x65, 0x8119},
153 {0x00, 0x00, 0x811a},
154 {0x00, 0x00, 0x811b},
155 {0x00, 0x55, 0x811c},
156 {0x00, 0x65, 0x811d},
157 {0x00, 0x55, 0x811e},
158 {0x00, 0x16, 0x811f},
159 {0x00, 0x19, 0x8120},
160 {0x00, 0x80, 0x8103},
161 {0x00, 0x83, 0x816b},
162 {0x00, 0x25, 0x8168},
163 {0x00, 0x01, 0x820f},
164 {0x00, 0xff, 0x8115},
165 {0x00, 0x48, 0x8116},
166 {0x00, 0x50, 0x8151},
167 {0x00, 0x40, 0x8152},
168 {0x00, 0x78, 0x8153},
169 {0x00, 0x40, 0x8154},
170 {0x00, 0x00, 0x8167},
171 {0x00, 0x20, 0x8168},
172 {0x00, 0x00, 0x816a},
173 {0x00, 0x03, 0x816b},
174 {0x00, 0x20, 0x8169},
175 {0x00, 0x60, 0x8157},
176 {0x00, 0x00, 0x8190},
177 {0x00, 0x00, 0x81a1},
178 {0x00, 0x00, 0x81b2},
179 {0x00, 0x27, 0x8191},
180 {0x00, 0x27, 0x81a2},
181 {0x00, 0x27, 0x81b3},
182 {0x00, 0x4b, 0x8192},
183 {0x00, 0x4b, 0x81a3},
184 {0x00, 0x4b, 0x81b4},
185 {0x00, 0x66, 0x8193},
186 {0x00, 0x66, 0x81a4},
187 {0x00, 0x66, 0x81b5},
188 {0x00, 0x79, 0x8194},
189 {0x00, 0x79, 0x81a5},
190 {0x00, 0x79, 0x81b6},
191 {0x00, 0x8a, 0x8195},
192 {0x00, 0x8a, 0x81a6},
193 {0x00, 0x8a, 0x81b7},
194 {0x00, 0x9b, 0x8196},
195 {0x00, 0x9b, 0x81a7},
196 {0x00, 0x9b, 0x81b8},
197 {0x00, 0xa6, 0x8197},
198 {0x00, 0xa6, 0x81a8},
199 {0x00, 0xa6, 0x81b9},
200 {0x00, 0xb2, 0x8198},
201 {0x00, 0xb2, 0x81a9},
202 {0x00, 0xb2, 0x81ba},
203 {0x00, 0xbe, 0x8199},
204 {0x00, 0xbe, 0x81aa},
205 {0x00, 0xbe, 0x81bb},
206 {0x00, 0xc8, 0x819a},
207 {0x00, 0xc8, 0x81ab},
208 {0x00, 0xc8, 0x81bc},
209 {0x00, 0xd2, 0x819b},
210 {0x00, 0xd2, 0x81ac},
211 {0x00, 0xd2, 0x81bd},
212 {0x00, 0xdb, 0x819c},
213 {0x00, 0xdb, 0x81ad},
214 {0x00, 0xdb, 0x81be},
215 {0x00, 0xe4, 0x819d},
216 {0x00, 0xe4, 0x81ae},
217 {0x00, 0xe4, 0x81bf},
218 {0x00, 0xed, 0x819e},
219 {0x00, 0xed, 0x81af},
220 {0x00, 0xed, 0x81c0},
221 {0x00, 0xf7, 0x819f},
222 {0x00, 0xf7, 0x81b0},
223 {0x00, 0xf7, 0x81c1},
224 {0x00, 0xff, 0x81a0},
225 {0x00, 0xff, 0x81b1},
226 {0x00, 0xff, 0x81c2},
227 {0x00, 0x03, 0x8156},
228 {0x00, 0x00, 0x8211},
229 {0x00, 0x20, 0x8168},
230 {0x00, 0x01, 0x8202},
231 {0x00, 0x30, 0x8101},
232 {0x00, 0x00, 0x8111},
233 {0x00, 0x00, 0x8112},
234 {0x00, 0x00, 0x8113},
235 {0x00, 0x00, 0x8114},
239 static const __u8 qtable_creative_pccam
[2][64] = {
240 { /* Q-table Y-components */
241 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
242 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
243 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
244 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
245 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
246 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
247 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
248 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
249 { /* Q-table C-components */
250 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
251 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
252 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
253 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
254 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
255 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
256 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
257 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
260 static const __u8 qtable_kodak_ez200
[2][64] = {
261 { /* Q-table Y-components */
262 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
263 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
264 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
265 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
266 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
267 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
268 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
269 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
270 { /* Q-table C-components */
271 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
272 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
273 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
274 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
275 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
276 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
277 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
278 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
281 static const __u8 qtable_pocketdv
[2][64] = {
282 { /* Q-table Y-components start registers 0x8800 */
283 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
284 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
285 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
286 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
287 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
288 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
289 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
290 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
292 { /* Q-table C-components start registers 0x8840 */
293 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
294 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
295 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
296 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
297 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
298 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
299 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
300 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
303 /* read 'len' bytes to gspca_dev->usb_buf */
304 static void reg_r(struct gspca_dev
*gspca_dev
,
308 usb_control_msg(gspca_dev
->dev
,
309 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
311 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
313 index
, gspca_dev
->usb_buf
, length
, 500);
316 static int reg_w(struct gspca_dev
*gspca_dev
,
317 __u16 req
, __u16 index
, __u16 value
)
321 gspca_dbg(gspca_dev
, D_USBO
, "reg write: [0x%02x] = 0x%02x\n",
323 ret
= usb_control_msg(gspca_dev
->dev
,
324 usb_sndctrlpipe(gspca_dev
->dev
, 0),
326 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
327 value
, index
, NULL
, 0, 500);
329 pr_err("reg write: error %d\n", ret
);
333 /* returns: negative is error, pos or zero is data */
334 static int reg_r_12(struct gspca_dev
*gspca_dev
,
335 __u16 req
, /* bRequest */
336 __u16 index
, /* wIndex */
337 __u16 length
) /* wLength (1 or 2 only) */
341 gspca_dev
->usb_buf
[1] = 0;
342 ret
= usb_control_msg(gspca_dev
->dev
,
343 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
345 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_DEVICE
,
348 gspca_dev
->usb_buf
, length
,
351 pr_err("reg_r_12 err %d\n", ret
);
354 return (gspca_dev
->usb_buf
[1] << 8) + gspca_dev
->usb_buf
[0];
358 * Simple function to wait for a given 8-bit value to be returned from
360 * Returns: negative is error or timeout, zero is success.
362 static int reg_r_wait(struct gspca_dev
*gspca_dev
,
363 __u16 reg
, __u16 index
, __u16 value
)
368 ret
= reg_r_12(gspca_dev
, reg
, index
, 1);
376 static int write_vector(struct gspca_dev
*gspca_dev
,
377 const __u16 data
[][3])
381 while (data
[i
][0] != 0 || data
[i
][1] != 0 || data
[i
][2] != 0) {
382 ret
= reg_w(gspca_dev
, data
[i
][0], data
[i
][2], data
[i
][1]);
390 static int spca50x_setup_qtable(struct gspca_dev
*gspca_dev
,
391 unsigned int request
,
394 const __u8 qtable
[2][64])
398 /* loop over y components */
399 for (i
= 0; i
< 64; i
++) {
400 err
= reg_w(gspca_dev
, request
, ybase
+ i
, qtable
[0][i
]);
405 /* loop over c components */
406 for (i
= 0; i
< 64; i
++) {
407 err
= reg_w(gspca_dev
, request
, cbase
+ i
, qtable
[1][i
]);
414 static void spca500_ping310(struct gspca_dev
*gspca_dev
)
416 reg_r(gspca_dev
, 0x0d04, 2);
417 gspca_dbg(gspca_dev
, D_STREAM
, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x\n",
418 gspca_dev
->usb_buf
[0], gspca_dev
->usb_buf
[1]);
421 static void spca500_clksmart310_init(struct gspca_dev
*gspca_dev
)
423 reg_r(gspca_dev
, 0x0d05, 2);
424 gspca_dbg(gspca_dev
, D_STREAM
, "ClickSmart310 init 0x0d05 0x%02x 0x%02x\n",
425 gspca_dev
->usb_buf
[0], gspca_dev
->usb_buf
[1]);
426 reg_w(gspca_dev
, 0x00, 0x8167, 0x5a);
427 spca500_ping310(gspca_dev
);
429 reg_w(gspca_dev
, 0x00, 0x8168, 0x22);
430 reg_w(gspca_dev
, 0x00, 0x816a, 0xc0);
431 reg_w(gspca_dev
, 0x00, 0x816b, 0x0b);
432 reg_w(gspca_dev
, 0x00, 0x8169, 0x25);
433 reg_w(gspca_dev
, 0x00, 0x8157, 0x5b);
434 reg_w(gspca_dev
, 0x00, 0x8158, 0x5b);
435 reg_w(gspca_dev
, 0x00, 0x813f, 0x03);
436 reg_w(gspca_dev
, 0x00, 0x8151, 0x4a);
437 reg_w(gspca_dev
, 0x00, 0x8153, 0x78);
438 reg_w(gspca_dev
, 0x00, 0x0d01, 0x04);
439 /* 00 for adjust shutter */
440 reg_w(gspca_dev
, 0x00, 0x0d02, 0x01);
441 reg_w(gspca_dev
, 0x00, 0x8169, 0x25);
442 reg_w(gspca_dev
, 0x00, 0x0d01, 0x02);
445 static void spca500_setmode(struct gspca_dev
*gspca_dev
,
446 __u8 xmult
, __u8 ymult
)
450 /* set x multiplier */
451 reg_w(gspca_dev
, 0, 0x8001, xmult
);
453 /* set y multiplier */
454 reg_w(gspca_dev
, 0, 0x8002, ymult
);
456 /* use compressed mode, VGA, with mode specific subsample */
457 mode
= gspca_dev
->cam
.cam_mode
[(int) gspca_dev
->curr_mode
].priv
;
458 reg_w(gspca_dev
, 0, 0x8003, mode
<< 4);
461 static int spca500_full_reset(struct gspca_dev
*gspca_dev
)
465 /* send the reset command */
466 err
= reg_w(gspca_dev
, 0xe0, 0x0001, 0x0000);
470 /* wait for the reset to complete */
471 err
= reg_r_wait(gspca_dev
, 0x06, 0x0000, 0x0000);
474 err
= reg_w(gspca_dev
, 0xe0, 0x0000, 0x0000);
477 err
= reg_r_wait(gspca_dev
, 0x06, 0, 0);
479 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
486 /* Synchro the Bridge with sensor */
487 /* Maybe that will work on all spca500 chip */
488 /* because i only own a clicksmart310 try for that chip */
489 /* using spca50x_set_packet_size() cause an Ooops here */
490 /* usb_set_interface from kernel 2.6.x clear all the urb stuff */
491 /* up-port the same feature as in 2.4.x kernel */
492 static int spca500_synch310(struct gspca_dev
*gspca_dev
)
494 if (usb_set_interface(gspca_dev
->dev
, gspca_dev
->iface
, 0) < 0) {
495 gspca_err(gspca_dev
, "Set packet size: set interface error\n");
498 spca500_ping310(gspca_dev
);
500 reg_r(gspca_dev
, 0x0d00, 1);
502 /* need alt setting here */
503 gspca_dbg(gspca_dev
, D_PACK
, "ClickSmart310 sync alt: %d\n",
506 /* Windoze use pipe with altsetting 6 why 7 here */
507 if (usb_set_interface(gspca_dev
->dev
,
509 gspca_dev
->alt
) < 0) {
510 gspca_err(gspca_dev
, "Set packet size: set interface error\n");
518 static void spca500_reinit(struct gspca_dev
*gspca_dev
)
523 /* some unknown command from Aiptek pocket dv and family300 */
525 reg_w(gspca_dev
, 0x00, 0x0d01, 0x01);
526 reg_w(gspca_dev
, 0x00, 0x0d03, 0x00);
527 reg_w(gspca_dev
, 0x00, 0x0d02, 0x01);
529 /* enable drop packet */
530 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
532 err
= spca50x_setup_qtable(gspca_dev
, 0x00, 0x8800, 0x8840,
535 gspca_err(gspca_dev
, "spca50x_setup_qtable failed on init\n");
537 /* set qtable index */
538 reg_w(gspca_dev
, 0x00, 0x8880, 2);
539 /* family cam Quicksmart stuff */
540 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
541 /* Set agc transfer: synced between frames */
542 reg_w(gspca_dev
, 0x00, 0x820f, 0x01);
543 /* Init SDRAM - needed for SDRAM access */
544 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
545 /*Start init sequence or stream */
546 reg_w(gspca_dev
, 0, 0x8003, 0x00);
547 /* switch to video camera mode */
548 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
550 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0) {
551 reg_r(gspca_dev
, 0x816b, 1);
552 Data
= gspca_dev
->usb_buf
[0];
553 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
557 /* this function is called at probe time */
558 static int sd_config(struct gspca_dev
*gspca_dev
,
559 const struct usb_device_id
*id
)
561 struct sd
*sd
= (struct sd
*) gspca_dev
;
564 cam
= &gspca_dev
->cam
;
565 sd
->subtype
= id
->driver_info
;
566 if (sd
->subtype
!= LogitechClickSmart310
) {
567 cam
->cam_mode
= vga_mode
;
568 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
570 cam
->cam_mode
= sif_mode
;
571 cam
->nmodes
= ARRAY_SIZE(sif_mode
);
576 /* this function is called at probe and resume time */
577 static int sd_init(struct gspca_dev
*gspca_dev
)
579 struct sd
*sd
= (struct sd
*) gspca_dev
;
581 /* initialisation of spca500 based cameras is deferred */
582 gspca_dbg(gspca_dev
, D_STREAM
, "SPCA500 init\n");
583 if (sd
->subtype
== LogitechClickSmart310
)
584 spca500_clksmart310_init(gspca_dev
);
586 spca500_initialise(gspca_dev); */
587 gspca_dbg(gspca_dev
, D_STREAM
, "SPCA500 init done\n");
591 static int sd_start(struct gspca_dev
*gspca_dev
)
593 struct sd
*sd
= (struct sd
*) gspca_dev
;
598 /* create the JPEG header */
599 jpeg_define(sd
->jpeg_hdr
, gspca_dev
->pixfmt
.height
,
600 gspca_dev
->pixfmt
.width
,
601 0x22); /* JPEG 411 */
602 jpeg_set_qual(sd
->jpeg_hdr
, QUALITY
);
604 if (sd
->subtype
== LogitechClickSmart310
) {
612 /* is there a sensor here ? */
613 reg_r(gspca_dev
, 0x8a04, 1);
614 gspca_dbg(gspca_dev
, D_STREAM
, "Spca500 Sensor Address 0x%02x\n",
615 gspca_dev
->usb_buf
[0]);
616 gspca_dbg(gspca_dev
, D_STREAM
, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
617 gspca_dev
->curr_mode
, xmult
, ymult
);
620 switch (sd
->subtype
) {
621 case LogitechClickSmart310
:
622 spca500_setmode(gspca_dev
, xmult
, ymult
);
624 /* enable drop packet */
625 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
626 reg_w(gspca_dev
, 0x00, 0x8880, 3);
627 err
= spca50x_setup_qtable(gspca_dev
,
628 0x00, 0x8800, 0x8840,
629 qtable_creative_pccam
);
631 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
632 /* Init SDRAM - needed for SDRAM access */
633 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
635 /* switch to video camera mode */
636 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
638 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
639 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
641 reg_r(gspca_dev
, 0x816b, 1);
642 Data
= gspca_dev
->usb_buf
[0];
643 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
645 spca500_synch310(gspca_dev
);
647 write_vector(gspca_dev
, spca500_visual_defaults
);
648 spca500_setmode(gspca_dev
, xmult
, ymult
);
649 /* enable drop packet */
650 err
= reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
652 gspca_err(gspca_dev
, "failed to enable drop packet\n");
653 reg_w(gspca_dev
, 0x00, 0x8880, 3);
654 err
= spca50x_setup_qtable(gspca_dev
,
655 0x00, 0x8800, 0x8840,
656 qtable_creative_pccam
);
658 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
660 /* Init SDRAM - needed for SDRAM access */
661 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
663 /* switch to video camera mode */
664 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
666 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
667 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
669 reg_r(gspca_dev
, 0x816b, 1);
670 Data
= gspca_dev
->usb_buf
[0];
671 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
673 case CreativePCCam300
: /* Creative PC-CAM 300 640x480 CCD */
674 case IntelPocketPCCamera
: /* FIXME: Temporary fix for
675 * Intel Pocket PC Camera
676 * - NWG (Sat 29th March 2003) */
678 /* do a full reset */
679 err
= spca500_full_reset(gspca_dev
);
681 gspca_err(gspca_dev
, "spca500_full_reset failed\n");
683 /* enable drop packet */
684 err
= reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
686 gspca_err(gspca_dev
, "failed to enable drop packet\n");
687 reg_w(gspca_dev
, 0x00, 0x8880, 3);
688 err
= spca50x_setup_qtable(gspca_dev
,
689 0x00, 0x8800, 0x8840,
690 qtable_creative_pccam
);
692 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
694 spca500_setmode(gspca_dev
, xmult
, ymult
);
695 reg_w(gspca_dev
, 0x20, 0x0001, 0x0004);
697 /* switch to video camera mode */
698 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
700 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
701 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
703 reg_r(gspca_dev
, 0x816b, 1);
704 Data
= gspca_dev
->usb_buf
[0];
705 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
707 /* write_vector(gspca_dev, spca500_visual_defaults); */
709 case KodakEZ200
: /* Kodak EZ200 */
711 /* do a full reset */
712 err
= spca500_full_reset(gspca_dev
);
714 gspca_err(gspca_dev
, "spca500_full_reset failed\n");
715 /* enable drop packet */
716 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
717 reg_w(gspca_dev
, 0x00, 0x8880, 0);
718 err
= spca50x_setup_qtable(gspca_dev
,
719 0x00, 0x8800, 0x8840,
722 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
723 spca500_setmode(gspca_dev
, xmult
, ymult
);
725 reg_w(gspca_dev
, 0x20, 0x0001, 0x0004);
727 /* switch to video camera mode */
728 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
730 if (reg_r_wait(gspca_dev
, 0, 0x8000, 0x44) != 0)
731 gspca_err(gspca_dev
, "reg_r_wait() failed\n");
733 reg_r(gspca_dev
, 0x816b, 1);
734 Data
= gspca_dev
->usb_buf
[0];
735 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
737 /* write_vector(gspca_dev, spca500_visual_defaults); */
741 case DLinkDSC350
: /* FamilyCam 300 */
742 case AiptekPocketDV
: /* Aiptek PocketDV */
743 case Gsmartmini
: /*Mustek Gsmart Mini */
744 case MustekGsmart300
: /* Mustek Gsmart 300 */
749 spca500_reinit(gspca_dev
);
750 reg_w(gspca_dev
, 0x00, 0x0d01, 0x01);
751 /* enable drop packet */
752 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
754 err
= spca50x_setup_qtable(gspca_dev
,
755 0x00, 0x8800, 0x8840, qtable_pocketdv
);
757 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
758 reg_w(gspca_dev
, 0x00, 0x8880, 2);
760 /* familycam Quicksmart pocketDV stuff */
761 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
762 /* Set agc transfer: synced between frames */
763 reg_w(gspca_dev
, 0x00, 0x820f, 0x01);
764 /* Init SDRAM - needed for SDRAM access */
765 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
767 spca500_setmode(gspca_dev
, xmult
, ymult
);
768 /* switch to video camera mode */
769 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
771 reg_r_wait(gspca_dev
, 0, 0x8000, 0x44);
773 reg_r(gspca_dev
, 0x816b, 1);
774 Data
= gspca_dev
->usb_buf
[0];
775 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
777 case LogitechTraveler
:
778 case LogitechClickSmart510
:
779 reg_w(gspca_dev
, 0x02, 0x00, 0x00);
780 /* enable drop packet */
781 reg_w(gspca_dev
, 0x00, 0x850a, 0x0001);
783 err
= spca50x_setup_qtable(gspca_dev
,
785 0x8840, qtable_creative_pccam
);
787 gspca_err(gspca_dev
, "spca50x_setup_qtable failed\n");
788 reg_w(gspca_dev
, 0x00, 0x8880, 3);
789 reg_w(gspca_dev
, 0x00, 0x800a, 0x00);
790 /* Init SDRAM - needed for SDRAM access */
791 reg_w(gspca_dev
, 0x00, 0x870a, 0x04);
793 spca500_setmode(gspca_dev
, xmult
, ymult
);
795 /* switch to video camera mode */
796 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
797 reg_r_wait(gspca_dev
, 0, 0x8000, 0x44);
799 reg_r(gspca_dev
, 0x816b, 1);
800 Data
= gspca_dev
->usb_buf
[0];
801 reg_w(gspca_dev
, 0x00, 0x816b, Data
);
802 write_vector(gspca_dev
, Clicksmart510_defaults
);
808 static void sd_stopN(struct gspca_dev
*gspca_dev
)
810 reg_w(gspca_dev
, 0, 0x8003, 0x00);
812 /* switch to video camera mode */
813 reg_w(gspca_dev
, 0x00, 0x8000, 0x0004);
814 reg_r(gspca_dev
, 0x8000, 1);
815 gspca_dbg(gspca_dev
, D_STREAM
, "stop SPCA500 done reg8000: 0x%2x\n",
816 gspca_dev
->usb_buf
[0]);
819 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
820 u8
*data
, /* isoc packet */
821 int len
) /* iso packet length */
823 struct sd
*sd
= (struct sd
*) gspca_dev
;
825 static __u8 ffd9
[] = {0xff, 0xd9};
827 /* frames are jpeg 4.1.1 without 0xff escape */
828 if (data
[0] == 0xff) {
829 if (data
[1] != 0x01) { /* drop packet */
830 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
833 gspca_frame_add(gspca_dev
, LAST_PACKET
,
836 /* put the JPEG header in the new frame */
837 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
838 sd
->jpeg_hdr
, JPEG_HDR_SZ
);
840 data
+= SPCA500_OFFSET_DATA
;
841 len
-= SPCA500_OFFSET_DATA
;
847 /* add 0x00 after 0xff */
850 if (data
[i
] == 0xff) {
851 gspca_frame_add(gspca_dev
, INTER_PACKET
,
860 gspca_frame_add(gspca_dev
, INTER_PACKET
, data
, len
);
863 static void setbrightness(struct gspca_dev
*gspca_dev
, s32 val
)
865 reg_w(gspca_dev
, 0x00, 0x8167,
869 static void setcontrast(struct gspca_dev
*gspca_dev
, s32 val
)
871 reg_w(gspca_dev
, 0x00, 0x8168, val
);
874 static void setcolors(struct gspca_dev
*gspca_dev
, s32 val
)
876 reg_w(gspca_dev
, 0x00, 0x8169, val
);
879 static int sd_s_ctrl(struct v4l2_ctrl
*ctrl
)
881 struct gspca_dev
*gspca_dev
=
882 container_of(ctrl
->handler
, struct gspca_dev
, ctrl_handler
);
884 gspca_dev
->usb_err
= 0;
886 if (!gspca_dev
->streaming
)
890 case V4L2_CID_BRIGHTNESS
:
891 setbrightness(gspca_dev
, ctrl
->val
);
893 case V4L2_CID_CONTRAST
:
894 setcontrast(gspca_dev
, ctrl
->val
);
896 case V4L2_CID_SATURATION
:
897 setcolors(gspca_dev
, ctrl
->val
);
900 return gspca_dev
->usb_err
;
903 static const struct v4l2_ctrl_ops sd_ctrl_ops
= {
907 static int sd_init_controls(struct gspca_dev
*gspca_dev
)
909 struct v4l2_ctrl_handler
*hdl
= &gspca_dev
->ctrl_handler
;
911 gspca_dev
->vdev
.ctrl_handler
= hdl
;
912 v4l2_ctrl_handler_init(hdl
, 3);
913 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
914 V4L2_CID_BRIGHTNESS
, 0, 255, 1, 127);
915 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
916 V4L2_CID_CONTRAST
, 0, 63, 1, 31);
917 v4l2_ctrl_new_std(hdl
, &sd_ctrl_ops
,
918 V4L2_CID_SATURATION
, 0, 63, 1, 31);
921 pr_err("Could not initialize controls\n");
927 /* sub-driver description */
928 static const struct sd_desc sd_desc
= {
932 .init_controls
= sd_init_controls
,
935 .pkt_scan
= sd_pkt_scan
,
938 /* -- module initialisation -- */
939 static const struct usb_device_id device_table
[] = {
940 {USB_DEVICE(0x040a, 0x0300), .driver_info
= KodakEZ200
},
941 {USB_DEVICE(0x041e, 0x400a), .driver_info
= CreativePCCam300
},
942 {USB_DEVICE(0x046d, 0x0890), .driver_info
= LogitechTraveler
},
943 {USB_DEVICE(0x046d, 0x0900), .driver_info
= LogitechClickSmart310
},
944 {USB_DEVICE(0x046d, 0x0901), .driver_info
= LogitechClickSmart510
},
945 {USB_DEVICE(0x04a5, 0x300c), .driver_info
= BenqDC1016
},
946 {USB_DEVICE(0x04fc, 0x7333), .driver_info
= PalmPixDC85
},
947 {USB_DEVICE(0x055f, 0xc200), .driver_info
= MustekGsmart300
},
948 {USB_DEVICE(0x055f, 0xc220), .driver_info
= Gsmartmini
},
949 {USB_DEVICE(0x06bd, 0x0404), .driver_info
= AgfaCl20
},
950 {USB_DEVICE(0x06be, 0x0800), .driver_info
= Optimedia
},
951 {USB_DEVICE(0x084d, 0x0003), .driver_info
= DLinkDSC350
},
952 {USB_DEVICE(0x08ca, 0x0103), .driver_info
= AiptekPocketDV
},
953 {USB_DEVICE(0x2899, 0x012c), .driver_info
= ToptroIndus
},
954 {USB_DEVICE(0x8086, 0x0630), .driver_info
= IntelPocketPCCamera
},
957 MODULE_DEVICE_TABLE(usb
, device_table
);
959 /* -- device connect -- */
960 static int sd_probe(struct usb_interface
*intf
,
961 const struct usb_device_id
*id
)
963 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
967 static struct usb_driver sd_driver
= {
969 .id_table
= device_table
,
971 .disconnect
= gspca_disconnect
,
973 .suspend
= gspca_suspend
,
974 .resume
= gspca_resume
,
975 .reset_resume
= gspca_resume
,
979 module_usb_driver(sd_driver
);