2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define MODULE_NAME "sonixb"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28 static const char version[] = "2.1.8";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
39 sensor, so we use a per cam copy */
43 unsigned char exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
49 unsigned char fr_h_sz; /* size of frame header */
50 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
64 #define COMP 0xc7 /* 0x87 //0x07 */
65 #define COMP1 0xc9 /* 0x89 //0x09 */
68 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
72 /* We calculate the autogain at the end of the transfer of a frame, at this
73 moment a frame with the old settings is being transmitted, and a frame is
74 being captured with the old settings. So if we adjust the autogain we must
75 ignore atleast the 2 next frames for the new settings to come into effect
76 before doing any other adjustments */
77 #define AUTOGAIN_IGNORE_FRAMES 3
78 #define AUTOGAIN_DEADZONE 1000
79 #define DESIRED_AVG_LUM 7000
81 /* V4L2 controls supported by the driver */
82 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
93 static struct ctrl sd_ctrls[] = {
96 .id = V4L2_CID_BRIGHTNESS,
97 .type = V4L2_CTRL_TYPE_INTEGER,
102 #define BRIGHTNESS_DEF 127
103 .default_value = BRIGHTNESS_DEF,
105 .set = sd_setbrightness,
106 .get = sd_getbrightness,
111 .type = V4L2_CTRL_TYPE_INTEGER,
117 #define GAIN_KNEE 200
118 .default_value = GAIN_DEF,
125 .id = V4L2_CID_EXPOSURE,
126 .type = V4L2_CTRL_TYPE_INTEGER,
128 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
129 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
133 .default_value = EXPOSURE_DEF,
136 .set = sd_setexposure,
137 .get = sd_getexposure,
141 .id = V4L2_CID_AUTOGAIN,
142 .type = V4L2_CTRL_TYPE_BOOLEAN,
143 .name = "Automatic Gain (and Exposure)",
147 #define AUTOGAIN_DEF 1
148 .default_value = AUTOGAIN_DEF,
151 .set = sd_setautogain,
152 .get = sd_getautogain,
156 .id = V4L2_CID_POWER_LINE_FREQUENCY,
157 .type = V4L2_CTRL_TYPE_MENU,
158 .name = "Light frequency filter",
160 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
163 .default_value = FREQ_DEF,
170 static struct v4l2_pix_format vga_mode[] = {
171 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
173 .sizeimage = 160 * 120,
174 .colorspace = V4L2_COLORSPACE_SRGB,
176 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
178 .sizeimage = 320 * 240,
179 .colorspace = V4L2_COLORSPACE_SRGB,
181 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
183 .sizeimage = 640 * 480,
184 .colorspace = V4L2_COLORSPACE_SRGB,
187 static struct v4l2_pix_format sif_mode[] = {
188 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
190 .sizeimage = 176 * 144,
191 .colorspace = V4L2_COLORSPACE_SRGB,
193 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
195 .sizeimage = 352 * 288,
196 .colorspace = V4L2_COLORSPACE_SRGB,
200 static const __u8 probe_ov7630[] = {0x08, 0x44};
202 static const __u8 initHv7131[] = {
203 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
206 0x28, 0x1e, 0x60, 0x8a, 0x20,
207 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
209 static const __u8 hv7131_sensor_init[][8] = {
210 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
211 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
212 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
213 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
214 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
216 static const __u8 initOv6650[] = {
217 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
218 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
220 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
222 static const __u8 ov6650_sensor_init[][8] =
224 /* Bright, contrast, etc are set througth SCBB interface.
225 * AVCAP on win2 do not send any data on this controls. */
226 /* Anyway, some registers appears to alter bright and constrat */
229 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
230 /* Set clock register 0x11 low nibble is clock divider */
231 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
232 /* Next some unknown stuff */
233 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
234 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
235 * THIS SET GREEN SCREEN
236 * (pixels could be innverted in decode kind of "brg",
237 * but blue wont be there. Avoid this data ... */
238 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
239 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
240 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
241 /* Disable autobright ? */
242 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
243 /* Some more unknown stuff */
244 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
245 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
248 static const __u8 initOv7630[] = {
249 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
250 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
251 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
252 0x28, 0x1e, /* H & V sizes r15 .. r16 */
253 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
254 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
256 static const __u8 initOv7630_3[] = {
257 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
258 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
259 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
260 0x28, 0x1e, /* H & V sizes r15 .. r16 */
261 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
262 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
263 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
264 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
266 static const __u8 ov7630_sensor_init_com[][8] = {
267 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
268 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
269 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
270 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
271 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
272 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
273 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
274 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
275 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
276 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
277 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
278 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
279 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
280 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
281 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
282 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
283 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
284 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
285 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
287 static const __u8 ov7630_sensor_init[][8] = {
288 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
289 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
290 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
291 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
292 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
294 static const __u8 ov7630_sensor_init_3[][8] = {
295 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
296 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
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) {
487 case SENSOR_OV7630_3:
488 case SENSOR_OV7630: {
490 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
492 /* change reg 0x06 */
493 i2cOV[1] = sd->sensor_addr;
494 i2cOV[3] = sd->brightness;
495 if (i2c_w(gspca_dev, i2cOV) < 0)
499 case SENSOR_PAS106: {
501 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
503 i2c1[3] = sd->brightness >> 3;
505 if (i2c_w(gspca_dev, i2c1) < 0)
509 if (i2c_w(gspca_dev, i2c1) < 0)
513 case SENSOR_PAS202: {
514 /* __u8 i2cpexpo1[] =
515 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
517 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
519 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
520 static __u8 i2cpdoit[] =
521 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
523 /* change reg 0x10 */
524 i2cpexpo[4] = 0xff - sd->brightness;
525 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
527 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
529 if (i2c_w(gspca_dev, i2cpexpo) < 0)
531 if (i2c_w(gspca_dev, i2cpdoit) < 0)
533 i2cp202[3] = sd->brightness >> 3;
534 if (i2c_w(gspca_dev, i2cp202) < 0)
536 if (i2c_w(gspca_dev, i2cpdoit) < 0)
540 case SENSOR_TAS5130CXX: {
542 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
544 value = 0xff - sd->brightness;
546 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
547 if (i2c_w(gspca_dev, i2c) < 0)
552 /* FIXME figure out howto control brightness on TAS5110 */
557 PDEBUG(D_ERR, "i2c error brightness");
560 static void setsensorgain(struct gspca_dev *gspca_dev)
562 struct sd *sd = (struct sd *) gspca_dev;
563 unsigned char gain = sd->gain;
565 switch (sd->sensor) {
567 case SENSOR_TAS5110: {
569 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
572 if (i2c_w(gspca_dev, i2c) < 0)
580 case SENSOR_OV7630_3: {
581 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
583 i2c[1] = sd->sensor_addr;
585 if (i2c_w(gspca_dev, i2c) < 0)
592 PDEBUG(D_ERR, "i2c error gain");
595 static void setgain(struct gspca_dev *gspca_dev)
597 struct sd *sd = (struct sd *) gspca_dev;
601 gain = sd->gain >> 4;
603 /* red and blue gain */
604 rgb_value = gain << 4 | gain;
605 reg_w(gspca_dev, 0x10, &rgb_value, 1);
608 reg_w(gspca_dev, 0x11, &rgb_value, 1);
610 if (sd->sensor_has_gain)
611 setsensorgain(gspca_dev);
614 static void setexposure(struct gspca_dev *gspca_dev)
616 struct sd *sd = (struct sd *) gspca_dev;
618 switch (sd->sensor) {
619 case SENSOR_TAS5110: {
622 /* register 19's high nibble contains the sn9c10x clock divider
623 The high nibble configures the no fps according to the
624 formula: 60 / high_nibble. With a maximum of 30 fps */
625 reg = 120 * sd->exposure / 1000;
630 reg = (reg << 4) | 0x0b;
631 reg_w(gspca_dev, 0x19, ®, 1);
635 case SENSOR_OV7630_3: {
636 /* The ov6650 / ov7630 have 2 registers which both influence
637 exposure, register 11, whose low nibble sets the nr off fps
638 according to: fps = 30 / (low_nibble + 1)
640 The fps configures the maximum exposure setting, but it is
641 possible to use less exposure then what the fps maximum
642 allows by setting register 10. register 10 configures the
643 actual exposure as quotient of the full exposure, with 0
644 being no exposure at all (not very usefull) and reg10_max
645 being max exposure possible at that framerate.
647 The code maps our 0 - 510 ms exposure ctrl to these 2
648 registers, trying to keep fps as high as possible.
650 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
652 /* ov6645 datasheet says reg10_max is 9a, but that uses
653 tline * 2 * reg10 as formula for calculating texpo, the
654 ov6650 probably uses the same formula as the 7730 which uses
655 tline * 4 * reg10, which explains why the reg10max we've
656 found experimentally for the ov6650 is exactly half that of
657 the ov6645. The ov7630 datasheet says the max is 0x41. */
658 const int reg10_max = (sd->sensor == SENSOR_OV6650)? 0x4d:0x41;
660 reg11 = (60 * sd->exposure + 999) / 1000;
666 /* frame exposure time in ms = 1000 * reg11 / 30 ->
667 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
668 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
670 /* Don't allow this to get below 10 when using autogain, the
671 steps become very large (relatively) when below 10 causing
672 the image to oscilate from much too dark, to much too bright
674 if (sd->autogain && reg10 < 10)
676 else if (reg10 > reg10_max)
679 /* Write reg 10 and reg11 low nibble */
680 i2c[1] = sd->sensor_addr;
683 if (sd->sensor == SENSOR_OV7630_3) {
684 __u8 reg76 = reg10 & 0x03;
685 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
686 0x00, 0x00, 0x00, 0x10};
688 i2c_reg76[3] = reg76;
689 if (i2c_w(gspca_dev, i2c_reg76) < 0)
690 PDEBUG(D_ERR, "i2c error exposure");
692 if (i2c_w(gspca_dev, i2c) < 0)
693 PDEBUG(D_ERR, "i2c error exposure");
699 static void setfreq(struct gspca_dev *gspca_dev)
701 struct sd *sd = (struct sd *) gspca_dev;
703 switch (sd->sensor) {
705 case SENSOR_OV7630_3: {
706 /* Framerate adjust register for artificial light 50 hz flicker
707 compensation, identical to ov6630 0x2b register, see ov6630
709 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
710 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
713 /* case 0: * no filter*/
714 /* case 2: * 60 hz */
718 i2c[3] = (sd->sensor == SENSOR_OV6650)? 0x4f:0x8a;
721 i2c[1] = sd->sensor_addr;
722 if (i2c_w(gspca_dev, i2c) < 0)
723 PDEBUG(D_ERR, "i2c error setfreq");
730 static void do_autogain(struct gspca_dev *gspca_dev)
732 struct sd *sd = (struct sd *) gspca_dev;
733 int avg_lum = atomic_read(&sd->avg_lum);
738 if (sd->autogain_ignore_frames > 0)
739 sd->autogain_ignore_frames--;
740 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
741 sd->brightness * DESIRED_AVG_LUM / 127,
742 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
743 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
744 (int)sd->gain, (int)sd->exposure);
745 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
749 /* this function is called at probe time */
750 static int sd_config(struct gspca_dev *gspca_dev,
751 const struct usb_device_id *id)
753 struct sd *sd = (struct sd *) gspca_dev;
758 /* nctrls depends upon the sensor, so we use a per cam copy */
759 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
760 gspca_dev->sd_desc = &sd->sd_desc;
762 sd->fr_h_sz = 12; /* default size of the frame header */
763 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
764 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
767 product = id->idProduct;
768 /* switch (id->idVendor) { */
769 /* case 0x0c45: * Sonix */
771 case 0x6001: /* SN9C102 */
772 case 0x6005: /* SN9C101 */
773 case 0x6007: /* SN9C101 */
774 sd->sensor = SENSOR_TAS5110;
775 sd->sensor_has_gain = 1;
776 sd->sd_desc.nctrls = 4;
777 sd->sd_desc.dq_callback = do_autogain;
780 case 0x6009: /* SN9C101 */
781 case 0x600d: /* SN9C101 */
782 case 0x6029: /* SN9C101 */
783 sd->sensor = SENSOR_PAS106;
786 case 0x6011: /* SN9C101 - SN9C101G */
787 sd->sensor = SENSOR_OV6650;
788 sd->sensor_has_gain = 1;
789 sd->sensor_addr = 0x60;
790 sd->sd_desc.nctrls = 4;
791 sd->sd_desc.dq_callback = do_autogain;
794 case 0x6019: /* SN9C101 */
795 case 0x602c: /* SN9C102 */
796 case 0x602e: /* SN9C102 */
797 sd->sensor = SENSOR_OV7630;
798 sd->sensor_addr = 0x21;
800 case 0x60b0: /* SN9C103 */
801 sd->sensor = SENSOR_OV7630_3;
802 sd->sensor_addr = 0x21;
803 sd->fr_h_sz = 18; /* size of frame header */
804 sd->sensor_has_gain = 1;
805 sd->sd_desc.nctrls = 5;
806 sd->sd_desc.dq_callback = do_autogain;
809 case 0x6024: /* SN9C102 */
810 case 0x6025: /* SN9C102 */
811 sd->sensor = SENSOR_TAS5130CXX;
813 case 0x6028: /* SN9C102 */
814 sd->sensor = SENSOR_PAS202;
816 case 0x602d: /* SN9C102 */
817 sd->sensor = SENSOR_HV7131R;
819 case 0x60af: /* SN9C103 */
820 sd->sensor = SENSOR_PAS202;
821 sd->fr_h_sz = 18; /* size of frame header (?) */
827 cam = &gspca_dev->cam;
828 cam->dev_name = (char *) id->driver_info;
831 cam->cam_mode = vga_mode;
832 cam->nmodes = ARRAY_SIZE(vga_mode);
833 if (sd->sensor == SENSOR_OV7630_3) {
834 /* We only have 320x240 & 640x480 */
839 cam->cam_mode = sif_mode;
840 cam->nmodes = ARRAY_SIZE(sif_mode);
842 sd->brightness = BRIGHTNESS_DEF;
844 sd->exposure = EXPOSURE_DEF;
845 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
846 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
850 /* this function is called at open time */
851 static int sd_open(struct gspca_dev *gspca_dev)
853 reg_r(gspca_dev, 0x00);
854 if (gspca_dev->usb_buf[0] != 0x10)
859 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
863 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
865 i = ARRAY_SIZE(pas106_data);
866 data = pas106_data[0];
868 memcpy(&i2c1[2], data, 2);
869 /* copy 2 bytes from the template */
870 if (i2c_w(gspca_dev, i2c1) < 0)
871 PDEBUG(D_ERR, "i2c error pas106");
876 /* -- start the camera -- */
877 static void sd_start(struct gspca_dev *gspca_dev)
879 struct sd *sd = (struct sd *) gspca_dev;
885 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
886 switch (sd->sensor) {
888 sn9c10x = initHv7131;
890 reg17_19[1] = (mode << 4) | 0x8a;
894 sn9c10x = initOv6650;
896 reg17_19[1] = (mode << 4) | 0x8b;
900 sn9c10x = initOv7630;
902 reg17_19[1] = (mode << 4) | COMP2;
903 reg17_19[2] = MCK_INIT1;
905 case SENSOR_OV7630_3:
906 sn9c10x = initOv7630_3;
908 reg17_19[1] = (mode << 4) | COMP2;
909 reg17_19[2] = MCK_INIT1;
912 sn9c10x = initPas106;
913 reg17_19[0] = 0x24; /* 0x28 */
914 reg17_19[1] = (mode << 4) | COMP1;
915 reg17_19[2] = MCK_INIT1;
918 sn9c10x = initPas202;
919 reg17_19[0] = mode ? 0x24 : 0x20;
920 reg17_19[1] = (mode << 4) | 0x89;
924 sn9c10x = initTas5110;
926 reg17_19[1] = (mode << 4) | 0x86;
927 reg17_19[2] = 0x2b; /* 0xf3; */
930 /* case SENSOR_TAS5130CXX: */
931 sn9c10x = initTas5130;
933 reg17_19[1] = (mode << 4) | COMP;
934 reg17_19[2] = mode ? 0x23 : 0x43;
937 switch (sd->sensor) {
941 l = sizeof initOv7630;
943 case SENSOR_OV7630_3:
946 l = sizeof initOv7630_3;
950 reg17 = sn9c10x[0x17 - 1];
955 /* reg 0x01 bit 2 video transfert on */
956 reg_w(gspca_dev, 0x01, ®01, 1);
957 /* reg 0x17 SensorClk enable inv Clk 0x60 */
958 reg_w(gspca_dev, 0x17, ®17, 1);
959 /*fixme: for ov7630 102
960 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
961 /* Set the registers from the template */
962 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
963 switch (sd->sensor) {
965 i2c_w_vector(gspca_dev, hv7131_sensor_init,
966 sizeof hv7131_sensor_init);
969 i2c_w_vector(gspca_dev, ov6650_sensor_init,
970 sizeof ov6650_sensor_init);
973 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
974 sizeof ov7630_sensor_init_com);
976 i2c_w_vector(gspca_dev, ov7630_sensor_init,
977 sizeof ov7630_sensor_init);
979 case SENSOR_OV7630_3:
980 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
981 sizeof ov7630_sensor_init_com);
983 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
986 pas106_i2cinit(gspca_dev);
989 i2c_w_vector(gspca_dev, pas202_sensor_init,
990 sizeof pas202_sensor_init);
993 i2c_w_vector(gspca_dev, tas5110_sensor_init,
994 sizeof tas5110_sensor_init);
997 /* case SENSOR_TAS5130CXX: */
998 i2c_w_vector(gspca_dev, tas5130_sensor_init,
999 sizeof tas5130_sensor_init);
1002 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1003 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1004 /* compression register */
1005 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
1007 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1009 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1010 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1011 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1012 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
1013 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1014 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
1015 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1016 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1017 /* Enable video transfert */
1018 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1020 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
1024 setbrightness(gspca_dev);
1025 setexposure(gspca_dev);
1028 sd->autogain_ignore_frames = 0;
1029 atomic_set(&sd->avg_lum, -1);
1032 static void sd_stopN(struct gspca_dev *gspca_dev)
1036 ByteSend = 0x09; /* 0X00 */
1037 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1040 static void sd_stop0(struct gspca_dev *gspca_dev)
1044 static void sd_close(struct gspca_dev *gspca_dev)
1048 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1049 struct gspca_frame *frame, /* target */
1050 unsigned char *data, /* isoc packet */
1051 int len) /* iso packet length */
1054 struct sd *sd = (struct sd *) gspca_dev;
1056 /* frames start with:
1057 * ff ff 00 c4 c4 96 synchro
1059 * xx (frame sequence / size / compression)
1060 * (xx) (idem - extra byte for sn9c103)
1061 * ll mm brightness sum inside auto exposure
1062 * ll mm brightness sum outside auto exposure
1063 * (xx xx xx xx xx) audio values for snc103
1065 if (len > 6 && len < 24) {
1066 for (i = 0; i < len - 6; i++) {
1067 if (data[0 + i] == 0xff
1068 && data[1 + i] == 0xff
1069 && data[2 + i] == 0x00
1070 && data[3 + i] == 0xc4
1071 && data[4 + i] == 0xc4
1072 && data[5 + i] == 0x96) { /* start of frame */
1073 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1075 if (len - i < sd->fr_h_sz) {
1076 atomic_set(&sd->avg_lum, -1);
1077 PDEBUG(D_STREAM, "packet too short to"
1078 " get avg brightness");
1079 } else if (sd->fr_h_sz == 12) {
1080 atomic_set(&sd->avg_lum,
1082 (data[i + 9] << 8));
1084 atomic_set(&sd->avg_lum,
1086 (data[i + 10] << 8));
1088 data += i + sd->fr_h_sz;
1089 len -= i + sd->fr_h_sz;
1090 gspca_frame_add(gspca_dev, FIRST_PACKET,
1096 gspca_frame_add(gspca_dev, INTER_PACKET,
1100 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1102 struct sd *sd = (struct sd *) gspca_dev;
1104 sd->brightness = val;
1105 if (gspca_dev->streaming)
1106 setbrightness(gspca_dev);
1110 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1112 struct sd *sd = (struct sd *) gspca_dev;
1114 *val = sd->brightness;
1118 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1120 struct sd *sd = (struct sd *) gspca_dev;
1123 if (gspca_dev->streaming)
1128 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1130 struct sd *sd = (struct sd *) gspca_dev;
1136 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1138 struct sd *sd = (struct sd *) gspca_dev;
1141 if (gspca_dev->streaming)
1142 setexposure(gspca_dev);
1146 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1148 struct sd *sd = (struct sd *) gspca_dev;
1150 *val = sd->exposure;
1154 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1156 struct sd *sd = (struct sd *) gspca_dev;
1159 /* when switching to autogain set defaults to make sure
1160 we are on a valid point of the autogain gain /
1161 exposure knee graph, and give this change time to
1162 take effect before doing autogain. */
1164 sd->exposure = EXPOSURE_DEF;
1165 sd->gain = GAIN_DEF;
1166 if (gspca_dev->streaming) {
1167 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1168 setexposure(gspca_dev);
1176 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1178 struct sd *sd = (struct sd *) gspca_dev;
1180 *val = sd->autogain;
1184 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1186 struct sd *sd = (struct sd *) gspca_dev;
1189 if (gspca_dev->streaming)
1194 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1196 struct sd *sd = (struct sd *) gspca_dev;
1202 static int sd_querymenu(struct gspca_dev *gspca_dev,
1203 struct v4l2_querymenu *menu)
1206 case V4L2_CID_POWER_LINE_FREQUENCY:
1207 switch (menu->index) {
1208 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1209 strcpy((char *) menu->name, "NoFliker");
1211 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1212 strcpy((char *) menu->name, "50 Hz");
1214 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1215 strcpy((char *) menu->name, "60 Hz");
1223 /* sub-driver description */
1224 static const struct sd_desc sd_desc = {
1225 .name = MODULE_NAME,
1227 .nctrls = ARRAY_SIZE(sd_ctrls),
1228 .config = sd_config,
1234 .pkt_scan = sd_pkt_scan,
1235 .querymenu = sd_querymenu,
1238 /* -- module initialisation -- */
1239 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1240 static __devinitdata struct usb_device_id device_table[] = {
1241 #ifndef CONFIG_USB_SN9C102
1242 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1243 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1244 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1245 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1246 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1247 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1248 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1249 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1250 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1251 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1252 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1253 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1254 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1255 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1256 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1257 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1261 MODULE_DEVICE_TABLE(usb, device_table);
1263 /* -- device connect -- */
1264 static int sd_probe(struct usb_interface *intf,
1265 const struct usb_device_id *id)
1267 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1271 static struct usb_driver sd_driver = {
1272 .name = MODULE_NAME,
1273 .id_table = device_table,
1275 .disconnect = gspca_disconnect,
1278 /* -- module insert / remove -- */
1279 static int __init sd_mod_init(void)
1281 if (usb_register(&sd_driver) < 0)
1283 PDEBUG(D_PROBE, "v%s registered", version);
1286 static void __exit sd_mod_exit(void)
1288 usb_deregister(&sd_driver);
1289 PDEBUG(D_PROBE, "deregistered");
1292 module_init(sd_mod_init);
1293 module_exit(sd_mod_exit);