]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/media/usb/gspca/spca500.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / drivers / media / usb / gspca / spca500.c
CommitLineData
6a7eba24
JFM
1/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
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
9 * any later version.
10 *
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.
15 *
6a7eba24
JFM
16 */
17
133a9fe9
JP
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
6a7eba24
JFM
20#define MODULE_NAME "spca500"
21
22#include "gspca.h"
23#include "jpeg.h"
24
6a7eba24
JFM
25MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
26MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
27MODULE_LICENSE("GPL");
28
b56ab4ca
HG
29#define QUALITY 85
30
6a7eba24
JFM
31/* specific webcam descriptor */
32struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
6a7eba24
JFM
35 char subtype;
36#define AgfaCl20 0
37#define AiptekPocketDV 1
38#define BenqDC1016 2
39#define CreativePCCam300 3
40#define DLinkDSC350 4
41#define Gsmartmini 5
42#define IntelPocketPCCamera 6
43#define KodakEZ200 7
44#define LogitechClickSmart310 8
45#define LogitechClickSmart510 9
46#define LogitechTraveler 10
47#define MustekGsmart300 11
48#define Optimedia 12
49#define PalmPixDC85 13
50#define ToptroIndus 14
71cb2764 51
9a731a32 52 u8 jpeg_hdr[JPEG_HDR_SZ];
6a7eba24
JFM
53};
54
cc611b8a 55static const struct v4l2_pix_format vga_mode[] = {
c2446b3e
JFM
56 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
57 .bytesperline = 320,
58 .sizeimage = 320 * 240 * 3 / 8 + 590,
59 .colorspace = V4L2_COLORSPACE_JPEG,
60 .priv = 1},
61 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
62 .bytesperline = 640,
63 .sizeimage = 640 * 480 * 3 / 8 + 590,
64 .colorspace = V4L2_COLORSPACE_JPEG,
65 .priv = 0},
6a7eba24
JFM
66};
67
cc611b8a 68static const struct v4l2_pix_format sif_mode[] = {
c2446b3e
JFM
69 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
70 .bytesperline = 176,
71 .sizeimage = 176 * 144 * 3 / 8 + 590,
72 .colorspace = V4L2_COLORSPACE_JPEG,
73 .priv = 1},
74 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
75 .bytesperline = 352,
76 .sizeimage = 352 * 288 * 3 / 8 + 590,
77 .colorspace = V4L2_COLORSPACE_JPEG,
78 .priv = 0},
6a7eba24
JFM
79};
80
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
94
95
a5ae2062 96static const __u16 spca500_visual_defaults[][3] = {
6a7eba24
JFM
97 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
98 * hue (H byte) = 0,
99 * saturation/hue enable,
100 * brightness/contrast enable.
101 */
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.
108 */
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},
117 /* set interface */
a5ae2062 118 {}
6a7eba24 119};
a5ae2062 120static const __u16 Clicksmart510_defaults[][3] = {
6a7eba24
JFM
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},
246 {}
247};
248
a5ae2062 249static const __u8 qtable_creative_pccam[2][64] = {
6a7eba24
JFM
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}
268};
269
a5ae2062 270static const __u8 qtable_kodak_ez200[2][64] = {
6a7eba24
JFM
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}
289};
290
a5ae2062 291static const __u8 qtable_pocketdv[2][64] = {
956e42d2 292 { /* Q-table Y-components start registers 0x8800 */
6a7eba24
JFM
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,
301 },
956e42d2 302 { /* Q-table C-components start registers 0x8840 */
6a7eba24
JFM
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}
311};
312
739570bb
JFM
313/* read 'len' bytes to gspca_dev->usb_buf */
314static void reg_r(struct gspca_dev *gspca_dev,
315 __u16 index,
316 __u16 length)
6a7eba24 317{
739570bb
JFM
318 usb_control_msg(gspca_dev->dev,
319 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
320 0,
321 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
322 0, /* value */
739570bb 323 index, gspca_dev->usb_buf, length, 500);
6a7eba24
JFM
324}
325
739570bb 326static int reg_w(struct gspca_dev *gspca_dev,
6a7eba24
JFM
327 __u16 req, __u16 index, __u16 value)
328{
329 int ret;
330
a5ae2062 331 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
739570bb
JFM
332 ret = usb_control_msg(gspca_dev->dev,
333 usb_sndctrlpipe(gspca_dev->dev, 0),
6a7eba24 334 req,
bf7f0b98 335 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6a7eba24 336 value, index, NULL, 0, 500);
6a7eba24 337 if (ret < 0)
133a9fe9 338 pr_err("reg write: error %d\n", ret);
6a7eba24
JFM
339 return ret;
340}
341
342/* returns: negative is error, pos or zero is data */
739570bb 343static int reg_r_12(struct gspca_dev *gspca_dev,
6a7eba24
JFM
344 __u16 req, /* bRequest */
345 __u16 index, /* wIndex */
346 __u16 length) /* wLength (1 or 2 only) */
347{
348 int ret;
6a7eba24 349
739570bb
JFM
350 gspca_dev->usb_buf[1] = 0;
351 ret = usb_control_msg(gspca_dev->dev,
352 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
353 req,
354 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
355 0, /* value */
356 index,
739570bb 357 gspca_dev->usb_buf, length,
6a7eba24
JFM
358 500); /* timeout */
359 if (ret < 0) {
133a9fe9 360 pr_err("reg_r_12 err %d\n", ret);
0b656321 361 return ret;
6a7eba24 362 }
739570bb 363 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
6a7eba24
JFM
364}
365
366/*
367 * Simple function to wait for a given 8-bit value to be returned from
368 * a reg_read call.
369 * Returns: negative is error or timeout, zero is success.
370 */
739570bb 371static int reg_r_wait(struct gspca_dev *gspca_dev,
6a7eba24
JFM
372 __u16 reg, __u16 index, __u16 value)
373{
374 int ret, cnt = 20;
375
376 while (--cnt > 0) {
739570bb 377 ret = reg_r_12(gspca_dev, reg, index, 1);
6a7eba24
JFM
378 if (ret == value)
379 return 0;
380 msleep(50);
381 }
382 return -EIO;
383}
384
385static int write_vector(struct gspca_dev *gspca_dev,
a5ae2062 386 const __u16 data[][3])
6a7eba24 387{
6a7eba24
JFM
388 int ret, i = 0;
389
390 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
739570bb 391 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
6a7eba24
JFM
392 if (ret < 0)
393 return ret;
394 i++;
395 }
396 return 0;
397}
398
399static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
400 unsigned int request,
401 unsigned int ybase,
402 unsigned int cbase,
a5ae2062 403 const __u8 qtable[2][64])
6a7eba24 404{
6a7eba24
JFM
405 int i, err;
406
407 /* loop over y components */
408 for (i = 0; i < 64; i++) {
739570bb 409 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
6a7eba24
JFM
410 if (err < 0)
411 return err;
412 }
413
414 /* loop over c components */
415 for (i = 0; i < 64; i++) {
739570bb 416 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
6a7eba24
JFM
417 if (err < 0)
418 return err;
419 }
420 return 0;
421}
422
423static void spca500_ping310(struct gspca_dev *gspca_dev)
424{
739570bb 425 reg_r(gspca_dev, 0x0d04, 2);
a5ae2062 426 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
739570bb 427 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
6a7eba24
JFM
428}
429
430static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
431{
739570bb 432 reg_r(gspca_dev, 0x0d05, 2);
a5ae2062 433 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
739570bb
JFM
434 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
435 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
6a7eba24
JFM
436 spca500_ping310(gspca_dev);
437
739570bb
JFM
438 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
439 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
440 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
441 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
442 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
443 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
444 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
445 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
446 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
447 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
6a7eba24 448 /* 00 for adjust shutter */
739570bb
JFM
449 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
450 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
451 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
6a7eba24
JFM
452}
453
454static void spca500_setmode(struct gspca_dev *gspca_dev,
455 __u8 xmult, __u8 ymult)
456{
457 int mode;
458
459 /* set x multiplier */
739570bb 460 reg_w(gspca_dev, 0, 0x8001, xmult);
6a7eba24
JFM
461
462 /* set y multiplier */
739570bb 463 reg_w(gspca_dev, 0, 0x8002, ymult);
6a7eba24
JFM
464
465 /* use compressed mode, VGA, with mode specific subsample */
c2446b3e 466 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
739570bb 467 reg_w(gspca_dev, 0, 0x8003, mode << 4);
6a7eba24
JFM
468}
469
470static int spca500_full_reset(struct gspca_dev *gspca_dev)
471{
472 int err;
473
474 /* send the reset command */
739570bb 475 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
6a7eba24
JFM
476 if (err < 0)
477 return err;
478
479 /* wait for the reset to complete */
739570bb 480 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
6a7eba24
JFM
481 if (err < 0)
482 return err;
739570bb 483 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
6a7eba24
JFM
484 if (err < 0)
485 return err;
739570bb 486 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
6a7eba24 487 if (err < 0) {
c93396e1 488 PERR("reg_r_wait() failed");
6a7eba24
JFM
489 return err;
490 }
491 /* all ok */
492 return 0;
493}
494
495/* Synchro the Bridge with sensor */
496/* Maybe that will work on all spca500 chip */
497/* because i only own a clicksmart310 try for that chip */
498/* using spca50x_set_packet_size() cause an Ooops here */
499/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
500/* up-port the same feature as in 2.4.x kernel */
501static int spca500_synch310(struct gspca_dev *gspca_dev)
502{
6a7eba24 503 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
c93396e1 504 PERR("Set packet size: set interface error");
6a7eba24
JFM
505 goto error;
506 }
507 spca500_ping310(gspca_dev);
508
739570bb 509 reg_r(gspca_dev, 0x0d00, 1);
6a7eba24
JFM
510
511 /* need alt setting here */
512 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
513
514 /* Windoze use pipe with altsetting 6 why 7 here */
515 if (usb_set_interface(gspca_dev->dev,
516 gspca_dev->iface,
517 gspca_dev->alt) < 0) {
c93396e1 518 PERR("Set packet size: set interface error");
6a7eba24
JFM
519 goto error;
520 }
521 return 0;
522error:
523 return -EBUSY;
524}
525
526static void spca500_reinit(struct gspca_dev *gspca_dev)
527{
528 int err;
529 __u8 Data;
530
af901ca1 531 /* some unknown command from Aiptek pocket dv and family300 */
6a7eba24 532
739570bb
JFM
533 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
534 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
535 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
6a7eba24
JFM
536
537 /* enable drop packet */
739570bb 538 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
539
540 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
541 qtable_pocketdv);
542 if (err < 0)
c93396e1 543 PERR("spca50x_setup_qtable failed on init");
6a7eba24
JFM
544
545 /* set qtable index */
739570bb 546 reg_w(gspca_dev, 0x00, 0x8880, 2);
6a7eba24 547 /* family cam Quicksmart stuff */
739570bb 548 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
25985edc 549 /* Set agc transfer: synced between frames */
739570bb 550 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
6a7eba24 551 /* Init SDRAM - needed for SDRAM access */
739570bb 552 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24 553 /*Start init sequence or stream */
739570bb 554 reg_w(gspca_dev, 0, 0x8003, 0x00);
6a7eba24 555 /* switch to video camera mode */
739570bb 556 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 557 msleep(2000);
739570bb
JFM
558 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
559 reg_r(gspca_dev, 0x816b, 1);
560 Data = gspca_dev->usb_buf[0];
561 reg_w(gspca_dev, 0x00, 0x816b, Data);
562 }
6a7eba24
JFM
563}
564
565/* this function is called at probe time */
566static int sd_config(struct gspca_dev *gspca_dev,
567 const struct usb_device_id *id)
568{
569 struct sd *sd = (struct sd *) gspca_dev;
570 struct cam *cam;
9d64fdb1 571
6a7eba24 572 cam = &gspca_dev->cam;
9d64fdb1 573 sd->subtype = id->driver_info;
6a7eba24
JFM
574 if (sd->subtype != LogitechClickSmart310) {
575 cam->cam_mode = vga_mode;
80297125 576 cam->nmodes = ARRAY_SIZE(vga_mode);
6a7eba24
JFM
577 } else {
578 cam->cam_mode = sif_mode;
80297125 579 cam->nmodes = ARRAY_SIZE(sif_mode);
6a7eba24 580 }
6a7eba24
JFM
581 return 0;
582}
583
012d6b02
JFM
584/* this function is called at probe and resume time */
585static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24
JFM
586{
587 struct sd *sd = (struct sd *) gspca_dev;
588
589 /* initialisation of spca500 based cameras is deferred */
590 PDEBUG(D_STREAM, "SPCA500 init");
591 if (sd->subtype == LogitechClickSmart310)
592 spca500_clksmart310_init(gspca_dev);
593/* else
594 spca500_initialise(gspca_dev); */
595 PDEBUG(D_STREAM, "SPCA500 init done");
596 return 0;
597}
598
72ab97ce 599static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24
JFM
600{
601 struct sd *sd = (struct sd *) gspca_dev;
602 int err;
603 __u8 Data;
604 __u8 xmult, ymult;
605
71cb2764 606 /* create the JPEG header */
1966bc2a
OZ
607 jpeg_define(sd->jpeg_hdr, gspca_dev->pixfmt.height,
608 gspca_dev->pixfmt.width,
71cb2764 609 0x22); /* JPEG 411 */
b56ab4ca 610 jpeg_set_qual(sd->jpeg_hdr, QUALITY);
71cb2764 611
6a7eba24
JFM
612 if (sd->subtype == LogitechClickSmart310) {
613 xmult = 0x16;
614 ymult = 0x12;
615 } else {
616 xmult = 0x28;
617 ymult = 0x1e;
618 }
619
620 /* is there a sensor here ? */
739570bb
JFM
621 reg_r(gspca_dev, 0x8a04, 1);
622 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
623 gspca_dev->usb_buf[0]);
624 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
6a7eba24
JFM
625 gspca_dev->curr_mode, xmult, ymult);
626
627 /* setup qtable */
628 switch (sd->subtype) {
629 case LogitechClickSmart310:
630 spca500_setmode(gspca_dev, xmult, ymult);
631
632 /* enable drop packet */
739570bb
JFM
633 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
634 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
635 err = spca50x_setup_qtable(gspca_dev,
636 0x00, 0x8800, 0x8840,
637 qtable_creative_pccam);
638 if (err < 0)
c93396e1 639 PERR("spca50x_setup_qtable failed");
6a7eba24 640 /* Init SDRAM - needed for SDRAM access */
739570bb 641 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
642
643 /* switch to video camera mode */
739570bb 644 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 645 msleep(500);
739570bb 646 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
c93396e1 647 PERR("reg_r_wait() failed");
6a7eba24 648
739570bb
JFM
649 reg_r(gspca_dev, 0x816b, 1);
650 Data = gspca_dev->usb_buf[0];
651 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
652
653 spca500_synch310(gspca_dev);
654
655 write_vector(gspca_dev, spca500_visual_defaults);
656 spca500_setmode(gspca_dev, xmult, ymult);
657 /* enable drop packet */
48d7a891
JFM
658 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
659 if (err < 0)
c93396e1 660 PERR("failed to enable drop packet");
739570bb 661 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
662 err = spca50x_setup_qtable(gspca_dev,
663 0x00, 0x8800, 0x8840,
664 qtable_creative_pccam);
665 if (err < 0)
c93396e1 666 PERR("spca50x_setup_qtable failed");
6a7eba24
JFM
667
668 /* Init SDRAM - needed for SDRAM access */
739570bb 669 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
670
671 /* switch to video camera mode */
739570bb 672 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 673
739570bb 674 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
c93396e1 675 PERR("reg_r_wait() failed");
6a7eba24 676
739570bb
JFM
677 reg_r(gspca_dev, 0x816b, 1);
678 Data = gspca_dev->usb_buf[0];
679 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
680 break;
681 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
682 case IntelPocketPCCamera: /* FIXME: Temporary fix for
683 * Intel Pocket PC Camera
684 * - NWG (Sat 29th March 2003) */
685
686 /* do a full reset */
956e42d2
JFM
687 err = spca500_full_reset(gspca_dev);
688 if (err < 0)
c93396e1 689 PERR("spca500_full_reset failed");
6a7eba24
JFM
690
691 /* enable drop packet */
739570bb 692 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24 693 if (err < 0)
c93396e1 694 PERR("failed to enable drop packet");
739570bb 695 reg_w(gspca_dev, 0x00, 0x8880, 3);
6a7eba24
JFM
696 err = spca50x_setup_qtable(gspca_dev,
697 0x00, 0x8800, 0x8840,
698 qtable_creative_pccam);
699 if (err < 0)
c93396e1 700 PERR("spca50x_setup_qtable failed");
6a7eba24
JFM
701
702 spca500_setmode(gspca_dev, xmult, ymult);
739570bb 703 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
6a7eba24
JFM
704
705 /* switch to video camera mode */
739570bb 706 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 707
739570bb 708 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
c93396e1 709 PERR("reg_r_wait() failed");
6a7eba24 710
739570bb
JFM
711 reg_r(gspca_dev, 0x816b, 1);
712 Data = gspca_dev->usb_buf[0];
713 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24 714
a5ae2062 715/* write_vector(gspca_dev, spca500_visual_defaults); */
6a7eba24
JFM
716 break;
717 case KodakEZ200: /* Kodak EZ200 */
718
719 /* do a full reset */
720 err = spca500_full_reset(gspca_dev);
721 if (err < 0)
c93396e1 722 PERR("spca500_full_reset failed");
6a7eba24 723 /* enable drop packet */
739570bb
JFM
724 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
725 reg_w(gspca_dev, 0x00, 0x8880, 0);
6a7eba24
JFM
726 err = spca50x_setup_qtable(gspca_dev,
727 0x00, 0x8800, 0x8840,
728 qtable_kodak_ez200);
729 if (err < 0)
c93396e1 730 PERR("spca50x_setup_qtable failed");
6a7eba24
JFM
731 spca500_setmode(gspca_dev, xmult, ymult);
732
739570bb 733 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
6a7eba24
JFM
734
735 /* switch to video camera mode */
739570bb 736 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 737
739570bb 738 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
c93396e1 739 PERR("reg_r_wait() failed");
6a7eba24 740
739570bb
JFM
741 reg_r(gspca_dev, 0x816b, 1);
742 Data = gspca_dev->usb_buf[0];
743 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24 744
a5ae2062 745/* write_vector(gspca_dev, spca500_visual_defaults); */
6a7eba24
JFM
746 break;
747
748 case BenqDC1016:
749 case DLinkDSC350: /* FamilyCam 300 */
750 case AiptekPocketDV: /* Aiptek PocketDV */
751 case Gsmartmini: /*Mustek Gsmart Mini */
752 case MustekGsmart300: /* Mustek Gsmart 300 */
753 case PalmPixDC85:
754 case Optimedia:
755 case ToptroIndus:
756 case AgfaCl20:
757 spca500_reinit(gspca_dev);
739570bb 758 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
6a7eba24 759 /* enable drop packet */
739570bb 760 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
761
762 err = spca50x_setup_qtable(gspca_dev,
763 0x00, 0x8800, 0x8840, qtable_pocketdv);
764 if (err < 0)
c93396e1 765 PERR("spca50x_setup_qtable failed");
739570bb 766 reg_w(gspca_dev, 0x00, 0x8880, 2);
6a7eba24
JFM
767
768 /* familycam Quicksmart pocketDV stuff */
739570bb 769 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
25985edc 770 /* Set agc transfer: synced between frames */
739570bb 771 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
6a7eba24 772 /* Init SDRAM - needed for SDRAM access */
739570bb 773 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24 774
956e42d2 775 spca500_setmode(gspca_dev, xmult, ymult);
6a7eba24 776 /* switch to video camera mode */
739570bb 777 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
6a7eba24 778
739570bb 779 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
6a7eba24 780
739570bb
JFM
781 reg_r(gspca_dev, 0x816b, 1);
782 Data = gspca_dev->usb_buf[0];
783 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
784 break;
785 case LogitechTraveler:
786 case LogitechClickSmart510:
739570bb 787 reg_w(gspca_dev, 0x02, 0x00, 0x00);
6a7eba24 788 /* enable drop packet */
739570bb 789 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
6a7eba24
JFM
790
791 err = spca50x_setup_qtable(gspca_dev,
792 0x00, 0x8800,
793 0x8840, qtable_creative_pccam);
794 if (err < 0)
c93396e1 795 PERR("spca50x_setup_qtable failed");
739570bb
JFM
796 reg_w(gspca_dev, 0x00, 0x8880, 3);
797 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
6a7eba24 798 /* Init SDRAM - needed for SDRAM access */
739570bb 799 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
6a7eba24
JFM
800
801 spca500_setmode(gspca_dev, xmult, ymult);
802
803 /* switch to video camera mode */
739570bb
JFM
804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
805 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
6a7eba24 806
739570bb
JFM
807 reg_r(gspca_dev, 0x816b, 1);
808 Data = gspca_dev->usb_buf[0];
809 reg_w(gspca_dev, 0x00, 0x816b, Data);
6a7eba24
JFM
810 write_vector(gspca_dev, Clicksmart510_defaults);
811 break;
812 }
72ab97ce 813 return 0;
6a7eba24
JFM
814}
815
816static void sd_stopN(struct gspca_dev *gspca_dev)
817{
739570bb 818 reg_w(gspca_dev, 0, 0x8003, 0x00);
6a7eba24
JFM
819
820 /* switch to video camera mode */
739570bb
JFM
821 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
822 reg_r(gspca_dev, 0x8000, 1);
823 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
824 gspca_dev->usb_buf[0]);
6a7eba24
JFM
825}
826
6a7eba24 827static void sd_pkt_scan(struct gspca_dev *gspca_dev,
76dd272b 828 u8 *data, /* isoc packet */
6a7eba24
JFM
829 int len) /* iso packet length */
830{
831 struct sd *sd = (struct sd *) gspca_dev;
832 int i;
a5ae2062 833 static __u8 ffd9[] = {0xff, 0xd9};
6a7eba24
JFM
834
835/* frames are jpeg 4.1.1 without 0xff escape */
836 if (data[0] == 0xff) {
837 if (data[1] != 0x01) { /* drop packet */
838/* gspca_dev->last_packet_type = DISCARD_PACKET; */
839 return;
840 }
76dd272b 841 gspca_frame_add(gspca_dev, LAST_PACKET,
6a7eba24
JFM
842 ffd9, 2);
843
844 /* put the JPEG header in the new frame */
76dd272b 845 gspca_frame_add(gspca_dev, FIRST_PACKET,
71cb2764 846 sd->jpeg_hdr, JPEG_HDR_SZ);
6a7eba24
JFM
847
848 data += SPCA500_OFFSET_DATA;
849 len -= SPCA500_OFFSET_DATA;
850 } else {
851 data += 1;
852 len -= 1;
853 }
854
855 /* add 0x00 after 0xff */
59746e13
JFM
856 i = 0;
857 do {
858 if (data[i] == 0xff) {
76dd272b 859 gspca_frame_add(gspca_dev, INTER_PACKET,
59746e13
JFM
860 data, i + 1);
861 len -= i;
862 data += i;
863 *data = 0x00;
864 i = 0;
865 }
866 i++;
867 } while (i < len);
76dd272b 868 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6a7eba24
JFM
869}
870
9bf0c43e 871static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 872{
739570bb 873 reg_w(gspca_dev, 0x00, 0x8167,
9bf0c43e 874 (__u8) (val - 128));
6a7eba24
JFM
875}
876
9bf0c43e 877static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 878{
9bf0c43e 879 reg_w(gspca_dev, 0x00, 0x8168, val);
6a7eba24
JFM
880}
881
9bf0c43e 882static void setcolors(struct gspca_dev *gspca_dev, s32 val)
6a7eba24 883{
9bf0c43e 884 reg_w(gspca_dev, 0x00, 0x8169, val);
6a7eba24
JFM
885}
886
9bf0c43e 887static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
6a7eba24 888{
9bf0c43e
HV
889 struct gspca_dev *gspca_dev =
890 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
6a7eba24 891
9bf0c43e 892 gspca_dev->usb_err = 0;
6a7eba24 893
9bf0c43e
HV
894 if (!gspca_dev->streaming)
895 return 0;
6a7eba24 896
9bf0c43e
HV
897 switch (ctrl->id) {
898 case V4L2_CID_BRIGHTNESS:
899 setbrightness(gspca_dev, ctrl->val);
900 break;
901 case V4L2_CID_CONTRAST:
902 setcontrast(gspca_dev, ctrl->val);
903 break;
904 case V4L2_CID_SATURATION:
905 setcolors(gspca_dev, ctrl->val);
906 break;
9bf0c43e
HV
907 }
908 return gspca_dev->usb_err;
6a7eba24
JFM
909}
910
9bf0c43e
HV
911static const struct v4l2_ctrl_ops sd_ctrl_ops = {
912 .s_ctrl = sd_s_ctrl,
913};
77ac0baf 914
9bf0c43e 915static int sd_init_controls(struct gspca_dev *gspca_dev)
77ac0baf 916{
9bf0c43e
HV
917 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
918
919 gspca_dev->vdev.ctrl_handler = hdl;
b56ab4ca 920 v4l2_ctrl_handler_init(hdl, 3);
9bf0c43e
HV
921 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
922 V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
923 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
924 V4L2_CID_CONTRAST, 0, 63, 1, 31);
925 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
926 V4L2_CID_SATURATION, 0, 63, 1, 31);
9bf0c43e
HV
927
928 if (hdl->error) {
929 pr_err("Could not initialize controls\n");
930 return hdl->error;
931 }
77ac0baf
JFM
932 return 0;
933}
934
6a7eba24 935/* sub-driver description */
aabcdfb6 936static const struct sd_desc sd_desc = {
6a7eba24 937 .name = MODULE_NAME,
6a7eba24 938 .config = sd_config,
012d6b02 939 .init = sd_init,
9bf0c43e 940 .init_controls = sd_init_controls,
6a7eba24
JFM
941 .start = sd_start,
942 .stopN = sd_stopN,
6a7eba24
JFM
943 .pkt_scan = sd_pkt_scan,
944};
945
946/* -- module initialisation -- */
95c967c1 947static const struct usb_device_id device_table[] = {
87581aa5
JFM
948 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
949 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
950 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
951 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
952 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
953 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
954 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
955 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
956 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
957 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
958 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
959 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
960 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
961 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
962 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
6a7eba24
JFM
963 {}
964};
965MODULE_DEVICE_TABLE(usb, device_table);
966
967/* -- device connect -- */
968static int sd_probe(struct usb_interface *intf,
969 const struct usb_device_id *id)
970{
971 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
972 THIS_MODULE);
973}
974
975static struct usb_driver sd_driver = {
976 .name = MODULE_NAME,
977 .id_table = device_table,
978 .probe = sd_probe,
979 .disconnect = gspca_disconnect,
6a709749
JFM
980#ifdef CONFIG_PM
981 .suspend = gspca_suspend,
982 .resume = gspca_resume,
8bb58964 983 .reset_resume = gspca_resume,
6a709749 984#endif
6a7eba24
JFM
985};
986
ecb3b2b3 987module_usb_driver(sd_driver);