2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define MODULE_NAME "sonixb"
27 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev
; /* !! must be the first item */
35 struct sd_desc sd_desc
; /* our nctrls differ dependend upon the
36 sensor, so we use a per cam copy */
40 unsigned char exposure
;
41 unsigned char brightness
;
42 unsigned char autogain
;
43 unsigned char autogain_ignore_frames
;
44 unsigned char frames_to_drop
;
45 unsigned char freq
; /* light freq filter setting */
46 unsigned char saturation
;
48 unsigned char contrast
;
50 unsigned char fr_h_sz
; /* size of frame header */
51 char sensor
; /* Type of image sensor chip */
52 #define SENSOR_HV7131R 0
53 #define SENSOR_OV6650 1
54 #define SENSOR_OV7630 2
55 #define SENSOR_PAS106 3
56 #define SENSOR_PAS202 4
57 #define SENSOR_TAS5110 5
58 #define SENSOR_TAS5130CXX 6
65 #define COMP 0xc7 /* 0x87 //0x07 */
66 #define COMP1 0xc9 /* 0x89 //0x09 */
69 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
73 /* We calculate the autogain at the end of the transfer of a frame, at this
74 moment a frame with the old settings is being transmitted, and a frame is
75 being captured with the old settings. So if we adjust the autogain we must
76 ignore atleast the 2 next frames for the new settings to come into effect
77 before doing any other adjustments */
78 #define AUTOGAIN_IGNORE_FRAMES 3
79 #define AUTOGAIN_DEADZONE 1000
80 #define DESIRED_AVG_LUM 7000
82 /* V4L2 controls supported by the driver */
83 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
);
84 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
);
85 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
);
86 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
);
87 static int sd_setexposure(struct gspca_dev
*gspca_dev
, __s32 val
);
88 static int sd_getexposure(struct gspca_dev
*gspca_dev
, __s32
*val
);
89 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
);
90 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
);
91 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
);
92 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
);
93 static int sd_setsaturation(struct gspca_dev
*gspca_dev
, __s32 val
);
94 static int sd_getsaturation(struct gspca_dev
*gspca_dev
, __s32
*val
);
95 static int sd_sethue(struct gspca_dev
*gspca_dev
, __s32 val
);
96 static int sd_gethue(struct gspca_dev
*gspca_dev
, __s32
*val
);
97 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
);
98 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
);
100 static struct ctrl sd_ctrls
[] = {
103 .id
= V4L2_CID_BRIGHTNESS
,
104 .type
= V4L2_CTRL_TYPE_INTEGER
,
105 .name
= "Brightness",
109 #define BRIGHTNESS_DEF 127
110 .default_value
= BRIGHTNESS_DEF
,
112 .set
= sd_setbrightness
,
113 .get
= sd_getbrightness
,
118 .type
= V4L2_CTRL_TYPE_INTEGER
,
124 #define GAIN_KNEE 200
125 .default_value
= GAIN_DEF
,
132 .id
= V4L2_CID_EXPOSURE
,
133 .type
= V4L2_CTRL_TYPE_INTEGER
,
135 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
140 .default_value
= EXPOSURE_DEF
,
143 .set
= sd_setexposure
,
144 .get
= sd_getexposure
,
148 .id
= V4L2_CID_AUTOGAIN
,
149 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
150 .name
= "Automatic Gain (and Exposure)",
154 #define AUTOGAIN_DEF 1
155 .default_value
= AUTOGAIN_DEF
,
158 .set
= sd_setautogain
,
159 .get
= sd_getautogain
,
163 .id
= V4L2_CID_POWER_LINE_FREQUENCY
,
164 .type
= V4L2_CTRL_TYPE_MENU
,
165 .name
= "Light frequency filter",
167 .maximum
= 2, /* 0: 0, 1: 50Hz, 2:60Hz */
170 .default_value
= FREQ_DEF
,
177 .id
= V4L2_CID_SATURATION
,
178 .type
= V4L2_CTRL_TYPE_INTEGER
,
179 .name
= "Saturation",
183 #define SATURATION_DEF 127
184 .default_value
= SATURATION_DEF
,
186 .set
= sd_setsaturation
,
187 .get
= sd_getsaturation
,
192 .type
= V4L2_CTRL_TYPE_INTEGER
,
198 .default_value
= HUE_DEF
,
205 .id
= V4L2_CID_CONTRAST
,
206 .type
= V4L2_CTRL_TYPE_INTEGER
,
211 #define CONTRAST_DEF 127
212 .default_value
= CONTRAST_DEF
,
214 .set
= sd_setcontrast
,
215 .get
= sd_getcontrast
,
219 static struct v4l2_pix_format vga_mode
[] = {
220 {160, 120, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
222 .sizeimage
= 160 * 120,
223 .colorspace
= V4L2_COLORSPACE_SRGB
,
225 {320, 240, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
227 .sizeimage
= 320 * 240,
228 .colorspace
= V4L2_COLORSPACE_SRGB
,
230 {640, 480, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
232 .sizeimage
= 640 * 480,
233 .colorspace
= V4L2_COLORSPACE_SRGB
,
236 static struct v4l2_pix_format sif_mode
[] = {
237 {176, 144, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
239 .sizeimage
= 176 * 144,
240 .colorspace
= V4L2_COLORSPACE_SRGB
,
242 {352, 288, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
244 .sizeimage
= 352 * 288,
245 .colorspace
= V4L2_COLORSPACE_SRGB
,
249 static const __u8 probe_ov7630
[] = {0x08, 0x44};
251 static const __u8 initHv7131
[] = {
252 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
254 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
255 0x28, 0x1e, 0x60, 0x8a, 0x20,
256 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
258 static const __u8 hv7131_sensor_init
[][8] = {
259 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
260 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
261 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
262 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
263 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
265 static const __u8 initOv6650
[] = {
266 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
267 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
269 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
271 static const __u8 ov6650_sensor_init
[][8] =
273 /* Bright, contrast, etc are set througth SCBB interface.
274 * AVCAP on win2 do not send any data on this controls. */
275 /* Anyway, some registers appears to alter bright and constrat */
278 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
279 /* Set clock register 0x11 low nibble is clock divider */
280 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
281 /* Next some unknown stuff */
282 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
283 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
284 * THIS SET GREEN SCREEN
285 * (pixels could be innverted in decode kind of "brg",
286 * but blue wont be there. Avoid this data ... */
287 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
288 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
289 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
290 /* Enable rgb brightness control */
291 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
292 /* HDG: Note windows uses the line below, which sets both register 0x60
293 and 0x61 I believe these registers of the ov6650 are identical as
294 those of the ov7630, because if this is true the windows settings
295 add a bit additional red gain and a lot additional blue gain, which
296 matches my findings that the windows settings make blue much too
297 blue and red a little too red.
298 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
299 /* Some more unknown stuff */
300 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
301 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
304 static const __u8 initOv7630
[] = {
305 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
306 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
307 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
308 0x28, 0x1e, /* H & V sizes r15 .. r16 */
309 0x68, COMP1
, MCK_INIT1
, /* r17 .. r19 */
310 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
312 static const __u8 initOv7630_3
[] = {
313 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
314 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
315 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
316 0x28, 0x1e, /* H & V sizes r15 .. r16 */
317 0x68, 0x8f, MCK_INIT1
, /* r17 .. r19 */
318 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
319 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
320 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
322 static const __u8 ov7630_sensor_init
[][8] = {
323 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
324 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
325 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
326 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
327 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
328 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
329 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
330 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
331 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
332 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
333 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
334 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
335 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
336 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
337 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
338 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
339 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
340 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
341 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
344 static const __u8 initPas106
[] = {
345 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
348 0x16, 0x12, 0x28, COMP1
, MCK_INIT1
,
349 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
351 /* compression 0x86 mckinit1 0x2b */
352 static const __u8 pas106_data
[][2] = {
353 {0x02, 0x04}, /* Pixel Clock Divider 6 */
354 {0x03, 0x13}, /* Frame Time MSB */
355 /* {0x03, 0x12}, * Frame Time MSB */
356 {0x04, 0x06}, /* Frame Time LSB */
357 /* {0x04, 0x05}, * Frame Time LSB */
358 {0x05, 0x65}, /* Shutter Time Line Offset */
359 /* {0x05, 0x6d}, * Shutter Time Line Offset */
360 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
361 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
362 {0x07, 0xc1}, /* Black Level Subtract Sign */
363 /* {0x07, 0x00}, * Black Level Subtract Sign */
364 {0x08, 0x06}, /* Black Level Subtract Level */
365 {0x08, 0x06}, /* Black Level Subtract Level */
366 /* {0x08, 0x01}, * Black Level Subtract Level */
367 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
368 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
369 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
370 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
371 {0x0d, 0x00}, /* Color GainH Pixel */
372 {0x0e, 0x0e}, /* Global Gain */
373 {0x0f, 0x00}, /* Contrast */
374 {0x10, 0x06}, /* H&V synchro polarity */
375 {0x11, 0x06}, /* ?default */
376 {0x12, 0x06}, /* DAC scale */
377 {0x14, 0x02}, /* ?default */
378 {0x13, 0x01}, /* Validate Settings */
380 static const __u8 initPas202
[] = {
381 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
384 0x28, 0x1e, 0x28, 0x89, 0x30,
385 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
387 static const __u8 pas202_sensor_init
[][8] = {
388 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
389 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
390 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
391 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
392 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
393 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
394 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
395 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
396 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
397 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
398 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
399 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
401 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
402 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
403 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
404 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
405 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
406 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
407 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
408 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
411 static const __u8 initTas5110
[] = {
412 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
414 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
415 0x16, 0x12, 0x60, 0x86, 0x2b,
416 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
418 static const __u8 tas5110_sensor_init
[][8] = {
419 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
420 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
421 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
424 static const __u8 initTas5130
[] = {
425 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
427 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
428 0x28, 0x1e, 0x60, COMP
, MCK_INIT
,
429 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
431 static const __u8 tas5130_sensor_init
[][8] = {
432 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
433 * shutter 0x47 short exposure? */
434 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
435 /* shutter 0x01 long exposure */
436 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
439 /* get one byte in gspca_dev->usb_buf */
440 static void reg_r(struct gspca_dev
*gspca_dev
,
443 usb_control_msg(gspca_dev
->dev
,
444 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
446 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
449 gspca_dev
->usb_buf
, 1,
453 static void reg_w(struct gspca_dev
*gspca_dev
,
458 #ifdef CONFIG_VIDEO_ADV_DEBUG
459 if (len
> sizeof gspca_dev
->usb_buf
) {
460 PDEBUG(D_ERR
|D_PACK
, "reg_w: buffer overflow");
464 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
465 usb_control_msg(gspca_dev
->dev
,
466 usb_sndctrlpipe(gspca_dev
->dev
, 0),
468 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
471 gspca_dev
->usb_buf
, len
,
475 static void reg_w_big(struct gspca_dev
*gspca_dev
,
482 tmpbuf
= kmalloc(len
, GFP_KERNEL
);
483 memcpy(tmpbuf
, buffer
, len
);
484 usb_control_msg(gspca_dev
->dev
,
485 usb_sndctrlpipe(gspca_dev
->dev
, 0),
487 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
495 static int i2c_w(struct gspca_dev
*gspca_dev
, const __u8
*buffer
)
500 reg_w(gspca_dev
, 0x08, buffer
, 8);
503 reg_r(gspca_dev
, 0x08);
504 if (gspca_dev
->usb_buf
[0] & 0x04) {
505 if (gspca_dev
->usb_buf
[0] & 0x08)
513 static void i2c_w_vector(struct gspca_dev
*gspca_dev
,
514 const __u8 buffer
[][8], int len
)
517 reg_w(gspca_dev
, 0x08, *buffer
, 8);
525 static void setbrightness(struct gspca_dev
*gspca_dev
)
527 struct sd
*sd
= (struct sd
*) gspca_dev
;
530 switch (sd
->sensor
) {
532 case SENSOR_OV7630
: {
534 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
536 /* change reg 0x06 */
537 i2cOV
[1] = sd
->sensor_addr
;
538 i2cOV
[3] = sd
->brightness
;
539 if (i2c_w(gspca_dev
, i2cOV
) < 0)
543 case SENSOR_PAS106
: {
545 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
547 i2c1
[3] = sd
->brightness
>> 3;
549 if (i2c_w(gspca_dev
, i2c1
) < 0)
553 if (i2c_w(gspca_dev
, i2c1
) < 0)
557 case SENSOR_PAS202
: {
558 /* __u8 i2cpexpo1[] =
559 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
561 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
563 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
564 static __u8 i2cpdoit
[] =
565 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
567 /* change reg 0x10 */
568 i2cpexpo
[4] = 0xff - sd
->brightness
;
569 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
571 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
573 if (i2c_w(gspca_dev
, i2cpexpo
) < 0)
575 if (i2c_w(gspca_dev
, i2cpdoit
) < 0)
577 i2cp202
[3] = sd
->brightness
>> 3;
578 if (i2c_w(gspca_dev
, i2cp202
) < 0)
580 if (i2c_w(gspca_dev
, i2cpdoit
) < 0)
584 case SENSOR_TAS5130CXX
: {
586 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
588 value
= 0xff - sd
->brightness
;
590 PDEBUG(D_CONF
, "brightness %d : %d", value
, i2c
[4]);
591 if (i2c_w(gspca_dev
, i2c
) < 0)
596 /* FIXME figure out howto control brightness on TAS5110 */
601 PDEBUG(D_ERR
, "i2c error brightness");
604 static void setsensorgain(struct gspca_dev
*gspca_dev
)
606 struct sd
*sd
= (struct sd
*) gspca_dev
;
607 unsigned char gain
= sd
->gain
;
609 switch (sd
->sensor
) {
611 case SENSOR_TAS5110
: {
613 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
616 if (i2c_w(gspca_dev
, i2c
) < 0)
624 case SENSOR_OV7630
: {
625 __u8 i2c
[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
627 i2c
[1] = sd
->sensor_addr
;
629 if (i2c_w(gspca_dev
, i2c
) < 0)
636 PDEBUG(D_ERR
, "i2c error gain");
639 static void setgain(struct gspca_dev
*gspca_dev
)
641 struct sd
*sd
= (struct sd
*) gspca_dev
;
645 gain
= sd
->gain
>> 4;
647 /* red and blue gain */
648 rgb_value
= gain
<< 4 | gain
;
649 reg_w(gspca_dev
, 0x10, &rgb_value
, 1);
652 reg_w(gspca_dev
, 0x11, &rgb_value
, 1);
654 if (sd
->sensor_has_gain
)
655 setsensorgain(gspca_dev
);
658 static void setexposure(struct gspca_dev
*gspca_dev
)
660 struct sd
*sd
= (struct sd
*) gspca_dev
;
662 switch (sd
->sensor
) {
663 case SENSOR_TAS5110
: {
666 /* register 19's high nibble contains the sn9c10x clock divider
667 The high nibble configures the no fps according to the
668 formula: 60 / high_nibble. With a maximum of 30 fps */
669 reg
= 120 * sd
->exposure
/ 1000;
674 reg
= (reg
<< 4) | 0x0b;
675 reg_w(gspca_dev
, 0x19, ®
, 1);
679 case SENSOR_OV7630
: {
680 /* The ov6650 / ov7630 have 2 registers which both influence
681 exposure, register 11, whose low nibble sets the nr off fps
682 according to: fps = 30 / (low_nibble + 1)
684 The fps configures the maximum exposure setting, but it is
685 possible to use less exposure then what the fps maximum
686 allows by setting register 10. register 10 configures the
687 actual exposure as quotient of the full exposure, with 0
688 being no exposure at all (not very usefull) and reg10_max
689 being max exposure possible at that framerate.
691 The code maps our 0 - 510 ms exposure ctrl to these 2
692 registers, trying to keep fps as high as possible.
694 __u8 i2c
[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
695 int reg10
, reg11
, reg10_max
;
697 /* ov6645 datasheet says reg10_max is 9a, but that uses
698 tline * 2 * reg10 as formula for calculating texpo, the
699 ov6650 probably uses the same formula as the 7730 which uses
700 tline * 4 * reg10, which explains why the reg10max we've
701 found experimentally for the ov6650 is exactly half that of
702 the ov6645. The ov7630 datasheet says the max is 0x41. */
703 if (sd
->sensor
== SENSOR_OV6650
) {
705 i2c
[4] = 0xc0; /* OV6650 needs non default vsync pol */
709 reg11
= (60 * sd
->exposure
+ 999) / 1000;
715 /* frame exposure time in ms = 1000 * reg11 / 30 ->
716 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
717 reg10
= (sd
->exposure
* 60 * reg10_max
) / (1000 * reg11
);
719 /* Don't allow this to get below 10 when using autogain, the
720 steps become very large (relatively) when below 10 causing
721 the image to oscilate from much too dark, to much too bright
723 if (sd
->autogain
&& reg10
< 10)
725 else if (reg10
> reg10_max
)
728 /* In 640x480, if the reg11 has less than 3, the image is
729 unstable (not enough bandwidth). */
730 if (gspca_dev
->width
== 640 && reg11
< 3)
733 /* Write reg 10 and reg11 low nibble */
734 i2c
[1] = sd
->sensor_addr
;
738 /* If register 11 didn't change, don't change it */
739 if (sd
->reg11
== reg11
)
742 if (i2c_w(gspca_dev
, i2c
) == 0)
745 PDEBUG(D_ERR
, "i2c error exposure");
751 static void setfreq(struct gspca_dev
*gspca_dev
)
753 struct sd
*sd
= (struct sd
*) gspca_dev
;
755 switch (sd
->sensor
) {
757 case SENSOR_OV7630
: {
758 /* Framerate adjust register for artificial light 50 hz flicker
759 compensation, for the ov6650 this is identical to ov6630
760 0x2b register, see ov6630 datasheet.
761 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
762 __u8 i2c
[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
765 /* case 0: * no filter*/
766 /* case 2: * 60 hz */
770 i2c
[3] = (sd
->sensor
== SENSOR_OV6650
)
774 i2c
[1] = sd
->sensor_addr
;
775 if (i2c_w(gspca_dev
, i2c
) < 0)
776 PDEBUG(D_ERR
, "i2c error setfreq");
782 static void setsaturation(struct gspca_dev
*gspca_dev
)
784 struct sd
*sd
= (struct sd
*) gspca_dev
;
786 switch (sd
->sensor
) {
787 /* case SENSOR_OV6650: */
788 case SENSOR_OV7630
: {
789 __u8 i2c
[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
790 i2c
[1] = sd
->sensor_addr
;
791 i2c
[3] = sd
->saturation
& 0xf0;
792 if (i2c_w(gspca_dev
, i2c
) < 0)
793 PDEBUG(D_ERR
, "i2c error setsaturation");
795 PDEBUG(D_CONF
, "saturation set to: %d",
796 (int)sd
->saturation
);
802 static void sethue(struct gspca_dev
*gspca_dev
)
804 struct sd
*sd
= (struct sd
*) gspca_dev
;
806 switch (sd
->sensor
) {
807 /* case SENSOR_OV6650: */
808 case SENSOR_OV7630
: {
809 __u8 i2c
[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
810 i2c
[1] = sd
->sensor_addr
;
811 i2c
[3] = 0x20 | (sd
->hue
>> 3);
812 if (i2c_w(gspca_dev
, i2c
) < 0)
813 PDEBUG(D_ERR
, "i2c error setsaturation");
815 PDEBUG(D_CONF
, "hue set to: %d", (int)sd
->hue
);
821 static void setcontrast(struct gspca_dev
*gspca_dev
)
823 struct sd
*sd
= (struct sd
*) gspca_dev
;
825 switch (sd
->sensor
) {
826 /* case SENSOR_OV6650: */
827 case SENSOR_OV7630
: {
828 __u8 i2c
[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
829 i2c
[1] = sd
->sensor_addr
;
830 i2c
[3] = 0x20 | (sd
->contrast
>> 3);
831 if (i2c_w(gspca_dev
, i2c
) < 0)
832 PDEBUG(D_ERR
, "i2c error setcontrast");
834 PDEBUG(D_CONF
, "contrast set to: %d",
842 static void do_autogain(struct gspca_dev
*gspca_dev
)
844 struct sd
*sd
= (struct sd
*) gspca_dev
;
845 int avg_lum
= atomic_read(&sd
->avg_lum
);
850 if (sd
->autogain_ignore_frames
> 0)
851 sd
->autogain_ignore_frames
--;
852 else if (gspca_auto_gain_n_exposure(gspca_dev
, avg_lum
,
853 sd
->brightness
* DESIRED_AVG_LUM
/ 127,
854 AUTOGAIN_DEADZONE
, GAIN_KNEE
, EXPOSURE_KNEE
)) {
855 PDEBUG(D_FRAM
, "autogain: gain changed: gain: %d expo: %d\n",
856 (int)sd
->gain
, (int)sd
->exposure
);
857 sd
->autogain_ignore_frames
= AUTOGAIN_IGNORE_FRAMES
;
861 /* this function is called at probe time */
862 static int sd_config(struct gspca_dev
*gspca_dev
,
863 const struct usb_device_id
*id
)
865 struct sd
*sd
= (struct sd
*) gspca_dev
;
870 /* nctrls depends upon the sensor, so we use a per cam copy */
871 memcpy(&sd
->sd_desc
, gspca_dev
->sd_desc
, sizeof(struct sd_desc
));
872 gspca_dev
->sd_desc
= &sd
->sd_desc
;
874 sd
->fr_h_sz
= 12; /* default size of the frame header */
875 sd
->sd_desc
.nctrls
= 2; /* default nb of ctrls */
876 product
= id
->idProduct
;
877 /* switch (id->idVendor) { */
878 /* case 0x0c45: * Sonix */
880 case 0x6001: /* SN9C102 */
881 case 0x6005: /* SN9C101 */
882 case 0x6007: /* SN9C101 */
883 sd
->sensor
= SENSOR_TAS5110
;
884 sd
->sensor_has_gain
= 1;
885 sd
->sd_desc
.nctrls
= 4;
886 sd
->sd_desc
.dq_callback
= do_autogain
;
889 case 0x6009: /* SN9C101 */
890 case 0x600d: /* SN9C101 */
891 case 0x6029: /* SN9C101 */
892 sd
->sensor
= SENSOR_PAS106
;
895 case 0x6011: /* SN9C101 - SN9C101G */
896 sd
->sensor
= SENSOR_OV6650
;
897 sd
->sensor_has_gain
= 1;
898 sd
->sensor_addr
= 0x60;
899 sd
->sd_desc
.nctrls
= 5;
900 sd
->sd_desc
.dq_callback
= do_autogain
;
903 case 0x6019: /* SN9C101 */
904 case 0x602c: /* SN9C102 */
905 case 0x602e: /* SN9C102 */
906 case 0x60b0: /* SN9C103 */
907 sd
->sensor
= SENSOR_OV7630
;
908 sd
->sensor_addr
= 0x21;
909 sd
->sensor_has_gain
= 1;
910 sd
->sd_desc
.nctrls
= 5;
911 sd
->sd_desc
.dq_callback
= do_autogain
;
912 if (product
== 0x60b0)
913 sd
->fr_h_sz
= 18; /* size of frame header */
915 case 0x6024: /* SN9C102 */
916 case 0x6025: /* SN9C102 */
917 sd
->sensor
= SENSOR_TAS5130CXX
;
919 case 0x6028: /* SN9C102 */
920 sd
->sensor
= SENSOR_PAS202
;
922 case 0x602d: /* SN9C102 */
923 sd
->sensor
= SENSOR_HV7131R
;
925 case 0x60af: /* SN9C103 */
926 sd
->sensor
= SENSOR_PAS202
;
927 sd
->fr_h_sz
= 18; /* size of frame header (?) */
933 cam
= &gspca_dev
->cam
;
934 cam
->dev_name
= (char *) id
->driver_info
;
937 cam
->cam_mode
= vga_mode
;
938 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
939 if (product
== 0x60b0) { /* SN9C103 with OV7630 */
940 /* We only have 320x240 & 640x480 */
945 cam
->cam_mode
= sif_mode
;
946 cam
->nmodes
= ARRAY_SIZE(sif_mode
);
948 sd
->brightness
= BRIGHTNESS_DEF
;
950 sd
->exposure
= EXPOSURE_DEF
;
951 sd
->autogain
= AUTOGAIN_DEF
;
953 sd
->contrast
= CONTRAST_DEF
;
954 sd
->saturation
= SATURATION_DEF
;
957 if (product
== 0x60b0) /* SN9C103 with OV7630 */
958 reg_w(gspca_dev
, 0x01, probe_ov7630
, sizeof probe_ov7630
);
963 /* this function is called at open time */
964 static int sd_open(struct gspca_dev
*gspca_dev
)
966 reg_r(gspca_dev
, 0x00);
967 if (gspca_dev
->usb_buf
[0] != 0x10)
972 static void pas106_i2cinit(struct gspca_dev
*gspca_dev
)
976 __u8 i2c1
[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
978 i
= ARRAY_SIZE(pas106_data
);
979 data
= pas106_data
[0];
981 memcpy(&i2c1
[2], data
, 2);
982 /* copy 2 bytes from the template */
983 if (i2c_w(gspca_dev
, i2c1
) < 0)
984 PDEBUG(D_ERR
, "i2c error pas106");
989 /* -- start the camera -- */
990 static void sd_start(struct gspca_dev
*gspca_dev
)
992 struct sd
*sd
= (struct sd
*) gspca_dev
;
998 mode
= gspca_dev
->cam
.cam_mode
[(int) gspca_dev
->curr_mode
].priv
;
999 switch (sd
->sensor
) {
1000 case SENSOR_HV7131R
:
1001 sn9c10x
= initHv7131
;
1003 reg17_19
[1] = (mode
<< 4) | 0x8a;
1007 sn9c10x
= initOv6650
;
1009 reg17_19
[1] = (mode
<< 4) | 0x8b;
1013 if (sd
->fr_h_sz
== 18) { /* SN9C103 */
1014 sn9c10x
= initOv7630_3
;
1015 l
= sizeof initOv7630_3
;
1017 sn9c10x
= initOv7630
;
1019 reg17_19
[1] = (mode
<< 4) | COMP2
;
1020 reg17_19
[2] = MCK_INIT1
;
1023 sn9c10x
= initPas106
;
1024 reg17_19
[0] = 0x24; /* 0x28 */
1025 reg17_19
[1] = (mode
<< 4) | COMP1
;
1026 reg17_19
[2] = MCK_INIT1
;
1029 sn9c10x
= initPas202
;
1030 reg17_19
[0] = mode
? 0x24 : 0x20;
1031 reg17_19
[1] = (mode
<< 4) | 0x89;
1034 case SENSOR_TAS5110
:
1035 sn9c10x
= initTas5110
;
1037 reg17_19
[1] = (mode
<< 4) | 0x86;
1038 reg17_19
[2] = 0x2b; /* 0xf3; */
1041 /* case SENSOR_TAS5130CXX: */
1042 sn9c10x
= initTas5130
;
1044 reg17_19
[1] = (mode
<< 4) | COMP
;
1045 reg17_19
[2] = mode
? 0x23 : 0x43;
1049 /* Special case for SN9C101/2 with OV 7630 */
1050 /* HDG: is this really necessary we overwrite the values immediately
1051 afterwards with the ones from the template ?? */
1052 if (sd
->sensor
== SENSOR_OV7630
&& sd
->fr_h_sz
== 12) {
1057 reg17
= sn9c10x
[0x17 - 1];
1060 /* reg 0x01 bit 2 video transfert on */
1061 reg_w(gspca_dev
, 0x01, ®01
, 1);
1062 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1063 reg_w(gspca_dev
, 0x17, ®17
, 1);
1064 /* Set the registers from the template */
1065 reg_w_big(gspca_dev
, 0x01, sn9c10x
, l
);
1066 switch (sd
->sensor
) {
1067 case SENSOR_HV7131R
:
1068 i2c_w_vector(gspca_dev
, hv7131_sensor_init
,
1069 sizeof hv7131_sensor_init
);
1072 i2c_w_vector(gspca_dev
, ov6650_sensor_init
,
1073 sizeof ov6650_sensor_init
);
1076 i2c_w_vector(gspca_dev
, ov7630_sensor_init
,
1077 sizeof ov7630_sensor_init
);
1078 if (sd
->fr_h_sz
== 18) { /* SN9C103 */
1079 const __u8 i2c
[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
1081 i2c_w(gspca_dev
, i2c
);
1085 pas106_i2cinit(gspca_dev
);
1088 i2c_w_vector(gspca_dev
, pas202_sensor_init
,
1089 sizeof pas202_sensor_init
);
1091 case SENSOR_TAS5110
:
1092 i2c_w_vector(gspca_dev
, tas5110_sensor_init
,
1093 sizeof tas5110_sensor_init
);
1096 /* case SENSOR_TAS5130CXX: */
1097 i2c_w_vector(gspca_dev
, tas5130_sensor_init
,
1098 sizeof tas5130_sensor_init
);
1101 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1102 reg_w(gspca_dev
, 0x15, &sn9c10x
[0x15 - 1], 2);
1103 /* compression register */
1104 reg_w(gspca_dev
, 0x18, ®17_19
[1], 1);
1106 reg_w(gspca_dev
, 0x12, &sn9c10x
[0x12 - 1], 1);
1108 reg_w(gspca_dev
, 0x13, &sn9c10x
[0x13 - 1], 1);
1109 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1110 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1111 reg_w(gspca_dev
, 0x17, ®17_19
[0], 1);
1112 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1113 reg_w(gspca_dev
, 0x19, ®17_19
[2], 1);
1114 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1115 reg_w(gspca_dev
, 0x1c, &sn9c10x
[0x1c - 1], 4);
1116 /* Enable video transfert */
1117 reg_w(gspca_dev
, 0x01, &sn9c10x
[0], 1);
1119 reg_w(gspca_dev
, 0x18, ®17_19
[1], 2);
1125 setbrightness(gspca_dev
);
1126 setexposure(gspca_dev
);
1128 setsaturation(gspca_dev
);
1130 setcontrast(gspca_dev
);
1132 sd
->frames_to_drop
= 0;
1133 sd
->autogain_ignore_frames
= 0;
1134 atomic_set(&sd
->avg_lum
, -1);
1137 static void sd_stopN(struct gspca_dev
*gspca_dev
)
1141 ByteSend
= 0x09; /* 0X00 */
1142 reg_w(gspca_dev
, 0x01, &ByteSend
, 1);
1145 static void sd_stop0(struct gspca_dev
*gspca_dev
)
1149 static void sd_close(struct gspca_dev
*gspca_dev
)
1153 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
1154 struct gspca_frame
*frame
, /* target */
1155 unsigned char *data
, /* isoc packet */
1156 int len
) /* iso packet length */
1159 struct sd
*sd
= (struct sd
*) gspca_dev
;
1161 /* frames start with:
1162 * ff ff 00 c4 c4 96 synchro
1164 * xx (frame sequence / size / compression)
1165 * (xx) (idem - extra byte for sn9c103)
1166 * ll mm brightness sum inside auto exposure
1167 * ll mm brightness sum outside auto exposure
1168 * (xx xx xx xx xx) audio values for snc103
1170 if (len
> 6 && len
< 24) {
1171 for (i
= 0; i
< len
- 6; i
++) {
1172 if (data
[0 + i
] == 0xff
1173 && data
[1 + i
] == 0xff
1174 && data
[2 + i
] == 0x00
1175 && data
[3 + i
] == 0xc4
1176 && data
[4 + i
] == 0xc4
1177 && data
[5 + i
] == 0x96) { /* start of frame */
1179 int pkt_type
= LAST_PACKET
;
1181 if (len
- i
< sd
->fr_h_sz
) {
1182 PDEBUG(D_STREAM
, "packet too short to"
1183 " get avg brightness");
1184 } else if (sd
->fr_h_sz
== 12) {
1185 lum
= data
[i
+ 8] + (data
[i
+ 9] << 8);
1188 (data
[i
+ 10] << 8);
1192 sd
->frames_to_drop
= 2;
1194 atomic_set(&sd
->avg_lum
, lum
);
1196 if (sd
->frames_to_drop
) {
1197 sd
->frames_to_drop
--;
1198 pkt_type
= DISCARD_PACKET
;
1201 frame
= gspca_frame_add(gspca_dev
, pkt_type
,
1203 data
+= i
+ sd
->fr_h_sz
;
1204 len
-= i
+ sd
->fr_h_sz
;
1205 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
1211 gspca_frame_add(gspca_dev
, INTER_PACKET
,
1215 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1217 struct sd
*sd
= (struct sd
*) gspca_dev
;
1219 sd
->brightness
= val
;
1220 if (gspca_dev
->streaming
)
1221 setbrightness(gspca_dev
);
1225 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1227 struct sd
*sd
= (struct sd
*) gspca_dev
;
1229 *val
= sd
->brightness
;
1233 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
)
1235 struct sd
*sd
= (struct sd
*) gspca_dev
;
1238 if (gspca_dev
->streaming
)
1243 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1245 struct sd
*sd
= (struct sd
*) gspca_dev
;
1251 static int sd_setexposure(struct gspca_dev
*gspca_dev
, __s32 val
)
1253 struct sd
*sd
= (struct sd
*) gspca_dev
;
1256 if (gspca_dev
->streaming
)
1257 setexposure(gspca_dev
);
1261 static int sd_getexposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
1263 struct sd
*sd
= (struct sd
*) gspca_dev
;
1265 *val
= sd
->exposure
;
1269 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
1271 struct sd
*sd
= (struct sd
*) gspca_dev
;
1274 /* when switching to autogain set defaults to make sure
1275 we are on a valid point of the autogain gain /
1276 exposure knee graph, and give this change time to
1277 take effect before doing autogain. */
1279 sd
->exposure
= EXPOSURE_DEF
;
1280 sd
->gain
= GAIN_DEF
;
1281 if (gspca_dev
->streaming
) {
1282 sd
->autogain_ignore_frames
= AUTOGAIN_IGNORE_FRAMES
;
1283 setexposure(gspca_dev
);
1291 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1293 struct sd
*sd
= (struct sd
*) gspca_dev
;
1295 *val
= sd
->autogain
;
1299 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
)
1301 struct sd
*sd
= (struct sd
*) gspca_dev
;
1304 if (gspca_dev
->streaming
)
1309 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
)
1311 struct sd
*sd
= (struct sd
*) gspca_dev
;
1317 static int sd_setsaturation(struct gspca_dev
*gspca_dev
, __s32 val
)
1319 struct sd
*sd
= (struct sd
*) gspca_dev
;
1321 sd
->saturation
= val
;
1322 if (gspca_dev
->streaming
)
1323 setsaturation(gspca_dev
);
1327 static int sd_getsaturation(struct gspca_dev
*gspca_dev
, __s32
*val
)
1329 struct sd
*sd
= (struct sd
*) gspca_dev
;
1331 *val
= sd
->saturation
;
1335 static int sd_sethue(struct gspca_dev
*gspca_dev
, __s32 val
)
1337 struct sd
*sd
= (struct sd
*) gspca_dev
;
1340 if (gspca_dev
->streaming
)
1345 static int sd_gethue(struct gspca_dev
*gspca_dev
, __s32
*val
)
1347 struct sd
*sd
= (struct sd
*) gspca_dev
;
1353 static int sd_setcontrast(struct gspca_dev
*gspca_dev
, __s32 val
)
1355 struct sd
*sd
= (struct sd
*) gspca_dev
;
1358 if (gspca_dev
->streaming
)
1359 setcontrast(gspca_dev
);
1363 static int sd_getcontrast(struct gspca_dev
*gspca_dev
, __s32
*val
)
1365 struct sd
*sd
= (struct sd
*) gspca_dev
;
1367 *val
= sd
->contrast
;
1371 static int sd_querymenu(struct gspca_dev
*gspca_dev
,
1372 struct v4l2_querymenu
*menu
)
1375 case V4L2_CID_POWER_LINE_FREQUENCY
:
1376 switch (menu
->index
) {
1377 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1378 strcpy((char *) menu
->name
, "NoFliker");
1380 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1381 strcpy((char *) menu
->name
, "50 Hz");
1383 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1384 strcpy((char *) menu
->name
, "60 Hz");
1392 /* sub-driver description */
1393 static const struct sd_desc sd_desc
= {
1394 .name
= MODULE_NAME
,
1396 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1397 .config
= sd_config
,
1403 .pkt_scan
= sd_pkt_scan
,
1404 .querymenu
= sd_querymenu
,
1407 /* -- module initialisation -- */
1408 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1409 static __devinitdata
struct usb_device_id device_table
[] = {
1410 #ifndef CONFIG_USB_SN9C102
1411 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1412 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1413 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1414 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1415 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1417 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1418 #ifndef CONFIG_USB_SN9C102
1419 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1420 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1421 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1422 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1423 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1424 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1425 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1426 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1427 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1428 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1432 MODULE_DEVICE_TABLE(usb
, device_table
);
1434 /* -- device connect -- */
1435 static int sd_probe(struct usb_interface
*intf
,
1436 const struct usb_device_id
*id
)
1438 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1442 static struct usb_driver sd_driver
= {
1443 .name
= MODULE_NAME
,
1444 .id_table
= device_table
,
1446 .disconnect
= gspca_disconnect
,
1449 /* -- module insert / remove -- */
1450 static int __init
sd_mod_init(void)
1452 if (usb_register(&sd_driver
) < 0)
1454 PDEBUG(D_PROBE
, "registered");
1457 static void __exit
sd_mod_exit(void)
1459 usb_deregister(&sd_driver
);
1460 PDEBUG(D_PROBE
, "deregistered");
1463 module_init(sd_mod_init
);
1464 module_exit(sd_mod_exit
);