diff options
author | Theodore Kilgore <kilgota@auburn.edu> | 2009-08-14 05:51:52 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:19:54 -0400 |
commit | 89f0863c4225aaed2763f526815c54a9e1b0f788 (patch) | |
tree | 614b31d404ad07454d1731204a14397398d3aa8a /drivers | |
parent | 0e4a90993dceffa881ee6d42266eb3080b7fad04 (diff) |
V4L/DVB (12618): gspca: mr97310a add support for CIF and more VGA camera's
This patch adds supports for mr97310a camera's with CIF sensors (2 different
types) and for VGA mr97310a camera with a different sensor then supported
until now.
This patch also add support for controls for one of the 2 CIF sensors, this
was written by Thomas Kaiser <thomas@kaiser-linux.li>
Signed-off-by: Theodore Kilgore <kilgota@auburn.edu>
Signed-off-by: Thomas Kaiser <thomas@kaiser-linux.li>
Signed-off-by: Hans de Goede <hdgoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/gspca/mr97310a.c | 797 |
1 files changed, 682 insertions, 115 deletions
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c index 30132513400c..3a3edf82a361 100644 --- a/drivers/media/video/gspca/mr97310a.c +++ b/drivers/media/video/gspca/mr97310a.c | |||
@@ -3,6 +3,21 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> | 4 | * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com> |
5 | * | 5 | * |
6 | * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+ | ||
7 | * and for the routines for detecting and classifying these various cameras, | ||
8 | * | ||
9 | * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu> | ||
10 | * | ||
11 | * Acknowledgements: | ||
12 | * | ||
13 | * The MR97311A support in gspca/mars.c has been helpful in understanding some | ||
14 | * of the registers in these cameras. | ||
15 | * | ||
16 | * Hans de Goede <hdgoede@redhat.com> and | ||
17 | * Thomas Kaiser <thomas@kaiser-linux.li> | ||
18 | * have assisted with their experience. Each of them has also helped by | ||
19 | * testing a previously unsupported camera. | ||
20 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 21 | * 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 | 22 | * 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 | 23 | * the Free Software Foundation; either version 2 of the License, or |
@@ -22,7 +37,23 @@ | |||
22 | 37 | ||
23 | #include "gspca.h" | 38 | #include "gspca.h" |
24 | 39 | ||
25 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>"); | 40 | #define CAM_TYPE_CIF 0 |
41 | #define CAM_TYPE_VGA 1 | ||
42 | |||
43 | #define MR97310A_BRIGHTNESS_MIN -254 | ||
44 | #define MR97310A_BRIGHTNESS_MAX 255 | ||
45 | #define MR97310A_BRIGHTNESS_DEFAULT 0 | ||
46 | |||
47 | #define MR97310A_EXPOSURE_MIN 300 | ||
48 | #define MR97310A_EXPOSURE_MAX 4095 | ||
49 | #define MR97310A_EXPOSURE_DEFAULT 1000 | ||
50 | |||
51 | #define MR97310A_GAIN_MIN 0 | ||
52 | #define MR97310A_GAIN_MAX 31 | ||
53 | #define MR97310A_GAIN_DEFAULT 25 | ||
54 | |||
55 | MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>," | ||
56 | "Theodore Kilgore <kilgota@auburn.edu>"); | ||
26 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); | 57 | MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver"); |
27 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
28 | 59 | ||
@@ -30,10 +61,75 @@ MODULE_LICENSE("GPL"); | |||
30 | struct sd { | 61 | struct sd { |
31 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 62 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
32 | u8 sof_read; | 63 | u8 sof_read; |
64 | u8 cam_type; /* 0 is CIF and 1 is VGA */ | ||
65 | u8 sensor_type; /* We use 0 and 1 here, too. */ | ||
66 | u8 do_lcd_stop; | ||
67 | u8 regs[15]; | ||
68 | |||
69 | int brightness; | ||
70 | u16 exposure; | ||
71 | u8 autogain; | ||
72 | u8 gain; | ||
33 | }; | 73 | }; |
34 | 74 | ||
75 | struct sensor_w_data { | ||
76 | u8 reg; | ||
77 | u8 flags; | ||
78 | u8 data[16]; | ||
79 | int len; | ||
80 | }; | ||
81 | |||
82 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
83 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
84 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val); | ||
85 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val); | ||
86 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val); | ||
87 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val); | ||
88 | |||
35 | /* V4L2 controls supported by the driver */ | 89 | /* V4L2 controls supported by the driver */ |
36 | static struct ctrl sd_ctrls[] = { | 90 | static struct ctrl sd_ctrls[] = { |
91 | { | ||
92 | { | ||
93 | .id = V4L2_CID_BRIGHTNESS, | ||
94 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
95 | .name = "Brightness", | ||
96 | .minimum = MR97310A_BRIGHTNESS_MIN, | ||
97 | .maximum = MR97310A_BRIGHTNESS_MAX, | ||
98 | .step = 1, | ||
99 | .default_value = MR97310A_BRIGHTNESS_DEFAULT, | ||
100 | .flags = 0, | ||
101 | }, | ||
102 | .set = sd_setbrightness, | ||
103 | .get = sd_getbrightness, | ||
104 | }, | ||
105 | { | ||
106 | { | ||
107 | .id = V4L2_CID_EXPOSURE, | ||
108 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
109 | .name = "Exposure", | ||
110 | .minimum = MR97310A_EXPOSURE_MIN, | ||
111 | .maximum = MR97310A_EXPOSURE_MAX, | ||
112 | .step = 1, | ||
113 | .default_value = MR97310A_EXPOSURE_DEFAULT, | ||
114 | .flags = 0, | ||
115 | }, | ||
116 | .set = sd_setexposure, | ||
117 | .get = sd_getexposure, | ||
118 | }, | ||
119 | { | ||
120 | { | ||
121 | .id = V4L2_CID_GAIN, | ||
122 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
123 | .name = "Gain", | ||
124 | .minimum = MR97310A_GAIN_MIN, | ||
125 | .maximum = MR97310A_GAIN_MAX, | ||
126 | .step = 1, | ||
127 | .default_value = MR97310A_GAIN_DEFAULT, | ||
128 | .flags = 0, | ||
129 | }, | ||
130 | .set = sd_setgain, | ||
131 | .get = sd_getgain, | ||
132 | }, | ||
37 | }; | 133 | }; |
38 | 134 | ||
39 | static const struct v4l2_pix_format vga_mode[] = { | 135 | static const struct v4l2_pix_format vga_mode[] = { |
@@ -65,7 +161,7 @@ static const struct v4l2_pix_format vga_mode[] = { | |||
65 | }; | 161 | }; |
66 | 162 | ||
67 | /* the bytes to write are in gspca_dev->usb_buf */ | 163 | /* the bytes to write are in gspca_dev->usb_buf */ |
68 | static int reg_w(struct gspca_dev *gspca_dev, int len) | 164 | static int mr_write(struct gspca_dev *gspca_dev, int len) |
69 | { | 165 | { |
70 | int rc; | 166 | int rc; |
71 | 167 | ||
@@ -78,15 +174,200 @@ static int reg_w(struct gspca_dev *gspca_dev, int len) | |||
78 | return rc; | 174 | return rc; |
79 | } | 175 | } |
80 | 176 | ||
177 | /* the bytes are read into gspca_dev->usb_buf */ | ||
178 | static int mr_read(struct gspca_dev *gspca_dev, int len) | ||
179 | { | ||
180 | int rc; | ||
181 | |||
182 | rc = usb_bulk_msg(gspca_dev->dev, | ||
183 | usb_rcvbulkpipe(gspca_dev->dev, 3), | ||
184 | gspca_dev->usb_buf, len, NULL, 500); | ||
185 | if (rc < 0) | ||
186 | PDEBUG(D_ERR, "reg read [%02x] error %d", | ||
187 | gspca_dev->usb_buf[0], rc); | ||
188 | return rc; | ||
189 | } | ||
190 | |||
191 | static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags, | ||
192 | const u8 *data, int len) | ||
193 | { | ||
194 | gspca_dev->usb_buf[0] = 0x1f; | ||
195 | gspca_dev->usb_buf[1] = flags; | ||
196 | gspca_dev->usb_buf[2] = reg; | ||
197 | memcpy(gspca_dev->usb_buf + 3, data, len); | ||
198 | |||
199 | return mr_write(gspca_dev, len + 3); | ||
200 | } | ||
201 | |||
202 | static int sensor_write_regs(struct gspca_dev *gspca_dev, | ||
203 | const struct sensor_w_data *data, int len) | ||
204 | { | ||
205 | int i, rc; | ||
206 | |||
207 | for (i = 0; i < len; i++) { | ||
208 | rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags, | ||
209 | data[i].data, data[i].len); | ||
210 | if (rc < 0) | ||
211 | return rc; | ||
212 | } | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data) | ||
218 | { | ||
219 | u8 buf; | ||
220 | int rc; | ||
221 | |||
222 | buf = data; | ||
223 | rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1); | ||
224 | if (rc < 0) | ||
225 | return rc; | ||
226 | |||
227 | buf = 0x01; | ||
228 | rc = sensor_write_reg(gspca_dev, 0x13, 0x00, &buf, 1); | ||
229 | if (rc < 0) | ||
230 | return rc; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int cam_get_response16(struct gspca_dev *gspca_dev) | ||
236 | { | ||
237 | __u8 *data = gspca_dev->usb_buf; | ||
238 | int err_code; | ||
239 | |||
240 | data[0] = 0x21; | ||
241 | err_code = mr_write(gspca_dev, 1); | ||
242 | if (err_code < 0) | ||
243 | return err_code; | ||
244 | |||
245 | err_code = mr_read(gspca_dev, 16); | ||
246 | return err_code; | ||
247 | } | ||
248 | |||
249 | static int zero_the_pointer(struct gspca_dev *gspca_dev) | ||
250 | { | ||
251 | __u8 *data = gspca_dev->usb_buf; | ||
252 | int err_code; | ||
253 | u8 status = 0; | ||
254 | int tries = 0; | ||
255 | |||
256 | err_code = cam_get_response16(gspca_dev); | ||
257 | if (err_code < 0) | ||
258 | return err_code; | ||
259 | |||
260 | err_code = mr_write(gspca_dev, 1); | ||
261 | data[0] = 0x19; | ||
262 | data[1] = 0x51; | ||
263 | err_code = mr_write(gspca_dev, 2); | ||
264 | if (err_code < 0) | ||
265 | return err_code; | ||
266 | |||
267 | err_code = cam_get_response16(gspca_dev); | ||
268 | if (err_code < 0) | ||
269 | return err_code; | ||
270 | |||
271 | data[0] = 0x19; | ||
272 | data[1] = 0xba; | ||
273 | err_code = mr_write(gspca_dev, 2); | ||
274 | if (err_code < 0) | ||
275 | return err_code; | ||
276 | |||
277 | err_code = cam_get_response16(gspca_dev); | ||
278 | if (err_code < 0) | ||
279 | return err_code; | ||
280 | |||
281 | data[0] = 0x19; | ||
282 | data[1] = 0x00; | ||
283 | err_code = mr_write(gspca_dev, 2); | ||
284 | if (err_code < 0) | ||
285 | return err_code; | ||
286 | |||
287 | err_code = cam_get_response16(gspca_dev); | ||
288 | if (err_code < 0) | ||
289 | return err_code; | ||
290 | |||
291 | data[0] = 0x19; | ||
292 | data[1] = 0x00; | ||
293 | err_code = mr_write(gspca_dev, 2); | ||
294 | if (err_code < 0) | ||
295 | return err_code; | ||
296 | |||
297 | while (status != 0x0a && tries < 256) { | ||
298 | err_code = cam_get_response16(gspca_dev); | ||
299 | status = data[0]; | ||
300 | tries++; | ||
301 | if (err_code < 0) | ||
302 | return err_code; | ||
303 | } | ||
304 | PDEBUG(D_ERR, "status is %02x", status); | ||
305 | |||
306 | tries = 0; | ||
307 | while (tries < 4) { | ||
308 | data[0] = 0x19; | ||
309 | data[1] = 0x00; | ||
310 | err_code = mr_write(gspca_dev, 2); | ||
311 | if (err_code < 0) | ||
312 | return err_code; | ||
313 | |||
314 | err_code = cam_get_response16(gspca_dev); | ||
315 | status = data[0]; | ||
316 | tries++; | ||
317 | if (err_code < 0) | ||
318 | return err_code; | ||
319 | } | ||
320 | PDEBUG(D_ERR, "Read 16 bytes from camera"); | ||
321 | |||
322 | data[0] = 0x19; | ||
323 | err_code = mr_write(gspca_dev, 1); | ||
324 | if (err_code < 0) | ||
325 | return err_code; | ||
326 | |||
327 | err_code = mr_read(gspca_dev, 16); | ||
328 | if (err_code < 0) | ||
329 | return err_code; | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static u8 get_sensor_id(struct gspca_dev *gspca_dev) | ||
335 | { | ||
336 | int err_code; | ||
337 | |||
338 | gspca_dev->usb_buf[0] = 0x1e; | ||
339 | err_code = mr_write(gspca_dev, 1); | ||
340 | if (err_code < 0) | ||
341 | return err_code; | ||
342 | |||
343 | err_code = mr_read(gspca_dev, 16); | ||
344 | if (err_code < 0) | ||
345 | return err_code; | ||
346 | |||
347 | PDEBUG(D_ERR, "Read 16 bytes from camera"); | ||
348 | PDEBUG(D_ERR, "Byte zero reported is %01x", gspca_dev->usb_buf[0]); | ||
349 | |||
350 | return gspca_dev->usb_buf[0]; | ||
351 | } | ||
352 | |||
81 | /* this function is called at probe time */ | 353 | /* this function is called at probe time */ |
82 | static int sd_config(struct gspca_dev *gspca_dev, | 354 | static int sd_config(struct gspca_dev *gspca_dev, |
83 | const struct usb_device_id *id) | 355 | const struct usb_device_id *id) |
84 | { | 356 | { |
357 | struct sd *sd = (struct sd *) gspca_dev; | ||
85 | struct cam *cam; | 358 | struct cam *cam; |
86 | 359 | ||
87 | cam = &gspca_dev->cam; | 360 | cam = &gspca_dev->cam; |
88 | cam->cam_mode = vga_mode; | 361 | cam->cam_mode = vga_mode; |
89 | cam->nmodes = ARRAY_SIZE(vga_mode); | 362 | cam->nmodes = ARRAY_SIZE(vga_mode); |
363 | sd->cam_type = CAM_TYPE_VGA; | ||
364 | PDEBUG(D_PROBE, | ||
365 | "MR97310A camera detected" | ||
366 | " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct); | ||
367 | if (id->idProduct == 0x010e) { | ||
368 | cam->nmodes--; | ||
369 | sd->cam_type = CAM_TYPE_CIF; | ||
370 | } | ||
90 | return 0; | 371 | return 0; |
91 | } | 372 | } |
92 | 373 | ||
@@ -96,183 +377,468 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
96 | return 0; | 377 | return 0; |
97 | } | 378 | } |
98 | 379 | ||
99 | static int sd_start(struct gspca_dev *gspca_dev) | 380 | static int adjust_cif_sensor(struct gspca_dev *gspca_dev) |
381 | { | ||
382 | /* | ||
383 | * FIXME: The following sequence resets brightness, contrast, and | ||
384 | * related settings. Some of the values are adjustable, presumably | ||
385 | * based upon what is detected in the frames. Here, only some | ||
386 | * vaules are used which are compromises. When more is known about | ||
387 | * what is done here, this needs to be moved out to presently | ||
388 | * nonexistent functions which do controls. The same control messages | ||
389 | * do work for all of the CIF cameras. | ||
390 | */ | ||
391 | |||
392 | const struct sensor_w_data cif_sensor1_adjust_data[] = { | ||
393 | {0x02, 0x01, {0x10, 0x12, 0x0a}, 3}, | ||
394 | /* Last or possibly two last bytes adjustable, above. */ | ||
395 | {0x13, 0x04, {0x01}, 1}, /* seems to mean "write" */ | ||
396 | {0x05, 0x01, {0x22, 0x00, 0x81, 0x06}, 4}, | ||
397 | /* Last or possibly two last bytes adjustable, above. */ | ||
398 | {0x13, 0x04, {0x01}, 1}, | ||
399 | {0x09, 0x02, {0x05, 0x00, 0x00, 0x05, 0x07, 0x16}, 6}, | ||
400 | /* Last or possibly two last bytes adjustable, above. */ | ||
401 | {0x13, 0x04, {0x01}, 1}, | ||
402 | {0, 0, {0}, 0} | ||
403 | }; | ||
404 | |||
405 | return sensor_write_regs(gspca_dev, cif_sensor1_adjust_data, | ||
406 | ARRAY_SIZE(cif_sensor1_adjust_data)); | ||
407 | } | ||
408 | |||
409 | static int start_cif_cam(struct gspca_dev *gspca_dev) | ||
100 | { | 410 | { |
101 | struct sd *sd = (struct sd *) gspca_dev; | 411 | struct sd *sd = (struct sd *) gspca_dev; |
102 | __u8 *data = gspca_dev->usb_buf; | 412 | __u8 *data = gspca_dev->usb_buf; |
103 | int err_code; | 413 | int err_code; |
104 | 414 | const __u8 startup_string[] = { | |
105 | sd->sof_read = 0; | 415 | 0x00, |
106 | 416 | 0x0d, | |
107 | /* Note: register descriptions guessed from MR97113A driver */ | 417 | 0x01, |
108 | 418 | 0x00, /* Hsize/8 for 352 or 320 */ | |
419 | 0x00, /* Vsize/4 for 288 or 240 */ | ||
420 | 0x13, /* or 0xbb, depends on sensor */ | ||
421 | 0x00, /* Hstart, depends on res. */ | ||
422 | 0x00, /* reserved ? */ | ||
423 | 0x00, /* Vstart, depends on res. and sensor */ | ||
424 | 0x50, /* 0x54 to get 176 or 160 */ | ||
425 | 0xc0 | ||
426 | }; | ||
427 | |||
428 | /* Note: Some of the above descriptions guessed from MR97113A driver */ | ||
429 | sd->sensor_type = 0; | ||
109 | data[0] = 0x01; | 430 | data[0] = 0x01; |
110 | data[1] = 0x01; | 431 | data[1] = 0x01; |
111 | err_code = reg_w(gspca_dev, 2); | 432 | err_code = mr_write(gspca_dev, 2); |
112 | if (err_code < 0) | 433 | if (err_code < 0) |
113 | return err_code; | 434 | return err_code; |
114 | 435 | ||
115 | data[0] = 0x00; | 436 | msleep(200); |
116 | data[1] = 0x0d; | 437 | data[0] = get_sensor_id(gspca_dev); |
117 | data[2] = 0x01; | 438 | /* |
118 | data[5] = 0x2b; | 439 | * Known CIF cameras. If you have another to report, please do |
119 | data[7] = 0x00; | 440 | * |
120 | data[9] = 0x50; /* reg 8, no scale down */ | 441 | * Name byte just read sd->sensor_type |
121 | data[10] = 0xc0; | 442 | * reported by |
443 | * Sakar Spy-shot 0x28 T. Kilgore 0 | ||
444 | * Innovage 0xf5 (unstable) T. Kilgore 0 | ||
445 | * Vivitar Mini 0x53 H. De Goede 0 | ||
446 | * Vivitar Mini 0x08 T. Kilgore 1 | ||
447 | * Elta-Media 8212dc 0x23 T. Kaiser 1 | ||
448 | * Philips dig. keych. 0x37 T. Kilgore 1 | ||
449 | */ | ||
450 | if ((data[0] & 0x78) == 8 || (data[0] & 0x2) == 0x2) | ||
451 | sd->sensor_type = 1; | ||
452 | |||
453 | PDEBUG(D_ERR, "Sensor type is %01x", sd->sensor_type); | ||
454 | memcpy(data, startup_string, 11); | ||
455 | if (sd->sensor_type) | ||
456 | data[5] = 0xbb; | ||
122 | 457 | ||
123 | switch (gspca_dev->width) { | 458 | switch (gspca_dev->width) { |
124 | case 160: | 459 | case 160: |
125 | data[9] |= 0x0c; /* reg 8, 4:1 scale down */ | 460 | data[9] |= 0x04; /* reg 8, 2:1 scale down from 320 */ |
126 | /* fall thru */ | 461 | /* fall thru */ |
127 | case 320: | 462 | case 320: |
128 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | ||
129 | /* fall thru */ | ||
130 | case 640: | ||
131 | default: | 463 | default: |
132 | data[3] = 0x50; /* reg 2, H size */ | 464 | data[3] = 0x28; /* reg 2, H size/8 */ |
133 | data[4] = 0x78; /* reg 3, V size */ | 465 | data[4] = 0x3c; /* reg 3, V size/4 */ |
134 | data[6] = 0x04; /* reg 5, H start */ | 466 | data[6] = 0x14; /* reg 5, H start */ |
135 | data[8] = 0x03; /* reg 7, V start */ | 467 | data[8] = 0x1a + sd->sensor_type; /* reg 7, V start */ |
136 | break; | 468 | break; |
137 | |||
138 | case 176: | 469 | case 176: |
139 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | 470 | data[9] |= 0x04; /* reg 8, 2:1 scale down from 352 */ |
140 | /* fall thru */ | 471 | /* fall thru */ |
141 | case 352: | 472 | case 352: |
142 | data[3] = 0x2c; /* reg 2, H size */ | 473 | data[3] = 0x2c; /* reg 2, H size/8 */ |
143 | data[4] = 0x48; /* reg 3, V size */ | 474 | data[4] = 0x48; /* reg 3, V size/4 */ |
144 | data[6] = 0x94; /* reg 5, H start */ | 475 | data[6] = 0x06; /* reg 5, H start */ |
145 | data[8] = 0x63; /* reg 7, V start */ | 476 | data[8] = 0x06 + sd->sensor_type; /* reg 7, V start */ |
146 | break; | 477 | break; |
147 | } | 478 | } |
148 | 479 | err_code = mr_write(gspca_dev, 11); | |
149 | err_code = reg_w(gspca_dev, 11); | ||
150 | if (err_code < 0) | 480 | if (err_code < 0) |
151 | return err_code; | 481 | return err_code; |
152 | 482 | ||
153 | data[0] = 0x0a; | 483 | if (!sd->sensor_type) { |
154 | data[1] = 0x80; | 484 | const struct sensor_w_data cif_sensor0_init_data[] = { |
155 | err_code = reg_w(gspca_dev, 2); | 485 | {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01, |
486 | 0x0f, 0x14, 0x0f, 0x10}, 8}, | ||
487 | {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5}, | ||
488 | {0x12, 0x00, {0x07}, 1}, | ||
489 | {0x1f, 0x00, {0x06}, 1}, | ||
490 | {0x27, 0x00, {0x04}, 1}, | ||
491 | {0x29, 0x00, {0x0c}, 1}, | ||
492 | {0x40, 0x00, {0x40, 0x00, 0x04}, 3}, | ||
493 | {0x50, 0x00, {0x60}, 1}, | ||
494 | {0x60, 0x00, {0x06}, 1}, | ||
495 | {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6}, | ||
496 | {0x72, 0x00, {0x1e, 0x56}, 2}, | ||
497 | {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02, | ||
498 | 0x31, 0x80, 0x00}, 9}, | ||
499 | {0x11, 0x00, {0x01}, 1}, | ||
500 | {0, 0, {0}, 0} | ||
501 | }; | ||
502 | err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data, | ||
503 | ARRAY_SIZE(cif_sensor0_init_data)); | ||
504 | } else { /* sd->sensor_type = 1 */ | ||
505 | const struct sensor_w_data cif_sensor1_init_data[] = { | ||
506 | {0x02, 0x00, {0x10}, 1}, | ||
507 | {0x03, 0x01, {0x12}, 1}, | ||
508 | {0x04, 0x01, {0x05}, 1}, | ||
509 | {0x05, 0x01, {0x65}, 1}, | ||
510 | {0x06, 0x01, {0x32}, 1}, | ||
511 | {0x07, 0x01, {0x00}, 1}, | ||
512 | {0x08, 0x02, {0x06}, 1}, | ||
513 | {0x09, 0x02, {0x0e}, 1}, | ||
514 | {0x0a, 0x02, {0x05}, 1}, | ||
515 | {0x0b, 0x02, {0x05}, 1}, | ||
516 | {0x0c, 0x02, {0x0f}, 1}, | ||
517 | {0x0d, 0x02, {0x00}, 1}, | ||
518 | {0x0e, 0x02, {0x0c}, 1}, | ||
519 | {0x0f, 0x00, {0x00}, 1}, | ||
520 | {0x10, 0x00, {0x06}, 1}, | ||
521 | {0x11, 0x00, {0x07}, 1}, | ||
522 | {0x12, 0x00, {0x00}, 1}, | ||
523 | {0x13, 0x00, {0x01}, 1}, | ||
524 | {0, 0, {0}, 0} | ||
525 | }; | ||
526 | err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data, | ||
527 | ARRAY_SIZE(cif_sensor1_init_data)); | ||
528 | } | ||
156 | if (err_code < 0) | 529 | if (err_code < 0) |
157 | return err_code; | 530 | return err_code; |
158 | 531 | ||
159 | data[0] = 0x14; | 532 | msleep(200); |
160 | data[1] = 0x0a; | 533 | data[0] = 0x00; |
161 | err_code = reg_w(gspca_dev, 2); | 534 | data[1] = 0x4d; /* ISOC transfering enable... */ |
535 | err_code = mr_write(gspca_dev, 2); | ||
162 | if (err_code < 0) | 536 | if (err_code < 0) |
163 | return err_code; | 537 | return err_code; |
164 | 538 | ||
165 | data[0] = 0x1b; | 539 | msleep(200); |
166 | data[1] = 0x00; | 540 | err_code = adjust_cif_sensor(gspca_dev); |
167 | err_code = reg_w(gspca_dev, 2); | ||
168 | if (err_code < 0) | 541 | if (err_code < 0) |
169 | return err_code; | 542 | return err_code; |
170 | 543 | ||
171 | data[0] = 0x15; | 544 | msleep(200); |
172 | data[1] = 0x16; | 545 | return 0; |
173 | err_code = reg_w(gspca_dev, 2); | 546 | } |
174 | if (err_code < 0) | ||
175 | return err_code; | ||
176 | 547 | ||
177 | data[0] = 0x16; | 548 | static int start_vga_cam(struct gspca_dev *gspca_dev) |
178 | data[1] = 0x10; | 549 | { |
179 | err_code = reg_w(gspca_dev, 2); | 550 | struct sd *sd = (struct sd *) gspca_dev; |
180 | if (err_code < 0) | 551 | __u8 *data = gspca_dev->usb_buf; |
181 | return err_code; | 552 | int err_code; |
553 | const __u8 startup_string[] = {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, | ||
554 | 0x00, 0x00, 0x00, 0x50, 0xc0}; | ||
182 | 555 | ||
183 | data[0] = 0x17; | 556 | /* What some of these mean is explained in start_cif_cam(), above */ |
184 | data[1] = 0x3a; | 557 | sd->sof_read = 0; |
185 | err_code = reg_w(gspca_dev, 2); | ||
186 | if (err_code < 0) | ||
187 | return err_code; | ||
188 | 558 | ||
189 | data[0] = 0x18; | 559 | /* |
190 | data[1] = 0x68; | 560 | * We have to know which camera we have, because the register writes |
191 | err_code = reg_w(gspca_dev, 2); | 561 | * depend upon the camera. This test, run before we actually enter |
562 | * the initialization routine, distinguishes most of the cameras, If | ||
563 | * needed, another routine is done later, too. | ||
564 | */ | ||
565 | memset(data, 0, 16); | ||
566 | data[0] = 0x20; | ||
567 | err_code = mr_write(gspca_dev, 1); | ||
192 | if (err_code < 0) | 568 | if (err_code < 0) |
193 | return err_code; | 569 | return err_code; |
194 | 570 | ||
195 | data[0] = 0x1f; | 571 | err_code = mr_read(gspca_dev, 16); |
196 | data[1] = 0x00; | ||
197 | data[2] = 0x02; | ||
198 | data[3] = 0x06; | ||
199 | data[4] = 0x59; | ||
200 | data[5] = 0x0c; | ||
201 | data[6] = 0x16; | ||
202 | data[7] = 0x00; | ||
203 | data[8] = 0x07; | ||
204 | data[9] = 0x00; | ||
205 | data[10] = 0x01; | ||
206 | err_code = reg_w(gspca_dev, 11); | ||
207 | if (err_code < 0) | 572 | if (err_code < 0) |
208 | return err_code; | 573 | return err_code; |
209 | 574 | ||
210 | data[0] = 0x1f; | 575 | PDEBUG(D_ERR, "Read 16 bytes from camera"); |
211 | data[1] = 0x04; | 576 | PDEBUG(D_ERR, "Byte reported is %02x", data[0]); |
212 | data[2] = 0x11; | ||
213 | data[3] = 0x01; | ||
214 | err_code = reg_w(gspca_dev, 4); | ||
215 | if (err_code < 0) | ||
216 | return err_code; | ||
217 | 577 | ||
218 | data[0] = 0x1f; | 578 | msleep(200); |
219 | data[1] = 0x00; | 579 | /* |
220 | data[2] = 0x0a; | 580 | * Known VGA cameras. If you have another to report, please do |
221 | data[3] = 0x00; | 581 | * |
222 | data[4] = 0x01; | 582 | * Name byte just read sd->sensor_type |
223 | data[5] = 0x00; | 583 | * sd->do_lcd_stop |
224 | data[6] = 0x00; | 584 | * Aiptek Pencam VGA+ 0x31 0 1 |
225 | data[7] = 0x01; | 585 | * ION digital 0x31 0 1 |
226 | data[8] = 0x00; | 586 | * Argus DC-1620 0x30 1 0 |
227 | data[9] = 0x0a; | 587 | * Argus QuickClix 0x30 1 1 (not caught here) |
228 | err_code = reg_w(gspca_dev, 10); | 588 | */ |
229 | if (err_code < 0) | 589 | sd->sensor_type = data[0] & 1; |
230 | return err_code; | 590 | sd->do_lcd_stop = (~data[0]) & 1; |
231 | 591 | ||
232 | data[0] = 0x1f; | 592 | |
233 | data[1] = 0x04; | 593 | |
234 | data[2] = 0x11; | 594 | /* Streaming setup begins here. */ |
235 | data[3] = 0x01; | 595 | |
236 | err_code = reg_w(gspca_dev, 4); | 596 | |
597 | data[0] = 0x01; | ||
598 | data[1] = 0x01; | ||
599 | err_code = mr_write(gspca_dev, 2); | ||
237 | if (err_code < 0) | 600 | if (err_code < 0) |
238 | return err_code; | 601 | return err_code; |
239 | 602 | ||
240 | data[0] = 0x1f; | 603 | /* |
241 | data[1] = 0x00; | 604 | * A second test can now resolve any remaining ambiguity in the |
242 | data[2] = 0x12; | 605 | * identification of the camera type, |
243 | data[3] = 0x00; | 606 | */ |
244 | data[4] = 0x63; | 607 | if (!sd->sensor_type) { |
245 | data[5] = 0x00; | 608 | data[0] = get_sensor_id(gspca_dev); |
246 | data[6] = 0x70; | 609 | if (data[0] == 0x7f) { |
247 | data[7] = 0x00; | 610 | sd->sensor_type = 1; |
248 | data[8] = 0x00; | 611 | PDEBUG(D_ERR, "sensor_type corrected to 1"); |
249 | err_code = reg_w(gspca_dev, 9); | 612 | } |
613 | msleep(200); | ||
614 | } | ||
615 | |||
616 | /* | ||
617 | * Known VGA cameras. | ||
618 | * This test is only run if the previous test returned 0x30, but | ||
619 | * here is the information for all others, too, just for reference. | ||
620 | * | ||
621 | * Name byte just read sd->sensor_type | ||
622 | * | ||
623 | * Aiptek Pencam VGA+ 0xfb (this test not run) 1 | ||
624 | * ION digital 0xbd (this test not run) 1 | ||
625 | * Argus DC-1620 0xe5 (no change) 0 | ||
626 | * Argus QuickClix 0x7f (reclassified) 1 | ||
627 | */ | ||
628 | memcpy(data, startup_string, 11); | ||
629 | if (!sd->sensor_type) { | ||
630 | data[5] = 0x00; | ||
631 | data[10] = 0x91; | ||
632 | } | ||
633 | |||
634 | switch (gspca_dev->width) { | ||
635 | case 160: | ||
636 | data[9] |= 0x0c; /* reg 8, 4:1 scale down */ | ||
637 | /* fall thru */ | ||
638 | case 320: | ||
639 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | ||
640 | /* fall thru */ | ||
641 | case 640: | ||
642 | default: | ||
643 | data[3] = 0x50; /* reg 2, H size/8 */ | ||
644 | data[4] = 0x78; /* reg 3, V size/4 */ | ||
645 | data[6] = 0x04; /* reg 5, H start */ | ||
646 | data[8] = 0x03; /* reg 7, V start */ | ||
647 | if (sd->do_lcd_stop) | ||
648 | data[8] = 0x04; /* Bayer tile shifted */ | ||
649 | break; | ||
650 | |||
651 | case 176: | ||
652 | data[9] |= 0x04; /* reg 8, 2:1 scale down */ | ||
653 | /* fall thru */ | ||
654 | case 352: | ||
655 | data[3] = 0x2c; /* reg 2, H size */ | ||
656 | data[4] = 0x48; /* reg 3, V size */ | ||
657 | data[6] = 0x94; /* reg 5, H start */ | ||
658 | data[8] = 0x63; /* reg 7, V start */ | ||
659 | if (sd->do_lcd_stop) | ||
660 | data[8] = 0x64; /* Bayer tile shifted */ | ||
661 | break; | ||
662 | } | ||
663 | |||
664 | err_code = mr_write(gspca_dev, 11); | ||
250 | if (err_code < 0) | 665 | if (err_code < 0) |
251 | return err_code; | 666 | return err_code; |
252 | 667 | ||
253 | data[0] = 0x1f; | 668 | if (!sd->sensor_type) { |
254 | data[1] = 0x04; | 669 | /* The only known sensor_type 0 cam is the Argus DC-1620 */ |
255 | data[2] = 0x11; | 670 | const struct sensor_w_data vga_sensor0_init_data[] = { |
256 | data[3] = 0x01; | 671 | {0x01, 0x00, {0x0c, 0x00, 0x04}, 3}, |
257 | err_code = reg_w(gspca_dev, 4); | 672 | {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4}, |
673 | {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4}, | ||
674 | {0x25, 0x00, {0x03, 0xa9, 0x80}, 3}, | ||
675 | {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4}, | ||
676 | {0, 0, {0}, 0} | ||
677 | }; | ||
678 | err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data, | ||
679 | ARRAY_SIZE(vga_sensor0_init_data)); | ||
680 | } else { /* sd->sensor_type = 1 */ | ||
681 | const struct sensor_w_data vga_sensor1_init_data[] = { | ||
682 | {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00, | ||
683 | 0x07, 0x00, 0x01}, 8}, | ||
684 | {0x11, 0x04, {0x01}, 1}, | ||
685 | /*{0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01, */ | ||
686 | {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, | ||
687 | 0x00, 0x0a}, 7}, | ||
688 | {0x11, 0x04, {0x01}, 1}, | ||
689 | {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6}, | ||
690 | {0x11, 0x04, {0x01}, 1}, | ||
691 | {0, 0, {0}, 0} | ||
692 | }; | ||
693 | err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data, | ||
694 | ARRAY_SIZE(vga_sensor1_init_data)); | ||
695 | } | ||
258 | if (err_code < 0) | 696 | if (err_code < 0) |
259 | return err_code; | 697 | return err_code; |
260 | 698 | ||
699 | msleep(200); | ||
261 | data[0] = 0x00; | 700 | data[0] = 0x00; |
262 | data[1] = 0x4d; /* ISOC transfering enable... */ | 701 | data[1] = 0x4d; /* ISOC transfering enable... */ |
263 | err_code = reg_w(gspca_dev, 2); | 702 | err_code = mr_write(gspca_dev, 2); |
703 | |||
704 | return err_code; | ||
705 | } | ||
706 | |||
707 | static int sd_start(struct gspca_dev *gspca_dev) | ||
708 | { | ||
709 | struct sd *sd = (struct sd *) gspca_dev; | ||
710 | int err_code; | ||
711 | struct cam *cam; | ||
712 | |||
713 | /* TEST TEST */ | ||
714 | int i; | ||
715 | for (i = 2; i <= 14; i++) | ||
716 | sd->regs[i] = sd_ctrls[i - 2].qctrl.default_value; | ||
717 | |||
718 | cam = &gspca_dev->cam; | ||
719 | sd->sof_read = 0; | ||
720 | /* | ||
721 | * Some of the supported cameras require the memory pointer to be | ||
722 | * set to 0, or else they will not stream. | ||
723 | */ | ||
724 | zero_the_pointer(gspca_dev); | ||
725 | msleep(200); | ||
726 | if (sd->cam_type == CAM_TYPE_CIF) { | ||
727 | PDEBUG(D_ERR, "CIF camera"); | ||
728 | err_code = start_cif_cam(gspca_dev); | ||
729 | } else { | ||
730 | PDEBUG(D_ERR, "VGA camera"); | ||
731 | err_code = start_vga_cam(gspca_dev); | ||
732 | } | ||
264 | return err_code; | 733 | return err_code; |
265 | } | 734 | } |
266 | 735 | ||
267 | static void sd_stopN(struct gspca_dev *gspca_dev) | 736 | static void sd_stopN(struct gspca_dev *gspca_dev) |
268 | { | 737 | { |
738 | struct sd *sd = (struct sd *) gspca_dev; | ||
269 | int result; | 739 | int result; |
270 | 740 | ||
271 | gspca_dev->usb_buf[0] = 1; | 741 | gspca_dev->usb_buf[0] = 1; |
272 | gspca_dev->usb_buf[1] = 0; | 742 | gspca_dev->usb_buf[1] = 0; |
273 | result = reg_w(gspca_dev, 2); | 743 | result = mr_write(gspca_dev, 2); |
274 | if (result < 0) | 744 | if (result < 0) |
275 | PDEBUG(D_ERR, "Camera Stop failed"); | 745 | PDEBUG(D_ERR, "Camera Stop failed"); |
746 | |||
747 | /* Not all the cams need this, but even if not, probably a good idea */ | ||
748 | zero_the_pointer(gspca_dev); | ||
749 | if (sd->do_lcd_stop) { | ||
750 | gspca_dev->usb_buf[0] = 0x19; | ||
751 | gspca_dev->usb_buf[1] = 0x54; | ||
752 | result = mr_write(gspca_dev, 2); | ||
753 | if (result < 0) | ||
754 | PDEBUG(D_ERR, "Camera Stop failed"); | ||
755 | } | ||
756 | } | ||
757 | |||
758 | static void setbrightness(struct gspca_dev *gspca_dev) | ||
759 | { | ||
760 | struct sd *sd = (struct sd *) gspca_dev; | ||
761 | u8 val; | ||
762 | if (sd->brightness > 0) { | ||
763 | sensor_write1(gspca_dev, 7, 0); | ||
764 | val = sd->brightness; | ||
765 | } else { | ||
766 | sensor_write1(gspca_dev, 7, 1); | ||
767 | val = 257 - sd->brightness; | ||
768 | } | ||
769 | sensor_write1(gspca_dev, 8, val); | ||
770 | } | ||
771 | |||
772 | static void setexposure(struct gspca_dev *gspca_dev) | ||
773 | { | ||
774 | struct sd *sd = (struct sd *) gspca_dev; | ||
775 | u8 val; | ||
776 | |||
777 | val = sd->exposure >> 4; | ||
778 | sensor_write1(gspca_dev, 3, val); | ||
779 | val = sd->exposure & 0xf; | ||
780 | sensor_write1(gspca_dev, 4, val); | ||
781 | } | ||
782 | |||
783 | static void setgain(struct gspca_dev *gspca_dev) | ||
784 | { | ||
785 | struct sd *sd = (struct sd *) gspca_dev; | ||
786 | |||
787 | sensor_write1(gspca_dev, 3, sd->gain); | ||
788 | } | ||
789 | |||
790 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | ||
791 | { | ||
792 | struct sd *sd = (struct sd *) gspca_dev; | ||
793 | |||
794 | sd->brightness = val; | ||
795 | if (gspca_dev->streaming) | ||
796 | setbrightness(gspca_dev); | ||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
801 | { | ||
802 | struct sd *sd = (struct sd *) gspca_dev; | ||
803 | |||
804 | *val = sd->brightness; | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val) | ||
809 | { | ||
810 | struct sd *sd = (struct sd *) gspca_dev; | ||
811 | |||
812 | sd->exposure = val; | ||
813 | if (gspca_dev->streaming) | ||
814 | setexposure(gspca_dev); | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val) | ||
819 | { | ||
820 | struct sd *sd = (struct sd *) gspca_dev; | ||
821 | |||
822 | *val = sd->exposure; | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val) | ||
827 | { | ||
828 | struct sd *sd = (struct sd *) gspca_dev; | ||
829 | |||
830 | sd->gain = val; | ||
831 | if (gspca_dev->streaming) | ||
832 | setgain(gspca_dev); | ||
833 | return 0; | ||
834 | } | ||
835 | |||
836 | static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val) | ||
837 | { | ||
838 | struct sd *sd = (struct sd *) gspca_dev; | ||
839 | |||
840 | *val = sd->gain; | ||
841 | return 0; | ||
276 | } | 842 | } |
277 | 843 | ||
278 | /* Include pac common sof detection functions */ | 844 | /* Include pac common sof detection functions */ |
@@ -320,8 +886,9 @@ static const struct sd_desc sd_desc = { | |||
320 | 886 | ||
321 | /* -- module initialisation -- */ | 887 | /* -- module initialisation -- */ |
322 | static const __devinitdata struct usb_device_id device_table[] = { | 888 | static const __devinitdata struct usb_device_id device_table[] = { |
323 | {USB_DEVICE(0x08ca, 0x0111)}, | 889 | {USB_DEVICE(0x08ca, 0x0111)}, /* Aiptek Pencam VGA+ */ |
324 | {USB_DEVICE(0x093a, 0x010f)}, | 890 | {USB_DEVICE(0x093a, 0x010f)}, /* All other known MR97310A VGA cams */ |
891 | {USB_DEVICE(0x093a, 0x010e)}, /* All known MR97310A CIF cams */ | ||
325 | {} | 892 | {} |
326 | }; | 893 | }; |
327 | MODULE_DEVICE_TABLE(usb, device_table); | 894 | MODULE_DEVICE_TABLE(usb, device_table); |