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 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
28 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
29 MODULE_LICENSE("GPL");
31 /* specific webcam descriptor */
33 struct gspca_dev gspca_dev; /* !! must be the first item */
35 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
36 sensor, so we use a per cam copy */
40 unsigned char exposure;
41 unsigned char brightness;
42 unsigned char autogain;
43 unsigned char autogain_ignore_frames;
44 unsigned char frames_to_drop;
45 unsigned char freq; /* light freq filter setting */
47 unsigned char fr_h_sz; /* size of frame header */
48 char sensor; /* Type of image sensor chip */
49 #define SENSOR_HV7131R 0
50 #define SENSOR_OV6650 1
51 #define SENSOR_OV7630 2
52 #define SENSOR_PAS106 3
53 #define SENSOR_PAS202 4
54 #define SENSOR_TAS5110 5
55 #define SENSOR_TAS5130CXX 6
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);
88 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
91 static struct ctrl sd_ctrls[] = {
94 .id = V4L2_CID_BRIGHTNESS,
95 .type = V4L2_CTRL_TYPE_INTEGER,
100 #define BRIGHTNESS_DEF 127
101 .default_value = BRIGHTNESS_DEF,
103 .set = sd_setbrightness,
104 .get = sd_getbrightness,
109 .type = V4L2_CTRL_TYPE_INTEGER,
115 #define GAIN_KNEE 200
116 .default_value = GAIN_DEF,
123 .id = V4L2_CID_EXPOSURE,
124 .type = V4L2_CTRL_TYPE_INTEGER,
126 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
127 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
131 .default_value = EXPOSURE_DEF,
134 .set = sd_setexposure,
135 .get = sd_getexposure,
139 .id = V4L2_CID_AUTOGAIN,
140 .type = V4L2_CTRL_TYPE_BOOLEAN,
141 .name = "Automatic Gain (and Exposure)",
145 #define AUTOGAIN_DEF 1
146 .default_value = AUTOGAIN_DEF,
149 .set = sd_setautogain,
150 .get = sd_getautogain,
154 .id = V4L2_CID_POWER_LINE_FREQUENCY,
155 .type = V4L2_CTRL_TYPE_MENU,
156 .name = "Light frequency filter",
158 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
161 .default_value = FREQ_DEF,
168 static struct v4l2_pix_format vga_mode[] = {
169 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
171 .sizeimage = 160 * 120,
172 .colorspace = V4L2_COLORSPACE_SRGB,
174 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
176 .sizeimage = 320 * 240,
177 .colorspace = V4L2_COLORSPACE_SRGB,
179 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
181 .sizeimage = 640 * 480,
182 .colorspace = V4L2_COLORSPACE_SRGB,
185 static struct v4l2_pix_format sif_mode[] = {
186 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
188 .sizeimage = 176 * 144,
189 .colorspace = V4L2_COLORSPACE_SRGB,
191 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
193 .sizeimage = 352 * 288,
194 .colorspace = V4L2_COLORSPACE_SRGB,
198 static const __u8 probe_ov7630[] = {0x08, 0x44};
200 static const __u8 initHv7131[] = {
201 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
204 0x28, 0x1e, 0x60, 0x8a, 0x20,
205 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
207 static const __u8 hv7131_sensor_init[][8] = {
208 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
209 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
210 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
211 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
212 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
214 static const __u8 initOv6650[] = {
215 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
216 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
218 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
220 static const __u8 ov6650_sensor_init[][8] =
222 /* Bright, contrast, etc are set througth SCBB interface.
223 * AVCAP on win2 do not send any data on this controls. */
224 /* Anyway, some registers appears to alter bright and constrat */
227 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
228 /* Set clock register 0x11 low nibble is clock divider */
229 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
230 /* Next some unknown stuff */
231 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
232 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
233 * THIS SET GREEN SCREEN
234 * (pixels could be innverted in decode kind of "brg",
235 * but blue wont be there. Avoid this data ... */
236 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
237 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
238 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
239 /* Enable rgb brightness control */
240 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
241 /* HDG: Note windows uses the line below, which sets both register 0x60
242 and 0x61 I believe these registers of the ov6650 are identical as
243 those of the ov7630, because if this is true the windows settings
244 add a bit additional red gain and a lot additional blue gain, which
245 matches my findings that the windows settings make blue much too
246 blue and red a little too red.
247 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
248 /* Some more unknown stuff */
249 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
250 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
253 static const __u8 initOv7630[] = {
254 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
255 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
256 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
257 0x28, 0x1e, /* H & V sizes r15 .. r16 */
258 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
259 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
261 static const __u8 initOv7630_3[] = {
262 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
263 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
264 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
265 0x28, 0x1e, /* H & V sizes r15 .. r16 */
266 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
267 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
268 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
269 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
271 static const __u8 ov7630_sensor_init[][8] = {
272 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
273 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
274 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
275 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
276 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
277 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
278 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
279 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
280 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
281 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
282 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
283 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
284 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
285 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
286 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
287 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
288 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
289 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
290 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
293 static const __u8 initPas106[] = {
294 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
297 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
298 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
300 /* compression 0x86 mckinit1 0x2b */
301 static const __u8 pas106_data[][2] = {
302 {0x02, 0x04}, /* Pixel Clock Divider 6 */
303 {0x03, 0x13}, /* Frame Time MSB */
304 /* {0x03, 0x12}, * Frame Time MSB */
305 {0x04, 0x06}, /* Frame Time LSB */
306 /* {0x04, 0x05}, * Frame Time LSB */
307 {0x05, 0x65}, /* Shutter Time Line Offset */
308 /* {0x05, 0x6d}, * Shutter Time Line Offset */
309 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
310 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
311 {0x07, 0xc1}, /* Black Level Subtract Sign */
312 /* {0x07, 0x00}, * Black Level Subtract Sign */
313 {0x08, 0x06}, /* Black Level Subtract Level */
314 {0x08, 0x06}, /* Black Level Subtract Level */
315 /* {0x08, 0x01}, * Black Level Subtract Level */
316 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
317 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
318 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
319 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
320 {0x0d, 0x00}, /* Color GainH Pixel */
321 {0x0e, 0x0e}, /* Global Gain */
322 {0x0f, 0x00}, /* Contrast */
323 {0x10, 0x06}, /* H&V synchro polarity */
324 {0x11, 0x06}, /* ?default */
325 {0x12, 0x06}, /* DAC scale */
326 {0x14, 0x02}, /* ?default */
327 {0x13, 0x01}, /* Validate Settings */
329 static const __u8 initPas202[] = {
330 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
333 0x28, 0x1e, 0x28, 0x89, 0x30,
334 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
336 static const __u8 pas202_sensor_init[][8] = {
337 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
338 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
339 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
340 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
341 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
342 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
343 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
344 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
345 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
346 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
347 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
348 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
350 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
351 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
352 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
353 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
354 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
355 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
356 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
357 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
360 static const __u8 initTas5110[] = {
361 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
363 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
364 0x16, 0x12, 0x60, 0x86, 0x2b,
365 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
367 static const __u8 tas5110_sensor_init[][8] = {
368 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
369 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
370 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
373 static const __u8 initTas5130[] = {
374 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
376 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
377 0x28, 0x1e, 0x60, COMP, MCK_INIT,
378 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
380 static const __u8 tas5130_sensor_init[][8] = {
381 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
382 * shutter 0x47 short exposure? */
383 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
384 /* shutter 0x01 long exposure */
385 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
388 /* get one byte in gspca_dev->usb_buf */
389 static void reg_r(struct gspca_dev *gspca_dev,
392 usb_control_msg(gspca_dev->dev,
393 usb_rcvctrlpipe(gspca_dev->dev, 0),
395 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
398 gspca_dev->usb_buf, 1,
402 static void reg_w(struct gspca_dev *gspca_dev,
407 #ifdef CONFIG_VIDEO_ADV_DEBUG
408 if (len > sizeof gspca_dev->usb_buf) {
409 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
413 memcpy(gspca_dev->usb_buf, buffer, len);
414 usb_control_msg(gspca_dev->dev,
415 usb_sndctrlpipe(gspca_dev->dev, 0),
417 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
420 gspca_dev->usb_buf, len,
424 static void reg_w_big(struct gspca_dev *gspca_dev,
431 tmpbuf = kmalloc(len, GFP_KERNEL);
432 memcpy(tmpbuf, buffer, len);
433 usb_control_msg(gspca_dev->dev,
434 usb_sndctrlpipe(gspca_dev->dev, 0),
436 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
444 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
449 reg_w(gspca_dev, 0x08, buffer, 8);
452 reg_r(gspca_dev, 0x08);
453 if (gspca_dev->usb_buf[0] & 0x04) {
454 if (gspca_dev->usb_buf[0] & 0x08)
462 static void i2c_w_vector(struct gspca_dev *gspca_dev,
463 const __u8 buffer[][8], int len)
466 reg_w(gspca_dev, 0x08, *buffer, 8);
474 static void setbrightness(struct gspca_dev *gspca_dev)
476 struct sd *sd = (struct sd *) gspca_dev;
479 switch (sd->sensor) {
481 case SENSOR_OV7630: {
483 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
485 /* change reg 0x06 */
486 i2cOV[1] = sd->sensor_addr;
487 i2cOV[3] = sd->brightness;
488 if (i2c_w(gspca_dev, i2cOV) < 0)
492 case SENSOR_PAS106: {
494 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
496 i2c1[3] = sd->brightness >> 3;
498 if (i2c_w(gspca_dev, i2c1) < 0)
502 if (i2c_w(gspca_dev, i2c1) < 0)
506 case SENSOR_PAS202: {
507 /* __u8 i2cpexpo1[] =
508 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
510 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
512 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
513 static __u8 i2cpdoit[] =
514 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
516 /* change reg 0x10 */
517 i2cpexpo[4] = 0xff - sd->brightness;
518 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
520 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
522 if (i2c_w(gspca_dev, i2cpexpo) < 0)
524 if (i2c_w(gspca_dev, i2cpdoit) < 0)
526 i2cp202[3] = sd->brightness >> 3;
527 if (i2c_w(gspca_dev, i2cp202) < 0)
529 if (i2c_w(gspca_dev, i2cpdoit) < 0)
533 case SENSOR_TAS5130CXX: {
535 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
537 value = 0xff - sd->brightness;
539 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
540 if (i2c_w(gspca_dev, i2c) < 0)
545 /* FIXME figure out howto control brightness on TAS5110 */
550 PDEBUG(D_ERR, "i2c error brightness");
553 static void setsensorgain(struct gspca_dev *gspca_dev)
555 struct sd *sd = (struct sd *) gspca_dev;
556 unsigned char gain = sd->gain;
558 switch (sd->sensor) {
560 case SENSOR_TAS5110: {
562 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
565 if (i2c_w(gspca_dev, i2c) < 0)
573 case SENSOR_OV7630: {
574 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
576 i2c[1] = sd->sensor_addr;
578 if (i2c_w(gspca_dev, i2c) < 0)
585 PDEBUG(D_ERR, "i2c error gain");
588 static void setgain(struct gspca_dev *gspca_dev)
590 struct sd *sd = (struct sd *) gspca_dev;
594 gain = sd->gain >> 4;
596 /* red and blue gain */
597 rgb_value = gain << 4 | gain;
598 reg_w(gspca_dev, 0x10, &rgb_value, 1);
601 reg_w(gspca_dev, 0x11, &rgb_value, 1);
603 if (sd->sensor_has_gain)
604 setsensorgain(gspca_dev);
607 static void setexposure(struct gspca_dev *gspca_dev)
609 struct sd *sd = (struct sd *) gspca_dev;
611 switch (sd->sensor) {
612 case SENSOR_TAS5110: {
615 /* register 19's high nibble contains the sn9c10x clock divider
616 The high nibble configures the no fps according to the
617 formula: 60 / high_nibble. With a maximum of 30 fps */
618 reg = 120 * sd->exposure / 1000;
623 reg = (reg << 4) | 0x0b;
624 reg_w(gspca_dev, 0x19, ®, 1);
628 case SENSOR_OV7630: {
629 /* The ov6650 / ov7630 have 2 registers which both influence
630 exposure, register 11, whose low nibble sets the nr off fps
631 according to: fps = 30 / (low_nibble + 1)
633 The fps configures the maximum exposure setting, but it is
634 possible to use less exposure then what the fps maximum
635 allows by setting register 10. register 10 configures the
636 actual exposure as quotient of the full exposure, with 0
637 being no exposure at all (not very usefull) and reg10_max
638 being max exposure possible at that framerate.
640 The code maps our 0 - 510 ms exposure ctrl to these 2
641 registers, trying to keep fps as high as possible.
643 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
644 int reg10, reg11, reg10_max;
646 /* ov6645 datasheet says reg10_max is 9a, but that uses
647 tline * 2 * reg10 as formula for calculating texpo, the
648 ov6650 probably uses the same formula as the 7730 which uses
649 tline * 4 * reg10, which explains why the reg10max we've
650 found experimentally for the ov6650 is exactly half that of
651 the ov6645. The ov7630 datasheet says the max is 0x41. */
652 if (sd->sensor == SENSOR_OV6650) {
654 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
658 reg11 = (60 * sd->exposure + 999) / 1000;
664 /* frame exposure time in ms = 1000 * reg11 / 30 ->
665 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
666 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
668 /* Don't allow this to get below 10 when using autogain, the
669 steps become very large (relatively) when below 10 causing
670 the image to oscilate from much too dark, to much too bright
672 if (sd->autogain && reg10 < 10)
674 else if (reg10 > reg10_max)
677 /* In 640x480, if the reg11 has less than 3, the image is
678 unstable (not enough bandwidth). */
679 if (gspca_dev->width == 640 && reg11 < 3)
682 /* Write reg 10 and reg11 low nibble */
683 i2c[1] = sd->sensor_addr;
687 /* If register 11 didn't change, don't change it */
688 if (sd->reg11 == reg11 )
691 if (i2c_w(gspca_dev, i2c) == 0)
694 PDEBUG(D_ERR, "i2c error exposure");
700 static void setfreq(struct gspca_dev *gspca_dev)
702 struct sd *sd = (struct sd *) gspca_dev;
704 switch (sd->sensor) {
706 case SENSOR_OV7630: {
707 /* Framerate adjust register for artificial light 50 hz flicker
708 compensation, for the ov6650 this is identical to ov6630
709 0x2b register, see ov6630 datasheet.
710 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
711 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
714 /* case 0: * no filter*/
715 /* case 2: * 60 hz */
719 i2c[3] = (sd->sensor == SENSOR_OV6650)
723 i2c[1] = sd->sensor_addr;
724 if (i2c_w(gspca_dev, i2c) < 0)
725 PDEBUG(D_ERR, "i2c error setfreq");
731 static void do_autogain(struct gspca_dev *gspca_dev)
733 struct sd *sd = (struct sd *) gspca_dev;
734 int avg_lum = atomic_read(&sd->avg_lum);
739 if (sd->autogain_ignore_frames > 0)
740 sd->autogain_ignore_frames--;
741 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
742 sd->brightness * DESIRED_AVG_LUM / 127,
743 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
744 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
745 (int)sd->gain, (int)sd->exposure);
746 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
750 /* this function is called at probe time */
751 static int sd_config(struct gspca_dev *gspca_dev,
752 const struct usb_device_id *id)
754 struct sd *sd = (struct sd *) gspca_dev;
759 /* nctrls depends upon the sensor, so we use a per cam copy */
760 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
761 gspca_dev->sd_desc = &sd->sd_desc;
763 sd->fr_h_sz = 12; /* default size of the frame header */
764 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
765 product = id->idProduct;
766 /* switch (id->idVendor) { */
767 /* case 0x0c45: * Sonix */
769 case 0x6001: /* SN9C102 */
770 case 0x6005: /* SN9C101 */
771 case 0x6007: /* SN9C101 */
772 sd->sensor = SENSOR_TAS5110;
773 sd->sensor_has_gain = 1;
774 sd->sd_desc.nctrls = 4;
775 sd->sd_desc.dq_callback = do_autogain;
778 case 0x6009: /* SN9C101 */
779 case 0x600d: /* SN9C101 */
780 case 0x6029: /* SN9C101 */
781 sd->sensor = SENSOR_PAS106;
784 case 0x6011: /* SN9C101 - SN9C101G */
785 sd->sensor = SENSOR_OV6650;
786 sd->sensor_has_gain = 1;
787 sd->sensor_addr = 0x60;
788 sd->sd_desc.nctrls = 5;
789 sd->sd_desc.dq_callback = do_autogain;
792 case 0x6019: /* SN9C101 */
793 case 0x602c: /* SN9C102 */
794 case 0x602e: /* SN9C102 */
795 case 0x60b0: /* SN9C103 */
796 sd->sensor = SENSOR_OV7630;
797 sd->sensor_addr = 0x21;
798 sd->sensor_has_gain = 1;
799 sd->sd_desc.nctrls = 5;
800 sd->sd_desc.dq_callback = do_autogain;
801 if (product == 0x60b0)
802 sd->fr_h_sz = 18; /* size of frame header */
804 case 0x6024: /* SN9C102 */
805 case 0x6025: /* SN9C102 */
806 sd->sensor = SENSOR_TAS5130CXX;
808 case 0x6028: /* SN9C102 */
809 sd->sensor = SENSOR_PAS202;
811 case 0x602d: /* SN9C102 */
812 sd->sensor = SENSOR_HV7131R;
814 case 0x60af: /* SN9C103 */
815 sd->sensor = SENSOR_PAS202;
816 sd->fr_h_sz = 18; /* size of frame header (?) */
822 cam = &gspca_dev->cam;
823 cam->dev_name = (char *) id->driver_info;
826 cam->cam_mode = vga_mode;
827 cam->nmodes = ARRAY_SIZE(vga_mode);
828 if (product == 0x60b0) { /* SN9C103 with OV7630 */
829 /* We only have 320x240 & 640x480 */
834 cam->cam_mode = sif_mode;
835 cam->nmodes = ARRAY_SIZE(sif_mode);
837 sd->brightness = BRIGHTNESS_DEF;
839 sd->exposure = EXPOSURE_DEF;
840 sd->autogain = AUTOGAIN_DEF;
843 if (product == 0x60b0) /* SN9C103 with OV7630 */
844 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
849 /* this function is called at open time */
850 static int sd_open(struct gspca_dev *gspca_dev)
852 reg_r(gspca_dev, 0x00);
853 if (gspca_dev->usb_buf[0] != 0x10)
858 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
862 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
864 i = ARRAY_SIZE(pas106_data);
865 data = pas106_data[0];
867 memcpy(&i2c1[2], data, 2);
868 /* copy 2 bytes from the template */
869 if (i2c_w(gspca_dev, i2c1) < 0)
870 PDEBUG(D_ERR, "i2c error pas106");
875 /* -- start the camera -- */
876 static void sd_start(struct gspca_dev *gspca_dev)
878 struct sd *sd = (struct sd *) gspca_dev;
884 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
885 switch (sd->sensor) {
887 sn9c10x = initHv7131;
889 reg17_19[1] = (mode << 4) | 0x8a;
893 sn9c10x = initOv6650;
895 reg17_19[1] = (mode << 4) | 0x8b;
899 if (sd->fr_h_sz == 18) { /* SN9C103 */
900 sn9c10x = initOv7630_3;
901 l = sizeof initOv7630_3;
903 sn9c10x = initOv7630;
905 reg17_19[1] = (mode << 4) | COMP2;
906 reg17_19[2] = MCK_INIT1;
909 sn9c10x = initPas106;
910 reg17_19[0] = 0x24; /* 0x28 */
911 reg17_19[1] = (mode << 4) | COMP1;
912 reg17_19[2] = MCK_INIT1;
915 sn9c10x = initPas202;
916 reg17_19[0] = mode ? 0x24 : 0x20;
917 reg17_19[1] = (mode << 4) | 0x89;
921 sn9c10x = initTas5110;
923 reg17_19[1] = (mode << 4) | 0x86;
924 reg17_19[2] = 0x2b; /* 0xf3; */
927 /* case SENSOR_TAS5130CXX: */
928 sn9c10x = initTas5130;
930 reg17_19[1] = (mode << 4) | COMP;
931 reg17_19[2] = mode ? 0x23 : 0x43;
935 /* Special case for SN9C101/2 with OV 7630 */
936 /* HDG: is this really necessary we overwrite the values immediately
937 afterwards with the ones from the template ?? */
938 if (sd->sensor == SENSOR_OV7630 && sd->fr_h_sz == 12) {
943 reg17 = sn9c10x[0x17 - 1];
946 /* reg 0x01 bit 2 video transfert on */
947 reg_w(gspca_dev, 0x01, ®01, 1);
948 /* reg 0x17 SensorClk enable inv Clk 0x60 */
949 reg_w(gspca_dev, 0x17, ®17, 1);
950 /* Set the registers from the template */
951 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
952 switch (sd->sensor) {
954 i2c_w_vector(gspca_dev, hv7131_sensor_init,
955 sizeof hv7131_sensor_init);
958 i2c_w_vector(gspca_dev, ov6650_sensor_init,
959 sizeof ov6650_sensor_init);
962 i2c_w_vector(gspca_dev, ov7630_sensor_init,
963 sizeof ov7630_sensor_init);
964 if (sd->fr_h_sz == 18) { /* SN9C103 */
965 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
967 i2c_w(gspca_dev, i2c);
971 pas106_i2cinit(gspca_dev);
974 i2c_w_vector(gspca_dev, pas202_sensor_init,
975 sizeof pas202_sensor_init);
978 i2c_w_vector(gspca_dev, tas5110_sensor_init,
979 sizeof tas5110_sensor_init);
982 /* case SENSOR_TAS5130CXX: */
983 i2c_w_vector(gspca_dev, tas5130_sensor_init,
984 sizeof tas5130_sensor_init);
987 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
988 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
989 /* compression register */
990 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
992 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
994 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
995 /* reset 0x17 SensorClk enable inv Clk 0x60 */
996 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
997 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
998 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
999 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
1000 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1001 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1002 /* Enable video transfert */
1003 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1005 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
1011 setbrightness(gspca_dev);
1012 setexposure(gspca_dev);
1015 sd->frames_to_drop = 0;
1016 sd->autogain_ignore_frames = 0;
1017 atomic_set(&sd->avg_lum, -1);
1020 static void sd_stopN(struct gspca_dev *gspca_dev)
1024 ByteSend = 0x09; /* 0X00 */
1025 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1028 static void sd_stop0(struct gspca_dev *gspca_dev)
1032 static void sd_close(struct gspca_dev *gspca_dev)
1036 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1037 struct gspca_frame *frame, /* target */
1038 unsigned char *data, /* isoc packet */
1039 int len) /* iso packet length */
1042 struct sd *sd = (struct sd *) gspca_dev;
1044 /* frames start with:
1045 * ff ff 00 c4 c4 96 synchro
1047 * xx (frame sequence / size / compression)
1048 * (xx) (idem - extra byte for sn9c103)
1049 * ll mm brightness sum inside auto exposure
1050 * ll mm brightness sum outside auto exposure
1051 * (xx xx xx xx xx) audio values for snc103
1053 if (len > 6 && len < 24) {
1054 for (i = 0; i < len - 6; i++) {
1055 if (data[0 + i] == 0xff
1056 && data[1 + i] == 0xff
1057 && data[2 + i] == 0x00
1058 && data[3 + i] == 0xc4
1059 && data[4 + i] == 0xc4
1060 && data[5 + i] == 0x96) { /* start of frame */
1062 int pkt_type = LAST_PACKET;
1064 if (len - i < sd->fr_h_sz) {
1065 PDEBUG(D_STREAM, "packet too short to"
1066 " get avg brightness");
1067 } else if (sd->fr_h_sz == 12) {
1068 lum = data[i + 8] + (data[i + 9] << 8);
1071 (data[i + 10] << 8);
1075 sd->frames_to_drop = 2;
1077 atomic_set(&sd->avg_lum, lum);
1079 if (sd->frames_to_drop) {
1080 sd->frames_to_drop--;
1081 pkt_type = DISCARD_PACKET;
1084 frame = gspca_frame_add(gspca_dev, pkt_type,
1086 data += i + sd->fr_h_sz;
1087 len -= i + sd->fr_h_sz;
1088 gspca_frame_add(gspca_dev, FIRST_PACKET,
1094 gspca_frame_add(gspca_dev, INTER_PACKET,
1098 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1100 struct sd *sd = (struct sd *) gspca_dev;
1102 sd->brightness = val;
1103 if (gspca_dev->streaming)
1104 setbrightness(gspca_dev);
1108 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1110 struct sd *sd = (struct sd *) gspca_dev;
1112 *val = sd->brightness;
1116 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1118 struct sd *sd = (struct sd *) gspca_dev;
1121 if (gspca_dev->streaming)
1126 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1128 struct sd *sd = (struct sd *) gspca_dev;
1134 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1136 struct sd *sd = (struct sd *) gspca_dev;
1139 if (gspca_dev->streaming)
1140 setexposure(gspca_dev);
1144 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1146 struct sd *sd = (struct sd *) gspca_dev;
1148 *val = sd->exposure;
1152 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1154 struct sd *sd = (struct sd *) gspca_dev;
1157 /* when switching to autogain set defaults to make sure
1158 we are on a valid point of the autogain gain /
1159 exposure knee graph, and give this change time to
1160 take effect before doing autogain. */
1162 sd->exposure = EXPOSURE_DEF;
1163 sd->gain = GAIN_DEF;
1164 if (gspca_dev->streaming) {
1165 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1166 setexposure(gspca_dev);
1174 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1176 struct sd *sd = (struct sd *) gspca_dev;
1178 *val = sd->autogain;
1182 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1184 struct sd *sd = (struct sd *) gspca_dev;
1187 if (gspca_dev->streaming)
1192 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1194 struct sd *sd = (struct sd *) gspca_dev;
1200 static int sd_querymenu(struct gspca_dev *gspca_dev,
1201 struct v4l2_querymenu *menu)
1204 case V4L2_CID_POWER_LINE_FREQUENCY:
1205 switch (menu->index) {
1206 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1207 strcpy((char *) menu->name, "NoFliker");
1209 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1210 strcpy((char *) menu->name, "50 Hz");
1212 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1213 strcpy((char *) menu->name, "60 Hz");
1221 /* sub-driver description */
1222 static const struct sd_desc sd_desc = {
1223 .name = MODULE_NAME,
1225 .nctrls = ARRAY_SIZE(sd_ctrls),
1226 .config = sd_config,
1232 .pkt_scan = sd_pkt_scan,
1233 .querymenu = sd_querymenu,
1236 /* -- module initialisation -- */
1237 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1238 static __devinitdata struct usb_device_id device_table[] = {
1239 #ifndef CONFIG_USB_SN9C102
1240 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1241 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1242 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1243 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1244 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1246 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1247 #ifndef CONFIG_USB_SN9C102
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, "registered");
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);