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 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28 static const char version[] = "2.1.8";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
39 sensor, so we use a per cam copy */
43 unsigned char exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
48 unsigned char saturation;
50 unsigned char contrast;
52 unsigned char fr_h_sz; /* size of frame header */
53 char sensor; /* Type of image sensor chip */
54 #define SENSOR_HV7131R 0
55 #define SENSOR_OV6650 1
56 #define SENSOR_OV7630 2
57 #define SENSOR_OV7630_3 3
58 #define SENSOR_PAS106 4
59 #define SENSOR_PAS202 5
60 #define SENSOR_TAS5110 6
61 #define SENSOR_TAS5130CXX 7
67 #define COMP 0xc7 /* 0x87 //0x07 */
68 #define COMP1 0xc9 /* 0x89 //0x09 */
71 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
75 /* We calculate the autogain at the end of the transfer of a frame, at this
76 moment a frame with the old settings is being transmitted, and a frame is
77 being captured with the old settings. So if we adjust the autogain we must
78 ignore atleast the 2 next frames for the new settings to come into effect
79 before doing any other adjustments */
80 #define AUTOGAIN_IGNORE_FRAMES 3
81 #define AUTOGAIN_DEADZONE 1000
82 #define DESIRED_AVG_LUM 7000
84 /* V4L2 controls supported by the driver */
85 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
92 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
93 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
94 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
95 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
96 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
97 static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
98 static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
99 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
100 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
102 static struct ctrl sd_ctrls[] = {
105 .id = V4L2_CID_BRIGHTNESS,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Brightness",
111 #define BRIGHTNESS_DEF 127
112 .default_value = BRIGHTNESS_DEF,
114 .set = sd_setbrightness,
115 .get = sd_getbrightness,
120 .type = V4L2_CTRL_TYPE_INTEGER,
126 #define GAIN_KNEE 200
127 .default_value = GAIN_DEF,
134 .id = V4L2_CID_EXPOSURE,
135 .type = V4L2_CTRL_TYPE_INTEGER,
137 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
138 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
142 .default_value = EXPOSURE_DEF,
145 .set = sd_setexposure,
146 .get = sd_getexposure,
150 .id = V4L2_CID_AUTOGAIN,
151 .type = V4L2_CTRL_TYPE_BOOLEAN,
152 .name = "Automatic Gain (and Exposure)",
156 #define AUTOGAIN_DEF 1
157 .default_value = AUTOGAIN_DEF,
160 .set = sd_setautogain,
161 .get = sd_getautogain,
165 .id = V4L2_CID_POWER_LINE_FREQUENCY,
166 .type = V4L2_CTRL_TYPE_MENU,
167 .name = "Light frequency filter",
169 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
172 .default_value = FREQ_DEF,
179 .id = V4L2_CID_SATURATION,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Saturation",
185 #define SATURATION_DEF 127
186 .default_value = SATURATION_DEF,
188 .set = sd_setsaturation,
189 .get = sd_getsaturation,
194 .type = V4L2_CTRL_TYPE_INTEGER,
200 .default_value = HUE_DEF,
207 .id = V4L2_CID_CONTRAST,
208 .type = V4L2_CTRL_TYPE_INTEGER,
213 #define CONTRAST_DEF 127
214 .default_value = CONTRAST_DEF,
216 .set = sd_setcontrast,
217 .get = sd_getcontrast,
221 static struct v4l2_pix_format vga_mode[] = {
222 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
224 .sizeimage = 160 * 120,
225 .colorspace = V4L2_COLORSPACE_SRGB,
227 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
229 .sizeimage = 320 * 240,
230 .colorspace = V4L2_COLORSPACE_SRGB,
232 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
234 .sizeimage = 640 * 480,
235 .colorspace = V4L2_COLORSPACE_SRGB,
238 static struct v4l2_pix_format sif_mode[] = {
239 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
241 .sizeimage = 176 * 144,
242 .colorspace = V4L2_COLORSPACE_SRGB,
244 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
246 .sizeimage = 352 * 288,
247 .colorspace = V4L2_COLORSPACE_SRGB,
251 static const __u8 probe_ov7630[] = {0x08, 0x44};
253 static const __u8 initHv7131[] = {
254 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
257 0x28, 0x1e, 0x60, 0x8a, 0x20,
258 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
260 static const __u8 hv7131_sensor_init[][8] = {
261 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
262 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
263 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
264 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
265 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
267 static const __u8 initOv6650[] = {
268 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
269 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
271 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
273 static const __u8 ov6650_sensor_init[][8] =
275 /* Bright, contrast, etc are set througth SCBB interface.
276 * AVCAP on win2 do not send any data on this controls. */
277 /* Anyway, some registers appears to alter bright and constrat */
280 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
281 /* Set clock register 0x11 low nibble is clock divider */
282 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
283 /* Next some unknown stuff */
284 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
285 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
286 * THIS SET GREEN SCREEN
287 * (pixels could be innverted in decode kind of "brg",
288 * but blue wont be there. Avoid this data ... */
289 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
290 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
291 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
292 /* Enable rgb brightness control */
293 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
294 /* HDG: Note windows uses the line below, which sets both register 0x60
295 and 0x61 I believe these registers of the ov6650 are identical as
296 those of the ov7630, because if this is true the windows settings
297 add a bit additional red gain and a lot additional blue gain, which
298 matches my findings that the windows settings make blue much too
299 blue and red a little too red.
300 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
301 /* Some more unknown stuff */
302 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
303 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
306 static const __u8 initOv7630[] = {
307 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
308 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
309 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
310 0x28, 0x1e, /* H & V sizes r15 .. r16 */
311 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
312 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
314 static const __u8 initOv7630_3[] = {
315 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
316 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
317 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
318 0x28, 0x1e, /* H & V sizes r15 .. r16 */
319 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
320 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
321 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
322 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
324 static const __u8 ov7630_sensor_init_com[][8] = {
325 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
326 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
327 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
328 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
329 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
330 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
331 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
332 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
333 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
334 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
335 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
336 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
337 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
338 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
339 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
340 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
341 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
342 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
343 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
345 static const __u8 ov7630_sensor_init[][8] = {
346 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
347 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
348 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
349 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
350 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
352 static const __u8 ov7630_sensor_init_3[][8] = {
353 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
354 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
357 static const __u8 initPas106[] = {
358 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
361 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
362 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
364 /* compression 0x86 mckinit1 0x2b */
365 static const __u8 pas106_data[][2] = {
366 {0x02, 0x04}, /* Pixel Clock Divider 6 */
367 {0x03, 0x13}, /* Frame Time MSB */
368 /* {0x03, 0x12}, * Frame Time MSB */
369 {0x04, 0x06}, /* Frame Time LSB */
370 /* {0x04, 0x05}, * Frame Time LSB */
371 {0x05, 0x65}, /* Shutter Time Line Offset */
372 /* {0x05, 0x6d}, * Shutter Time Line Offset */
373 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
374 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
375 {0x07, 0xc1}, /* Black Level Subtract Sign */
376 /* {0x07, 0x00}, * Black Level Subtract Sign */
377 {0x08, 0x06}, /* Black Level Subtract Level */
378 {0x08, 0x06}, /* Black Level Subtract Level */
379 /* {0x08, 0x01}, * Black Level Subtract Level */
380 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
381 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
382 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
383 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
384 {0x0d, 0x00}, /* Color GainH Pixel */
385 {0x0e, 0x0e}, /* Global Gain */
386 {0x0f, 0x00}, /* Contrast */
387 {0x10, 0x06}, /* H&V synchro polarity */
388 {0x11, 0x06}, /* ?default */
389 {0x12, 0x06}, /* DAC scale */
390 {0x14, 0x02}, /* ?default */
391 {0x13, 0x01}, /* Validate Settings */
393 static const __u8 initPas202[] = {
394 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
397 0x28, 0x1e, 0x28, 0x89, 0x30,
398 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
400 static const __u8 pas202_sensor_init[][8] = {
401 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
402 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
403 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
404 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
405 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
406 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
407 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
408 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
409 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
410 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
411 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
412 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
414 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
415 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
416 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
417 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
418 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
419 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
420 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
421 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
424 static const __u8 initTas5110[] = {
425 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
427 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
428 0x16, 0x12, 0x60, 0x86, 0x2b,
429 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
431 static const __u8 tas5110_sensor_init[][8] = {
432 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
433 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
434 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
437 static const __u8 initTas5130[] = {
438 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
440 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
441 0x28, 0x1e, 0x60, COMP, MCK_INIT,
442 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
444 static const __u8 tas5130_sensor_init[][8] = {
445 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
446 * shutter 0x47 short exposure? */
447 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
448 /* shutter 0x01 long exposure */
449 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
452 /* get one byte in gspca_dev->usb_buf */
453 static void reg_r(struct gspca_dev *gspca_dev,
456 usb_control_msg(gspca_dev->dev,
457 usb_rcvctrlpipe(gspca_dev->dev, 0),
459 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
462 gspca_dev->usb_buf, 1,
466 static void reg_w(struct gspca_dev *gspca_dev,
471 #ifdef CONFIG_VIDEO_ADV_DEBUG
472 if (len > sizeof gspca_dev->usb_buf) {
473 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
477 memcpy(gspca_dev->usb_buf, buffer, len);
478 usb_control_msg(gspca_dev->dev,
479 usb_sndctrlpipe(gspca_dev->dev, 0),
481 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
484 gspca_dev->usb_buf, len,
488 static void reg_w_big(struct gspca_dev *gspca_dev,
495 tmpbuf = kmalloc(len, GFP_KERNEL);
496 memcpy(tmpbuf, buffer, len);
497 usb_control_msg(gspca_dev->dev,
498 usb_sndctrlpipe(gspca_dev->dev, 0),
500 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
508 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
513 reg_w(gspca_dev, 0x08, buffer, 8);
516 reg_r(gspca_dev, 0x08);
517 if (gspca_dev->usb_buf[0] & 0x04) {
518 if (gspca_dev->usb_buf[0] & 0x08)
526 static void i2c_w_vector(struct gspca_dev *gspca_dev,
527 const __u8 buffer[][8], int len)
530 reg_w(gspca_dev, 0x08, *buffer, 8);
538 static void setbrightness(struct gspca_dev *gspca_dev)
540 struct sd *sd = (struct sd *) gspca_dev;
543 switch (sd->sensor) {
545 case SENSOR_OV7630_3:
546 case SENSOR_OV7630: {
548 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
550 /* change reg 0x06 */
551 i2cOV[1] = sd->sensor_addr;
552 i2cOV[3] = sd->brightness;
553 if (i2c_w(gspca_dev, i2cOV) < 0)
557 case SENSOR_PAS106: {
559 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
561 i2c1[3] = sd->brightness >> 3;
563 if (i2c_w(gspca_dev, i2c1) < 0)
567 if (i2c_w(gspca_dev, i2c1) < 0)
571 case SENSOR_PAS202: {
572 /* __u8 i2cpexpo1[] =
573 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
575 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
577 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
578 static __u8 i2cpdoit[] =
579 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
581 /* change reg 0x10 */
582 i2cpexpo[4] = 0xff - sd->brightness;
583 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
585 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
587 if (i2c_w(gspca_dev, i2cpexpo) < 0)
589 if (i2c_w(gspca_dev, i2cpdoit) < 0)
591 i2cp202[3] = sd->brightness >> 3;
592 if (i2c_w(gspca_dev, i2cp202) < 0)
594 if (i2c_w(gspca_dev, i2cpdoit) < 0)
598 case SENSOR_TAS5130CXX: {
600 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
602 value = 0xff - sd->brightness;
604 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
605 if (i2c_w(gspca_dev, i2c) < 0)
610 /* FIXME figure out howto control brightness on TAS5110 */
615 PDEBUG(D_ERR, "i2c error brightness");
618 static void setsensorgain(struct gspca_dev *gspca_dev)
620 struct sd *sd = (struct sd *) gspca_dev;
621 unsigned char gain = sd->gain;
623 switch (sd->sensor) {
625 case SENSOR_TAS5110: {
627 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
630 if (i2c_w(gspca_dev, i2c) < 0)
638 case SENSOR_OV7630_3: {
639 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
641 i2c[1] = sd->sensor_addr;
643 if (i2c_w(gspca_dev, i2c) < 0)
650 PDEBUG(D_ERR, "i2c error gain");
653 static void setgain(struct gspca_dev *gspca_dev)
655 struct sd *sd = (struct sd *) gspca_dev;
659 gain = sd->gain >> 4;
661 /* red and blue gain */
662 rgb_value = gain << 4 | gain;
663 reg_w(gspca_dev, 0x10, &rgb_value, 1);
666 reg_w(gspca_dev, 0x11, &rgb_value, 1);
668 if (sd->sensor_has_gain)
669 setsensorgain(gspca_dev);
672 static void setexposure(struct gspca_dev *gspca_dev)
674 struct sd *sd = (struct sd *) gspca_dev;
676 switch (sd->sensor) {
677 case SENSOR_TAS5110: {
680 /* register 19's high nibble contains the sn9c10x clock divider
681 The high nibble configures the no fps according to the
682 formula: 60 / high_nibble. With a maximum of 30 fps */
683 reg = 120 * sd->exposure / 1000;
688 reg = (reg << 4) | 0x0b;
689 reg_w(gspca_dev, 0x19, ®, 1);
693 case SENSOR_OV7630_3: {
694 /* The ov6650 / ov7630 have 2 registers which both influence
695 exposure, register 11, whose low nibble sets the nr off fps
696 according to: fps = 30 / (low_nibble + 1)
698 The fps configures the maximum exposure setting, but it is
699 possible to use less exposure then what the fps maximum
700 allows by setting register 10. register 10 configures the
701 actual exposure as quotient of the full exposure, with 0
702 being no exposure at all (not very usefull) and reg10_max
703 being max exposure possible at that framerate.
705 The code maps our 0 - 510 ms exposure ctrl to these 2
706 registers, trying to keep fps as high as possible.
708 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
710 /* ov6645 datasheet says reg10_max is 9a, but that uses
711 tline * 2 * reg10 as formula for calculating texpo, the
712 ov6650 probably uses the same formula as the 7730 which uses
713 tline * 4 * reg10, which explains why the reg10max we've
714 found experimentally for the ov6650 is exactly half that of
715 the ov6645. The ov7630 datasheet says the max is 0x41. */
716 const int reg10_max = (sd->sensor == SENSOR_OV6650)
719 reg11 = (60 * sd->exposure + 999) / 1000;
725 /* frame exposure time in ms = 1000 * reg11 / 30 ->
726 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
727 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
729 /* Don't allow this to get below 10 when using autogain, the
730 steps become very large (relatively) when below 10 causing
731 the image to oscilate from much too dark, to much too bright
733 if (sd->autogain && reg10 < 10)
735 else if (reg10 > reg10_max)
738 /* Write reg 10 and reg11 low nibble */
739 i2c[1] = sd->sensor_addr;
742 if (sd->sensor == SENSOR_OV7630_3) {
743 __u8 reg76 = reg10 & 0x03;
744 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
745 0x00, 0x00, 0x00, 0x10};
747 i2c_reg76[3] = reg76;
748 if (i2c_w(gspca_dev, i2c_reg76) < 0)
749 PDEBUG(D_ERR, "i2c error exposure");
751 if (i2c_w(gspca_dev, i2c) < 0)
752 PDEBUG(D_ERR, "i2c error exposure");
758 static void setfreq(struct gspca_dev *gspca_dev)
760 struct sd *sd = (struct sd *) gspca_dev;
762 switch (sd->sensor) {
764 case SENSOR_OV7630_3: {
765 /* Framerate adjust register for artificial light 50 hz flicker
766 compensation, identical to ov6630 0x2b register, see ov6630
768 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
769 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
772 /* case 0: * no filter*/
773 /* case 2: * 60 hz */
777 i2c[3] = (sd->sensor == SENSOR_OV6650)
781 i2c[1] = sd->sensor_addr;
782 if (i2c_w(gspca_dev, i2c) < 0)
783 PDEBUG(D_ERR, "i2c error setfreq");
789 static void setsaturation(struct gspca_dev *gspca_dev)
791 struct sd *sd = (struct sd *) gspca_dev;
793 switch (sd->sensor) {
794 /* case SENSOR_OV6650: */
795 case SENSOR_OV7630_3:
796 case SENSOR_OV7630: {
797 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
798 i2c[1] = sd->sensor_addr;
799 i2c[3] = sd->saturation & 0xf0;
800 if (i2c_w(gspca_dev, i2c) < 0)
801 PDEBUG(D_ERR, "i2c error setsaturation");
803 PDEBUG(D_CONF, "saturation set to: %d",
804 (int)sd->saturation);
810 static void sethue(struct gspca_dev *gspca_dev)
812 struct sd *sd = (struct sd *) gspca_dev;
814 switch (sd->sensor) {
815 /* case SENSOR_OV6650: */
816 case SENSOR_OV7630_3:
817 case SENSOR_OV7630: {
818 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
819 i2c[1] = sd->sensor_addr;
820 i2c[3] = 0x20 | (sd->hue >> 3);
821 if (i2c_w(gspca_dev, i2c) < 0)
822 PDEBUG(D_ERR, "i2c error setsaturation");
824 PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
830 static void setcontrast(struct gspca_dev *gspca_dev)
832 struct sd *sd = (struct sd *) gspca_dev;
834 switch (sd->sensor) {
835 /* case SENSOR_OV6650: */
836 case SENSOR_OV7630_3:
837 case SENSOR_OV7630: {
838 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
839 i2c[1] = sd->sensor_addr;
840 i2c[3] = 0x20 | (sd->contrast >> 3);
841 if (i2c_w(gspca_dev, i2c) < 0)
842 PDEBUG(D_ERR, "i2c error setcontrast");
844 PDEBUG(D_CONF, "contrast set to: %d",
852 static void do_autogain(struct gspca_dev *gspca_dev)
854 struct sd *sd = (struct sd *) gspca_dev;
855 int avg_lum = atomic_read(&sd->avg_lum);
860 if (sd->autogain_ignore_frames > 0)
861 sd->autogain_ignore_frames--;
862 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
863 sd->brightness * DESIRED_AVG_LUM / 127,
864 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
865 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
866 (int)sd->gain, (int)sd->exposure);
867 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
871 /* this function is called at probe time */
872 static int sd_config(struct gspca_dev *gspca_dev,
873 const struct usb_device_id *id)
875 struct sd *sd = (struct sd *) gspca_dev;
880 /* nctrls depends upon the sensor, so we use a per cam copy */
881 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
882 gspca_dev->sd_desc = &sd->sd_desc;
884 sd->fr_h_sz = 12; /* default size of the frame header */
885 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
886 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
888 product = id->idProduct;
889 /* switch (id->idVendor) { */
890 /* case 0x0c45: * Sonix */
892 case 0x6001: /* SN9C102 */
893 case 0x6005: /* SN9C101 */
894 case 0x6007: /* SN9C101 */
895 sd->sensor = SENSOR_TAS5110;
896 sd->sensor_has_gain = 1;
897 sd->sd_desc.nctrls = 4;
898 sd->sd_desc.dq_callback = do_autogain;
901 case 0x6009: /* SN9C101 */
902 case 0x600d: /* SN9C101 */
903 case 0x6029: /* SN9C101 */
904 sd->sensor = SENSOR_PAS106;
907 case 0x6011: /* SN9C101 - SN9C101G */
908 sd->sensor = SENSOR_OV6650;
909 sd->sensor_has_gain = 1;
910 sd->sensor_addr = 0x60;
911 sd->sd_desc.nctrls = 5;
912 sd->sd_desc.dq_callback = do_autogain;
915 case 0x6019: /* SN9C101 */
916 case 0x602c: /* SN9C102 */
917 case 0x602e: /* SN9C102 */
918 sd->sensor = SENSOR_OV7630;
919 sd->sensor_addr = 0x21;
921 case 0x60b0: /* SN9C103 */
922 sd->sensor = SENSOR_OV7630_3;
923 sd->sensor_addr = 0x21;
924 sd->fr_h_sz = 18; /* size of frame header */
925 sd->sensor_has_gain = 1;
926 sd->sd_desc.nctrls = 8;
927 sd->sd_desc.dq_callback = do_autogain;
930 case 0x6024: /* SN9C102 */
931 case 0x6025: /* SN9C102 */
932 sd->sensor = SENSOR_TAS5130CXX;
934 case 0x6028: /* SN9C102 */
935 sd->sensor = SENSOR_PAS202;
937 case 0x602d: /* SN9C102 */
938 sd->sensor = SENSOR_HV7131R;
940 case 0x60af: /* SN9C103 */
941 sd->sensor = SENSOR_PAS202;
942 sd->fr_h_sz = 18; /* size of frame header (?) */
948 cam = &gspca_dev->cam;
949 cam->dev_name = (char *) id->driver_info;
952 cam->cam_mode = vga_mode;
953 cam->nmodes = ARRAY_SIZE(vga_mode);
954 if (sd->sensor == SENSOR_OV7630_3) {
955 /* We only have 320x240 & 640x480 */
960 cam->cam_mode = sif_mode;
961 cam->nmodes = ARRAY_SIZE(sif_mode);
963 sd->brightness = BRIGHTNESS_DEF;
965 sd->exposure = EXPOSURE_DEF;
967 sd->contrast = CONTRAST_DEF;
968 sd->saturation = SATURATION_DEF;
970 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
971 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
975 /* this function is called at open time */
976 static int sd_open(struct gspca_dev *gspca_dev)
978 reg_r(gspca_dev, 0x00);
979 if (gspca_dev->usb_buf[0] != 0x10)
984 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
988 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
990 i = ARRAY_SIZE(pas106_data);
991 data = pas106_data[0];
993 memcpy(&i2c1[2], data, 2);
994 /* copy 2 bytes from the template */
995 if (i2c_w(gspca_dev, i2c1) < 0)
996 PDEBUG(D_ERR, "i2c error pas106");
1001 /* -- start the camera -- */
1002 static void sd_start(struct gspca_dev *gspca_dev)
1004 struct sd *sd = (struct sd *) gspca_dev;
1006 const __u8 *sn9c10x;
1010 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1011 switch (sd->sensor) {
1012 case SENSOR_HV7131R:
1013 sn9c10x = initHv7131;
1015 reg17_19[1] = (mode << 4) | 0x8a;
1019 sn9c10x = initOv6650;
1021 reg17_19[1] = (mode << 4) | 0x8b;
1025 sn9c10x = initOv7630;
1027 reg17_19[1] = (mode << 4) | COMP2;
1028 reg17_19[2] = MCK_INIT1;
1030 case SENSOR_OV7630_3:
1031 sn9c10x = initOv7630_3;
1033 reg17_19[1] = (mode << 4) | COMP2;
1034 reg17_19[2] = MCK_INIT1;
1037 sn9c10x = initPas106;
1038 reg17_19[0] = 0x24; /* 0x28 */
1039 reg17_19[1] = (mode << 4) | COMP1;
1040 reg17_19[2] = MCK_INIT1;
1043 sn9c10x = initPas202;
1044 reg17_19[0] = mode ? 0x24 : 0x20;
1045 reg17_19[1] = (mode << 4) | 0x89;
1048 case SENSOR_TAS5110:
1049 sn9c10x = initTas5110;
1051 reg17_19[1] = (mode << 4) | 0x86;
1052 reg17_19[2] = 0x2b; /* 0xf3; */
1055 /* case SENSOR_TAS5130CXX: */
1056 sn9c10x = initTas5130;
1058 reg17_19[1] = (mode << 4) | COMP;
1059 reg17_19[2] = mode ? 0x23 : 0x43;
1062 switch (sd->sensor) {
1066 l = sizeof initOv7630;
1068 case SENSOR_OV7630_3:
1071 l = sizeof initOv7630_3;
1075 reg17 = sn9c10x[0x17 - 1];
1080 /* reg 0x01 bit 2 video transfert on */
1081 reg_w(gspca_dev, 0x01, ®01, 1);
1082 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1083 reg_w(gspca_dev, 0x17, ®17, 1);
1084 /*fixme: for ov7630 102
1085 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
1086 /* Set the registers from the template */
1087 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
1088 switch (sd->sensor) {
1089 case SENSOR_HV7131R:
1090 i2c_w_vector(gspca_dev, hv7131_sensor_init,
1091 sizeof hv7131_sensor_init);
1094 i2c_w_vector(gspca_dev, ov6650_sensor_init,
1095 sizeof ov6650_sensor_init);
1098 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1099 sizeof ov7630_sensor_init_com);
1101 i2c_w_vector(gspca_dev, ov7630_sensor_init,
1102 sizeof ov7630_sensor_init);
1104 case SENSOR_OV7630_3:
1105 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1106 sizeof ov7630_sensor_init_com);
1108 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
1111 pas106_i2cinit(gspca_dev);
1114 i2c_w_vector(gspca_dev, pas202_sensor_init,
1115 sizeof pas202_sensor_init);
1117 case SENSOR_TAS5110:
1118 i2c_w_vector(gspca_dev, tas5110_sensor_init,
1119 sizeof tas5110_sensor_init);
1122 /* case SENSOR_TAS5130CXX: */
1123 i2c_w_vector(gspca_dev, tas5130_sensor_init,
1124 sizeof tas5130_sensor_init);
1127 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1128 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1129 /* compression register */
1130 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
1132 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1134 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1135 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1136 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1137 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
1138 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1139 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
1140 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1141 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1142 /* Enable video transfert */
1143 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1145 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
1149 setbrightness(gspca_dev);
1150 setexposure(gspca_dev);
1152 setsaturation(gspca_dev);
1154 setcontrast(gspca_dev);
1156 sd->autogain_ignore_frames = 0;
1157 atomic_set(&sd->avg_lum, -1);
1160 static void sd_stopN(struct gspca_dev *gspca_dev)
1164 ByteSend = 0x09; /* 0X00 */
1165 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1168 static void sd_stop0(struct gspca_dev *gspca_dev)
1172 static void sd_close(struct gspca_dev *gspca_dev)
1176 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1177 struct gspca_frame *frame, /* target */
1178 unsigned char *data, /* isoc packet */
1179 int len) /* iso packet length */
1182 struct sd *sd = (struct sd *) gspca_dev;
1184 /* frames start with:
1185 * ff ff 00 c4 c4 96 synchro
1187 * xx (frame sequence / size / compression)
1188 * (xx) (idem - extra byte for sn9c103)
1189 * ll mm brightness sum inside auto exposure
1190 * ll mm brightness sum outside auto exposure
1191 * (xx xx xx xx xx) audio values for snc103
1193 if (len > 6 && len < 24) {
1194 for (i = 0; i < len - 6; i++) {
1195 if (data[0 + i] == 0xff
1196 && data[1 + i] == 0xff
1197 && data[2 + i] == 0x00
1198 && data[3 + i] == 0xc4
1199 && data[4 + i] == 0xc4
1200 && data[5 + i] == 0x96) { /* start of frame */
1201 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1203 if (len - i < sd->fr_h_sz) {
1204 atomic_set(&sd->avg_lum, -1);
1205 PDEBUG(D_STREAM, "packet too short to"
1206 " get avg brightness");
1207 } else if (sd->fr_h_sz == 12) {
1208 atomic_set(&sd->avg_lum,
1210 (data[i + 9] << 8));
1212 atomic_set(&sd->avg_lum,
1214 (data[i + 10] << 8));
1216 data += i + sd->fr_h_sz;
1217 len -= i + sd->fr_h_sz;
1218 gspca_frame_add(gspca_dev, FIRST_PACKET,
1224 gspca_frame_add(gspca_dev, INTER_PACKET,
1228 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1230 struct sd *sd = (struct sd *) gspca_dev;
1232 sd->brightness = val;
1233 if (gspca_dev->streaming)
1234 setbrightness(gspca_dev);
1238 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1240 struct sd *sd = (struct sd *) gspca_dev;
1242 *val = sd->brightness;
1246 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1248 struct sd *sd = (struct sd *) gspca_dev;
1251 if (gspca_dev->streaming)
1256 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1258 struct sd *sd = (struct sd *) gspca_dev;
1264 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1266 struct sd *sd = (struct sd *) gspca_dev;
1269 if (gspca_dev->streaming)
1270 setexposure(gspca_dev);
1274 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1276 struct sd *sd = (struct sd *) gspca_dev;
1278 *val = sd->exposure;
1282 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1284 struct sd *sd = (struct sd *) gspca_dev;
1287 /* when switching to autogain set defaults to make sure
1288 we are on a valid point of the autogain gain /
1289 exposure knee graph, and give this change time to
1290 take effect before doing autogain. */
1292 sd->exposure = EXPOSURE_DEF;
1293 sd->gain = GAIN_DEF;
1294 if (gspca_dev->streaming) {
1295 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1296 setexposure(gspca_dev);
1304 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1306 struct sd *sd = (struct sd *) gspca_dev;
1308 *val = sd->autogain;
1312 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1314 struct sd *sd = (struct sd *) gspca_dev;
1317 if (gspca_dev->streaming)
1322 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1324 struct sd *sd = (struct sd *) gspca_dev;
1330 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1332 struct sd *sd = (struct sd *) gspca_dev;
1334 sd->saturation = val;
1335 if (gspca_dev->streaming)
1336 setsaturation(gspca_dev);
1340 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1342 struct sd *sd = (struct sd *) gspca_dev;
1344 *val = sd->saturation;
1348 static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
1350 struct sd *sd = (struct sd *) gspca_dev;
1353 if (gspca_dev->streaming)
1358 static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
1360 struct sd *sd = (struct sd *) gspca_dev;
1366 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1368 struct sd *sd = (struct sd *) gspca_dev;
1371 if (gspca_dev->streaming)
1372 setcontrast(gspca_dev);
1376 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1378 struct sd *sd = (struct sd *) gspca_dev;
1380 *val = sd->contrast;
1384 static int sd_querymenu(struct gspca_dev *gspca_dev,
1385 struct v4l2_querymenu *menu)
1388 case V4L2_CID_POWER_LINE_FREQUENCY:
1389 switch (menu->index) {
1390 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1391 strcpy((char *) menu->name, "NoFliker");
1393 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1394 strcpy((char *) menu->name, "50 Hz");
1396 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1397 strcpy((char *) menu->name, "60 Hz");
1405 /* sub-driver description */
1406 static const struct sd_desc sd_desc = {
1407 .name = MODULE_NAME,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1416 .pkt_scan = sd_pkt_scan,
1417 .querymenu = sd_querymenu,
1420 /* -- module initialisation -- */
1421 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1422 static __devinitdata struct usb_device_id device_table[] = {
1423 #ifndef CONFIG_USB_SN9C102
1424 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1425 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1426 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1427 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1428 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1430 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1431 #ifndef CONFIG_USB_SN9C102
1432 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1433 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1434 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1435 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1436 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1437 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1438 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1439 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1440 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1441 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1445 MODULE_DEVICE_TABLE(usb, device_table);
1447 /* -- device connect -- */
1448 static int sd_probe(struct usb_interface *intf,
1449 const struct usb_device_id *id)
1451 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1455 static struct usb_driver sd_driver = {
1456 .name = MODULE_NAME,
1457 .id_table = device_table,
1459 .disconnect = gspca_disconnect,
1462 /* -- module insert / remove -- */
1463 static int __init sd_mod_init(void)
1465 if (usb_register(&sd_driver) < 0)
1467 PDEBUG(D_PROBE, "v%s registered", version);
1470 static void __exit sd_mod_exit(void)
1472 usb_deregister(&sd_driver);
1473 PDEBUG(D_PROBE, "deregistered");
1476 module_init(sd_mod_init);
1477 module_exit(sd_mod_exit);