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 short 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 500
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 400
114 .default_value = GAIN_DEF,
121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER,
124 #define EXPOSURE_DEF 0
125 #define EXPOSURE_KNEE 353 /* 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 0x16, 0x12, /* 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, 0x78, 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}, jfm */
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: {
494 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
496 /* change reg 0x06 */
497 i2cOV[3] = sd->brightness;
498 if (i2c_w(gspca_dev, i2cOV) < 0)
502 case SENSOR_PAS106: {
504 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
506 i2c1[3] = sd->brightness >> 3;
508 if (i2c_w(gspca_dev, i2c1) < 0)
512 if (i2c_w(gspca_dev, i2c1) < 0)
516 case SENSOR_PAS202: {
517 /* __u8 i2cpexpo1[] =
518 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
520 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
522 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
523 static __u8 i2cpdoit[] =
524 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
526 /* change reg 0x10 */
527 i2cpexpo[4] = 0xff - sd->brightness;
528 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
530 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
532 if (i2c_w(gspca_dev, i2cpexpo) < 0)
534 if (i2c_w(gspca_dev, i2cpdoit) < 0)
536 i2cp202[3] = sd->brightness >> 3;
537 if (i2c_w(gspca_dev, i2cp202) < 0)
539 if (i2c_w(gspca_dev, i2cpdoit) < 0)
543 case SENSOR_TAS5130CXX: {
545 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
547 value = 0xff - sd->brightness;
549 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
550 if (i2c_w(gspca_dev, i2c) < 0)
555 /* FIXME figure out howto control brightness on TAS5110 */
560 PDEBUG(D_ERR, "i2c error brightness");
563 static void setsensorgain(struct gspca_dev *gspca_dev)
565 struct sd *sd = (struct sd *) gspca_dev;
568 gain = (sd->gain + 1) >> 1;
572 switch (sd->sensor) {
574 case SENSOR_TAS5110: {
576 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
579 if (i2c_w(gspca_dev, i2c) < 0)
583 case SENSOR_OV6650: {
584 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
586 if (i2c_w(gspca_dev, i2c) < 0)
593 PDEBUG(D_ERR, "i2c error gain");
596 static void setgain(struct gspca_dev *gspca_dev)
598 struct sd *sd = (struct sd *) gspca_dev;
602 gain = sd->gain >> 5;
604 /* red and blue gain */
605 rgb_value = gain << 4 | gain;
606 reg_w(gspca_dev, 0x10, &rgb_value, 1);
609 reg_w(gspca_dev, 0x11, &rgb_value, 1);
611 if (sd->sensor_has_gain)
612 setsensorgain(gspca_dev);
615 static void setexposure(struct gspca_dev *gspca_dev)
617 struct sd *sd = (struct sd *) gspca_dev;
618 /* translate 0 - 255 to a number of fps in a 30 - 1 scale */
619 int fps = 30 - sd->exposure * 29 / 511;
621 switch (sd->sensor) {
622 case SENSOR_TAS5110: {
625 /* register 19's high nibble contains the sn9c10x clock divider
626 The high nibble configures the no fps according to the
627 formula: 60 / high_nibble. With a maximum of 30 fps */
631 reg = (reg << 4) | 0x0b;
632 reg_w(gspca_dev, 0x19, ®, 1);
635 case SENSOR_OV6650: {
636 __u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
637 i2c[3] = 30 / fps - 1;
641 if (i2c_w(gspca_dev, i2c) < 0)
642 PDEBUG(D_ERR, "i2c error exposure");
649 static void do_autogain(struct gspca_dev *gspca_dev)
651 struct sd *sd = (struct sd *) gspca_dev;
652 int avg_lum = atomic_read(&sd->avg_lum);
657 if (sd->autogain_ignore_frames > 0)
658 sd->autogain_ignore_frames--;
659 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
660 sd->brightness * DESIRED_AVG_LUM / 127,
661 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE))
662 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
665 /* this function is called at probe time */
666 static int sd_config(struct gspca_dev *gspca_dev,
667 const struct usb_device_id *id)
669 struct sd *sd = (struct sd *) gspca_dev;
674 /* nctrls depends upon the sensor, so we use a per cam copy */
675 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
676 gspca_dev->sd_desc = &sd->sd_desc;
678 sd->fr_h_sz = 12; /* default size of the frame header */
679 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
681 product = id->idProduct;
682 /* switch (id->idVendor) { */
683 /* case 0x0c45: * Sonix */
685 case 0x6001: /* SN9C102 */
686 case 0x6005: /* SN9C101 */
687 case 0x6007: /* SN9C101 */
688 sd->sensor = SENSOR_TAS5110;
689 sd->sensor_has_gain = 1;
690 sd->sd_desc.nctrls = 4;
691 sd->sd_desc.dq_callback = do_autogain;
694 case 0x6009: /* SN9C101 */
695 case 0x600d: /* SN9C101 */
696 case 0x6029: /* SN9C101 */
697 sd->sensor = SENSOR_PAS106;
700 case 0x6011: /* SN9C101 - SN9C101G */
701 sd->sensor = SENSOR_OV6650;
702 sd->sensor_has_gain = 1;
703 sd->sd_desc.nctrls = 4;
704 sd->sd_desc.dq_callback = do_autogain;
707 case 0x6019: /* SN9C101 */
708 case 0x602c: /* SN9C102 */
709 case 0x602e: /* SN9C102 */
710 sd->sensor = SENSOR_OV7630;
712 case 0x60b0: /* SN9C103 */
713 sd->sensor = SENSOR_OV7630_3;
714 sd->fr_h_sz = 18; /* size of frame header */
716 case 0x6024: /* SN9C102 */
717 case 0x6025: /* SN9C102 */
718 sd->sensor = SENSOR_TAS5130CXX;
720 case 0x6028: /* SN9C102 */
721 sd->sensor = SENSOR_PAS202;
723 case 0x602d: /* SN9C102 */
724 sd->sensor = SENSOR_HV7131R;
726 case 0x60af: /* SN9C103 */
727 sd->sensor = SENSOR_PAS202;
728 sd->fr_h_sz = 18; /* size of frame header (?) */
734 cam = &gspca_dev->cam;
735 cam->dev_name = (char *) id->driver_info;
738 cam->cam_mode = vga_mode;
739 cam->nmodes = ARRAY_SIZE(vga_mode);
740 if (sd->sensor == SENSOR_OV7630_3) {
741 /* We only have 320x240 & 640x480 */
746 cam->cam_mode = sif_mode;
747 cam->nmodes = ARRAY_SIZE(sif_mode);
749 sd->brightness = BRIGHTNESS_DEF;
751 sd->exposure = EXPOSURE_DEF;
752 sd->autogain = AUTOGAIN_DEF;
753 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
754 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
758 /* this function is called at open time */
759 static int sd_open(struct gspca_dev *gspca_dev)
761 reg_r(gspca_dev, 0x00);
762 if (gspca_dev->usb_buf[0] != 0x10)
767 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
771 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
773 i = ARRAY_SIZE(pas106_data);
774 data = pas106_data[0];
776 memcpy(&i2c1[2], data, 2);
777 /* copy 2 bytes from the template */
778 if (i2c_w(gspca_dev, i2c1) < 0)
779 PDEBUG(D_ERR, "i2c error pas106");
784 /* -- start the camera -- */
785 static void sd_start(struct gspca_dev *gspca_dev)
787 struct sd *sd = (struct sd *) gspca_dev;
792 static const __u8 reg15[2] = { 0x28, 0x1e };
794 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
795 switch (sd->sensor) {
797 sn9c10x = initHv7131;
799 reg17_19[1] = (mode << 4) | 0x8a;
803 sn9c10x = initOv6650;
805 reg17_19[1] = (mode << 4) | 0x8b;
809 sn9c10x = initOv7630;
811 reg17_19[1] = (mode << 4) | COMP2;
812 reg17_19[2] = MCK_INIT1;
814 case SENSOR_OV7630_3:
815 sn9c10x = initOv7630_3;
817 reg17_19[1] = (mode << 4) | COMP2;
818 reg17_19[2] = MCK_INIT1;
821 sn9c10x = initPas106;
822 reg17_19[0] = 0x24; /* 0x28 */
823 reg17_19[1] = (mode << 4) | COMP1;
824 reg17_19[2] = MCK_INIT1;
827 sn9c10x = initPas202;
828 reg17_19[0] = mode ? 0x24 : 0x20;
829 reg17_19[1] = (mode << 4) | 0x89;
833 sn9c10x = initTas5110;
835 reg17_19[1] = (mode << 4) | 0x86;
836 reg17_19[2] = 0x2b; /* 0xf3; */
839 /* case SENSOR_TAS5130CXX: */
840 sn9c10x = initTas5130;
842 reg17_19[1] = (mode << 4) | COMP;
843 reg17_19[2] = mode ? 0x23 : 0x43;
846 switch (sd->sensor) {
852 case SENSOR_OV7630_3:
855 l = sizeof initOv7630_3;
859 reg17 = sn9c10x[0x17 - 1];
864 /* reg 0x01 bit 2 video transfert on */
865 reg_w(gspca_dev, 0x01, ®01, 1);
866 /* reg 0x17 SensorClk enable inv Clk 0x60 */
867 reg_w(gspca_dev, 0x17, ®17, 1);
868 /*fixme: for ov7630 102
869 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
870 /* Set the registers from the template */
871 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
872 switch (sd->sensor) {
874 i2c_w_vector(gspca_dev, hv7131_sensor_init,
875 sizeof hv7131_sensor_init);
878 i2c_w_vector(gspca_dev, ov6650_sensor_init,
879 sizeof ov6650_sensor_init);
882 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
883 sizeof ov7630_sensor_init_com);
885 i2c_w_vector(gspca_dev, ov7630_sensor_init,
886 sizeof ov7630_sensor_init);
888 case SENSOR_OV7630_3:
889 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
890 sizeof ov7630_sensor_init_com);
892 i2c_w_vector(gspca_dev, ov7630_sensor_init_3[mode],
893 sizeof ov7630_sensor_init_3[mode]);
896 pas106_i2cinit(gspca_dev);
899 i2c_w_vector(gspca_dev, pas202_sensor_init,
900 sizeof pas202_sensor_init);
903 i2c_w_vector(gspca_dev, tas5110_sensor_init,
904 sizeof tas5110_sensor_init);
907 /* case SENSOR_TAS5130CXX: */
908 i2c_w_vector(gspca_dev, tas5130_sensor_init,
909 sizeof tas5130_sensor_init);
912 /* H_size V_size 0x28, 0x1e maybe 640x480 */
913 reg_w(gspca_dev, 0x15, reg15, 2);
914 /* compression register */
915 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
916 if (sd->sensor != SENSOR_OV7630_3) {
918 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
920 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
922 /* reset 0x17 SensorClk enable inv Clk 0x60 */
923 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
924 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
925 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
926 if (sd->sensor != SENSOR_OV7630_3)
927 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
928 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
929 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
930 /* Enable video transfert */
931 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
933 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
937 setbrightness(gspca_dev);
938 setexposure(gspca_dev);
940 sd->autogain_ignore_frames = 0;
941 atomic_set(&sd->avg_lum, -1);
944 static void sd_stopN(struct gspca_dev *gspca_dev)
948 ByteSend = 0x09; /* 0X00 */
949 reg_w(gspca_dev, 0x01, &ByteSend, 1);
952 static void sd_stop0(struct gspca_dev *gspca_dev)
956 static void sd_close(struct gspca_dev *gspca_dev)
960 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
961 struct gspca_frame *frame, /* target */
962 unsigned char *data, /* isoc packet */
963 int len) /* iso packet length */
966 struct sd *sd = (struct sd *) gspca_dev;
968 if (len > 6 && len < 24) {
969 for (i = 0; i < len - 6; i++) {
970 if (data[0 + i] == 0xff
971 && data[1 + i] == 0xff
972 && data[2 + i] == 0x00
973 && data[3 + i] == 0xc4
974 && data[4 + i] == 0xc4
975 && data[5 + i] == 0x96) { /* start of frame */
976 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
978 if (i < (len - 10)) {
979 atomic_set(&sd->avg_lum, data[i + 8] +
982 atomic_set(&sd->avg_lum, -1);
983 #ifdef CONFIG_VIDEO_ADV_DEBUG
984 PDEBUG(D_STREAM, "packet too short to "
985 "get avg brightness");
988 data += i + sd->fr_h_sz;
989 len -= i + sd->fr_h_sz;
990 gspca_frame_add(gspca_dev, FIRST_PACKET,
996 gspca_frame_add(gspca_dev, INTER_PACKET,
1000 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1002 struct sd *sd = (struct sd *) gspca_dev;
1004 sd->brightness = val;
1005 if (gspca_dev->streaming)
1006 setbrightness(gspca_dev);
1010 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1012 struct sd *sd = (struct sd *) gspca_dev;
1014 *val = sd->brightness;
1018 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1020 struct sd *sd = (struct sd *) gspca_dev;
1023 if (gspca_dev->streaming)
1028 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1030 struct sd *sd = (struct sd *) gspca_dev;
1036 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1038 struct sd *sd = (struct sd *) gspca_dev;
1041 if (gspca_dev->streaming)
1042 setexposure(gspca_dev);
1046 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1048 struct sd *sd = (struct sd *) gspca_dev;
1050 *val = sd->exposure;
1054 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1056 struct sd *sd = (struct sd *) gspca_dev;
1059 /* when switching to autogain set defaults to make sure
1060 we are on a valid point of the autogain gain /
1061 exposure knee graph, and give this change time to
1062 take effect before doing autogain. */
1064 sd->exposure = EXPOSURE_DEF;
1065 sd->gain = GAIN_DEF;
1066 if (gspca_dev->streaming) {
1067 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1068 setexposure(gspca_dev);
1076 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1078 struct sd *sd = (struct sd *) gspca_dev;
1080 *val = sd->autogain;
1084 /* sub-driver description */
1085 static const struct sd_desc sd_desc = {
1086 .name = MODULE_NAME,
1088 .nctrls = ARRAY_SIZE(sd_ctrls),
1089 .config = sd_config,
1095 .pkt_scan = sd_pkt_scan,
1098 /* -- module initialisation -- */
1099 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1100 static __devinitdata struct usb_device_id device_table[] = {
1101 #ifndef CONFIG_USB_SN9C102
1102 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1103 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1104 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1105 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1106 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1107 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1108 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1109 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1110 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1111 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1112 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1113 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1114 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1115 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1116 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1117 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1121 MODULE_DEVICE_TABLE(usb, device_table);
1123 /* -- device connect -- */
1124 static int sd_probe(struct usb_interface *intf,
1125 const struct usb_device_id *id)
1127 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1131 static struct usb_driver sd_driver = {
1132 .name = MODULE_NAME,
1133 .id_table = device_table,
1135 .disconnect = gspca_disconnect,
1138 /* -- module insert / remove -- */
1139 static int __init sd_mod_init(void)
1141 if (usb_register(&sd_driver) < 0)
1143 PDEBUG(D_PROBE, "v%s registered", version);
1146 static void __exit sd_mod_exit(void)
1148 usb_deregister(&sd_driver);
1149 PDEBUG(D_PROBE, "deregistered");
1152 module_init(sd_mod_init);
1153 module_exit(sd_mod_exit);