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