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