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] == 4)
465 static void i2c_w_vector(struct gspca_dev *gspca_dev,
466 const __u8 buffer[][8], int len)
469 reg_w(gspca_dev, 0x08, *buffer, 8);
477 static void setbrightness(struct gspca_dev *gspca_dev)
479 struct sd *sd = (struct sd *) gspca_dev;
482 switch (sd->sensor) {
483 case SENSOR_OV6650: {
485 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
487 i2cOV6650[3] = sd->brightness;
488 if (i2c_w(gspca_dev, i2cOV6650) < 0)
492 case SENSOR_OV7630_3:
493 case SENSOR_OV7630: {
495 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
497 /* change reg 0x06 */
498 i2cOV[3] = sd->brightness;
499 if (i2c_w(gspca_dev, i2cOV) < 0)
503 case SENSOR_PAS106: {
505 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
507 i2c1[3] = sd->brightness >> 3;
509 if (i2c_w(gspca_dev, i2c1) < 0)
513 if (i2c_w(gspca_dev, i2c1) < 0)
517 case SENSOR_PAS202: {
518 /* __u8 i2cpexpo1[] =
519 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
521 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
523 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
524 static __u8 i2cpdoit[] =
525 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
527 /* change reg 0x10 */
528 i2cpexpo[4] = 0xff - sd->brightness;
529 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
531 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
533 if (i2c_w(gspca_dev, i2cpexpo) < 0)
535 if (i2c_w(gspca_dev, i2cpdoit) < 0)
537 i2cp202[3] = sd->brightness >> 3;
538 if (i2c_w(gspca_dev, i2cp202) < 0)
540 if (i2c_w(gspca_dev, i2cpdoit) < 0)
544 case SENSOR_TAS5130CXX: {
546 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
548 value = 0xff - sd->brightness;
550 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
551 if (i2c_w(gspca_dev, i2c) < 0)
556 /* FIXME figure out howto control brightness on TAS5110 */
561 PDEBUG(D_ERR, "i2c error brightness");
564 static void setsensorgain(struct gspca_dev *gspca_dev)
566 struct sd *sd = (struct sd *) gspca_dev;
568 switch (sd->sensor) {
570 case SENSOR_TAS5110: {
572 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
574 i2c[4] = 255 - sd->gain;
575 if (i2c_w(gspca_dev, i2c) < 0)
579 case SENSOR_OV6650: {
580 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
582 i2c[3] = sd->gain >> 3;
583 if (i2c_w(gspca_dev, i2c) < 0)
587 case SENSOR_OV7630_3: {
588 __u8 i2c[] = {0xa0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
590 i2c[3] = sd->gain >> 2;
591 if (i2c_w(gspca_dev, i2c) < 0)
598 PDEBUG(D_ERR, "i2c error gain");
601 static void setgain(struct gspca_dev *gspca_dev)
603 struct sd *sd = (struct sd *) gspca_dev;
607 gain = sd->gain >> 4;
609 /* red and blue gain */
610 rgb_value = gain << 4 | gain;
611 reg_w(gspca_dev, 0x10, &rgb_value, 1);
614 reg_w(gspca_dev, 0x11, &rgb_value, 1);
616 if (sd->sensor_has_gain)
617 setsensorgain(gspca_dev);
620 static void setexposure(struct gspca_dev *gspca_dev)
622 struct sd *sd = (struct sd *) gspca_dev;
624 switch (sd->sensor) {
625 case SENSOR_TAS5110: {
628 /* register 19's high nibble contains the sn9c10x clock divider
629 The high nibble configures the no fps according to the
630 formula: 60 / high_nibble. With a maximum of 30 fps */
631 reg = 120 * sd->exposure / 1000;
636 reg = (reg << 4) | 0x0b;
637 reg_w(gspca_dev, 0x19, ®, 1);
640 case SENSOR_OV6650: {
641 /* The ov6650 has 2 registers which both influence exposure,
642 first there is register 11, whose low nibble sets the no fps
643 according to: fps = 30 / (low_nibble + 1)
645 The fps configures the maximum exposure setting, but it is
646 possible to use less exposure then what the fps maximum
647 allows by setting register 10. register 10 configures the
648 actual exposure as quotient of the full exposure, with 0
649 being no exposure at all (not very usefull) and reg10_max
650 being max exposure possible at that framerate.
652 The code maps our 0 - 510 ms exposure ctrl to these 2
653 registers, trying to keep fps as high as possible.
655 __u8 i2c[] = {0xb0, 0x60, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
657 /* No clear idea why, but setting reg10 above this value
658 results in no change */
659 const int reg10_max = 0x4d;
661 reg11 = (60 * sd->exposure + 999) / 1000;
667 /* frame exposure time in ms = 1000 * reg11 / 30 ->
668 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
669 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
670 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
672 else if (reg10 > reg10_max)
675 /* Write reg 10 and reg11 low nibble */
678 if (i2c_w(gspca_dev, i2c) < 0)
679 PDEBUG(D_ERR, "i2c error exposure");
682 case SENSOR_OV7630_3: {
683 __u8 i2c[] = {0xb0, 0x21, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
685 /* No clear idea why, but setting reg10 above this value
686 results in no change */
687 const int reg10_max = 0x4d;
689 reg11 = (60 * sd->exposure + 999) / 1000;
695 /* frame exposure time in ms = 1000 * reg11 / 30 ->
696 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
697 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
698 if (reg10 < 1) /* 0 is a valid value, but is very _black_ */
700 else if (reg10 > reg10_max)
703 /* Write reg 10 and reg11 low nibble */
706 if (i2c_w(gspca_dev, i2c) < 0)
707 PDEBUG(D_ERR, "i2c error exposure");
714 static void do_autogain(struct gspca_dev *gspca_dev)
716 struct sd *sd = (struct sd *) gspca_dev;
717 int avg_lum = atomic_read(&sd->avg_lum);
722 if (sd->autogain_ignore_frames > 0)
723 sd->autogain_ignore_frames--;
724 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
725 sd->brightness * DESIRED_AVG_LUM / 127,
726 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE))
727 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
730 /* this function is called at probe time */
731 static int sd_config(struct gspca_dev *gspca_dev,
732 const struct usb_device_id *id)
734 struct sd *sd = (struct sd *) gspca_dev;
739 /* nctrls depends upon the sensor, so we use a per cam copy */
740 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
741 gspca_dev->sd_desc = &sd->sd_desc;
743 sd->fr_h_sz = 12; /* default size of the frame header */
744 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
745 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
747 product = id->idProduct;
748 /* switch (id->idVendor) { */
749 /* case 0x0c45: * Sonix */
751 case 0x6001: /* SN9C102 */
752 case 0x6005: /* SN9C101 */
753 case 0x6007: /* SN9C101 */
754 sd->sensor = SENSOR_TAS5110;
755 sd->sensor_has_gain = 1;
756 sd->sd_desc.nctrls = 4;
757 sd->sd_desc.dq_callback = do_autogain;
760 case 0x6009: /* SN9C101 */
761 case 0x600d: /* SN9C101 */
762 case 0x6029: /* SN9C101 */
763 sd->sensor = SENSOR_PAS106;
766 case 0x6011: /* SN9C101 - SN9C101G */
767 sd->sensor = SENSOR_OV6650;
768 sd->sensor_has_gain = 1;
769 sd->sd_desc.nctrls = 4;
770 sd->sd_desc.dq_callback = do_autogain;
773 case 0x6019: /* SN9C101 */
774 case 0x602c: /* SN9C102 */
775 case 0x602e: /* SN9C102 */
776 sd->sensor = SENSOR_OV7630;
778 case 0x60b0: /* SN9C103 */
779 sd->sensor = SENSOR_OV7630_3;
780 sd->fr_h_sz = 18; /* size of frame header */
781 sd->sensor_has_gain = 1;
782 sd->sd_desc.nctrls = 4;
783 sd->sd_desc.dq_callback = do_autogain;
786 case 0x6024: /* SN9C102 */
787 case 0x6025: /* SN9C102 */
788 sd->sensor = SENSOR_TAS5130CXX;
790 case 0x6028: /* SN9C102 */
791 sd->sensor = SENSOR_PAS202;
793 case 0x602d: /* SN9C102 */
794 sd->sensor = SENSOR_HV7131R;
796 case 0x60af: /* SN9C103 */
797 sd->sensor = SENSOR_PAS202;
798 sd->fr_h_sz = 18; /* size of frame header (?) */
804 cam = &gspca_dev->cam;
805 cam->dev_name = (char *) id->driver_info;
808 cam->cam_mode = vga_mode;
809 cam->nmodes = ARRAY_SIZE(vga_mode);
810 if (sd->sensor == SENSOR_OV7630_3) {
811 /* We only have 320x240 & 640x480 */
816 cam->cam_mode = sif_mode;
817 cam->nmodes = ARRAY_SIZE(sif_mode);
819 sd->brightness = BRIGHTNESS_DEF;
821 sd->exposure = EXPOSURE_DEF;
822 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
823 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
827 /* this function is called at open time */
828 static int sd_open(struct gspca_dev *gspca_dev)
830 reg_r(gspca_dev, 0x00);
831 if (gspca_dev->usb_buf[0] != 0x10)
836 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
840 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
842 i = ARRAY_SIZE(pas106_data);
843 data = pas106_data[0];
845 memcpy(&i2c1[2], data, 2);
846 /* copy 2 bytes from the template */
847 if (i2c_w(gspca_dev, i2c1) < 0)
848 PDEBUG(D_ERR, "i2c error pas106");
853 /* -- start the camera -- */
854 static void sd_start(struct gspca_dev *gspca_dev)
856 struct sd *sd = (struct sd *) gspca_dev;
862 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
863 switch (sd->sensor) {
865 sn9c10x = initHv7131;
867 reg17_19[1] = (mode << 4) | 0x8a;
871 sn9c10x = initOv6650;
873 reg17_19[1] = (mode << 4) | 0x8b;
877 sn9c10x = initOv7630;
879 reg17_19[1] = (mode << 4) | COMP2;
880 reg17_19[2] = MCK_INIT1;
882 case SENSOR_OV7630_3:
883 sn9c10x = initOv7630_3;
885 reg17_19[1] = (mode << 4) | COMP2;
886 reg17_19[2] = MCK_INIT1;
889 sn9c10x = initPas106;
890 reg17_19[0] = 0x24; /* 0x28 */
891 reg17_19[1] = (mode << 4) | COMP1;
892 reg17_19[2] = MCK_INIT1;
895 sn9c10x = initPas202;
896 reg17_19[0] = mode ? 0x24 : 0x20;
897 reg17_19[1] = (mode << 4) | 0x89;
901 sn9c10x = initTas5110;
903 reg17_19[1] = (mode << 4) | 0x86;
904 reg17_19[2] = 0x2b; /* 0xf3; */
907 /* case SENSOR_TAS5130CXX: */
908 sn9c10x = initTas5130;
910 reg17_19[1] = (mode << 4) | COMP;
911 reg17_19[2] = mode ? 0x23 : 0x43;
914 switch (sd->sensor) {
920 case SENSOR_OV7630_3:
923 l = sizeof initOv7630_3;
927 reg17 = sn9c10x[0x17 - 1];
932 /* reg 0x01 bit 2 video transfert on */
933 reg_w(gspca_dev, 0x01, ®01, 1);
934 /* reg 0x17 SensorClk enable inv Clk 0x60 */
935 reg_w(gspca_dev, 0x17, ®17, 1);
936 /*fixme: for ov7630 102
937 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
938 /* Set the registers from the template */
939 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
940 switch (sd->sensor) {
942 i2c_w_vector(gspca_dev, hv7131_sensor_init,
943 sizeof hv7131_sensor_init);
946 i2c_w_vector(gspca_dev, ov6650_sensor_init,
947 sizeof ov6650_sensor_init);
950 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
951 sizeof ov7630_sensor_init_com);
953 i2c_w_vector(gspca_dev, ov7630_sensor_init,
954 sizeof ov7630_sensor_init);
956 case SENSOR_OV7630_3:
957 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
958 sizeof ov7630_sensor_init_com);
960 i2c_w_vector(gspca_dev, ov7630_sensor_init_3[mode],
961 sizeof ov7630_sensor_init_3[mode]);
964 pas106_i2cinit(gspca_dev);
967 i2c_w_vector(gspca_dev, pas202_sensor_init,
968 sizeof pas202_sensor_init);
971 i2c_w_vector(gspca_dev, tas5110_sensor_init,
972 sizeof tas5110_sensor_init);
975 /* case SENSOR_TAS5130CXX: */
976 i2c_w_vector(gspca_dev, tas5130_sensor_init,
977 sizeof tas5130_sensor_init);
980 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
981 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
982 /* compression register */
983 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
985 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
987 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
988 /* reset 0x17 SensorClk enable inv Clk 0x60 */
989 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
990 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
991 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
992 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
993 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
994 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
995 /* Enable video transfert */
996 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
998 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
1002 setbrightness(gspca_dev);
1003 setexposure(gspca_dev);
1005 sd->autogain_ignore_frames = 0;
1006 atomic_set(&sd->avg_lum, -1);
1009 static void sd_stopN(struct gspca_dev *gspca_dev)
1013 ByteSend = 0x09; /* 0X00 */
1014 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1017 static void sd_stop0(struct gspca_dev *gspca_dev)
1021 static void sd_close(struct gspca_dev *gspca_dev)
1025 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1026 struct gspca_frame *frame, /* target */
1027 unsigned char *data, /* isoc packet */
1028 int len) /* iso packet length */
1031 struct sd *sd = (struct sd *) gspca_dev;
1033 if (len > 6 && len < 24) {
1034 for (i = 0; i < len - 6; i++) {
1035 if (data[0 + i] == 0xff
1036 && data[1 + i] == 0xff
1037 && data[2 + i] == 0x00
1038 && data[3 + i] == 0xc4
1039 && data[4 + i] == 0xc4
1040 && data[5 + i] == 0x96) { /* start of frame */
1041 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1043 if (i < (len - 10)) {
1044 atomic_set(&sd->avg_lum, data[i + 8] +
1045 (data[i + 9] << 8));
1047 atomic_set(&sd->avg_lum, -1);
1048 #ifdef CONFIG_VIDEO_ADV_DEBUG
1049 PDEBUG(D_STREAM, "packet too short to "
1050 "get avg brightness");
1053 data += i + sd->fr_h_sz;
1054 len -= i + sd->fr_h_sz;
1055 gspca_frame_add(gspca_dev, FIRST_PACKET,
1061 gspca_frame_add(gspca_dev, INTER_PACKET,
1065 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1067 struct sd *sd = (struct sd *) gspca_dev;
1069 sd->brightness = val;
1070 if (gspca_dev->streaming)
1071 setbrightness(gspca_dev);
1075 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1077 struct sd *sd = (struct sd *) gspca_dev;
1079 *val = sd->brightness;
1083 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1085 struct sd *sd = (struct sd *) gspca_dev;
1088 if (gspca_dev->streaming)
1093 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1095 struct sd *sd = (struct sd *) gspca_dev;
1101 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1103 struct sd *sd = (struct sd *) gspca_dev;
1106 if (gspca_dev->streaming)
1107 setexposure(gspca_dev);
1111 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1113 struct sd *sd = (struct sd *) gspca_dev;
1115 *val = sd->exposure;
1119 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1121 struct sd *sd = (struct sd *) gspca_dev;
1124 /* when switching to autogain set defaults to make sure
1125 we are on a valid point of the autogain gain /
1126 exposure knee graph, and give this change time to
1127 take effect before doing autogain. */
1129 sd->exposure = EXPOSURE_DEF;
1130 sd->gain = GAIN_DEF;
1131 if (gspca_dev->streaming) {
1132 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1133 setexposure(gspca_dev);
1141 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1143 struct sd *sd = (struct sd *) gspca_dev;
1145 *val = sd->autogain;
1149 /* sub-driver description */
1150 static const struct sd_desc sd_desc = {
1151 .name = MODULE_NAME,
1153 .nctrls = ARRAY_SIZE(sd_ctrls),
1154 .config = sd_config,
1160 .pkt_scan = sd_pkt_scan,
1163 /* -- module initialisation -- */
1164 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1165 static __devinitdata struct usb_device_id device_table[] = {
1166 #ifndef CONFIG_USB_SN9C102
1167 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1168 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1169 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1170 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1171 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1172 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1173 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1174 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1175 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1176 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1177 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1178 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1179 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1180 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1181 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1182 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1186 MODULE_DEVICE_TABLE(usb, device_table);
1188 /* -- device connect -- */
1189 static int sd_probe(struct usb_interface *intf,
1190 const struct usb_device_id *id)
1192 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1196 static struct usb_driver sd_driver = {
1197 .name = MODULE_NAME,
1198 .id_table = device_table,
1200 .disconnect = gspca_disconnect,
1203 /* -- module insert / remove -- */
1204 static int __init sd_mod_init(void)
1206 if (usb_register(&sd_driver) < 0)
1208 PDEBUG(D_PROBE, "v%s registered", version);
1211 static void __exit sd_mod_exit(void)
1213 usb_deregister(&sd_driver);
1214 PDEBUG(D_PROBE, "deregistered");
1217 module_init(sd_mod_init);
1218 module_exit(sd_mod_exit);