Merge branch 'master' of git://git.infradead.org/users/dwmw2/solos-2.6
[deliverable/linux.git] / drivers / media / video / gspca / spca500.c
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 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #define MODULE_NAME "spca500"
23
24 #include "gspca.h"
25 #include "jpeg.h"
26
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
29 MODULE_LICENSE("GPL");
30
31 /* specific webcam descriptor */
32 struct sd {
33 struct gspca_dev gspca_dev; /* !! must be the first item */
34
35 unsigned char brightness;
36 unsigned char contrast;
37 unsigned char colors;
38 u8 quality;
39 #define QUALITY_MIN 70
40 #define QUALITY_MAX 95
41 #define QUALITY_DEF 85
42
43 char subtype;
44 #define AgfaCl20 0
45 #define AiptekPocketDV 1
46 #define BenqDC1016 2
47 #define CreativePCCam300 3
48 #define DLinkDSC350 4
49 #define Gsmartmini 5
50 #define IntelPocketPCCamera 6
51 #define KodakEZ200 7
52 #define LogitechClickSmart310 8
53 #define LogitechClickSmart510 9
54 #define LogitechTraveler 10
55 #define MustekGsmart300 11
56 #define Optimedia 12
57 #define PalmPixDC85 13
58 #define ToptroIndus 14
59
60 u8 *jpeg_hdr;
61 };
62
63 /* V4L2 controls supported by the driver */
64 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
65 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
66 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
67 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
68 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
69 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
70
71 static struct ctrl sd_ctrls[] = {
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 255,
79 .step = 1,
80 #define BRIGHTNESS_DEF 127
81 .default_value = BRIGHTNESS_DEF,
82 },
83 .set = sd_setbrightness,
84 .get = sd_getbrightness,
85 },
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 63,
93 .step = 1,
94 #define CONTRAST_DEF 31
95 .default_value = CONTRAST_DEF,
96 },
97 .set = sd_setcontrast,
98 .get = sd_getcontrast,
99 },
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 63,
107 .step = 1,
108 #define COLOR_DEF 31
109 .default_value = COLOR_DEF,
110 },
111 .set = sd_setcolors,
112 .get = sd_getcolors,
113 },
114 };
115
116 static const struct v4l2_pix_format vga_mode[] = {
117 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
118 .bytesperline = 320,
119 .sizeimage = 320 * 240 * 3 / 8 + 590,
120 .colorspace = V4L2_COLORSPACE_JPEG,
121 .priv = 1},
122 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
123 .bytesperline = 640,
124 .sizeimage = 640 * 480 * 3 / 8 + 590,
125 .colorspace = V4L2_COLORSPACE_JPEG,
126 .priv = 0},
127 };
128
129 static const struct v4l2_pix_format sif_mode[] = {
130 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 176,
132 .sizeimage = 176 * 144 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 352,
137 .sizeimage = 352 * 288 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
140 };
141
142 /* Frame packet header offsets for the spca500 */
143 #define SPCA500_OFFSET_PADDINGLB 2
144 #define SPCA500_OFFSET_PADDINGHB 3
145 #define SPCA500_OFFSET_MODE 4
146 #define SPCA500_OFFSET_IMGWIDTH 5
147 #define SPCA500_OFFSET_IMGHEIGHT 6
148 #define SPCA500_OFFSET_IMGMODE 7
149 #define SPCA500_OFFSET_QTBLINDEX 8
150 #define SPCA500_OFFSET_FRAMSEQ 9
151 #define SPCA500_OFFSET_CDSPINFO 10
152 #define SPCA500_OFFSET_GPIO 11
153 #define SPCA500_OFFSET_AUGPIO 12
154 #define SPCA500_OFFSET_DATA 16
155
156
157 static const __u16 spca500_visual_defaults[][3] = {
158 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
159 * hue (H byte) = 0,
160 * saturation/hue enable,
161 * brightness/contrast enable.
162 */
163 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
164 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
165 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
166 * hue (H byte) = 0, saturation/hue enable,
167 * brightness/contrast enable.
168 * was 0x0003, now 0x0000.
169 */
170 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
171 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
172 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
173 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
174 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
175 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
176 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
177 {0x0c, 0x0004, 0x0000},
178 /* set interface */
179 {}
180 };
181 static const __u16 Clicksmart510_defaults[][3] = {
182 {0x00, 0x00, 0x8211},
183 {0x00, 0x01, 0x82c0},
184 {0x00, 0x10, 0x82cb},
185 {0x00, 0x0f, 0x800d},
186 {0x00, 0x82, 0x8225},
187 {0x00, 0x21, 0x8228},
188 {0x00, 0x00, 0x8203},
189 {0x00, 0x00, 0x8204},
190 {0x00, 0x08, 0x8205},
191 {0x00, 0xf8, 0x8206},
192 {0x00, 0x28, 0x8207},
193 {0x00, 0xa0, 0x8208},
194 {0x00, 0x08, 0x824a},
195 {0x00, 0x08, 0x8214},
196 {0x00, 0x80, 0x82c1},
197 {0x00, 0x00, 0x82c2},
198 {0x00, 0x00, 0x82ca},
199 {0x00, 0x80, 0x82c1},
200 {0x00, 0x04, 0x82c2},
201 {0x00, 0x00, 0x82ca},
202 {0x00, 0xfc, 0x8100},
203 {0x00, 0xfc, 0x8105},
204 {0x00, 0x30, 0x8101},
205 {0x00, 0x00, 0x8102},
206 {0x00, 0x00, 0x8103},
207 {0x00, 0x66, 0x8107},
208 {0x00, 0x00, 0x816b},
209 {0x00, 0x00, 0x8155},
210 {0x00, 0x01, 0x8156},
211 {0x00, 0x60, 0x8157},
212 {0x00, 0x40, 0x8158},
213 {0x00, 0x0a, 0x8159},
214 {0x00, 0x06, 0x815a},
215 {0x00, 0x00, 0x813f},
216 {0x00, 0x00, 0x8200},
217 {0x00, 0x19, 0x8201},
218 {0x00, 0x00, 0x82c1},
219 {0x00, 0xa0, 0x82c2},
220 {0x00, 0x00, 0x82ca},
221 {0x00, 0x00, 0x8117},
222 {0x00, 0x00, 0x8118},
223 {0x00, 0x65, 0x8119},
224 {0x00, 0x00, 0x811a},
225 {0x00, 0x00, 0x811b},
226 {0x00, 0x55, 0x811c},
227 {0x00, 0x65, 0x811d},
228 {0x00, 0x55, 0x811e},
229 {0x00, 0x16, 0x811f},
230 {0x00, 0x19, 0x8120},
231 {0x00, 0x80, 0x8103},
232 {0x00, 0x83, 0x816b},
233 {0x00, 0x25, 0x8168},
234 {0x00, 0x01, 0x820f},
235 {0x00, 0xff, 0x8115},
236 {0x00, 0x48, 0x8116},
237 {0x00, 0x50, 0x8151},
238 {0x00, 0x40, 0x8152},
239 {0x00, 0x78, 0x8153},
240 {0x00, 0x40, 0x8154},
241 {0x00, 0x00, 0x8167},
242 {0x00, 0x20, 0x8168},
243 {0x00, 0x00, 0x816a},
244 {0x00, 0x03, 0x816b},
245 {0x00, 0x20, 0x8169},
246 {0x00, 0x60, 0x8157},
247 {0x00, 0x00, 0x8190},
248 {0x00, 0x00, 0x81a1},
249 {0x00, 0x00, 0x81b2},
250 {0x00, 0x27, 0x8191},
251 {0x00, 0x27, 0x81a2},
252 {0x00, 0x27, 0x81b3},
253 {0x00, 0x4b, 0x8192},
254 {0x00, 0x4b, 0x81a3},
255 {0x00, 0x4b, 0x81b4},
256 {0x00, 0x66, 0x8193},
257 {0x00, 0x66, 0x81a4},
258 {0x00, 0x66, 0x81b5},
259 {0x00, 0x79, 0x8194},
260 {0x00, 0x79, 0x81a5},
261 {0x00, 0x79, 0x81b6},
262 {0x00, 0x8a, 0x8195},
263 {0x00, 0x8a, 0x81a6},
264 {0x00, 0x8a, 0x81b7},
265 {0x00, 0x9b, 0x8196},
266 {0x00, 0x9b, 0x81a7},
267 {0x00, 0x9b, 0x81b8},
268 {0x00, 0xa6, 0x8197},
269 {0x00, 0xa6, 0x81a8},
270 {0x00, 0xa6, 0x81b9},
271 {0x00, 0xb2, 0x8198},
272 {0x00, 0xb2, 0x81a9},
273 {0x00, 0xb2, 0x81ba},
274 {0x00, 0xbe, 0x8199},
275 {0x00, 0xbe, 0x81aa},
276 {0x00, 0xbe, 0x81bb},
277 {0x00, 0xc8, 0x819a},
278 {0x00, 0xc8, 0x81ab},
279 {0x00, 0xc8, 0x81bc},
280 {0x00, 0xd2, 0x819b},
281 {0x00, 0xd2, 0x81ac},
282 {0x00, 0xd2, 0x81bd},
283 {0x00, 0xdb, 0x819c},
284 {0x00, 0xdb, 0x81ad},
285 {0x00, 0xdb, 0x81be},
286 {0x00, 0xe4, 0x819d},
287 {0x00, 0xe4, 0x81ae},
288 {0x00, 0xe4, 0x81bf},
289 {0x00, 0xed, 0x819e},
290 {0x00, 0xed, 0x81af},
291 {0x00, 0xed, 0x81c0},
292 {0x00, 0xf7, 0x819f},
293 {0x00, 0xf7, 0x81b0},
294 {0x00, 0xf7, 0x81c1},
295 {0x00, 0xff, 0x81a0},
296 {0x00, 0xff, 0x81b1},
297 {0x00, 0xff, 0x81c2},
298 {0x00, 0x03, 0x8156},
299 {0x00, 0x00, 0x8211},
300 {0x00, 0x20, 0x8168},
301 {0x00, 0x01, 0x8202},
302 {0x00, 0x30, 0x8101},
303 {0x00, 0x00, 0x8111},
304 {0x00, 0x00, 0x8112},
305 {0x00, 0x00, 0x8113},
306 {0x00, 0x00, 0x8114},
307 {}
308 };
309
310 static const __u8 qtable_creative_pccam[2][64] = {
311 { /* Q-table Y-components */
312 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
313 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
314 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
315 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
316 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
317 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
318 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
319 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
320 { /* Q-table C-components */
321 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
322 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
329 };
330
331 static const __u8 qtable_kodak_ez200[2][64] = {
332 { /* Q-table Y-components */
333 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
334 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
335 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
336 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
337 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
338 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
339 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
340 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
341 { /* Q-table C-components */
342 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
343 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
350 };
351
352 static const __u8 qtable_pocketdv[2][64] = {
353 { /* Q-table Y-components start registers 0x8800 */
354 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
355 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
356 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
357 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
358 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
359 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
360 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
361 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
362 },
363 { /* Q-table C-components start registers 0x8840 */
364 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
365 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
366 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
367 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
372 };
373
374 /* read 'len' bytes to gspca_dev->usb_buf */
375 static void reg_r(struct gspca_dev *gspca_dev,
376 __u16 index,
377 __u16 length)
378 {
379 usb_control_msg(gspca_dev->dev,
380 usb_rcvctrlpipe(gspca_dev->dev, 0),
381 0,
382 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
383 0, /* value */
384 index, gspca_dev->usb_buf, length, 500);
385 }
386
387 static int reg_w(struct gspca_dev *gspca_dev,
388 __u16 req, __u16 index, __u16 value)
389 {
390 int ret;
391
392 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
393 ret = usb_control_msg(gspca_dev->dev,
394 usb_sndctrlpipe(gspca_dev->dev, 0),
395 req,
396 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
397 value, index, NULL, 0, 500);
398 if (ret < 0)
399 PDEBUG(D_ERR, "reg write: error %d", ret);
400 return ret;
401 }
402
403 /* returns: negative is error, pos or zero is data */
404 static int reg_r_12(struct gspca_dev *gspca_dev,
405 __u16 req, /* bRequest */
406 __u16 index, /* wIndex */
407 __u16 length) /* wLength (1 or 2 only) */
408 {
409 int ret;
410
411 gspca_dev->usb_buf[1] = 0;
412 ret = usb_control_msg(gspca_dev->dev,
413 usb_rcvctrlpipe(gspca_dev->dev, 0),
414 req,
415 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
416 0, /* value */
417 index,
418 gspca_dev->usb_buf, length,
419 500); /* timeout */
420 if (ret < 0) {
421 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
422 return -1;
423 }
424 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
425 }
426
427 /*
428 * Simple function to wait for a given 8-bit value to be returned from
429 * a reg_read call.
430 * Returns: negative is error or timeout, zero is success.
431 */
432 static int reg_r_wait(struct gspca_dev *gspca_dev,
433 __u16 reg, __u16 index, __u16 value)
434 {
435 int ret, cnt = 20;
436
437 while (--cnt > 0) {
438 ret = reg_r_12(gspca_dev, reg, index, 1);
439 if (ret == value)
440 return 0;
441 msleep(50);
442 }
443 return -EIO;
444 }
445
446 static int write_vector(struct gspca_dev *gspca_dev,
447 const __u16 data[][3])
448 {
449 int ret, i = 0;
450
451 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
452 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
453 if (ret < 0)
454 return ret;
455 i++;
456 }
457 return 0;
458 }
459
460 static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
461 unsigned int request,
462 unsigned int ybase,
463 unsigned int cbase,
464 const __u8 qtable[2][64])
465 {
466 int i, err;
467
468 /* loop over y components */
469 for (i = 0; i < 64; i++) {
470 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
471 if (err < 0)
472 return err;
473 }
474
475 /* loop over c components */
476 for (i = 0; i < 64; i++) {
477 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
478 if (err < 0)
479 return err;
480 }
481 return 0;
482 }
483
484 static void spca500_ping310(struct gspca_dev *gspca_dev)
485 {
486 reg_r(gspca_dev, 0x0d04, 2);
487 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
488 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
489 }
490
491 static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
492 {
493 reg_r(gspca_dev, 0x0d05, 2);
494 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
495 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
496 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
497 spca500_ping310(gspca_dev);
498
499 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
500 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
501 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
502 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
503 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
504 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
506 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
507 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
508 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
509 /* 00 for adjust shutter */
510 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
511 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
512 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
513 }
514
515 static void spca500_setmode(struct gspca_dev *gspca_dev,
516 __u8 xmult, __u8 ymult)
517 {
518 int mode;
519
520 /* set x multiplier */
521 reg_w(gspca_dev, 0, 0x8001, xmult);
522
523 /* set y multiplier */
524 reg_w(gspca_dev, 0, 0x8002, ymult);
525
526 /* use compressed mode, VGA, with mode specific subsample */
527 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
528 reg_w(gspca_dev, 0, 0x8003, mode << 4);
529 }
530
531 static int spca500_full_reset(struct gspca_dev *gspca_dev)
532 {
533 int err;
534
535 /* send the reset command */
536 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
537 if (err < 0)
538 return err;
539
540 /* wait for the reset to complete */
541 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
542 if (err < 0)
543 return err;
544 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
545 if (err < 0)
546 return err;
547 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
548 if (err < 0) {
549 PDEBUG(D_ERR, "reg_r_wait() failed");
550 return err;
551 }
552 /* all ok */
553 return 0;
554 }
555
556 /* Synchro the Bridge with sensor */
557 /* Maybe that will work on all spca500 chip */
558 /* because i only own a clicksmart310 try for that chip */
559 /* using spca50x_set_packet_size() cause an Ooops here */
560 /* usb_set_interface from kernel 2.6.x clear all the urb stuff */
561 /* up-port the same feature as in 2.4.x kernel */
562 static int spca500_synch310(struct gspca_dev *gspca_dev)
563 {
564 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
565 PDEBUG(D_ERR, "Set packet size: set interface error");
566 goto error;
567 }
568 spca500_ping310(gspca_dev);
569
570 reg_r(gspca_dev, 0x0d00, 1);
571
572 /* need alt setting here */
573 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
574
575 /* Windoze use pipe with altsetting 6 why 7 here */
576 if (usb_set_interface(gspca_dev->dev,
577 gspca_dev->iface,
578 gspca_dev->alt) < 0) {
579 PDEBUG(D_ERR, "Set packet size: set interface error");
580 goto error;
581 }
582 return 0;
583 error:
584 return -EBUSY;
585 }
586
587 static void spca500_reinit(struct gspca_dev *gspca_dev)
588 {
589 int err;
590 __u8 Data;
591
592 /* some unknow command from Aiptek pocket dv and family300 */
593
594 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
595 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
596 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
597
598 /* enable drop packet */
599 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
600
601 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
602 qtable_pocketdv);
603 if (err < 0)
604 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
605
606 /* set qtable index */
607 reg_w(gspca_dev, 0x00, 0x8880, 2);
608 /* family cam Quicksmart stuff */
609 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
610 /* Set agc transfer: synced inbetween frames */
611 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
612 /* Init SDRAM - needed for SDRAM access */
613 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
614 /*Start init sequence or stream */
615 reg_w(gspca_dev, 0, 0x8003, 0x00);
616 /* switch to video camera mode */
617 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
618 msleep(2000);
619 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
620 reg_r(gspca_dev, 0x816b, 1);
621 Data = gspca_dev->usb_buf[0];
622 reg_w(gspca_dev, 0x00, 0x816b, Data);
623 }
624 }
625
626 /* this function is called at probe time */
627 static int sd_config(struct gspca_dev *gspca_dev,
628 const struct usb_device_id *id)
629 {
630 struct sd *sd = (struct sd *) gspca_dev;
631 struct cam *cam;
632
633 cam = &gspca_dev->cam;
634 sd->subtype = id->driver_info;
635 if (sd->subtype != LogitechClickSmart310) {
636 cam->cam_mode = vga_mode;
637 cam->nmodes = ARRAY_SIZE(vga_mode);
638 } else {
639 cam->cam_mode = sif_mode;
640 cam->nmodes = ARRAY_SIZE(sif_mode);
641 }
642 sd->brightness = BRIGHTNESS_DEF;
643 sd->contrast = CONTRAST_DEF;
644 sd->colors = COLOR_DEF;
645 sd->quality = QUALITY_DEF;
646 return 0;
647 }
648
649 /* this function is called at probe and resume time */
650 static int sd_init(struct gspca_dev *gspca_dev)
651 {
652 struct sd *sd = (struct sd *) gspca_dev;
653
654 /* initialisation of spca500 based cameras is deferred */
655 PDEBUG(D_STREAM, "SPCA500 init");
656 if (sd->subtype == LogitechClickSmart310)
657 spca500_clksmart310_init(gspca_dev);
658 /* else
659 spca500_initialise(gspca_dev); */
660 PDEBUG(D_STREAM, "SPCA500 init done");
661 return 0;
662 }
663
664 static int sd_start(struct gspca_dev *gspca_dev)
665 {
666 struct sd *sd = (struct sd *) gspca_dev;
667 int err;
668 __u8 Data;
669 __u8 xmult, ymult;
670
671 /* create the JPEG header */
672 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
673 if (!sd->jpeg_hdr)
674 return -ENOMEM;
675 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
676 0x22); /* JPEG 411 */
677 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
678
679 if (sd->subtype == LogitechClickSmart310) {
680 xmult = 0x16;
681 ymult = 0x12;
682 } else {
683 xmult = 0x28;
684 ymult = 0x1e;
685 }
686
687 /* is there a sensor here ? */
688 reg_r(gspca_dev, 0x8a04, 1);
689 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
690 gspca_dev->usb_buf[0]);
691 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
692 gspca_dev->curr_mode, xmult, ymult);
693
694 /* setup qtable */
695 switch (sd->subtype) {
696 case LogitechClickSmart310:
697 spca500_setmode(gspca_dev, xmult, ymult);
698
699 /* enable drop packet */
700 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
701 reg_w(gspca_dev, 0x00, 0x8880, 3);
702 err = spca50x_setup_qtable(gspca_dev,
703 0x00, 0x8800, 0x8840,
704 qtable_creative_pccam);
705 if (err < 0)
706 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
707 /* Init SDRAM - needed for SDRAM access */
708 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
709
710 /* switch to video camera mode */
711 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
712 msleep(500);
713 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
714 PDEBUG(D_ERR, "reg_r_wait() failed");
715
716 reg_r(gspca_dev, 0x816b, 1);
717 Data = gspca_dev->usb_buf[0];
718 reg_w(gspca_dev, 0x00, 0x816b, Data);
719
720 spca500_synch310(gspca_dev);
721
722 write_vector(gspca_dev, spca500_visual_defaults);
723 spca500_setmode(gspca_dev, xmult, ymult);
724 /* enable drop packet */
725 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
726 if (err < 0)
727 PDEBUG(D_ERR, "failed to enable drop packet");
728 reg_w(gspca_dev, 0x00, 0x8880, 3);
729 err = spca50x_setup_qtable(gspca_dev,
730 0x00, 0x8800, 0x8840,
731 qtable_creative_pccam);
732 if (err < 0)
733 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
734
735 /* Init SDRAM - needed for SDRAM access */
736 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
737
738 /* switch to video camera mode */
739 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
740
741 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
742 PDEBUG(D_ERR, "reg_r_wait() failed");
743
744 reg_r(gspca_dev, 0x816b, 1);
745 Data = gspca_dev->usb_buf[0];
746 reg_w(gspca_dev, 0x00, 0x816b, Data);
747 break;
748 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
749 case IntelPocketPCCamera: /* FIXME: Temporary fix for
750 * Intel Pocket PC Camera
751 * - NWG (Sat 29th March 2003) */
752
753 /* do a full reset */
754 err = spca500_full_reset(gspca_dev);
755 if (err < 0)
756 PDEBUG(D_ERR, "spca500_full_reset failed");
757
758 /* enable drop packet */
759 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
760 if (err < 0)
761 PDEBUG(D_ERR, "failed to enable drop packet");
762 reg_w(gspca_dev, 0x00, 0x8880, 3);
763 err = spca50x_setup_qtable(gspca_dev,
764 0x00, 0x8800, 0x8840,
765 qtable_creative_pccam);
766 if (err < 0)
767 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
768
769 spca500_setmode(gspca_dev, xmult, ymult);
770 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
771
772 /* switch to video camera mode */
773 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
774
775 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
776 PDEBUG(D_ERR, "reg_r_wait() failed");
777
778 reg_r(gspca_dev, 0x816b, 1);
779 Data = gspca_dev->usb_buf[0];
780 reg_w(gspca_dev, 0x00, 0x816b, Data);
781
782 /* write_vector(gspca_dev, spca500_visual_defaults); */
783 break;
784 case KodakEZ200: /* Kodak EZ200 */
785
786 /* do a full reset */
787 err = spca500_full_reset(gspca_dev);
788 if (err < 0)
789 PDEBUG(D_ERR, "spca500_full_reset failed");
790 /* enable drop packet */
791 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
792 reg_w(gspca_dev, 0x00, 0x8880, 0);
793 err = spca50x_setup_qtable(gspca_dev,
794 0x00, 0x8800, 0x8840,
795 qtable_kodak_ez200);
796 if (err < 0)
797 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
798 spca500_setmode(gspca_dev, xmult, ymult);
799
800 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
801
802 /* switch to video camera mode */
803 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
804
805 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
806 PDEBUG(D_ERR, "reg_r_wait() failed");
807
808 reg_r(gspca_dev, 0x816b, 1);
809 Data = gspca_dev->usb_buf[0];
810 reg_w(gspca_dev, 0x00, 0x816b, Data);
811
812 /* write_vector(gspca_dev, spca500_visual_defaults); */
813 break;
814
815 case BenqDC1016:
816 case DLinkDSC350: /* FamilyCam 300 */
817 case AiptekPocketDV: /* Aiptek PocketDV */
818 case Gsmartmini: /*Mustek Gsmart Mini */
819 case MustekGsmart300: /* Mustek Gsmart 300 */
820 case PalmPixDC85:
821 case Optimedia:
822 case ToptroIndus:
823 case AgfaCl20:
824 spca500_reinit(gspca_dev);
825 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
826 /* enable drop packet */
827 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
828
829 err = spca50x_setup_qtable(gspca_dev,
830 0x00, 0x8800, 0x8840, qtable_pocketdv);
831 if (err < 0)
832 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
833 reg_w(gspca_dev, 0x00, 0x8880, 2);
834
835 /* familycam Quicksmart pocketDV stuff */
836 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
837 /* Set agc transfer: synced inbetween frames */
838 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
839 /* Init SDRAM - needed for SDRAM access */
840 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
841
842 spca500_setmode(gspca_dev, xmult, ymult);
843 /* switch to video camera mode */
844 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
845
846 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
847
848 reg_r(gspca_dev, 0x816b, 1);
849 Data = gspca_dev->usb_buf[0];
850 reg_w(gspca_dev, 0x00, 0x816b, Data);
851 break;
852 case LogitechTraveler:
853 case LogitechClickSmart510:
854 reg_w(gspca_dev, 0x02, 0x00, 0x00);
855 /* enable drop packet */
856 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
857
858 err = spca50x_setup_qtable(gspca_dev,
859 0x00, 0x8800,
860 0x8840, qtable_creative_pccam);
861 if (err < 0)
862 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
863 reg_w(gspca_dev, 0x00, 0x8880, 3);
864 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
865 /* Init SDRAM - needed for SDRAM access */
866 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
867
868 spca500_setmode(gspca_dev, xmult, ymult);
869
870 /* switch to video camera mode */
871 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
872 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
873
874 reg_r(gspca_dev, 0x816b, 1);
875 Data = gspca_dev->usb_buf[0];
876 reg_w(gspca_dev, 0x00, 0x816b, Data);
877 write_vector(gspca_dev, Clicksmart510_defaults);
878 break;
879 }
880 return 0;
881 }
882
883 static void sd_stopN(struct gspca_dev *gspca_dev)
884 {
885 reg_w(gspca_dev, 0, 0x8003, 0x00);
886
887 /* switch to video camera mode */
888 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
889 reg_r(gspca_dev, 0x8000, 1);
890 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
891 gspca_dev->usb_buf[0]);
892 }
893
894 static void sd_stop0(struct gspca_dev *gspca_dev)
895 {
896 struct sd *sd = (struct sd *) gspca_dev;
897
898 kfree(sd->jpeg_hdr);
899 }
900
901 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
902 struct gspca_frame *frame, /* target */
903 __u8 *data, /* isoc packet */
904 int len) /* iso packet length */
905 {
906 struct sd *sd = (struct sd *) gspca_dev;
907 int i;
908 static __u8 ffd9[] = {0xff, 0xd9};
909
910 /* frames are jpeg 4.1.1 without 0xff escape */
911 if (data[0] == 0xff) {
912 if (data[1] != 0x01) { /* drop packet */
913 /* gspca_dev->last_packet_type = DISCARD_PACKET; */
914 return;
915 }
916 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
917 ffd9, 2);
918
919 /* put the JPEG header in the new frame */
920 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
921 sd->jpeg_hdr, JPEG_HDR_SZ);
922
923 data += SPCA500_OFFSET_DATA;
924 len -= SPCA500_OFFSET_DATA;
925 } else {
926 data += 1;
927 len -= 1;
928 }
929
930 /* add 0x00 after 0xff */
931 i = 0;
932 do {
933 if (data[i] == 0xff) {
934 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
935 data, i + 1);
936 len -= i;
937 data += i;
938 *data = 0x00;
939 i = 0;
940 }
941 i++;
942 } while (i < len);
943 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
944 }
945
946 static void setbrightness(struct gspca_dev *gspca_dev)
947 {
948 struct sd *sd = (struct sd *) gspca_dev;
949
950 reg_w(gspca_dev, 0x00, 0x8167,
951 (__u8) (sd->brightness - 128));
952 }
953
954 static void setcontrast(struct gspca_dev *gspca_dev)
955 {
956 struct sd *sd = (struct sd *) gspca_dev;
957
958 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
959 }
960
961 static void setcolors(struct gspca_dev *gspca_dev)
962 {
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
966 }
967
968 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
969 {
970 struct sd *sd = (struct sd *) gspca_dev;
971
972 sd->brightness = val;
973 if (gspca_dev->streaming)
974 setbrightness(gspca_dev);
975 return 0;
976 }
977
978 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
979 {
980 struct sd *sd = (struct sd *) gspca_dev;
981
982 *val = sd->brightness;
983 return 0;
984 }
985
986 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
987 {
988 struct sd *sd = (struct sd *) gspca_dev;
989
990 sd->contrast = val;
991 if (gspca_dev->streaming)
992 setcontrast(gspca_dev);
993 return 0;
994 }
995
996 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
997 {
998 struct sd *sd = (struct sd *) gspca_dev;
999
1000 *val = sd->contrast;
1001 return 0;
1002 }
1003
1004 static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1005 {
1006 struct sd *sd = (struct sd *) gspca_dev;
1007
1008 sd->colors = val;
1009 if (gspca_dev->streaming)
1010 setcolors(gspca_dev);
1011 return 0;
1012 }
1013
1014 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1015 {
1016 struct sd *sd = (struct sd *) gspca_dev;
1017
1018 *val = sd->colors;
1019 return 0;
1020 }
1021
1022 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
1023 struct v4l2_jpegcompression *jcomp)
1024 {
1025 struct sd *sd = (struct sd *) gspca_dev;
1026
1027 if (jcomp->quality < QUALITY_MIN)
1028 sd->quality = QUALITY_MIN;
1029 else if (jcomp->quality > QUALITY_MAX)
1030 sd->quality = QUALITY_MAX;
1031 else
1032 sd->quality = jcomp->quality;
1033 if (gspca_dev->streaming)
1034 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
1035 return 0;
1036 }
1037
1038 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
1039 struct v4l2_jpegcompression *jcomp)
1040 {
1041 struct sd *sd = (struct sd *) gspca_dev;
1042
1043 memset(jcomp, 0, sizeof *jcomp);
1044 jcomp->quality = sd->quality;
1045 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
1046 | V4L2_JPEG_MARKER_DQT;
1047 return 0;
1048 }
1049
1050 /* sub-driver description */
1051 static struct sd_desc sd_desc = {
1052 .name = MODULE_NAME,
1053 .ctrls = sd_ctrls,
1054 .nctrls = ARRAY_SIZE(sd_ctrls),
1055 .config = sd_config,
1056 .init = sd_init,
1057 .start = sd_start,
1058 .stopN = sd_stopN,
1059 .stop0 = sd_stop0,
1060 .pkt_scan = sd_pkt_scan,
1061 .get_jcomp = sd_get_jcomp,
1062 .set_jcomp = sd_set_jcomp,
1063 };
1064
1065 /* -- module initialisation -- */
1066 static const __devinitdata struct usb_device_id device_table[] = {
1067 {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
1068 {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
1069 {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
1070 {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
1071 {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
1072 {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
1073 {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
1074 {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
1075 {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
1076 {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
1077 {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
1078 {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
1079 {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
1080 {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
1081 {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
1082 {}
1083 };
1084 MODULE_DEVICE_TABLE(usb, device_table);
1085
1086 /* -- device connect -- */
1087 static int sd_probe(struct usb_interface *intf,
1088 const struct usb_device_id *id)
1089 {
1090 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1091 THIS_MODULE);
1092 }
1093
1094 static struct usb_driver sd_driver = {
1095 .name = MODULE_NAME,
1096 .id_table = device_table,
1097 .probe = sd_probe,
1098 .disconnect = gspca_disconnect,
1099 #ifdef CONFIG_PM
1100 .suspend = gspca_suspend,
1101 .resume = gspca_resume,
1102 #endif
1103 };
1104
1105 /* -- module insert / remove -- */
1106 static int __init sd_mod_init(void)
1107 {
1108 int ret;
1109 ret = usb_register(&sd_driver);
1110 if (ret < 0)
1111 return ret;
1112 PDEBUG(D_PROBE, "registered");
1113 return 0;
1114 }
1115 static void __exit sd_mod_exit(void)
1116 {
1117 usb_deregister(&sd_driver);
1118 PDEBUG(D_PROBE, "deregistered");
1119 }
1120
1121 module_init(sd_mod_init);
1122 module_exit(sd_mod_exit);
This page took 0.077159 seconds and 6 git commands to generate.