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 /* Some documentation on known sonixb registers:
26 0x10 high nibble red gain low nibble blue gain
27 0x11 low nibble green gain
30 0x15 hsize (hsize = register-value * 16)
31 0x16 vsize (vsize = register-value * 16)
32 0x17 bit 0 toggle compression quality (according to sn9c102 driver)
33 0x18 bit 7 enables compression, bit 4-5 set image down scaling:
34 00 scale 1, 01 scale 1/2, 10, scale 1/4
35 0x19 high-nibble is sensor clock divider, changes exposure on sensors which
36 use a clock generated by the bridge. Some sensors have their own clock.
37 0x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
38 0x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
39 0x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
40 0x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
43 #define MODULE_NAME "sonixb"
47 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
48 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
49 MODULE_LICENSE("GPL");
51 /* specific webcam descriptor */
53 struct gspca_dev gspca_dev
; /* !! must be the first item */
57 unsigned char exposure
;
58 unsigned char brightness
;
59 unsigned char autogain
;
60 unsigned char autogain_ignore_frames
;
61 unsigned char frames_to_drop
;
62 unsigned char freq
; /* light freq filter setting */
64 __u8 bridge
; /* Type of bridge */
66 #define BRIDGE_102 0 /* We make no difference between 101 and 102 */
69 __u8 sensor
; /* Type of image sensor chip */
70 #define SENSOR_HV7131R 0
71 #define SENSOR_OV6650 1
72 #define SENSOR_OV7630 2
73 #define SENSOR_PAS106 3
74 #define SENSOR_PAS202 4
75 #define SENSOR_TAS5110 5
76 #define SENSOR_TAS5130CXX 6
80 typedef const __u8 sensor_init_t
[8];
83 const __u8
*bridge_init
[2];
84 int bridge_init_size
[2];
85 sensor_init_t
*sensor_init
;
87 sensor_init_t
*sensor_bridge_init
[2];
88 int sensor_bridge_init_size
[2];
94 /* sensor_data flags */
95 #define F_GAIN 0x01 /* has gain */
96 #define F_SIF 0x02 /* sif or vga */
98 /* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
99 #define MODE_RAW 0x10 /* raw bayer mode */
100 #define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
102 /* ctrl_dis helper macros */
103 #define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
104 #define NO_FREQ (1 << FREQ_IDX)
105 #define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
108 #define COMP 0xc7 /* 0x87 //0x07 */
109 #define COMP1 0xc9 /* 0x89 //0x09 */
111 #define MCK_INIT 0x63
112 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
116 #define SENS(bridge_1, bridge_3, sensor, sensor_1, \
117 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
119 .bridge_init = { bridge_1, bridge_3 }, \
120 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
121 .sensor_init = sensor, \
122 .sensor_init_size = sizeof(sensor), \
123 .sensor_bridge_init = { sensor_1, sensor_3,}, \
124 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
125 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
128 /* We calculate the autogain at the end of the transfer of a frame, at this
129 moment a frame with the old settings is being transmitted, and a frame is
130 being captured with the old settings. So if we adjust the autogain we must
131 ignore atleast the 2 next frames for the new settings to come into effect
132 before doing any other adjustments */
133 #define AUTOGAIN_IGNORE_FRAMES 3
134 #define AUTOGAIN_DEADZONE 1000
135 #define DESIRED_AVG_LUM 7000
137 /* V4L2 controls supported by the driver */
138 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
);
139 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
);
140 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
);
141 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
);
142 static int sd_setexposure(struct gspca_dev
*gspca_dev
, __s32 val
);
143 static int sd_getexposure(struct gspca_dev
*gspca_dev
, __s32
*val
);
144 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
);
145 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
);
146 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
);
147 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
);
149 static struct ctrl sd_ctrls
[] = {
150 #define BRIGHTNESS_IDX 0
153 .id
= V4L2_CID_BRIGHTNESS
,
154 .type
= V4L2_CTRL_TYPE_INTEGER
,
155 .name
= "Brightness",
159 #define BRIGHTNESS_DEF 127
160 .default_value
= BRIGHTNESS_DEF
,
162 .set
= sd_setbrightness
,
163 .get
= sd_getbrightness
,
169 .type
= V4L2_CTRL_TYPE_INTEGER
,
175 #define GAIN_KNEE 200
176 .default_value
= GAIN_DEF
,
181 #define EXPOSURE_IDX 2
184 .id
= V4L2_CID_EXPOSURE
,
185 .type
= V4L2_CTRL_TYPE_INTEGER
,
187 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
188 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
192 .default_value
= EXPOSURE_DEF
,
195 .set
= sd_setexposure
,
196 .get
= sd_getexposure
,
198 #define AUTOGAIN_IDX 3
201 .id
= V4L2_CID_AUTOGAIN
,
202 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
203 .name
= "Automatic Gain (and Exposure)",
207 #define AUTOGAIN_DEF 1
208 .default_value
= AUTOGAIN_DEF
,
211 .set
= sd_setautogain
,
212 .get
= sd_getautogain
,
217 .id
= V4L2_CID_POWER_LINE_FREQUENCY
,
218 .type
= V4L2_CTRL_TYPE_MENU
,
219 .name
= "Light frequency filter",
221 .maximum
= 2, /* 0: 0, 1: 50Hz, 2:60Hz */
224 .default_value
= FREQ_DEF
,
231 static struct v4l2_pix_format vga_mode
[] = {
232 {160, 120, V4L2_PIX_FMT_SBGGR8
, V4L2_FIELD_NONE
,
234 .sizeimage
= 160 * 120 * 5 / 4,
235 .colorspace
= V4L2_COLORSPACE_SRGB
,
236 .priv
= 2 | MODE_RAW
},
237 {160, 120, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
239 .sizeimage
= 160 * 120 * 5 / 4,
240 .colorspace
= V4L2_COLORSPACE_SRGB
,
242 {320, 240, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
244 .sizeimage
= 320 * 240 * 5 / 4,
245 .colorspace
= V4L2_COLORSPACE_SRGB
,
247 {640, 480, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
249 .sizeimage
= 640 * 480 * 5 / 4,
250 .colorspace
= V4L2_COLORSPACE_SRGB
,
253 static struct v4l2_pix_format sif_mode
[] = {
254 {160, 120, V4L2_PIX_FMT_SBGGR8
, V4L2_FIELD_NONE
,
256 .sizeimage
= 160 * 120,
257 .colorspace
= V4L2_COLORSPACE_SRGB
,
258 .priv
= 1 | MODE_RAW
| MODE_REDUCED_SIF
},
259 {160, 120, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
261 .sizeimage
= 160 * 120 * 5 / 4,
262 .colorspace
= V4L2_COLORSPACE_SRGB
,
263 .priv
= 1 | MODE_REDUCED_SIF
},
264 {176, 144, V4L2_PIX_FMT_SBGGR8
, V4L2_FIELD_NONE
,
266 .sizeimage
= 176 * 144 * 5 / 4,
267 .colorspace
= V4L2_COLORSPACE_SRGB
,
268 .priv
= 1 | MODE_RAW
},
269 {176, 144, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
271 .sizeimage
= 176 * 144 * 5 / 4,
272 .colorspace
= V4L2_COLORSPACE_SRGB
,
274 {320, 240, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
276 .sizeimage
= 320 * 240 * 5 / 4,
277 .colorspace
= V4L2_COLORSPACE_SRGB
,
278 .priv
= 0 | MODE_REDUCED_SIF
},
279 {352, 288, V4L2_PIX_FMT_SN9C10X
, V4L2_FIELD_NONE
,
281 .sizeimage
= 352 * 288 * 5 / 4,
282 .colorspace
= V4L2_COLORSPACE_SRGB
,
286 static const __u8 initHv7131
[] = {
287 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
290 0x28, 0x1e, 0x60, 0x8a, 0x20,
291 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
293 static const __u8 hv7131_sensor_init
[][8] = {
294 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
295 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
296 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
297 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
298 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
300 static const __u8 initOv6650
[] = {
301 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
302 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
304 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
306 static const __u8 ov6650_sensor_init
[][8] =
308 /* Bright, contrast, etc are set througth SCBB interface.
309 * AVCAP on win2 do not send any data on this controls. */
310 /* Anyway, some registers appears to alter bright and constrat */
313 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
314 /* Set clock register 0x11 low nibble is clock divider */
315 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
316 /* Next some unknown stuff */
317 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
318 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
319 * THIS SET GREEN SCREEN
320 * (pixels could be innverted in decode kind of "brg",
321 * but blue wont be there. Avoid this data ... */
322 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
323 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
324 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
325 /* Enable rgb brightness control */
326 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
327 /* HDG: Note windows uses the line below, which sets both register 0x60
328 and 0x61 I believe these registers of the ov6650 are identical as
329 those of the ov7630, because if this is true the windows settings
330 add a bit additional red gain and a lot additional blue gain, which
331 matches my findings that the windows settings make blue much too
332 blue and red a little too red.
333 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
334 /* Some more unknown stuff */
335 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
336 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
339 static const __u8 initOv7630
[] = {
340 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
341 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
342 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
343 0x28, 0x1e, /* H & V sizes r15 .. r16 */
344 0x68, COMP2
, MCK_INIT1
, /* r17 .. r19 */
345 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
347 static const __u8 initOv7630_3
[] = {
348 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
349 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
350 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
351 0x28, 0x1e, /* H & V sizes r15 .. r16 */
352 0x68, 0x8f, MCK_INIT1
, /* r17 .. r19 */
353 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
354 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
355 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
357 static const __u8 ov7630_sensor_init
[][8] = {
358 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
359 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
360 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
361 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
362 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
363 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
365 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
366 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
368 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
369 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
370 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
371 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
372 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
373 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
374 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
375 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
376 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
379 static const __u8 ov7630_sensor_init_3
[][8] = {
380 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
383 static const __u8 initPas106
[] = {
384 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
387 0x16, 0x12, 0x24, COMP1
, MCK_INIT1
,
388 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
390 /* compression 0x86 mckinit1 0x2b */
391 static const __u8 pas106_sensor_init
[][8] = {
392 /* Pixel Clock Divider 6 */
393 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
394 /* Frame Time MSB (also seen as 0x12) */
395 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
396 /* Frame Time LSB (also seen as 0x05) */
397 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
398 /* Shutter Time Line Offset (also seen as 0x6d) */
399 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
400 /* Shutter Time Pixel Offset (also seen as 0xb1) */
401 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
402 /* Black Level Subtract Sign (also seen 0x00) */
403 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
404 /* Black Level Subtract Level (also seen 0x01) */
405 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
406 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
407 /* Color Gain B Pixel 5 a */
408 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
409 /* Color Gain G1 Pixel 1 5 */
410 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
411 /* Color Gain G2 Pixel 1 0 5 */
412 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
413 /* Color Gain R Pixel 3 1 */
414 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
415 /* Color GainH Pixel */
416 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
418 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
420 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
421 /* H&V synchro polarity */
422 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
424 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
428 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
429 /* Validate Settings */
430 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
433 static const __u8 initPas202
[] = {
434 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
437 0x28, 0x1e, 0x28, 0x89, 0x20,
438 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
440 static const __u8 pas202_sensor_init
[][8] = {
441 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
442 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
443 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
444 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
445 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
446 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
450 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
451 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
452 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
454 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
455 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
456 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
457 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
458 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
459 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
460 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
461 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
464 static const __u8 initTas5110
[] = {
465 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
467 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
468 0x16, 0x12, 0x60, 0x86, 0x2b,
469 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
471 static const __u8 tas5110_sensor_init
[][8] = {
472 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
473 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
474 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
477 static const __u8 initTas5130
[] = {
478 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
480 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
481 0x28, 0x1e, 0x60, COMP
, MCK_INIT
,
482 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
484 static const __u8 tas5130_sensor_init
[][8] = {
485 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
486 * shutter 0x47 short exposure? */
487 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
488 /* shutter 0x01 long exposure */
489 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
492 struct sensor_data sensor_data
[] = {
493 SENS(initHv7131
, NULL
, hv7131_sensor_init
, NULL
, NULL
, 0, NO_EXPO
|NO_FREQ
, 0),
494 SENS(initOv6650
, NULL
, ov6650_sensor_init
, NULL
, NULL
, F_GAIN
|F_SIF
, 0, 0x60),
495 SENS(initOv7630
, initOv7630_3
, ov7630_sensor_init
, NULL
, ov7630_sensor_init_3
,
497 SENS(initPas106
, NULL
, pas106_sensor_init
, NULL
, NULL
, F_SIF
, NO_EXPO
|NO_FREQ
,
499 SENS(initPas202
, initPas202
, pas202_sensor_init
, NULL
, NULL
, 0,
501 SENS(initTas5110
, NULL
, tas5110_sensor_init
, NULL
, NULL
, F_GAIN
|F_SIF
,
502 NO_BRIGHTNESS
|NO_FREQ
, 0),
503 SENS(initTas5130
, NULL
, tas5130_sensor_init
, NULL
, NULL
, 0, NO_EXPO
|NO_FREQ
,
507 /* get one byte in gspca_dev->usb_buf */
508 static void reg_r(struct gspca_dev
*gspca_dev
,
511 usb_control_msg(gspca_dev
->dev
,
512 usb_rcvctrlpipe(gspca_dev
->dev
, 0),
514 USB_DIR_IN
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
517 gspca_dev
->usb_buf
, 1,
521 static void reg_w(struct gspca_dev
*gspca_dev
,
527 if (len
> USB_BUF_SZ
) {
528 PDEBUG(D_ERR
|D_PACK
, "reg_w: buffer overflow");
532 memcpy(gspca_dev
->usb_buf
, buffer
, len
);
533 usb_control_msg(gspca_dev
->dev
,
534 usb_sndctrlpipe(gspca_dev
->dev
, 0),
536 USB_DIR_OUT
| USB_TYPE_VENDOR
| USB_RECIP_INTERFACE
,
539 gspca_dev
->usb_buf
, len
,
543 static int i2c_w(struct gspca_dev
*gspca_dev
, const __u8
*buffer
)
548 reg_w(gspca_dev
, 0x08, buffer
, 8);
551 reg_r(gspca_dev
, 0x08);
552 if (gspca_dev
->usb_buf
[0] & 0x04) {
553 if (gspca_dev
->usb_buf
[0] & 0x08)
561 static void i2c_w_vector(struct gspca_dev
*gspca_dev
,
562 const __u8 buffer
[][8], int len
)
565 reg_w(gspca_dev
, 0x08, *buffer
, 8);
573 static void setbrightness(struct gspca_dev
*gspca_dev
)
575 struct sd
*sd
= (struct sd
*) gspca_dev
;
578 switch (sd
->sensor
) {
580 case SENSOR_OV7630
: {
582 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
584 /* change reg 0x06 */
585 i2cOV
[1] = sensor_data
[sd
->sensor
].sensor_addr
;
586 i2cOV
[3] = sd
->brightness
;
587 if (i2c_w(gspca_dev
, i2cOV
) < 0)
591 case SENSOR_PAS106
: {
593 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
595 i2c1
[3] = sd
->brightness
>> 3;
597 if (i2c_w(gspca_dev
, i2c1
) < 0)
601 if (i2c_w(gspca_dev
, i2c1
) < 0)
605 case SENSOR_PAS202
: {
606 /* __u8 i2cpexpo1[] =
607 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
609 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
611 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
612 static __u8 i2cpdoit
[] =
613 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
615 /* change reg 0x10 */
616 i2cpexpo
[4] = 0xff - sd
->brightness
;
617 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
619 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
621 if (i2c_w(gspca_dev
, i2cpexpo
) < 0)
623 if (i2c_w(gspca_dev
, i2cpdoit
) < 0)
625 i2cp202
[3] = sd
->brightness
>> 3;
626 if (i2c_w(gspca_dev
, i2cp202
) < 0)
628 if (i2c_w(gspca_dev
, i2cpdoit
) < 0)
632 case SENSOR_TAS5130CXX
: {
634 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
636 value
= 0xff - sd
->brightness
;
638 PDEBUG(D_CONF
, "brightness %d : %d", value
, i2c
[4]);
639 if (i2c_w(gspca_dev
, i2c
) < 0)
646 PDEBUG(D_ERR
, "i2c error brightness");
649 static void setsensorgain(struct gspca_dev
*gspca_dev
)
651 struct sd
*sd
= (struct sd
*) gspca_dev
;
652 unsigned char gain
= sd
->gain
;
654 switch (sd
->sensor
) {
656 case SENSOR_TAS5110
: {
658 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
661 if (i2c_w(gspca_dev
, i2c
) < 0)
669 case SENSOR_OV7630
: {
670 __u8 i2c
[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
672 i2c
[1] = sensor_data
[sd
->sensor
].sensor_addr
;
674 if (i2c_w(gspca_dev
, i2c
) < 0)
681 PDEBUG(D_ERR
, "i2c error gain");
684 static void setgain(struct gspca_dev
*gspca_dev
)
686 struct sd
*sd
= (struct sd
*) gspca_dev
;
690 gain
= sd
->gain
>> 4;
692 /* red and blue gain */
693 rgb_value
= gain
<< 4 | gain
;
694 reg_w(gspca_dev
, 0x10, &rgb_value
, 1);
697 reg_w(gspca_dev
, 0x11, &rgb_value
, 1);
699 if (sensor_data
[sd
->sensor
].flags
& F_GAIN
)
700 setsensorgain(gspca_dev
);
703 static void setexposure(struct gspca_dev
*gspca_dev
)
705 struct sd
*sd
= (struct sd
*) gspca_dev
;
707 switch (sd
->sensor
) {
708 case SENSOR_TAS5110
: {
711 /* register 19's high nibble contains the sn9c10x clock divider
712 The high nibble configures the no fps according to the
713 formula: 60 / high_nibble. With a maximum of 30 fps */
714 reg
= 120 * sd
->exposure
/ 1000;
719 reg
= (reg
<< 4) | 0x0b;
720 reg_w(gspca_dev
, 0x19, ®
, 1);
724 case SENSOR_OV7630
: {
725 /* The ov6650 / ov7630 have 2 registers which both influence
726 exposure, register 11, whose low nibble sets the nr off fps
727 according to: fps = 30 / (low_nibble + 1)
729 The fps configures the maximum exposure setting, but it is
730 possible to use less exposure then what the fps maximum
731 allows by setting register 10. register 10 configures the
732 actual exposure as quotient of the full exposure, with 0
733 being no exposure at all (not very usefull) and reg10_max
734 being max exposure possible at that framerate.
736 The code maps our 0 - 510 ms exposure ctrl to these 2
737 registers, trying to keep fps as high as possible.
739 __u8 i2c
[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
740 int reg10
, reg11
, reg10_max
;
742 /* ov6645 datasheet says reg10_max is 9a, but that uses
743 tline * 2 * reg10 as formula for calculating texpo, the
744 ov6650 probably uses the same formula as the 7730 which uses
745 tline * 4 * reg10, which explains why the reg10max we've
746 found experimentally for the ov6650 is exactly half that of
747 the ov6645. The ov7630 datasheet says the max is 0x41. */
748 if (sd
->sensor
== SENSOR_OV6650
) {
750 i2c
[4] = 0xc0; /* OV6650 needs non default vsync pol */
754 reg11
= (60 * sd
->exposure
+ 999) / 1000;
760 /* In 640x480, if the reg11 has less than 3, the image is
761 unstable (not enough bandwidth). */
762 if (gspca_dev
->width
== 640 && reg11
< 3)
765 /* frame exposure time in ms = 1000 * reg11 / 30 ->
766 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
767 reg10
= (sd
->exposure
* 60 * reg10_max
) / (1000 * reg11
);
769 /* Don't allow this to get below 10 when using autogain, the
770 steps become very large (relatively) when below 10 causing
771 the image to oscilate from much too dark, to much too bright
773 if (sd
->autogain
&& reg10
< 10)
775 else if (reg10
> reg10_max
)
778 /* Write reg 10 and reg11 low nibble */
779 i2c
[1] = sensor_data
[sd
->sensor
].sensor_addr
;
783 /* If register 11 didn't change, don't change it */
784 if (sd
->reg11
== reg11
)
787 if (i2c_w(gspca_dev
, i2c
) == 0)
790 PDEBUG(D_ERR
, "i2c error exposure");
796 static void setfreq(struct gspca_dev
*gspca_dev
)
798 struct sd
*sd
= (struct sd
*) gspca_dev
;
800 switch (sd
->sensor
) {
802 case SENSOR_OV7630
: {
803 /* Framerate adjust register for artificial light 50 hz flicker
804 compensation, for the ov6650 this is identical to ov6630
805 0x2b register, see ov6630 datasheet.
806 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
807 __u8 i2c
[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
810 /* case 0: * no filter*/
811 /* case 2: * 60 hz */
815 i2c
[3] = (sd
->sensor
== SENSOR_OV6650
)
819 i2c
[1] = sensor_data
[sd
->sensor
].sensor_addr
;
820 if (i2c_w(gspca_dev
, i2c
) < 0)
821 PDEBUG(D_ERR
, "i2c error setfreq");
827 static void do_autogain(struct gspca_dev
*gspca_dev
)
829 struct sd
*sd
= (struct sd
*) gspca_dev
;
830 int avg_lum
= atomic_read(&sd
->avg_lum
);
835 if (sd
->autogain_ignore_frames
> 0)
836 sd
->autogain_ignore_frames
--;
837 else if (gspca_auto_gain_n_exposure(gspca_dev
, avg_lum
,
838 sd
->brightness
* DESIRED_AVG_LUM
/ 127,
839 AUTOGAIN_DEADZONE
, GAIN_KNEE
, EXPOSURE_KNEE
)) {
840 PDEBUG(D_FRAM
, "autogain: gain changed: gain: %d expo: %d\n",
841 (int)sd
->gain
, (int)sd
->exposure
);
842 sd
->autogain_ignore_frames
= AUTOGAIN_IGNORE_FRAMES
;
846 /* this function is called at probe time */
847 static int sd_config(struct gspca_dev
*gspca_dev
,
848 const struct usb_device_id
*id
)
850 struct sd
*sd
= (struct sd
*) gspca_dev
;
853 reg_r(gspca_dev
, 0x00);
854 if (gspca_dev
->usb_buf
[0] != 0x10)
857 /* copy the webcam info from the device id */
858 sd
->sensor
= id
->driver_info
>> 8;
859 sd
->bridge
= id
->driver_info
& 0xff;
860 gspca_dev
->ctrl_dis
= sensor_data
[sd
->sensor
].ctrl_dis
;
862 cam
= &gspca_dev
->cam
;
864 if (!(sensor_data
[sd
->sensor
].flags
& F_SIF
)) {
865 cam
->cam_mode
= vga_mode
;
866 cam
->nmodes
= ARRAY_SIZE(vga_mode
);
868 cam
->cam_mode
= sif_mode
;
869 cam
->nmodes
= ARRAY_SIZE(sif_mode
);
871 sd
->brightness
= BRIGHTNESS_DEF
;
873 sd
->exposure
= EXPOSURE_DEF
;
874 if (gspca_dev
->ctrl_dis
& (1 << AUTOGAIN_IDX
))
875 sd
->autogain
= 0; /* Disable do_autogain callback */
877 sd
->autogain
= AUTOGAIN_DEF
;
883 /* this function is called at probe and resume time */
884 static int sd_init(struct gspca_dev
*gspca_dev
)
886 const __u8 stop
= 0x09; /* Disable stream turn of LED */
888 reg_w(gspca_dev
, 0x01, &stop
, 1);
893 /* -- start the camera -- */
894 static void sd_start(struct gspca_dev
*gspca_dev
)
896 struct sd
*sd
= (struct sd
*) gspca_dev
;
897 struct cam
*cam
= &gspca_dev
->cam
;
902 mode
= cam
->cam_mode
[gspca_dev
->curr_mode
].priv
& 0x07;
903 sn9c10x
= sensor_data
[sd
->sensor
].bridge_init
[sd
->bridge
];
904 l
= sensor_data
[sd
->sensor
].bridge_init_size
[sd
->bridge
];
905 memcpy(reg12_19
, &sn9c10x
[0x12 - 1], 8);
906 reg12_19
[6] = sn9c10x
[0x18 - 1] | (mode
<< 4);
907 /* Special cases where reg 17 and or 19 value depends on mode */
908 switch (sd
->sensor
) {
910 reg12_19
[5] = mode
? 0x24 : 0x20;
912 case SENSOR_TAS5130CXX
:
913 /* probably not mode specific at all most likely the upper
914 nibble of 0x19 is exposure (clock divider) just as with
915 the tas5110, we need someone to test this. */
916 reg12_19
[7] = mode
? 0x23 : 0x43;
919 /* Disable compression when the raw bayer format has been selected */
920 if (cam
->cam_mode
[gspca_dev
->curr_mode
].priv
& MODE_RAW
)
921 reg12_19
[6] &= ~0x80;
923 /* Vga mode emulation on SIF sensor? */
924 if (cam
->cam_mode
[gspca_dev
->curr_mode
].priv
& MODE_REDUCED_SIF
) {
925 reg12_19
[0] += 16; /* 0x12: hstart adjust */
926 reg12_19
[1] += 24; /* 0x13: vstart adjust */
927 reg12_19
[3] = 320 / 16; /* 0x15: hsize */
928 reg12_19
[4] = 240 / 16; /* 0x16: vsize */
931 /* reg 0x01 bit 2 video transfert on */
932 reg_w(gspca_dev
, 0x01, &sn9c10x
[0x01 - 1], 1);
933 /* reg 0x17 SensorClk enable inv Clk 0x60 */
934 reg_w(gspca_dev
, 0x17, &sn9c10x
[0x17 - 1], 1);
935 /* Set the registers from the template */
936 reg_w(gspca_dev
, 0x01, sn9c10x
, l
);
938 /* Init the sensor */
939 i2c_w_vector(gspca_dev
, sensor_data
[sd
->sensor
].sensor_init
,
940 sensor_data
[sd
->sensor
].sensor_init_size
);
941 if (sensor_data
[sd
->sensor
].sensor_bridge_init
[sd
->bridge
])
942 i2c_w_vector(gspca_dev
,
943 sensor_data
[sd
->sensor
].sensor_bridge_init
[sd
->bridge
],
944 sensor_data
[sd
->sensor
].sensor_bridge_init_size
[
947 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
948 reg_w(gspca_dev
, 0x15, ®12_19
[3], 2);
949 /* compression register */
950 reg_w(gspca_dev
, 0x18, ®12_19
[6], 1);
952 reg_w(gspca_dev
, 0x12, ®12_19
[0], 1);
954 reg_w(gspca_dev
, 0x13, ®12_19
[1], 1);
955 /* reset 0x17 SensorClk enable inv Clk 0x60 */
956 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
957 reg_w(gspca_dev
, 0x17, ®12_19
[5], 1);
958 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
959 reg_w(gspca_dev
, 0x19, ®12_19
[7], 1);
960 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
961 reg_w(gspca_dev
, 0x1c, &sn9c10x
[0x1c - 1], 4);
962 /* Enable video transfert */
963 reg_w(gspca_dev
, 0x01, &sn9c10x
[0], 1);
965 reg_w(gspca_dev
, 0x18, ®12_19
[6], 2);
971 setbrightness(gspca_dev
);
972 setexposure(gspca_dev
);
975 sd
->frames_to_drop
= 0;
976 sd
->autogain_ignore_frames
= 0;
977 atomic_set(&sd
->avg_lum
, -1);
980 static void sd_stopN(struct gspca_dev
*gspca_dev
)
985 static void sd_pkt_scan(struct gspca_dev
*gspca_dev
,
986 struct gspca_frame
*frame
, /* target */
987 unsigned char *data
, /* isoc packet */
988 int len
) /* iso packet length */
991 struct sd
*sd
= (struct sd
*) gspca_dev
;
992 struct cam
*cam
= &gspca_dev
->cam
;
994 /* frames start with:
995 * ff ff 00 c4 c4 96 synchro
997 * xx (frame sequence / size / compression)
998 * (xx) (idem - extra byte for sn9c103)
999 * ll mm brightness sum inside auto exposure
1000 * ll mm brightness sum outside auto exposure
1001 * (xx xx xx xx xx) audio values for snc103
1003 if (len
> 6 && len
< 24) {
1004 for (i
= 0; i
< len
- 6; i
++) {
1005 if (data
[0 + i
] == 0xff
1006 && data
[1 + i
] == 0xff
1007 && data
[2 + i
] == 0x00
1008 && data
[3 + i
] == 0xc4
1009 && data
[4 + i
] == 0xc4
1010 && data
[5 + i
] == 0x96) { /* start of frame */
1012 int pkt_type
= LAST_PACKET
;
1013 int fr_h_sz
= (sd
->bridge
== BRIDGE_103
) ?
1016 if (len
- i
< fr_h_sz
) {
1017 PDEBUG(D_STREAM
, "packet too short to"
1018 " get avg brightness");
1019 } else if (sd
->bridge
== BRIDGE_103
) {
1021 (data
[i
+ 10] << 8);
1023 lum
= data
[i
+ 8] + (data
[i
+ 9] << 8);
1027 sd
->frames_to_drop
= 2;
1029 atomic_set(&sd
->avg_lum
, lum
);
1031 if (sd
->frames_to_drop
) {
1032 sd
->frames_to_drop
--;
1033 pkt_type
= DISCARD_PACKET
;
1036 frame
= gspca_frame_add(gspca_dev
, pkt_type
,
1038 data
+= i
+ fr_h_sz
;
1040 gspca_frame_add(gspca_dev
, FIRST_PACKET
,
1047 if (cam
->cam_mode
[gspca_dev
->curr_mode
].priv
& MODE_RAW
) {
1048 /* In raw mode we sometimes get some garbage after the frame
1050 int used
= frame
->data_end
- frame
->data
;
1051 int size
= cam
->cam_mode
[gspca_dev
->curr_mode
].sizeimage
;
1053 if (used
+ len
> size
)
1057 gspca_frame_add(gspca_dev
, INTER_PACKET
,
1061 static int sd_setbrightness(struct gspca_dev
*gspca_dev
, __s32 val
)
1063 struct sd
*sd
= (struct sd
*) gspca_dev
;
1065 sd
->brightness
= val
;
1066 if (gspca_dev
->streaming
)
1067 setbrightness(gspca_dev
);
1071 static int sd_getbrightness(struct gspca_dev
*gspca_dev
, __s32
*val
)
1073 struct sd
*sd
= (struct sd
*) gspca_dev
;
1075 *val
= sd
->brightness
;
1079 static int sd_setgain(struct gspca_dev
*gspca_dev
, __s32 val
)
1081 struct sd
*sd
= (struct sd
*) gspca_dev
;
1084 if (gspca_dev
->streaming
)
1089 static int sd_getgain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1091 struct sd
*sd
= (struct sd
*) gspca_dev
;
1097 static int sd_setexposure(struct gspca_dev
*gspca_dev
, __s32 val
)
1099 struct sd
*sd
= (struct sd
*) gspca_dev
;
1102 if (gspca_dev
->streaming
)
1103 setexposure(gspca_dev
);
1107 static int sd_getexposure(struct gspca_dev
*gspca_dev
, __s32
*val
)
1109 struct sd
*sd
= (struct sd
*) gspca_dev
;
1111 *val
= sd
->exposure
;
1115 static int sd_setautogain(struct gspca_dev
*gspca_dev
, __s32 val
)
1117 struct sd
*sd
= (struct sd
*) gspca_dev
;
1120 /* when switching to autogain set defaults to make sure
1121 we are on a valid point of the autogain gain /
1122 exposure knee graph, and give this change time to
1123 take effect before doing autogain. */
1125 sd
->exposure
= EXPOSURE_DEF
;
1126 sd
->gain
= GAIN_DEF
;
1127 if (gspca_dev
->streaming
) {
1128 sd
->autogain_ignore_frames
= AUTOGAIN_IGNORE_FRAMES
;
1129 setexposure(gspca_dev
);
1137 static int sd_getautogain(struct gspca_dev
*gspca_dev
, __s32
*val
)
1139 struct sd
*sd
= (struct sd
*) gspca_dev
;
1141 *val
= sd
->autogain
;
1145 static int sd_setfreq(struct gspca_dev
*gspca_dev
, __s32 val
)
1147 struct sd
*sd
= (struct sd
*) gspca_dev
;
1150 if (gspca_dev
->streaming
)
1155 static int sd_getfreq(struct gspca_dev
*gspca_dev
, __s32
*val
)
1157 struct sd
*sd
= (struct sd
*) gspca_dev
;
1163 static int sd_querymenu(struct gspca_dev
*gspca_dev
,
1164 struct v4l2_querymenu
*menu
)
1167 case V4L2_CID_POWER_LINE_FREQUENCY
:
1168 switch (menu
->index
) {
1169 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1170 strcpy((char *) menu
->name
, "NoFliker");
1172 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1173 strcpy((char *) menu
->name
, "50 Hz");
1175 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1176 strcpy((char *) menu
->name
, "60 Hz");
1184 /* sub-driver description */
1185 static const struct sd_desc sd_desc
= {
1186 .name
= MODULE_NAME
,
1188 .nctrls
= ARRAY_SIZE(sd_ctrls
),
1189 .config
= sd_config
,
1193 .pkt_scan
= sd_pkt_scan
,
1194 .querymenu
= sd_querymenu
,
1195 .dq_callback
= do_autogain
,
1198 /* -- module initialisation -- */
1199 #define SB(sensor, bridge) \
1200 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1203 static __devinitdata
struct usb_device_id device_table
[] = {
1204 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1205 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110
, 102)},
1206 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110
, 101)},
1207 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110
, 101)},
1208 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106
, 101)},
1209 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106
, 101)},
1211 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650
, 101)},
1212 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1213 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630
, 101)},
1214 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX
, 102)},
1215 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX
, 102)},
1216 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202
, 102)},
1217 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106
, 102)},
1218 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630
, 102)},
1220 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R
, 102)},
1221 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1222 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630
, 102)},
1223 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630
, 103)},
1224 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202
, 103)},
1225 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630
, 103)},
1229 MODULE_DEVICE_TABLE(usb
, device_table
);
1231 /* -- device connect -- */
1232 static int sd_probe(struct usb_interface
*intf
,
1233 const struct usb_device_id
*id
)
1235 return gspca_dev_probe(intf
, id
, &sd_desc
, sizeof(struct sd
),
1239 static struct usb_driver sd_driver
= {
1240 .name
= MODULE_NAME
,
1241 .id_table
= device_table
,
1243 .disconnect
= gspca_disconnect
,
1245 .suspend
= gspca_suspend
,
1246 .resume
= gspca_resume
,
1250 /* -- module insert / remove -- */
1251 static int __init
sd_mod_init(void)
1253 if (usb_register(&sd_driver
) < 0)
1255 PDEBUG(D_PROBE
, "registered");
1258 static void __exit
sd_mod_exit(void)
1260 usb_deregister(&sd_driver
);
1261 PDEBUG(D_PROBE
, "deregistered");
1264 module_init(sd_mod_init
);
1265 module_exit(sd_mod_exit
);