1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Mars MR97310A library |
4 | * |
5 | * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is |
6 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> |
7 | * |
8 | * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ |
9 | * and for the routines for detecting and classifying these various cameras, |
10 | * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> |
11 | * |
12 | * Support for the control settings for the CIF cameras is |
13 | * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and |
14 | * Thomas Kaiser <thomas@kaiser-linux.li> |
15 | * |
16 | * Support for the control settings for the VGA cameras is |
17 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> |
18 | * |
19 | * Several previously unsupported cameras are owned and have been tested by |
20 | * Hans de Goede <hdegoede@redhat.com> and |
21 | * Thomas Kaiser <thomas@kaiser-linux.li> and |
22 | * Theodore Kilgore <kilgota@auburn.edu> and |
23 | * Edmond Rodriguez <erodrig_97@yahoo.com> and |
24 | * Aurelien Jacobs <aurel@gnuage.org> |
25 | * |
26 | * The MR97311A support in gspca/mars.c has been helpful in understanding some |
27 | * of the registers in these cameras. |
28 | */ |
29 | |
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
31 | |
32 | #define MODULE_NAME "mr97310a" |
33 | |
34 | #include "gspca.h" |
35 | |
36 | #define CAM_TYPE_CIF 0 |
37 | #define CAM_TYPE_VGA 1 |
38 | |
39 | #define MR97310A_BRIGHTNESS_DEFAULT 0 |
40 | |
41 | #define MR97310A_EXPOSURE_MIN 0 |
42 | #define MR97310A_EXPOSURE_MAX 4095 |
43 | #define MR97310A_EXPOSURE_DEFAULT 1000 |
44 | |
45 | #define MR97310A_GAIN_MIN 0 |
46 | #define MR97310A_GAIN_MAX 31 |
47 | #define MR97310A_GAIN_DEFAULT 25 |
48 | |
49 | #define MR97310A_CONTRAST_MIN 0 |
50 | #define MR97310A_CONTRAST_MAX 31 |
51 | #define MR97310A_CONTRAST_DEFAULT 23 |
52 | |
53 | #define MR97310A_CS_GAIN_MIN 0 |
54 | #define MR97310A_CS_GAIN_MAX 0x7ff |
55 | #define MR97310A_CS_GAIN_DEFAULT 0x110 |
56 | |
57 | #define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000) |
58 | #define MR97310A_MIN_CLOCKDIV_MIN 3 |
59 | #define MR97310A_MIN_CLOCKDIV_MAX 8 |
60 | #define MR97310A_MIN_CLOCKDIV_DEFAULT 3 |
61 | |
62 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,Theodore Kilgore <kilgota@auburn.edu>" ); |
63 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver" ); |
64 | MODULE_LICENSE("GPL" ); |
65 | |
66 | /* global parameters */ |
67 | static int force_sensor_type = -1; |
68 | module_param(force_sensor_type, int, 0644); |
69 | MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)" ); |
70 | |
71 | /* specific webcam descriptor */ |
72 | struct sd { |
73 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
74 | struct { /* exposure/min_clockdiv control cluster */ |
75 | struct v4l2_ctrl *exposure; |
76 | struct v4l2_ctrl *min_clockdiv; |
77 | }; |
78 | u8 sof_read; |
79 | u8 cam_type; /* 0 is CIF and 1 is VGA */ |
80 | u8 sensor_type; /* We use 0 and 1 here, too. */ |
81 | u8 do_lcd_stop; |
82 | u8 adj_colors; |
83 | }; |
84 | |
85 | struct sensor_w_data { |
86 | u8 reg; |
87 | u8 flags; |
88 | u8 data[16]; |
89 | int len; |
90 | }; |
91 | |
92 | static void sd_stopN(struct gspca_dev *gspca_dev); |
93 | |
94 | static const struct v4l2_pix_format vga_mode[] = { |
95 | {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
96 | .bytesperline = 160, |
97 | .sizeimage = 160 * 120, |
98 | .colorspace = V4L2_COLORSPACE_SRGB, |
99 | .priv = 4}, |
100 | {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
101 | .bytesperline = 176, |
102 | .sizeimage = 176 * 144, |
103 | .colorspace = V4L2_COLORSPACE_SRGB, |
104 | .priv = 3}, |
105 | {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
106 | .bytesperline = 320, |
107 | .sizeimage = 320 * 240, |
108 | .colorspace = V4L2_COLORSPACE_SRGB, |
109 | .priv = 2}, |
110 | {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
111 | .bytesperline = 352, |
112 | .sizeimage = 352 * 288, |
113 | .colorspace = V4L2_COLORSPACE_SRGB, |
114 | .priv = 1}, |
115 | {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE, |
116 | .bytesperline = 640, |
117 | .sizeimage = 640 * 480, |
118 | .colorspace = V4L2_COLORSPACE_SRGB, |
119 | .priv = 0}, |
120 | }; |
121 | |
122 | /* the bytes to write are in gspca_dev->usb_buf */ |
123 | static int mr_write(struct gspca_dev *gspca_dev, int len) |
124 | { |
125 | int rc; |
126 | |
127 | rc = usb_bulk_msg(usb_dev: gspca_dev->dev, |
128 | usb_sndbulkpipe(gspca_dev->dev, 4), |
129 | data: gspca_dev->usb_buf, len, NULL, timeout: 500); |
130 | if (rc < 0) |
131 | pr_err("reg write [%02x] error %d\n" , |
132 | gspca_dev->usb_buf[0], rc); |
133 | return rc; |
134 | } |
135 | |
136 | /* the bytes are read into gspca_dev->usb_buf */ |
137 | static int mr_read(struct gspca_dev *gspca_dev, int len) |
138 | { |
139 | int rc; |
140 | |
141 | rc = usb_bulk_msg(usb_dev: gspca_dev->dev, |
142 | usb_rcvbulkpipe(gspca_dev->dev, 3), |
143 | data: gspca_dev->usb_buf, len, NULL, timeout: 500); |
144 | if (rc < 0) |
145 | pr_err("reg read [%02x] error %d\n" , |
146 | gspca_dev->usb_buf[0], rc); |
147 | return rc; |
148 | } |
149 | |
150 | static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags, |
151 | const u8 *data, int len) |
152 | { |
153 | gspca_dev->usb_buf[0] = 0x1f; |
154 | gspca_dev->usb_buf[1] = flags; |
155 | gspca_dev->usb_buf[2] = reg; |
156 | memcpy(gspca_dev->usb_buf + 3, data, len); |
157 | |
158 | return mr_write(gspca_dev, len: len + 3); |
159 | } |
160 | |
161 | static int sensor_write_regs(struct gspca_dev *gspca_dev, |
162 | const struct sensor_w_data *data, int len) |
163 | { |
164 | int i, rc; |
165 | |
166 | for (i = 0; i < len; i++) { |
167 | rc = sensor_write_reg(gspca_dev, reg: data[i].reg, flags: data[i].flags, |
168 | data: data[i].data, len: data[i].len); |
169 | if (rc < 0) |
170 | return rc; |
171 | } |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) |
177 | { |
178 | struct sd *sd = (struct sd *) gspca_dev; |
179 | u8 buf, confirm_reg; |
180 | int rc; |
181 | |
182 | buf = data; |
183 | if (sd->cam_type == CAM_TYPE_CIF) { |
184 | rc = sensor_write_reg(gspca_dev, reg, flags: 0x01, data: &buf, len: 1); |
185 | confirm_reg = sd->sensor_type ? 0x13 : 0x11; |
186 | } else { |
187 | rc = sensor_write_reg(gspca_dev, reg, flags: 0x00, data: &buf, len: 1); |
188 | confirm_reg = 0x11; |
189 | } |
190 | if (rc < 0) |
191 | return rc; |
192 | |
193 | buf = 0x01; |
194 | rc = sensor_write_reg(gspca_dev, reg: confirm_reg, flags: 0x00, data: &buf, len: 1); |
195 | if (rc < 0) |
196 | return rc; |
197 | |
198 | return 0; |
199 | } |
200 | |
201 | static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose) |
202 | { |
203 | int err_code; |
204 | |
205 | gspca_dev->usb_buf[0] = reg; |
206 | err_code = mr_write(gspca_dev, len: 1); |
207 | if (err_code < 0) |
208 | return err_code; |
209 | |
210 | err_code = mr_read(gspca_dev, len: 16); |
211 | if (err_code < 0) |
212 | return err_code; |
213 | |
214 | if (verbose) |
215 | gspca_dbg(gspca_dev, D_PROBE, "Register: %02x reads %02x%02x%02x\n" , |
216 | reg, |
217 | gspca_dev->usb_buf[0], |
218 | gspca_dev->usb_buf[1], |
219 | gspca_dev->usb_buf[2]); |
220 | |
221 | return 0; |
222 | } |
223 | |
224 | static int zero_the_pointer(struct gspca_dev *gspca_dev) |
225 | { |
226 | __u8 *data = gspca_dev->usb_buf; |
227 | int err_code; |
228 | u8 status = 0; |
229 | int tries = 0; |
230 | |
231 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
232 | if (err_code < 0) |
233 | return err_code; |
234 | |
235 | data[0] = 0x19; |
236 | data[1] = 0x51; |
237 | err_code = mr_write(gspca_dev, len: 2); |
238 | if (err_code < 0) |
239 | return err_code; |
240 | |
241 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
242 | if (err_code < 0) |
243 | return err_code; |
244 | |
245 | data[0] = 0x19; |
246 | data[1] = 0xba; |
247 | err_code = mr_write(gspca_dev, len: 2); |
248 | if (err_code < 0) |
249 | return err_code; |
250 | |
251 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
252 | if (err_code < 0) |
253 | return err_code; |
254 | |
255 | data[0] = 0x19; |
256 | data[1] = 0x00; |
257 | err_code = mr_write(gspca_dev, len: 2); |
258 | if (err_code < 0) |
259 | return err_code; |
260 | |
261 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
262 | if (err_code < 0) |
263 | return err_code; |
264 | |
265 | data[0] = 0x19; |
266 | data[1] = 0x00; |
267 | err_code = mr_write(gspca_dev, len: 2); |
268 | if (err_code < 0) |
269 | return err_code; |
270 | |
271 | while (status != 0x0a && tries < 256) { |
272 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
273 | status = data[0]; |
274 | tries++; |
275 | if (err_code < 0) |
276 | return err_code; |
277 | } |
278 | if (status != 0x0a) |
279 | gspca_err(gspca_dev, "status is %02x\n" , status); |
280 | |
281 | tries = 0; |
282 | while (tries < 4) { |
283 | data[0] = 0x19; |
284 | data[1] = 0x00; |
285 | err_code = mr_write(gspca_dev, len: 2); |
286 | if (err_code < 0) |
287 | return err_code; |
288 | |
289 | err_code = cam_get_response16(gspca_dev, reg: 0x21, verbose: 0); |
290 | tries++; |
291 | if (err_code < 0) |
292 | return err_code; |
293 | } |
294 | |
295 | data[0] = 0x19; |
296 | err_code = mr_write(gspca_dev, len: 1); |
297 | if (err_code < 0) |
298 | return err_code; |
299 | |
300 | err_code = mr_read(gspca_dev, len: 16); |
301 | if (err_code < 0) |
302 | return err_code; |
303 | |
304 | return 0; |
305 | } |
306 | |
307 | static int stream_start(struct gspca_dev *gspca_dev) |
308 | { |
309 | gspca_dev->usb_buf[0] = 0x01; |
310 | gspca_dev->usb_buf[1] = 0x01; |
311 | return mr_write(gspca_dev, len: 2); |
312 | } |
313 | |
314 | static void stream_stop(struct gspca_dev *gspca_dev) |
315 | { |
316 | gspca_dev->usb_buf[0] = 0x01; |
317 | gspca_dev->usb_buf[1] = 0x00; |
318 | if (mr_write(gspca_dev, len: 2) < 0) |
319 | gspca_err(gspca_dev, "Stream Stop failed\n" ); |
320 | } |
321 | |
322 | static void lcd_stop(struct gspca_dev *gspca_dev) |
323 | { |
324 | gspca_dev->usb_buf[0] = 0x19; |
325 | gspca_dev->usb_buf[1] = 0x54; |
326 | if (mr_write(gspca_dev, len: 2) < 0) |
327 | gspca_err(gspca_dev, "LCD Stop failed\n" ); |
328 | } |
329 | |
330 | static int isoc_enable(struct gspca_dev *gspca_dev) |
331 | { |
332 | gspca_dev->usb_buf[0] = 0x00; |
333 | gspca_dev->usb_buf[1] = 0x4d; /* ISOC transferring enable... */ |
334 | return mr_write(gspca_dev, len: 2); |
335 | } |
336 | |
337 | /* This function is called at probe time */ |
338 | static int sd_config(struct gspca_dev *gspca_dev, |
339 | const struct usb_device_id *id) |
340 | { |
341 | struct sd *sd = (struct sd *) gspca_dev; |
342 | struct cam *cam; |
343 | int err_code; |
344 | |
345 | cam = &gspca_dev->cam; |
346 | cam->cam_mode = vga_mode; |
347 | cam->nmodes = ARRAY_SIZE(vga_mode); |
348 | sd->do_lcd_stop = 0; |
349 | |
350 | /* Several of the supported CIF cameras share the same USB ID but |
351 | * require different initializations and different control settings. |
352 | * The same is true of the VGA cameras. Therefore, we are forced |
353 | * to start the initialization process in order to determine which |
354 | * camera is present. Some of the supported cameras require the |
355 | * memory pointer to be set to 0 as the very first item of business |
356 | * or else they will not stream. So we do that immediately. |
357 | */ |
358 | err_code = zero_the_pointer(gspca_dev); |
359 | if (err_code < 0) |
360 | return err_code; |
361 | |
362 | err_code = stream_start(gspca_dev); |
363 | if (err_code < 0) |
364 | return err_code; |
365 | |
366 | /* Now, the query for sensor type. */ |
367 | err_code = cam_get_response16(gspca_dev, reg: 0x07, verbose: 1); |
368 | if (err_code < 0) |
369 | return err_code; |
370 | |
371 | if (id->idProduct == 0x0110 || id->idProduct == 0x010e) { |
372 | sd->cam_type = CAM_TYPE_CIF; |
373 | cam->nmodes--; |
374 | /* |
375 | * All but one of the known CIF cameras share the same USB ID, |
376 | * but two different init routines are in use, and the control |
377 | * settings are different, too. We need to detect which camera |
378 | * of the two known varieties is connected! |
379 | * |
380 | * A list of known CIF cameras follows. They all report either |
381 | * 0200 for type 0 or 0300 for type 1. |
382 | * If you have another to report, please do |
383 | * |
384 | * Name sd->sensor_type reported by |
385 | * |
386 | * Sakar 56379 Spy-shot 0 T. Kilgore |
387 | * Innovage 0 T. Kilgore |
388 | * Vivitar Mini 0 H. De Goede |
389 | * Vivitar Mini 0 E. Rodriguez |
390 | * Vivitar Mini 1 T. Kilgore |
391 | * Elta-Media 8212dc 1 T. Kaiser |
392 | * Philips dig. keych. 1 T. Kilgore |
393 | * Trust Spyc@m 100 1 A. Jacobs |
394 | */ |
395 | switch (gspca_dev->usb_buf[0]) { |
396 | case 2: |
397 | sd->sensor_type = 0; |
398 | break; |
399 | case 3: |
400 | sd->sensor_type = 1; |
401 | break; |
402 | default: |
403 | pr_err("Unknown CIF Sensor id : %02x\n" , |
404 | gspca_dev->usb_buf[1]); |
405 | return -ENODEV; |
406 | } |
407 | gspca_dbg(gspca_dev, D_PROBE, "MR97310A CIF camera detected, sensor: %d\n" , |
408 | sd->sensor_type); |
409 | } else { |
410 | sd->cam_type = CAM_TYPE_VGA; |
411 | |
412 | /* |
413 | * Here is a table of the responses to the query for sensor |
414 | * type, from the known MR97310A VGA cameras. Six different |
415 | * cameras of which five share the same USB ID. |
416 | * |
417 | * Name gspca_dev->usb_buf[] sd->sensor_type |
418 | * sd->do_lcd_stop |
419 | * Aiptek Pencam VGA+ 0300 0 1 |
420 | * ION digital 0300 0 1 |
421 | * Argus DC-1620 0450 1 0 |
422 | * Argus QuickClix 0420 1 1 |
423 | * Sakar 77379 Digital 0350 0 1 |
424 | * Sakar 1638x CyberPix 0120 0 2 |
425 | * |
426 | * Based upon these results, we assume default settings |
427 | * and then correct as necessary, as follows. |
428 | * |
429 | */ |
430 | |
431 | sd->sensor_type = 1; |
432 | sd->do_lcd_stop = 0; |
433 | sd->adj_colors = 0; |
434 | if (gspca_dev->usb_buf[0] == 0x01) { |
435 | sd->sensor_type = 2; |
436 | } else if ((gspca_dev->usb_buf[0] != 0x03) && |
437 | (gspca_dev->usb_buf[0] != 0x04)) { |
438 | pr_err("Unknown VGA Sensor id Byte 0: %02x\n" , |
439 | gspca_dev->usb_buf[0]); |
440 | pr_err("Defaults assumed, may not work\n" ); |
441 | pr_err("Please report this\n" ); |
442 | } |
443 | /* Sakar Digital color needs to be adjusted. */ |
444 | if ((gspca_dev->usb_buf[0] == 0x03) && |
445 | (gspca_dev->usb_buf[1] == 0x50)) |
446 | sd->adj_colors = 1; |
447 | if (gspca_dev->usb_buf[0] == 0x04) { |
448 | sd->do_lcd_stop = 1; |
449 | switch (gspca_dev->usb_buf[1]) { |
450 | case 0x50: |
451 | sd->sensor_type = 0; |
452 | gspca_dbg(gspca_dev, D_PROBE, "sensor_type corrected to 0\n" ); |
453 | break; |
454 | case 0x20: |
455 | /* Nothing to do here. */ |
456 | break; |
457 | default: |
458 | pr_err("Unknown VGA Sensor id Byte 1: %02x\n" , |
459 | gspca_dev->usb_buf[1]); |
460 | pr_err("Defaults assumed, may not work\n" ); |
461 | pr_err("Please report this\n" ); |
462 | } |
463 | } |
464 | gspca_dbg(gspca_dev, D_PROBE, "MR97310A VGA camera detected, sensor: %d\n" , |
465 | sd->sensor_type); |
466 | } |
467 | /* Stop streaming as we've started it only to probe the sensor type. */ |
468 | sd_stopN(gspca_dev); |
469 | |
470 | if (force_sensor_type != -1) { |
471 | sd->sensor_type = !!force_sensor_type; |
472 | gspca_dbg(gspca_dev, D_PROBE, "Forcing sensor type to: %d\n" , |
473 | sd->sensor_type); |
474 | } |
475 | |
476 | return 0; |
477 | } |
478 | |
479 | /* this function is called at probe and resume time */ |
480 | static int sd_init(struct gspca_dev *gspca_dev) |
481 | { |
482 | return 0; |
483 | } |
484 | |
485 | static int start_cif_cam(struct gspca_dev *gspca_dev) |
486 | { |
487 | struct sd *sd = (struct sd *) gspca_dev; |
488 | __u8 *data = gspca_dev->usb_buf; |
489 | int err_code; |
490 | static const __u8 startup_string[] = { |
491 | 0x00, |
492 | 0x0d, |
493 | 0x01, |
494 | 0x00, /* Hsize/8 for 352 or 320 */ |
495 | 0x00, /* Vsize/4 for 288 or 240 */ |
496 | 0x13, /* or 0xbb, depends on sensor */ |
497 | 0x00, /* Hstart, depends on res. */ |
498 | 0x00, /* reserved ? */ |
499 | 0x00, /* Vstart, depends on res. and sensor */ |
500 | 0x50, /* 0x54 to get 176 or 160 */ |
501 | 0xc0 |
502 | }; |
503 | |
504 | /* Note: Some of the above descriptions guessed from MR97113A driver */ |
505 | |
506 | memcpy(data, startup_string, 11); |
507 | if (sd->sensor_type) |
508 | data[5] = 0xbb; |
509 | |
510 | switch (gspca_dev->pixfmt.width) { |
511 | case 160: |
512 | data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */ |
513 | fallthrough; |
514 | case 320: |
515 | default: |
516 | data[3] = 0x28; /* reg 2, H size/8 */ |
517 | data[4] = 0x3c; /* reg 3, V size/4 */ |
518 | data[6] = 0x14; /* reg 5, H start */ |
519 | data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ |
520 | break; |
521 | case 176: |
522 | data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */ |
523 | fallthrough; |
524 | case 352: |
525 | data[3] = 0x2c; /* reg 2, H size/8 */ |
526 | data[4] = 0x48; /* reg 3, V size/4 */ |
527 | data[6] = 0x06; /* reg 5, H start */ |
528 | data[8] = 0x06 - sd->sensor_type; /* reg 7, V start */ |
529 | break; |
530 | } |
531 | err_code = mr_write(gspca_dev, len: 11); |
532 | if (err_code < 0) |
533 | return err_code; |
534 | |
535 | if (!sd->sensor_type) { |
536 | static const struct sensor_w_data cif_sensor0_init_data[] = { |
537 | {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01, |
538 | 0x0f, 0x14, 0x0f, 0x10}, 8}, |
539 | {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5}, |
540 | {0x12, 0x00, {0x07}, 1}, |
541 | {0x1f, 0x00, {0x06}, 1}, |
542 | {0x27, 0x00, {0x04}, 1}, |
543 | {0x29, 0x00, {0x0c}, 1}, |
544 | {0x40, 0x00, {0x40, 0x00, 0x04}, 3}, |
545 | {0x50, 0x00, {0x60}, 1}, |
546 | {0x60, 0x00, {0x06}, 1}, |
547 | {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6}, |
548 | {0x72, 0x00, {0x1e, 0x56}, 2}, |
549 | {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02, |
550 | 0x31, 0x80, 0x00}, 9}, |
551 | {0x11, 0x00, {0x01}, 1}, |
552 | {0, 0, {0}, 0} |
553 | }; |
554 | err_code = sensor_write_regs(gspca_dev, data: cif_sensor0_init_data, |
555 | ARRAY_SIZE(cif_sensor0_init_data)); |
556 | } else { /* sd->sensor_type = 1 */ |
557 | static const struct sensor_w_data cif_sensor1_init_data[] = { |
558 | /* Reg 3,4, 7,8 get set by the controls */ |
559 | {0x02, 0x00, {0x10}, 1}, |
560 | {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */ |
561 | {0x06, 0x01, {0x00}, 1}, |
562 | {0x09, 0x02, {0x0e}, 1}, |
563 | {0x0a, 0x02, {0x05}, 1}, |
564 | {0x0b, 0x02, {0x05}, 1}, |
565 | {0x0c, 0x02, {0x0f}, 1}, |
566 | {0x0d, 0x02, {0x07}, 1}, |
567 | {0x0e, 0x02, {0x0c}, 1}, |
568 | {0x0f, 0x00, {0x00}, 1}, |
569 | {0x10, 0x00, {0x06}, 1}, |
570 | {0x11, 0x00, {0x07}, 1}, |
571 | {0x12, 0x00, {0x00}, 1}, |
572 | {0x13, 0x00, {0x01}, 1}, |
573 | {0, 0, {0}, 0} |
574 | }; |
575 | /* Without this command the cam won't work with USB-UHCI */ |
576 | gspca_dev->usb_buf[0] = 0x0a; |
577 | gspca_dev->usb_buf[1] = 0x00; |
578 | err_code = mr_write(gspca_dev, len: 2); |
579 | if (err_code < 0) |
580 | return err_code; |
581 | err_code = sensor_write_regs(gspca_dev, data: cif_sensor1_init_data, |
582 | ARRAY_SIZE(cif_sensor1_init_data)); |
583 | } |
584 | return err_code; |
585 | } |
586 | |
587 | static int start_vga_cam(struct gspca_dev *gspca_dev) |
588 | { |
589 | struct sd *sd = (struct sd *) gspca_dev; |
590 | __u8 *data = gspca_dev->usb_buf; |
591 | int err_code; |
592 | static const __u8 startup_string[] = |
593 | {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00, |
594 | 0x00, 0x50, 0xc0}; |
595 | /* What some of these mean is explained in start_cif_cam(), above */ |
596 | |
597 | memcpy(data, startup_string, 11); |
598 | if (!sd->sensor_type) { |
599 | data[5] = 0x00; |
600 | data[10] = 0x91; |
601 | } |
602 | if (sd->sensor_type == 2) { |
603 | data[5] = 0x00; |
604 | data[10] = 0x18; |
605 | } |
606 | |
607 | switch (gspca_dev->pixfmt.width) { |
608 | case 160: |
609 | data[9] |= 0x0c; /* reg 8, 4:1 scale down */ |
610 | fallthrough; |
611 | case 320: |
612 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ |
613 | fallthrough; |
614 | case 640: |
615 | default: |
616 | data[3] = 0x50; /* reg 2, H size/8 */ |
617 | data[4] = 0x78; /* reg 3, V size/4 */ |
618 | data[6] = 0x04; /* reg 5, H start */ |
619 | data[8] = 0x03; /* reg 7, V start */ |
620 | if (sd->sensor_type == 2) { |
621 | data[6] = 2; |
622 | data[8] = 1; |
623 | } |
624 | if (sd->do_lcd_stop) |
625 | data[8] = 0x04; /* Bayer tile shifted */ |
626 | break; |
627 | |
628 | case 176: |
629 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ |
630 | fallthrough; |
631 | case 352: |
632 | data[3] = 0x2c; /* reg 2, H size */ |
633 | data[4] = 0x48; /* reg 3, V size */ |
634 | data[6] = 0x94; /* reg 5, H start */ |
635 | data[8] = 0x63; /* reg 7, V start */ |
636 | if (sd->do_lcd_stop) |
637 | data[8] = 0x64; /* Bayer tile shifted */ |
638 | break; |
639 | } |
640 | |
641 | err_code = mr_write(gspca_dev, len: 11); |
642 | if (err_code < 0) |
643 | return err_code; |
644 | |
645 | if (!sd->sensor_type) { |
646 | static const struct sensor_w_data vga_sensor0_init_data[] = { |
647 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
648 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
649 | {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4}, |
650 | {0x25, 0x00, {0x03, 0xa9, 0x80}, 3}, |
651 | {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4}, |
652 | {0, 0, {0}, 0} |
653 | }; |
654 | err_code = sensor_write_regs(gspca_dev, data: vga_sensor0_init_data, |
655 | ARRAY_SIZE(vga_sensor0_init_data)); |
656 | } else if (sd->sensor_type == 1) { |
657 | static const struct sensor_w_data color_adj[] = { |
658 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
659 | /* adjusted blue, green, red gain correct |
660 | too much blue from the Sakar Digital */ |
661 | 0x05, 0x01, 0x04}, 8} |
662 | }; |
663 | |
664 | static const struct sensor_w_data color_no_adj[] = { |
665 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, |
666 | /* default blue, green, red gain settings */ |
667 | 0x07, 0x00, 0x01}, 8} |
668 | }; |
669 | |
670 | static const struct sensor_w_data vga_sensor1_init_data[] = { |
671 | {0x11, 0x04, {0x01}, 1}, |
672 | {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, |
673 | /* These settings may be better for some cameras */ |
674 | /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */ |
675 | 0x00, 0x0a}, 7}, |
676 | {0x11, 0x04, {0x01}, 1}, |
677 | {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, |
678 | {0x11, 0x04, {0x01}, 1}, |
679 | {0, 0, {0}, 0} |
680 | }; |
681 | |
682 | if (sd->adj_colors) |
683 | err_code = sensor_write_regs(gspca_dev, data: color_adj, |
684 | ARRAY_SIZE(color_adj)); |
685 | else |
686 | err_code = sensor_write_regs(gspca_dev, data: color_no_adj, |
687 | ARRAY_SIZE(color_no_adj)); |
688 | |
689 | if (err_code < 0) |
690 | return err_code; |
691 | |
692 | err_code = sensor_write_regs(gspca_dev, data: vga_sensor1_init_data, |
693 | ARRAY_SIZE(vga_sensor1_init_data)); |
694 | } else { /* sensor type == 2 */ |
695 | static const struct sensor_w_data vga_sensor2_init_data[] = { |
696 | |
697 | {0x01, 0x00, {0x48}, 1}, |
698 | {0x02, 0x00, {0x22}, 1}, |
699 | /* Reg 3 msb and 4 is lsb of the exposure setting*/ |
700 | {0x05, 0x00, {0x10}, 1}, |
701 | {0x06, 0x00, {0x00}, 1}, |
702 | {0x07, 0x00, {0x00}, 1}, |
703 | {0x08, 0x00, {0x00}, 1}, |
704 | {0x09, 0x00, {0x00}, 1}, |
705 | /* The following are used in the gain control |
706 | * which is BTW completely borked in the OEM driver |
707 | * The values for each color go from 0 to 0x7ff |
708 | *{0x0a, 0x00, {0x01}, 1}, green1 gain msb |
709 | *{0x0b, 0x00, {0x10}, 1}, green1 gain lsb |
710 | *{0x0c, 0x00, {0x01}, 1}, red gain msb |
711 | *{0x0d, 0x00, {0x10}, 1}, red gain lsb |
712 | *{0x0e, 0x00, {0x01}, 1}, blue gain msb |
713 | *{0x0f, 0x00, {0x10}, 1}, blue gain lsb |
714 | *{0x10, 0x00, {0x01}, 1}, green2 gain msb |
715 | *{0x11, 0x00, {0x10}, 1}, green2 gain lsb |
716 | */ |
717 | {0x12, 0x00, {0x00}, 1}, |
718 | {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */ |
719 | {0x14, 0x00, {0x00}, 1}, |
720 | {0x15, 0x00, {0x06}, 1}, |
721 | {0x16, 0x00, {0x01}, 1}, |
722 | {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */ |
723 | {0x18, 0x00, {0x02}, 1}, |
724 | {0x19, 0x00, {0x82}, 1}, /* don't mess with */ |
725 | {0x1a, 0x00, {0x00}, 1}, |
726 | {0x1b, 0x00, {0x20}, 1}, |
727 | /* {0x1c, 0x00, {0x17}, 1}, contrast control */ |
728 | {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */ |
729 | {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */ |
730 | {0x1f, 0x00, {0x0c}, 1}, |
731 | {0x20, 0x00, {0x00}, 1}, |
732 | {0, 0, {0}, 0} |
733 | }; |
734 | err_code = sensor_write_regs(gspca_dev, data: vga_sensor2_init_data, |
735 | ARRAY_SIZE(vga_sensor2_init_data)); |
736 | } |
737 | return err_code; |
738 | } |
739 | |
740 | static int sd_start(struct gspca_dev *gspca_dev) |
741 | { |
742 | struct sd *sd = (struct sd *) gspca_dev; |
743 | int err_code; |
744 | |
745 | sd->sof_read = 0; |
746 | |
747 | /* Some of the VGA cameras require the memory pointer |
748 | * to be set to 0 again. We have been forced to start the |
749 | * stream in sd_config() to detect the hardware, and closed it. |
750 | * Thus, we need here to do a completely fresh and clean start. */ |
751 | err_code = zero_the_pointer(gspca_dev); |
752 | if (err_code < 0) |
753 | return err_code; |
754 | |
755 | err_code = stream_start(gspca_dev); |
756 | if (err_code < 0) |
757 | return err_code; |
758 | |
759 | if (sd->cam_type == CAM_TYPE_CIF) { |
760 | err_code = start_cif_cam(gspca_dev); |
761 | } else { |
762 | err_code = start_vga_cam(gspca_dev); |
763 | } |
764 | if (err_code < 0) |
765 | return err_code; |
766 | |
767 | return isoc_enable(gspca_dev); |
768 | } |
769 | |
770 | static void sd_stopN(struct gspca_dev *gspca_dev) |
771 | { |
772 | struct sd *sd = (struct sd *) gspca_dev; |
773 | |
774 | stream_stop(gspca_dev); |
775 | /* Not all the cams need this, but even if not, probably a good idea */ |
776 | zero_the_pointer(gspca_dev); |
777 | if (sd->do_lcd_stop) |
778 | lcd_stop(gspca_dev); |
779 | } |
780 | |
781 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
782 | { |
783 | struct sd *sd = (struct sd *) gspca_dev; |
784 | u8 sign_reg = 7; /* This reg and the next one used on CIF cams. */ |
785 | u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */ |
786 | static const u8 quick_clix_table[] = |
787 | /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */ |
788 | { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9, 7, 10, 13, 11, 14, 15}; |
789 | if (sd->cam_type == CAM_TYPE_VGA) { |
790 | sign_reg += 4; |
791 | value_reg += 4; |
792 | } |
793 | |
794 | /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */ |
795 | if (val > 0) { |
796 | sensor_write1(gspca_dev, reg: sign_reg, data: 0x00); |
797 | } else { |
798 | sensor_write1(gspca_dev, reg: sign_reg, data: 0x01); |
799 | val = 257 - val; |
800 | } |
801 | /* Use lookup table for funky Argus QuickClix brightness */ |
802 | if (sd->do_lcd_stop) |
803 | val = quick_clix_table[val]; |
804 | |
805 | sensor_write1(gspca_dev, reg: value_reg, data: val); |
806 | } |
807 | |
808 | static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv) |
809 | { |
810 | struct sd *sd = (struct sd *) gspca_dev; |
811 | int exposure = MR97310A_EXPOSURE_DEFAULT; |
812 | u8 buf[2]; |
813 | |
814 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) { |
815 | /* This cam does not like exposure settings < 300, |
816 | so scale 0 - 4095 to 300 - 4095 */ |
817 | exposure = (expo * 9267) / 10000 + 300; |
818 | sensor_write1(gspca_dev, reg: 3, data: exposure >> 4); |
819 | sensor_write1(gspca_dev, reg: 4, data: exposure & 0x0f); |
820 | } else if (sd->sensor_type == 2) { |
821 | exposure = expo; |
822 | exposure >>= 3; |
823 | sensor_write1(gspca_dev, reg: 3, data: exposure >> 8); |
824 | sensor_write1(gspca_dev, reg: 4, data: exposure & 0xff); |
825 | } else { |
826 | /* We have both a clock divider and an exposure register. |
827 | We first calculate the clock divider, as that determines |
828 | the maximum exposure and then we calculate the exposure |
829 | register setting (which goes from 0 - 511). |
830 | |
831 | Note our 0 - 4095 exposure is mapped to 0 - 511 |
832 | milliseconds exposure time */ |
833 | u8 clockdiv = (60 * expo + 7999) / 8000; |
834 | |
835 | /* Limit framerate to not exceed usb bandwidth */ |
836 | if (clockdiv < min_clockdiv && gspca_dev->pixfmt.width >= 320) |
837 | clockdiv = min_clockdiv; |
838 | else if (clockdiv < 2) |
839 | clockdiv = 2; |
840 | |
841 | if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4) |
842 | clockdiv = 4; |
843 | |
844 | /* Frame exposure time in ms = 1000 * clockdiv / 60 -> |
845 | exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */ |
846 | exposure = (60 * 511 * expo) / (8000 * clockdiv); |
847 | if (exposure > 511) |
848 | exposure = 511; |
849 | |
850 | /* exposure register value is reversed! */ |
851 | exposure = 511 - exposure; |
852 | |
853 | buf[0] = exposure & 0xff; |
854 | buf[1] = exposure >> 8; |
855 | sensor_write_reg(gspca_dev, reg: 0x0e, flags: 0, data: buf, len: 2); |
856 | sensor_write1(gspca_dev, reg: 0x02, data: clockdiv); |
857 | } |
858 | } |
859 | |
860 | static void setgain(struct gspca_dev *gspca_dev, s32 val) |
861 | { |
862 | struct sd *sd = (struct sd *) gspca_dev; |
863 | u8 gainreg; |
864 | |
865 | if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) |
866 | sensor_write1(gspca_dev, reg: 0x0e, data: val); |
867 | else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2) |
868 | for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) { |
869 | sensor_write1(gspca_dev, reg: gainreg, data: val >> 8); |
870 | sensor_write1(gspca_dev, reg: gainreg + 1, data: val & 0xff); |
871 | } |
872 | else |
873 | sensor_write1(gspca_dev, reg: 0x10, data: val); |
874 | } |
875 | |
876 | static void setcontrast(struct gspca_dev *gspca_dev, s32 val) |
877 | { |
878 | sensor_write1(gspca_dev, reg: 0x1c, data: val); |
879 | } |
880 | |
881 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
882 | { |
883 | struct gspca_dev *gspca_dev = |
884 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); |
885 | struct sd *sd = (struct sd *)gspca_dev; |
886 | |
887 | gspca_dev->usb_err = 0; |
888 | |
889 | if (!gspca_dev->streaming) |
890 | return 0; |
891 | |
892 | switch (ctrl->id) { |
893 | case V4L2_CID_BRIGHTNESS: |
894 | setbrightness(gspca_dev, val: ctrl->val); |
895 | break; |
896 | case V4L2_CID_CONTRAST: |
897 | setcontrast(gspca_dev, val: ctrl->val); |
898 | break; |
899 | case V4L2_CID_EXPOSURE: |
900 | setexposure(gspca_dev, expo: sd->exposure->val, |
901 | min_clockdiv: sd->min_clockdiv ? sd->min_clockdiv->val : 0); |
902 | break; |
903 | case V4L2_CID_GAIN: |
904 | setgain(gspca_dev, val: ctrl->val); |
905 | break; |
906 | } |
907 | return gspca_dev->usb_err; |
908 | } |
909 | |
910 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
911 | .s_ctrl = sd_s_ctrl, |
912 | }; |
913 | |
914 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
915 | { |
916 | struct sd *sd = (struct sd *)gspca_dev; |
917 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
918 | static const struct v4l2_ctrl_config clockdiv = { |
919 | .ops = &sd_ctrl_ops, |
920 | .id = MR97310A_CID_CLOCKDIV, |
921 | .type = V4L2_CTRL_TYPE_INTEGER, |
922 | .name = "Minimum Clock Divider" , |
923 | .min = MR97310A_MIN_CLOCKDIV_MIN, |
924 | .max = MR97310A_MIN_CLOCKDIV_MAX, |
925 | .step = 1, |
926 | .def = MR97310A_MIN_CLOCKDIV_DEFAULT, |
927 | }; |
928 | bool has_brightness = false; |
929 | bool has_argus_brightness = false; |
930 | bool has_contrast = false; |
931 | bool has_gain = false; |
932 | bool has_cs_gain = false; |
933 | bool has_exposure = false; |
934 | bool has_clockdiv = false; |
935 | |
936 | gspca_dev->vdev.ctrl_handler = hdl; |
937 | v4l2_ctrl_handler_init(hdl, 4); |
938 | |
939 | /* Setup controls depending on camera type */ |
940 | if (sd->cam_type == CAM_TYPE_CIF) { |
941 | /* No brightness for sensor_type 0 */ |
942 | if (sd->sensor_type == 0) |
943 | has_exposure = has_gain = has_clockdiv = true; |
944 | else |
945 | has_exposure = has_gain = has_brightness = true; |
946 | } else { |
947 | /* All controls need to be disabled if VGA sensor_type is 0 */ |
948 | if (sd->sensor_type == 0) |
949 | ; /* no controls! */ |
950 | else if (sd->sensor_type == 2) |
951 | has_exposure = has_cs_gain = has_contrast = true; |
952 | else if (sd->do_lcd_stop) |
953 | has_exposure = has_gain = has_argus_brightness = |
954 | has_clockdiv = true; |
955 | else |
956 | has_exposure = has_gain = has_brightness = |
957 | has_clockdiv = true; |
958 | } |
959 | |
960 | /* Separate brightness control description for Argus QuickClix as it has |
961 | * different limits from the other mr97310a cameras, and separate gain |
962 | * control for Sakar CyberPix camera. */ |
963 | /* |
964 | * This control is disabled for CIF type 1 and VGA type 0 cameras. |
965 | * It does not quite act linearly for the Argus QuickClix camera, |
966 | * but it does control brightness. The values are 0 - 15 only, and |
967 | * the table above makes them act consecutively. |
968 | */ |
969 | if (has_brightness) |
970 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
971 | V4L2_CID_BRIGHTNESS, min: -254, max: 255, step: 1, |
972 | MR97310A_BRIGHTNESS_DEFAULT); |
973 | else if (has_argus_brightness) |
974 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
975 | V4L2_CID_BRIGHTNESS, min: 0, max: 15, step: 1, |
976 | MR97310A_BRIGHTNESS_DEFAULT); |
977 | if (has_contrast) |
978 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
979 | V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN, |
980 | MR97310A_CONTRAST_MAX, step: 1, MR97310A_CONTRAST_DEFAULT); |
981 | if (has_gain) |
982 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
983 | V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX, |
984 | step: 1, MR97310A_GAIN_DEFAULT); |
985 | else if (has_cs_gain) |
986 | v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, V4L2_CID_GAIN, |
987 | MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX, |
988 | step: 1, MR97310A_CS_GAIN_DEFAULT); |
989 | if (has_exposure) |
990 | sd->exposure = v4l2_ctrl_new_std(hdl, ops: &sd_ctrl_ops, |
991 | V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN, |
992 | MR97310A_EXPOSURE_MAX, step: 1, MR97310A_EXPOSURE_DEFAULT); |
993 | if (has_clockdiv) |
994 | sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, cfg: &clockdiv, NULL); |
995 | |
996 | if (hdl->error) { |
997 | pr_err("Could not initialize controls\n" ); |
998 | return hdl->error; |
999 | } |
1000 | if (has_exposure && has_clockdiv) |
1001 | v4l2_ctrl_cluster(ncontrols: 2, controls: &sd->exposure); |
1002 | return 0; |
1003 | } |
1004 | |
1005 | /* Include pac common sof detection functions */ |
1006 | #include "pac_common.h" |
1007 | |
1008 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1009 | u8 *data, /* isoc packet */ |
1010 | int len) /* iso packet length */ |
1011 | { |
1012 | struct sd *sd = (struct sd *) gspca_dev; |
1013 | unsigned char *sof; |
1014 | |
1015 | sof = pac_find_sof(gspca_dev, sof_read: &sd->sof_read, m: data, len); |
1016 | if (sof) { |
1017 | int n; |
1018 | |
1019 | /* finish decoding current frame */ |
1020 | n = sof - data; |
1021 | if (n > sizeof pac_sof_marker) |
1022 | n -= sizeof pac_sof_marker; |
1023 | else |
1024 | n = 0; |
1025 | gspca_frame_add(gspca_dev, packet_type: LAST_PACKET, |
1026 | data, len: n); |
1027 | /* Start next frame. */ |
1028 | gspca_frame_add(gspca_dev, packet_type: FIRST_PACKET, |
1029 | data: pac_sof_marker, len: sizeof pac_sof_marker); |
1030 | len -= sof - data; |
1031 | data = sof; |
1032 | } |
1033 | gspca_frame_add(gspca_dev, packet_type: INTER_PACKET, data, len); |
1034 | } |
1035 | |
1036 | /* sub-driver description */ |
1037 | static const struct sd_desc sd_desc = { |
1038 | .name = MODULE_NAME, |
1039 | .config = sd_config, |
1040 | .init = sd_init, |
1041 | .init_controls = sd_init_controls, |
1042 | .start = sd_start, |
1043 | .stopN = sd_stopN, |
1044 | .pkt_scan = sd_pkt_scan, |
1045 | }; |
1046 | |
1047 | /* -- module initialisation -- */ |
1048 | static const struct usb_device_id device_table[] = { |
1049 | {USB_DEVICE(0x08ca, 0x0110)}, /* Trust Spyc@m 100 */ |
1050 | {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ |
1051 | {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ |
1052 | {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ |
1053 | {} |
1054 | }; |
1055 | MODULE_DEVICE_TABLE(usb, device_table); |
1056 | |
1057 | /* -- device connect -- */ |
1058 | static int sd_probe(struct usb_interface *intf, |
1059 | const struct usb_device_id *id) |
1060 | { |
1061 | return gspca_dev_probe(intf, id, sd_desc: &sd_desc, dev_size: sizeof(struct sd), |
1062 | THIS_MODULE); |
1063 | } |
1064 | |
1065 | static struct usb_driver sd_driver = { |
1066 | .name = MODULE_NAME, |
1067 | .id_table = device_table, |
1068 | .probe = sd_probe, |
1069 | .disconnect = gspca_disconnect, |
1070 | #ifdef CONFIG_PM |
1071 | .suspend = gspca_suspend, |
1072 | .resume = gspca_resume, |
1073 | .reset_resume = gspca_resume, |
1074 | #endif |
1075 | }; |
1076 | |
1077 | module_usb_driver(sd_driver); |
1078 | |