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, 7)
28 static const char version[] = "2.1.7";
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;
48 unsigned char fr_h_sz; /* size of frame header */
49 char sensor; /* Type of image sensor chip */
51 #define SENSOR_HV7131R 0
52 #define SENSOR_OV6650 1
53 #define SENSOR_OV7630 2
54 #define SENSOR_OV7630_3 3
55 #define SENSOR_PAS106 4
56 #define SENSOR_PAS202 5
57 #define SENSOR_TAS5110 6
58 #define SENSOR_TAS5130CXX 7
62 #define COMP 0xc7 /* 0x87 //0x07 */
63 #define COMP1 0xc9 /* 0x89 //0x09 */
66 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
70 /* We calculate the autogain at the end of the transfer of a frame, at this
71 moment a frame with the old settings is being transmitted, and a frame is
72 being captured with the old settings. So if we adjust the autogain we must
73 ignore atleast the 2 next frames for the new settings to come into effect
74 before doing any other adjustments */
75 #define AUTOGAIN_IGNORE_FRAMES 3
76 #define AUTOGAIN_DEADZONE 1000
77 #define DESIRED_AVG_LUM 7000
79 /* V4L2 controls supported by the driver */
80 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
89 static struct ctrl sd_ctrls[] = {
92 .id = V4L2_CID_BRIGHTNESS,
93 .type = V4L2_CTRL_TYPE_INTEGER,
98 #define BRIGHTNESS_DEF 127
99 .default_value = BRIGHTNESS_DEF,
101 .set = sd_setbrightness,
102 .get = sd_getbrightness,
107 .type = V4L2_CTRL_TYPE_INTEGER,
113 #define GAIN_KNEE 200
114 .default_value = GAIN_DEF,
121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER,
124 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
125 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
129 .default_value = EXPOSURE_DEF,
132 .set = sd_setexposure,
133 .get = sd_getexposure,
137 .id = V4L2_CID_AUTOGAIN,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "Automatic Gain (and Exposure)",
143 #define AUTOGAIN_DEF 1
144 .default_value = AUTOGAIN_DEF,
147 .set = sd_setautogain,
148 .get = sd_getautogain,
152 static struct v4l2_pix_format vga_mode[] = {
153 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
155 .sizeimage = 160 * 120,
156 .colorspace = V4L2_COLORSPACE_SRGB,
158 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
160 .sizeimage = 320 * 240,
161 .colorspace = V4L2_COLORSPACE_SRGB,
163 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
165 .sizeimage = 640 * 480,
166 .colorspace = V4L2_COLORSPACE_SRGB,
169 static struct v4l2_pix_format sif_mode[] = {
170 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
172 .sizeimage = 176 * 144,
173 .colorspace = V4L2_COLORSPACE_SRGB,
175 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .sizeimage = 352 * 288,
178 .colorspace = V4L2_COLORSPACE_SRGB,
182 static const __u8 probe_ov7630[] = {0x08, 0x44};
184 static const __u8 initHv7131[] = {
185 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
188 0x28, 0x1e, 0x60, 0x8a, 0x20,
189 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
191 static const __u8 hv7131_sensor_init[][8] = {
192 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
193 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
194 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
195 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
196 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
198 static const __u8 initOv6650[] = {
199 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
200 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
202 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
204 static const __u8 ov6650_sensor_init[][8] =
206 /* Bright, contrast, etc are set througth SCBB interface.
207 * AVCAP on win2 do not send any data on this controls. */
208 /* Anyway, some registers appears to alter bright and constrat */
211 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
212 /* Set clock register 0x11 low nibble is clock divider */
213 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
214 /* Next some unknown stuff */
215 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
216 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
217 * THIS SET GREEN SCREEN
218 * (pixels could be innverted in decode kind of "brg",
219 * but blue wont be there. Avoid this data ... */
220 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
221 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
222 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
223 /* Disable autobright ? */
224 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
225 /* Some more unknown stuff */
226 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
227 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
228 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
229 /* Framerate adjust register for artificial light 50 hz flicker
230 compensation, identical to ov6630 0x2b register, see 6630 datasheet.
231 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
232 {0xa0, 0x60, 0x2b, 0x4f, 0x99, 0x04, 0x94, 0x15},
235 static const __u8 initOv7630[] = {
236 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
237 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
238 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
239 0x28, 0x1e, /* H & V sizes r15 .. r16 */
240 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
241 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
243 static const __u8 initOv7630_3[] = {
244 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
245 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
246 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
247 0x28, 0x1e, /* H & V sizes r15 .. r16 */
248 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
249 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
250 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
251 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
253 static const __u8 ov7630_sensor_init_com[][8] = {
254 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
255 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
256 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
257 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
258 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
259 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
260 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
261 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
262 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
263 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
264 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
265 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
266 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
267 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
268 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
269 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
270 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
271 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
272 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
274 static const __u8 ov7630_sensor_init[][8] = {
275 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
276 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
277 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
278 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
279 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
281 static const __u8 ov7630_sensor_init_3[][5][8] = {
282 { {0xa0, 0x21, 0x10, 0x36, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
283 {0xa0, 0x21, 0x76, 0x03, 0xbd, 0x06, 0xf6, 0x16},
284 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x16},
285 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
286 {0xb0, 0x21, 0x2a, 0xa0, 0x1c, 0x06, 0xf6, 0x1d},
288 { {0xa0, 0x21, 0x10, 0x83, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
289 {0xa0, 0x21, 0x76, 0x00, 0xbd, 0x06, 0xf6, 0x16},
290 {0xa0, 0x21, 0x11, 0x00, 0xbd, 0x06, 0xf6, 0x16},
291 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
292 /* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
293 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
294 /* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
295 {0xb0, 0x21, 0x2a, 0x80, 0x60, 0x06, 0xf6, 0x1d},
299 static const __u8 initPas106[] = {
300 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
303 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
304 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
306 /* compression 0x86 mckinit1 0x2b */
307 static const __u8 pas106_data[][2] = {
308 {0x02, 0x04}, /* Pixel Clock Divider 6 */
309 {0x03, 0x13}, /* Frame Time MSB */
310 /* {0x03, 0x12}, * Frame Time MSB */
311 {0x04, 0x06}, /* Frame Time LSB */
312 /* {0x04, 0x05}, * Frame Time LSB */
313 {0x05, 0x65}, /* Shutter Time Line Offset */
314 /* {0x05, 0x6d}, * Shutter Time Line Offset */
315 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
316 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
317 {0x07, 0xc1}, /* Black Level Subtract Sign */
318 /* {0x07, 0x00}, * Black Level Subtract Sign */
319 {0x08, 0x06}, /* Black Level Subtract Level */
320 {0x08, 0x06}, /* Black Level Subtract Level */
321 /* {0x08, 0x01}, * Black Level Subtract Level */
322 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
323 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
324 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
325 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
326 {0x0d, 0x00}, /* Color GainH Pixel */
327 {0x0e, 0x0e}, /* Global Gain */
328 {0x0f, 0x00}, /* Contrast */
329 {0x10, 0x06}, /* H&V synchro polarity */
330 {0x11, 0x06}, /* ?default */
331 {0x12, 0x06}, /* DAC scale */
332 {0x14, 0x02}, /* ?default */
333 {0x13, 0x01}, /* Validate Settings */
335 static const __u8 initPas202[] = {
336 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
339 0x28, 0x1e, 0x28, 0x89, 0x30,
340 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
342 static const __u8 pas202_sensor_init[][8] = {
343 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
344 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
345 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
346 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
347 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
348 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
349 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
350 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
351 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
352 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
353 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
354 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
356 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
357 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
358 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
359 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
360 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
361 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
362 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
363 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
366 static const __u8 initTas5110[] = {
367 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
369 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
370 0x16, 0x12, 0x60, 0x86, 0x2b,
371 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
373 static const __u8 tas5110_sensor_init[][8] = {
374 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
375 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
376 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
379 static const __u8 initTas5130[] = {
380 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
382 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
383 0x28, 0x1e, 0x60, COMP, MCK_INIT,
384 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
386 static const __u8 tas5130_sensor_init[][8] = {
387 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
388 * shutter 0x47 short exposure? */
389 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
390 /* shutter 0x01 long exposure */
391 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
394 /* get one byte in gspca_dev->usb_buf */
395 static void reg_r(struct gspca_dev *gspca_dev,
398 usb_control_msg(gspca_dev->dev,
399 usb_rcvctrlpipe(gspca_dev->dev, 0),
401 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
404 gspca_dev->usb_buf, 1,
408 static void reg_w(struct gspca_dev *gspca_dev,
413 #ifdef CONFIG_VIDEO_ADV_DEBUG
414 if (len > sizeof gspca_dev->usb_buf) {
415 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
419 memcpy(gspca_dev->usb_buf, buffer, len);
420 usb_control_msg(gspca_dev->dev,
421 usb_sndctrlpipe(gspca_dev->dev, 0),
423 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
426 gspca_dev->usb_buf, len,
430 static void reg_w_big(struct gspca_dev *gspca_dev,
437 tmpbuf = kmalloc(len, GFP_KERNEL);
438 memcpy(tmpbuf, buffer, len);
439 usb_control_msg(gspca_dev->dev,
440 usb_sndctrlpipe(gspca_dev->dev, 0),
442 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
450 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
455 reg_w(gspca_dev, 0x08, buffer, 8);
458 reg_r(gspca_dev, 0x08);
459 if (gspca_dev->usb_buf[0] & 0x04) {
460 if (gspca_dev->usb_buf[0] & 0x08)
468 static void i2c_w_vector(struct gspca_dev *gspca_dev,
469 const __u8 buffer[][8], int len)
472 reg_w(gspca_dev, 0x08, *buffer, 8);
480 static void setbrightness(struct gspca_dev *gspca_dev)
482 struct sd *sd = (struct sd *) gspca_dev;
485 switch (sd->sensor) {
486 case SENSOR_OV6650: {
488 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
490 i2cOV6650[3] = sd->brightness;
491 if (i2c_w(gspca_dev, i2cOV6650) < 0)
495 case SENSOR_OV7630_3:
496 case SENSOR_OV7630: {
498 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
500 /* change reg 0x06 */
501 i2cOV[3] = sd->brightness;
502 if (i2c_w(gspca_dev, i2cOV) < 0)
506 case SENSOR_PAS106: {
508 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
510 i2c1[3] = sd->brightness >> 3;
512 if (i2c_w(gspca_dev, i2c1) < 0)
516 if (i2c_w(gspca_dev, i2c1) < 0)
520 case SENSOR_PAS202: {
521 /* __u8 i2cpexpo1[] =
522 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
524 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
526 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
527 static __u8 i2cpdoit[] =
528 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
530 /* change reg 0x10 */
531 i2cpexpo[4] = 0xff - sd->brightness;
532 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
534 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
536 if (i2c_w(gspca_dev, i2cpexpo) < 0)
538 if (i2c_w(gspca_dev, i2cpdoit) < 0)
540 i2cp202[3] = sd->brightness >> 3;
541 if (i2c_w(gspca_dev, i2cp202) < 0)
543 if (i2c_w(gspca_dev, i2cpdoit) < 0)
547 case SENSOR_TAS5130CXX: {
549 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
551 value = 0xff - sd->brightness;
553 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
554 if (i2c_w(gspca_dev, i2c) < 0)
559 /* FIXME figure out howto control brightness on TAS5110 */
564 PDEBUG(D_ERR, "i2c error brightness");
567 static void setsensorgain(struct gspca_dev *gspca_dev)
569 struct sd *sd = (struct sd *) gspca_dev;
571 switch (sd->sensor) {
573 case SENSOR_TAS5110: {
575 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
577 i2c[4] = 255 - sd->gain;
578 if (i2c_w(gspca_dev, i2c) < 0)
582 case SENSOR_OV6650: {
583 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
585 i2c[3] = sd->gain >> 3;
586 if (i2c_w(gspca_dev, i2c) < 0)
590 case SENSOR_OV7630_3: {
591 __u8 i2c[] = {0xa0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
593 i2c[3] = sd->gain >> 2;
594 if (i2c_w(gspca_dev, i2c) < 0)
601 PDEBUG(D_ERR, "i2c error gain");
604 static void setgain(struct gspca_dev *gspca_dev)
606 struct sd *sd = (struct sd *) gspca_dev;
610 gain = sd->gain >> 4;
612 /* red and blue gain */
613 rgb_value = gain << 4 | gain;
614 reg_w(gspca_dev, 0x10, &rgb_value, 1);
617 reg_w(gspca_dev, 0x11, &rgb_value, 1);
619 if (sd->sensor_has_gain)
620 setsensorgain(gspca_dev);
623 static void setexposure(struct gspca_dev *gspca_dev)
625 struct sd *sd = (struct sd *) gspca_dev;
627 switch (sd->sensor) {
628 case SENSOR_TAS5110: {
631 /* register 19's high nibble contains the sn9c10x clock divider
632 The high nibble configures the no fps according to the
633 formula: 60 / high_nibble. With a maximum of 30 fps */
634 reg = 120 * sd->exposure / 1000;
639 reg = (reg << 4) | 0x0b;
640 reg_w(gspca_dev, 0x19, ®, 1);
643 case SENSOR_OV6650: {
644 /* The ov6650 has 2 registers which both influence exposure,
645 first there is register 11, whose low nibble sets the no fps
646 according to: fps = 30 / (low_nibble + 1)
648 The fps configures the maximum exposure setting, but it is
649 possible to use less exposure then what the fps maximum
650 allows by setting register 10. register 10 configures the
651 actual exposure as quotient of the full exposure, with 0
652 being no exposure at all (not very usefull) and reg10_max
653 being max exposure possible at that framerate.
655 The code maps our 0 - 510 ms exposure ctrl to these 2
656 registers, trying to keep fps as high as possible.
658 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
660 /* No clear idea why, but setting reg10 above this value
661 results in no change */
662 const int reg10_max = 0x4d;
664 reg11 = (60 * sd->exposure + 999) / 1000;
670 /* frame exposure time in ms = 1000 * reg11 / 30 ->
671 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
672 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
673 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
675 else if (reg10 > reg10_max)
678 /* Write reg 10 and reg11 low nibble */
681 if (i2c_w(gspca_dev, i2c) < 0)
682 PDEBUG(D_ERR, "i2c error exposure");
685 case SENSOR_OV7630_3: {
686 __u8 i2c[] = {0xb0, 0x21, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
688 /* No clear idea why, but setting reg10 above this value
689 results in no change */
690 const int reg10_max = 0x4d;
692 reg11 = (60 * sd->exposure + 999) / 1000;
698 /* frame exposure time in ms = 1000 * reg11 / 30 ->
699 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
700 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
701 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
703 else if (reg10 > reg10_max)
706 /* Write reg 10 and reg11 low nibble */
709 if (i2c_w(gspca_dev, i2c) < 0)
710 PDEBUG(D_ERR, "i2c error exposure");
717 static void do_autogain(struct gspca_dev *gspca_dev)
719 struct sd *sd = (struct sd *) gspca_dev;
720 int avg_lum = atomic_read(&sd->avg_lum);
725 if (sd->autogain_ignore_frames > 0)
726 sd->autogain_ignore_frames--;
727 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
728 sd->brightness * DESIRED_AVG_LUM / 127,
729 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE))
730 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
733 /* this function is called at probe time */
734 static int sd_config(struct gspca_dev *gspca_dev,
735 const struct usb_device_id *id)
737 struct sd *sd = (struct sd *) gspca_dev;
742 /* nctrls depends upon the sensor, so we use a per cam copy */
743 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
744 gspca_dev->sd_desc = &sd->sd_desc;
746 sd->fr_h_sz = 12; /* default size of the frame header */
747 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
748 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
750 product = id->idProduct;
751 /* switch (id->idVendor) { */
752 /* case 0x0c45: * Sonix */
754 case 0x6001: /* SN9C102 */
755 case 0x6005: /* SN9C101 */
756 case 0x6007: /* SN9C101 */
757 sd->sensor = SENSOR_TAS5110;
758 sd->sensor_has_gain = 1;
759 sd->sd_desc.nctrls = 4;
760 sd->sd_desc.dq_callback = do_autogain;
763 case 0x6009: /* SN9C101 */
764 case 0x600d: /* SN9C101 */
765 case 0x6029: /* SN9C101 */
766 sd->sensor = SENSOR_PAS106;
769 case 0x6011: /* SN9C101 - SN9C101G */
770 sd->sensor = SENSOR_OV6650;
771 sd->sensor_has_gain = 1;
772 sd->sd_desc.nctrls = 4;
773 sd->sd_desc.dq_callback = do_autogain;
776 case 0x6019: /* SN9C101 */
777 case 0x602c: /* SN9C102 */
778 case 0x602e: /* SN9C102 */
779 sd->sensor = SENSOR_OV7630;
781 case 0x60b0: /* SN9C103 */
782 sd->sensor = SENSOR_OV7630_3;
783 sd->fr_h_sz = 18; /* size of frame header */
784 sd->sensor_has_gain = 1;
785 sd->sd_desc.nctrls = 4;
786 sd->sd_desc.dq_callback = do_autogain;
789 case 0x6024: /* SN9C102 */
790 case 0x6025: /* SN9C102 */
791 sd->sensor = SENSOR_TAS5130CXX;
793 case 0x6028: /* SN9C102 */
794 sd->sensor = SENSOR_PAS202;
796 case 0x602d: /* SN9C102 */
797 sd->sensor = SENSOR_HV7131R;
799 case 0x60af: /* SN9C103 */
800 sd->sensor = SENSOR_PAS202;
801 sd->fr_h_sz = 18; /* size of frame header (?) */
807 cam = &gspca_dev->cam;
808 cam->dev_name = (char *) id->driver_info;
811 cam->cam_mode = vga_mode;
812 cam->nmodes = ARRAY_SIZE(vga_mode);
813 if (sd->sensor == SENSOR_OV7630_3) {
814 /* We only have 320x240 & 640x480 */
819 cam->cam_mode = sif_mode;
820 cam->nmodes = ARRAY_SIZE(sif_mode);
822 sd->brightness = BRIGHTNESS_DEF;
824 sd->exposure = EXPOSURE_DEF;
825 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
826 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
830 /* this function is called at open time */
831 static int sd_open(struct gspca_dev *gspca_dev)
833 reg_r(gspca_dev, 0x00);
834 if (gspca_dev->usb_buf[0] != 0x10)
839 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
843 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
845 i = ARRAY_SIZE(pas106_data);
846 data = pas106_data[0];
848 memcpy(&i2c1[2], data, 2);
849 /* copy 2 bytes from the template */
850 if (i2c_w(gspca_dev, i2c1) < 0)
851 PDEBUG(D_ERR, "i2c error pas106");
856 /* -- start the camera -- */
857 static void sd_start(struct gspca_dev *gspca_dev)
859 struct sd *sd = (struct sd *) gspca_dev;
865 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
866 switch (sd->sensor) {
868 sn9c10x = initHv7131;
870 reg17_19[1] = (mode << 4) | 0x8a;
874 sn9c10x = initOv6650;
876 reg17_19[1] = (mode << 4) | 0x8b;
880 sn9c10x = initOv7630;
882 reg17_19[1] = (mode << 4) | COMP2;
883 reg17_19[2] = MCK_INIT1;
885 case SENSOR_OV7630_3:
886 sn9c10x = initOv7630_3;
888 reg17_19[1] = (mode << 4) | COMP2;
889 reg17_19[2] = MCK_INIT1;
892 sn9c10x = initPas106;
893 reg17_19[0] = 0x24; /* 0x28 */
894 reg17_19[1] = (mode << 4) | COMP1;
895 reg17_19[2] = MCK_INIT1;
898 sn9c10x = initPas202;
899 reg17_19[0] = mode ? 0x24 : 0x20;
900 reg17_19[1] = (mode << 4) | 0x89;
904 sn9c10x = initTas5110;
906 reg17_19[1] = (mode << 4) | 0x86;
907 reg17_19[2] = 0x2b; /* 0xf3; */
910 /* case SENSOR_TAS5130CXX: */
911 sn9c10x = initTas5130;
913 reg17_19[1] = (mode << 4) | COMP;
914 reg17_19[2] = mode ? 0x23 : 0x43;
917 switch (sd->sensor) {
923 case SENSOR_OV7630_3:
926 l = sizeof initOv7630_3;
930 reg17 = sn9c10x[0x17 - 1];
935 /* reg 0x01 bit 2 video transfert on */
936 reg_w(gspca_dev, 0x01, ®01, 1);
937 /* reg 0x17 SensorClk enable inv Clk 0x60 */
938 reg_w(gspca_dev, 0x17, ®17, 1);
939 /*fixme: for ov7630 102
940 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
941 /* Set the registers from the template */
942 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
943 switch (sd->sensor) {
945 i2c_w_vector(gspca_dev, hv7131_sensor_init,
946 sizeof hv7131_sensor_init);
949 i2c_w_vector(gspca_dev, ov6650_sensor_init,
950 sizeof ov6650_sensor_init);
953 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
954 sizeof ov7630_sensor_init_com);
956 i2c_w_vector(gspca_dev, ov7630_sensor_init,
957 sizeof ov7630_sensor_init);
959 case SENSOR_OV7630_3:
960 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
961 sizeof ov7630_sensor_init_com);
963 i2c_w_vector(gspca_dev, ov7630_sensor_init_3[mode],
964 sizeof ov7630_sensor_init_3[mode]);
967 pas106_i2cinit(gspca_dev);
970 i2c_w_vector(gspca_dev, pas202_sensor_init,
971 sizeof pas202_sensor_init);
974 i2c_w_vector(gspca_dev, tas5110_sensor_init,
975 sizeof tas5110_sensor_init);
978 /* case SENSOR_TAS5130CXX: */
979 i2c_w_vector(gspca_dev, tas5130_sensor_init,
980 sizeof tas5130_sensor_init);
983 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
984 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
985 /* compression register */
986 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
988 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
990 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
991 /* reset 0x17 SensorClk enable inv Clk 0x60 */
992 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
993 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
994 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
995 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
996 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
997 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
998 /* Enable video transfert */
999 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1001 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
1005 setbrightness(gspca_dev);
1006 setexposure(gspca_dev);
1008 sd->autogain_ignore_frames = 0;
1009 atomic_set(&sd->avg_lum, -1);
1012 static void sd_stopN(struct gspca_dev *gspca_dev)
1016 ByteSend = 0x09; /* 0X00 */
1017 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1020 static void sd_stop0(struct gspca_dev *gspca_dev)
1024 static void sd_close(struct gspca_dev *gspca_dev)
1028 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1029 struct gspca_frame *frame, /* target */
1030 unsigned char *data, /* isoc packet */
1031 int len) /* iso packet length */
1034 struct sd *sd = (struct sd *) gspca_dev;
1036 if (len > 6 && len < 24) {
1037 for (i = 0; i < len - 6; i++) {
1038 if (data[0 + i] == 0xff
1039 && data[1 + i] == 0xff
1040 && data[2 + i] == 0x00
1041 && data[3 + i] == 0xc4
1042 && data[4 + i] == 0xc4
1043 && data[5 + i] == 0x96) { /* start of frame */
1044 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1046 if (i < (len - 10)) {
1047 atomic_set(&sd->avg_lum, data[i + 8] +
1048 (data[i + 9] << 8));
1050 atomic_set(&sd->avg_lum, -1);
1051 #ifdef CONFIG_VIDEO_ADV_DEBUG
1052 PDEBUG(D_STREAM, "packet too short to "
1053 "get avg brightness");
1056 data += i + sd->fr_h_sz;
1057 len -= i + sd->fr_h_sz;
1058 gspca_frame_add(gspca_dev, FIRST_PACKET,
1064 gspca_frame_add(gspca_dev, INTER_PACKET,
1068 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1070 struct sd *sd = (struct sd *) gspca_dev;
1072 sd->brightness = val;
1073 if (gspca_dev->streaming)
1074 setbrightness(gspca_dev);
1078 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1080 struct sd *sd = (struct sd *) gspca_dev;
1082 *val = sd->brightness;
1086 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1088 struct sd *sd = (struct sd *) gspca_dev;
1091 if (gspca_dev->streaming)
1096 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1098 struct sd *sd = (struct sd *) gspca_dev;
1104 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1106 struct sd *sd = (struct sd *) gspca_dev;
1109 if (gspca_dev->streaming)
1110 setexposure(gspca_dev);
1114 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1116 struct sd *sd = (struct sd *) gspca_dev;
1118 *val = sd->exposure;
1122 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1124 struct sd *sd = (struct sd *) gspca_dev;
1127 /* when switching to autogain set defaults to make sure
1128 we are on a valid point of the autogain gain /
1129 exposure knee graph, and give this change time to
1130 take effect before doing autogain. */
1132 sd->exposure = EXPOSURE_DEF;
1133 sd->gain = GAIN_DEF;
1134 if (gspca_dev->streaming) {
1135 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1136 setexposure(gspca_dev);
1144 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1146 struct sd *sd = (struct sd *) gspca_dev;
1148 *val = sd->autogain;
1152 /* sub-driver description */
1153 static const struct sd_desc sd_desc = {
1154 .name = MODULE_NAME,
1156 .nctrls = ARRAY_SIZE(sd_ctrls),
1157 .config = sd_config,
1163 .pkt_scan = sd_pkt_scan,
1166 /* -- module initialisation -- */
1167 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1168 static __devinitdata struct usb_device_id device_table[] = {
1169 #ifndef CONFIG_USB_SN9C102
1170 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1171 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1172 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1173 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1174 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1175 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1176 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1177 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1178 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1179 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1180 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1181 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1182 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1183 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1184 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1185 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1189 MODULE_DEVICE_TABLE(usb, device_table);
1191 /* -- device connect -- */
1192 static int sd_probe(struct usb_interface *intf,
1193 const struct usb_device_id *id)
1195 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1199 static struct usb_driver sd_driver = {
1200 .name = MODULE_NAME,
1201 .id_table = device_table,
1203 .disconnect = gspca_disconnect,
1206 /* -- module insert / remove -- */
1207 static int __init sd_mod_init(void)
1209 if (usb_register(&sd_driver) < 0)
1211 PDEBUG(D_PROBE, "v%s registered", version);
1214 static void __exit sd_mod_exit(void)
1216 usb_deregister(&sd_driver);
1217 PDEBUG(D_PROBE, "deregistered");
1220 module_init(sd_mod_init);
1221 module_exit(sd_mod_exit);