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
61 /* flags used in the device id table */
62 #define F_GAIN 0x01 /* has gain */
63 #define F_AUTO 0x02 /* has autogain */
64 #define F_SIF 0x04 /* sif or vga */
65 #define F_H18 0x08 /* long (18 b) or short (12 b) frame header */
68 #define COMP 0xc7 /* 0x87 //0x07 */
69 #define COMP1 0xc9 /* 0x89 //0x09 */
72 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
76 /* We calculate the autogain at the end of the transfer of a frame, at this
77 moment a frame with the old settings is being transmitted, and a frame is
78 being captured with the old settings. So if we adjust the autogain we must
79 ignore atleast the 2 next frames for the new settings to come into effect
80 before doing any other adjustments */
81 #define AUTOGAIN_IGNORE_FRAMES 3
82 #define AUTOGAIN_DEADZONE 1000
83 #define DESIRED_AVG_LUM 7000
85 /* V4L2 controls supported by the driver */
86 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
93 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
94 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
95 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
97 static struct ctrl sd_ctrls[] = {
100 .id = V4L2_CID_BRIGHTNESS,
101 .type = V4L2_CTRL_TYPE_INTEGER,
102 .name = "Brightness",
106 #define BRIGHTNESS_DEF 127
107 .default_value = BRIGHTNESS_DEF,
109 .set = sd_setbrightness,
110 .get = sd_getbrightness,
115 .type = V4L2_CTRL_TYPE_INTEGER,
121 #define GAIN_KNEE 200
122 .default_value = GAIN_DEF,
129 .id = V4L2_CID_EXPOSURE,
130 .type = V4L2_CTRL_TYPE_INTEGER,
132 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
133 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .default_value = EXPOSURE_DEF,
140 .set = sd_setexposure,
141 .get = sd_getexposure,
145 .id = V4L2_CID_AUTOGAIN,
146 .type = V4L2_CTRL_TYPE_BOOLEAN,
147 .name = "Automatic Gain (and Exposure)",
151 #define AUTOGAIN_DEF 1
152 .default_value = AUTOGAIN_DEF,
155 .set = sd_setautogain,
156 .get = sd_getautogain,
160 .id = V4L2_CID_POWER_LINE_FREQUENCY,
161 .type = V4L2_CTRL_TYPE_MENU,
162 .name = "Light frequency filter",
164 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
167 .default_value = FREQ_DEF,
174 static struct v4l2_pix_format vga_mode[] = {
175 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .sizeimage = 160 * 120,
178 .colorspace = V4L2_COLORSPACE_SRGB,
180 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
182 .sizeimage = 320 * 240,
183 .colorspace = V4L2_COLORSPACE_SRGB,
185 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
187 .sizeimage = 640 * 480,
188 .colorspace = V4L2_COLORSPACE_SRGB,
191 static struct v4l2_pix_format sif_mode[] = {
192 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
194 .sizeimage = 176 * 144,
195 .colorspace = V4L2_COLORSPACE_SRGB,
197 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
199 .sizeimage = 352 * 288,
200 .colorspace = V4L2_COLORSPACE_SRGB,
204 static const __u8 initHv7131[] = {
205 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
208 0x28, 0x1e, 0x60, 0x8a, 0x20,
209 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
211 static const __u8 hv7131_sensor_init[][8] = {
212 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
213 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
214 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
215 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
216 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
218 static const __u8 initOv6650[] = {
219 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
220 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
222 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
224 static const __u8 ov6650_sensor_init[][8] =
226 /* Bright, contrast, etc are set througth SCBB interface.
227 * AVCAP on win2 do not send any data on this controls. */
228 /* Anyway, some registers appears to alter bright and constrat */
231 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
232 /* Set clock register 0x11 low nibble is clock divider */
233 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
234 /* Next some unknown stuff */
235 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
236 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
237 * THIS SET GREEN SCREEN
238 * (pixels could be innverted in decode kind of "brg",
239 * but blue wont be there. Avoid this data ... */
240 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
241 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
242 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
243 /* Enable rgb brightness control */
244 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
245 /* HDG: Note windows uses the line below, which sets both register 0x60
246 and 0x61 I believe these registers of the ov6650 are identical as
247 those of the ov7630, because if this is true the windows settings
248 add a bit additional red gain and a lot additional blue gain, which
249 matches my findings that the windows settings make blue much too
250 blue and red a little too red.
251 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
252 /* Some more unknown stuff */
253 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
254 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
257 static const __u8 initOv7630[] = {
258 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
259 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
260 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
261 0x28, 0x1e, /* H & V sizes r15 .. r16 */
262 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
263 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
265 static const __u8 initOv7630_3[] = {
266 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
267 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
268 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
269 0x28, 0x1e, /* H & V sizes r15 .. r16 */
270 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
271 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
272 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
273 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
275 static const __u8 ov7630_sensor_init[][8] = {
276 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
277 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
278 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
279 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
280 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
281 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
282 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
283 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
284 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
285 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
286 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
287 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
288 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
289 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
290 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
291 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
292 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
293 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
294 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
297 static const __u8 initPas106[] = {
298 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
301 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
302 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
304 /* compression 0x86 mckinit1 0x2b */
305 static const __u8 pas106_data[][2] = {
306 {0x02, 0x04}, /* Pixel Clock Divider 6 */
307 {0x03, 0x13}, /* Frame Time MSB */
308 /* {0x03, 0x12}, * Frame Time MSB */
309 {0x04, 0x06}, /* Frame Time LSB */
310 /* {0x04, 0x05}, * Frame Time LSB */
311 {0x05, 0x65}, /* Shutter Time Line Offset */
312 /* {0x05, 0x6d}, * Shutter Time Line Offset */
313 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
314 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
315 {0x07, 0xc1}, /* Black Level Subtract Sign */
316 /* {0x07, 0x00}, * Black Level Subtract Sign */
317 {0x08, 0x06}, /* Black Level Subtract Level */
318 {0x08, 0x06}, /* Black Level Subtract Level */
319 /* {0x08, 0x01}, * Black Level Subtract Level */
320 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
321 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
322 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
323 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
324 {0x0d, 0x00}, /* Color GainH Pixel */
325 {0x0e, 0x0e}, /* Global Gain */
326 {0x0f, 0x00}, /* Contrast */
327 {0x10, 0x06}, /* H&V synchro polarity */
328 {0x11, 0x06}, /* ?default */
329 {0x12, 0x06}, /* DAC scale */
330 {0x14, 0x02}, /* ?default */
331 {0x13, 0x01}, /* Validate Settings */
333 static const __u8 initPas202[] = {
334 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
337 0x28, 0x1e, 0x28, 0x89, 0x30,
338 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
340 static const __u8 pas202_sensor_init[][8] = {
341 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
342 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
343 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
344 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
345 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
346 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
347 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
348 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
349 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
350 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
351 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
352 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
354 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
355 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
356 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
357 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
358 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
359 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
360 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
361 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
364 static const __u8 initTas5110[] = {
365 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
367 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
368 0x16, 0x12, 0x60, 0x86, 0x2b,
369 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
371 static const __u8 tas5110_sensor_init[][8] = {
372 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
373 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
374 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
377 static const __u8 initTas5130[] = {
378 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
380 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
381 0x28, 0x1e, 0x60, COMP, MCK_INIT,
382 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
384 static const __u8 tas5130_sensor_init[][8] = {
385 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
386 * shutter 0x47 short exposure? */
387 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
388 /* shutter 0x01 long exposure */
389 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
392 /* get one byte in gspca_dev->usb_buf */
393 static void reg_r(struct gspca_dev *gspca_dev,
396 usb_control_msg(gspca_dev->dev,
397 usb_rcvctrlpipe(gspca_dev->dev, 0),
399 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
402 gspca_dev->usb_buf, 1,
406 static void reg_w(struct gspca_dev *gspca_dev,
411 #ifdef CONFIG_VIDEO_ADV_DEBUG
412 if (len > sizeof gspca_dev->usb_buf) {
413 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
417 memcpy(gspca_dev->usb_buf, buffer, len);
418 usb_control_msg(gspca_dev->dev,
419 usb_sndctrlpipe(gspca_dev->dev, 0),
421 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
424 gspca_dev->usb_buf, len,
428 static void reg_w_big(struct gspca_dev *gspca_dev,
435 tmpbuf = kmalloc(len, GFP_KERNEL);
436 memcpy(tmpbuf, buffer, len);
437 usb_control_msg(gspca_dev->dev,
438 usb_sndctrlpipe(gspca_dev->dev, 0),
440 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
448 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
453 reg_w(gspca_dev, 0x08, buffer, 8);
456 reg_r(gspca_dev, 0x08);
457 if (gspca_dev->usb_buf[0] & 0x04) {
458 if (gspca_dev->usb_buf[0] & 0x08)
466 static void i2c_w_vector(struct gspca_dev *gspca_dev,
467 const __u8 buffer[][8], int len)
470 reg_w(gspca_dev, 0x08, *buffer, 8);
478 static void setbrightness(struct gspca_dev *gspca_dev)
480 struct sd *sd = (struct sd *) gspca_dev;
483 switch (sd->sensor) {
485 case SENSOR_OV7630: {
487 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
489 /* change reg 0x06 */
490 i2cOV[1] = sd->sensor_addr;
491 i2cOV[3] = sd->brightness;
492 if (i2c_w(gspca_dev, i2cOV) < 0)
496 case SENSOR_PAS106: {
498 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
500 i2c1[3] = sd->brightness >> 3;
502 if (i2c_w(gspca_dev, i2c1) < 0)
506 if (i2c_w(gspca_dev, i2c1) < 0)
510 case SENSOR_PAS202: {
511 /* __u8 i2cpexpo1[] =
512 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
514 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
516 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
517 static __u8 i2cpdoit[] =
518 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
520 /* change reg 0x10 */
521 i2cpexpo[4] = 0xff - sd->brightness;
522 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
524 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
526 if (i2c_w(gspca_dev, i2cpexpo) < 0)
528 if (i2c_w(gspca_dev, i2cpdoit) < 0)
530 i2cp202[3] = sd->brightness >> 3;
531 if (i2c_w(gspca_dev, i2cp202) < 0)
533 if (i2c_w(gspca_dev, i2cpdoit) < 0)
537 case SENSOR_TAS5130CXX: {
539 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
541 value = 0xff - sd->brightness;
543 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
544 if (i2c_w(gspca_dev, i2c) < 0)
549 /* FIXME figure out howto control brightness on TAS5110 */
554 PDEBUG(D_ERR, "i2c error brightness");
557 static void setsensorgain(struct gspca_dev *gspca_dev)
559 struct sd *sd = (struct sd *) gspca_dev;
560 unsigned char gain = sd->gain;
562 switch (sd->sensor) {
564 case SENSOR_TAS5110: {
566 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
569 if (i2c_w(gspca_dev, i2c) < 0)
577 case SENSOR_OV7630: {
578 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
580 i2c[1] = sd->sensor_addr;
582 if (i2c_w(gspca_dev, i2c) < 0)
589 PDEBUG(D_ERR, "i2c error gain");
592 static void setgain(struct gspca_dev *gspca_dev)
594 struct sd *sd = (struct sd *) gspca_dev;
598 gain = sd->gain >> 4;
600 /* red and blue gain */
601 rgb_value = gain << 4 | gain;
602 reg_w(gspca_dev, 0x10, &rgb_value, 1);
605 reg_w(gspca_dev, 0x11, &rgb_value, 1);
607 if (sd->sensor_has_gain)
608 setsensorgain(gspca_dev);
611 static void setexposure(struct gspca_dev *gspca_dev)
613 struct sd *sd = (struct sd *) gspca_dev;
615 switch (sd->sensor) {
616 case SENSOR_TAS5110: {
619 /* register 19's high nibble contains the sn9c10x clock divider
620 The high nibble configures the no fps according to the
621 formula: 60 / high_nibble. With a maximum of 30 fps */
622 reg = 120 * sd->exposure / 1000;
627 reg = (reg << 4) | 0x0b;
628 reg_w(gspca_dev, 0x19, ®, 1);
632 case SENSOR_OV7630: {
633 /* The ov6650 / ov7630 have 2 registers which both influence
634 exposure, register 11, whose low nibble sets the nr off fps
635 according to: fps = 30 / (low_nibble + 1)
637 The fps configures the maximum exposure setting, but it is
638 possible to use less exposure then what the fps maximum
639 allows by setting register 10. register 10 configures the
640 actual exposure as quotient of the full exposure, with 0
641 being no exposure at all (not very usefull) and reg10_max
642 being max exposure possible at that framerate.
644 The code maps our 0 - 510 ms exposure ctrl to these 2
645 registers, trying to keep fps as high as possible.
647 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
648 int reg10, reg11, reg10_max;
650 /* ov6645 datasheet says reg10_max is 9a, but that uses
651 tline * 2 * reg10 as formula for calculating texpo, the
652 ov6650 probably uses the same formula as the 7730 which uses
653 tline * 4 * reg10, which explains why the reg10max we've
654 found experimentally for the ov6650 is exactly half that of
655 the ov6645. The ov7630 datasheet says the max is 0x41. */
656 if (sd->sensor == SENSOR_OV6650) {
658 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
662 reg11 = (60 * sd->exposure + 999) / 1000;
668 /* frame exposure time in ms = 1000 * reg11 / 30 ->
669 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
670 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
672 /* Don't allow this to get below 10 when using autogain, the
673 steps become very large (relatively) when below 10 causing
674 the image to oscilate from much too dark, to much too bright
676 if (sd->autogain && reg10 < 10)
678 else if (reg10 > reg10_max)
681 /* In 640x480, if the reg11 has less than 3, the image is
682 unstable (not enough bandwidth). */
683 if (gspca_dev->width == 640 && reg11 < 3)
686 /* Write reg 10 and reg11 low nibble */
687 i2c[1] = sd->sensor_addr;
691 /* If register 11 didn't change, don't change it */
692 if (sd->reg11 == reg11 )
695 if (i2c_w(gspca_dev, i2c) == 0)
698 PDEBUG(D_ERR, "i2c error exposure");
704 static void setfreq(struct gspca_dev *gspca_dev)
706 struct sd *sd = (struct sd *) gspca_dev;
708 switch (sd->sensor) {
710 case SENSOR_OV7630: {
711 /* Framerate adjust register for artificial light 50 hz flicker
712 compensation, for the ov6650 this is identical to ov6630
713 0x2b register, see ov6630 datasheet.
714 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
715 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
718 /* case 0: * no filter*/
719 /* case 2: * 60 hz */
723 i2c[3] = (sd->sensor == SENSOR_OV6650)
727 i2c[1] = sd->sensor_addr;
728 if (i2c_w(gspca_dev, i2c) < 0)
729 PDEBUG(D_ERR, "i2c error setfreq");
735 static void do_autogain(struct gspca_dev *gspca_dev)
737 struct sd *sd = (struct sd *) gspca_dev;
738 int avg_lum = atomic_read(&sd->avg_lum);
743 if (sd->autogain_ignore_frames > 0)
744 sd->autogain_ignore_frames--;
745 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
746 sd->brightness * DESIRED_AVG_LUM / 127,
747 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
748 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
749 (int)sd->gain, (int)sd->exposure);
750 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
754 /* this function is called at probe time */
755 static int sd_config(struct gspca_dev *gspca_dev,
756 const struct usb_device_id *id)
758 struct sd *sd = (struct sd *) gspca_dev;
762 /* nctrls depends upon the sensor, so we use a per cam copy */
763 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
764 gspca_dev->sd_desc = &sd->sd_desc;
766 /* copy the webcam info from the device id */
767 sd->sensor = (id->driver_info >> 24) & 0xff;
768 if (id->driver_info & (F_GAIN << 16))
769 sd->sensor_has_gain = 1;
770 if (id->driver_info & (F_AUTO << 16))
771 sd->sd_desc.dq_callback = do_autogain;
772 if (id->driver_info & (F_SIF << 16))
774 if (id->driver_info & (F_H18 << 16))
775 sd->fr_h_sz = 18; /* size of frame header */
778 sd->sd_desc.nctrls = (id->driver_info >> 8) & 0xff;
779 sd->sensor_addr = id->driver_info & 0xff;
781 cam = &gspca_dev->cam;
784 cam->cam_mode = vga_mode;
785 cam->nmodes = ARRAY_SIZE(vga_mode);
787 cam->cam_mode = sif_mode;
788 cam->nmodes = ARRAY_SIZE(sif_mode);
790 sd->brightness = BRIGHTNESS_DEF;
792 sd->exposure = EXPOSURE_DEF;
793 sd->autogain = AUTOGAIN_DEF;
799 /* this function is called at open time */
800 static int sd_open(struct gspca_dev *gspca_dev)
802 reg_r(gspca_dev, 0x00);
803 if (gspca_dev->usb_buf[0] != 0x10)
808 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
812 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
814 i = ARRAY_SIZE(pas106_data);
815 data = pas106_data[0];
817 memcpy(&i2c1[2], data, 2);
818 /* copy 2 bytes from the template */
819 if (i2c_w(gspca_dev, i2c1) < 0)
820 PDEBUG(D_ERR, "i2c error pas106");
825 /* -- start the camera -- */
826 static void sd_start(struct gspca_dev *gspca_dev)
828 struct sd *sd = (struct sd *) gspca_dev;
833 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
834 switch (sd->sensor) {
836 sn9c10x = initHv7131;
838 reg17_19[1] = (mode << 4) | 0x8a;
842 sn9c10x = initOv6650;
844 reg17_19[1] = (mode << 4) | 0x8b;
848 if (sd->fr_h_sz == 18) { /* SN9C103 */
849 sn9c10x = initOv7630_3;
850 l = sizeof initOv7630_3;
852 sn9c10x = initOv7630;
854 reg17_19[1] = (mode << 4) | COMP2;
855 reg17_19[2] = MCK_INIT1;
858 sn9c10x = initPas106;
859 reg17_19[0] = 0x24; /* 0x28 */
860 reg17_19[1] = (mode << 4) | COMP1;
861 reg17_19[2] = MCK_INIT1;
864 sn9c10x = initPas202;
865 reg17_19[0] = mode ? 0x24 : 0x20;
866 reg17_19[1] = (mode << 4) | 0x89;
870 sn9c10x = initTas5110;
872 reg17_19[1] = (mode << 4) | 0x86;
873 reg17_19[2] = 0x2b; /* 0xf3; */
876 /* case SENSOR_TAS5130CXX: */
877 sn9c10x = initTas5130;
879 reg17_19[1] = (mode << 4) | COMP;
880 reg17_19[2] = mode ? 0x23 : 0x43;
884 /* reg 0x01 bit 2 video transfert on */
885 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
886 /* reg 0x17 SensorClk enable inv Clk 0x60 */
887 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
888 /* Set the registers from the template */
889 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
890 switch (sd->sensor) {
892 i2c_w_vector(gspca_dev, hv7131_sensor_init,
893 sizeof hv7131_sensor_init);
896 i2c_w_vector(gspca_dev, ov6650_sensor_init,
897 sizeof ov6650_sensor_init);
900 i2c_w_vector(gspca_dev, ov7630_sensor_init,
901 sizeof ov7630_sensor_init);
902 if (sd->fr_h_sz == 18) { /* SN9C103 */
903 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
905 i2c_w(gspca_dev, i2c);
909 pas106_i2cinit(gspca_dev);
912 i2c_w_vector(gspca_dev, pas202_sensor_init,
913 sizeof pas202_sensor_init);
916 i2c_w_vector(gspca_dev, tas5110_sensor_init,
917 sizeof tas5110_sensor_init);
920 /* case SENSOR_TAS5130CXX: */
921 i2c_w_vector(gspca_dev, tas5130_sensor_init,
922 sizeof tas5130_sensor_init);
925 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
926 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
927 /* compression register */
928 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
930 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
932 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
933 /* reset 0x17 SensorClk enable inv Clk 0x60 */
934 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
935 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
936 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
937 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
938 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
939 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
940 /* Enable video transfert */
941 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
943 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
949 setbrightness(gspca_dev);
950 setexposure(gspca_dev);
953 sd->frames_to_drop = 0;
954 sd->autogain_ignore_frames = 0;
955 atomic_set(&sd->avg_lum, -1);
958 static void sd_stopN(struct gspca_dev *gspca_dev)
962 ByteSend = 0x09; /* 0X00 */
963 reg_w(gspca_dev, 0x01, &ByteSend, 1);
966 static void sd_stop0(struct gspca_dev *gspca_dev)
970 static void sd_close(struct gspca_dev *gspca_dev)
974 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
975 struct gspca_frame *frame, /* target */
976 unsigned char *data, /* isoc packet */
977 int len) /* iso packet length */
980 struct sd *sd = (struct sd *) gspca_dev;
982 /* frames start with:
983 * ff ff 00 c4 c4 96 synchro
985 * xx (frame sequence / size / compression)
986 * (xx) (idem - extra byte for sn9c103)
987 * ll mm brightness sum inside auto exposure
988 * ll mm brightness sum outside auto exposure
989 * (xx xx xx xx xx) audio values for snc103
991 if (len > 6 && len < 24) {
992 for (i = 0; i < len - 6; i++) {
993 if (data[0 + i] == 0xff
994 && data[1 + i] == 0xff
995 && data[2 + i] == 0x00
996 && data[3 + i] == 0xc4
997 && data[4 + i] == 0xc4
998 && data[5 + i] == 0x96) { /* start of frame */
1000 int pkt_type = LAST_PACKET;
1002 if (len - i < sd->fr_h_sz) {
1003 PDEBUG(D_STREAM, "packet too short to"
1004 " get avg brightness");
1005 } else if (sd->fr_h_sz == 12) {
1006 lum = data[i + 8] + (data[i + 9] << 8);
1009 (data[i + 10] << 8);
1013 sd->frames_to_drop = 2;
1015 atomic_set(&sd->avg_lum, lum);
1017 if (sd->frames_to_drop) {
1018 sd->frames_to_drop--;
1019 pkt_type = DISCARD_PACKET;
1022 frame = gspca_frame_add(gspca_dev, pkt_type,
1024 data += i + sd->fr_h_sz;
1025 len -= i + sd->fr_h_sz;
1026 gspca_frame_add(gspca_dev, FIRST_PACKET,
1032 gspca_frame_add(gspca_dev, INTER_PACKET,
1036 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1038 struct sd *sd = (struct sd *) gspca_dev;
1040 sd->brightness = val;
1041 if (gspca_dev->streaming)
1042 setbrightness(gspca_dev);
1046 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1048 struct sd *sd = (struct sd *) gspca_dev;
1050 *val = sd->brightness;
1054 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1056 struct sd *sd = (struct sd *) gspca_dev;
1059 if (gspca_dev->streaming)
1064 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1066 struct sd *sd = (struct sd *) gspca_dev;
1072 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1074 struct sd *sd = (struct sd *) gspca_dev;
1077 if (gspca_dev->streaming)
1078 setexposure(gspca_dev);
1082 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1084 struct sd *sd = (struct sd *) gspca_dev;
1086 *val = sd->exposure;
1090 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1092 struct sd *sd = (struct sd *) gspca_dev;
1095 /* when switching to autogain set defaults to make sure
1096 we are on a valid point of the autogain gain /
1097 exposure knee graph, and give this change time to
1098 take effect before doing autogain. */
1100 sd->exposure = EXPOSURE_DEF;
1101 sd->gain = GAIN_DEF;
1102 if (gspca_dev->streaming) {
1103 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1104 setexposure(gspca_dev);
1112 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1114 struct sd *sd = (struct sd *) gspca_dev;
1116 *val = sd->autogain;
1120 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1122 struct sd *sd = (struct sd *) gspca_dev;
1125 if (gspca_dev->streaming)
1130 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1132 struct sd *sd = (struct sd *) gspca_dev;
1138 static int sd_querymenu(struct gspca_dev *gspca_dev,
1139 struct v4l2_querymenu *menu)
1142 case V4L2_CID_POWER_LINE_FREQUENCY:
1143 switch (menu->index) {
1144 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1145 strcpy((char *) menu->name, "NoFliker");
1147 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1148 strcpy((char *) menu->name, "50 Hz");
1150 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1151 strcpy((char *) menu->name, "60 Hz");
1159 /* sub-driver description */
1160 static const struct sd_desc sd_desc = {
1161 .name = MODULE_NAME,
1163 .nctrls = ARRAY_SIZE(sd_ctrls),
1164 .config = sd_config,
1170 .pkt_scan = sd_pkt_scan,
1171 .querymenu = sd_querymenu,
1174 /* -- module initialisation -- */
1175 #define SFCI(sensor, flags, nctrls, i2c_addr) \
1176 .driver_info = (SENSOR_ ## sensor << 24) \
1180 static __devinitdata struct usb_device_id device_table[] = {
1181 #ifndef CONFIG_USB_SN9C102
1182 {USB_DEVICE(0x0c45, 0x6001), /* SN9C102 */
1183 SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
1184 {USB_DEVICE(0x0c45, 0x6005), /* SN9C101 */
1185 SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
1186 {USB_DEVICE(0x0c45, 0x6007), /* SN9C101 */
1187 SFCI(TAS5110, F_GAIN|F_AUTO|F_SIF, 4, 0)},
1188 {USB_DEVICE(0x0c45, 0x6009), /* SN9C101 */
1189 SFCI(PAS106, F_SIF, 2, 0)},
1190 {USB_DEVICE(0x0c45, 0x600d), /* SN9C101 */
1191 SFCI(PAS106, F_SIF, 2, 0)},
1193 {USB_DEVICE(0x0c45, 0x6011), /* SN9C101 - SN9C101G */
1194 SFCI(OV6650, F_GAIN|F_AUTO|F_SIF, 5, 0x60)},
1195 #ifndef CONFIG_USB_SN9C102
1196 {USB_DEVICE(0x0c45, 0x6019), /* SN9C101 */
1197 SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
1198 {USB_DEVICE(0x0c45, 0x6024), /* SN9C102 */
1199 SFCI(TAS5130CXX, 0, 2, 0)},
1200 {USB_DEVICE(0x0c45, 0x6025), /* SN9C102 */
1201 SFCI(TAS5130CXX, 0, 2, 0)},
1202 {USB_DEVICE(0x0c45, 0x6028), /* SN9C102 */
1203 SFCI(PAS202, 0, 2, 0)},
1204 {USB_DEVICE(0x0c45, 0x6029), /* SN9C101 */
1205 SFCI(PAS106, F_SIF, 2, 0)},
1206 {USB_DEVICE(0x0c45, 0x602c), /* SN9C102 */
1207 SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
1208 {USB_DEVICE(0x0c45, 0x602d), /* SN9C102 */
1209 SFCI(HV7131R, 0, 2, 0)},
1210 {USB_DEVICE(0x0c45, 0x602e), /* SN9C102 */
1211 SFCI(OV7630, F_GAIN|F_AUTO, 5, 0x21)},
1212 {USB_DEVICE(0x0c45, 0x60af), /* SN9C103 */
1213 SFCI(PAS202, F_H18, 2, 0)},
1214 {USB_DEVICE(0x0c45, 0x60b0), /* SN9C103 */
1215 SFCI(OV7630, F_GAIN|F_AUTO|F_H18, 5, 0x21)},
1219 MODULE_DEVICE_TABLE(usb, device_table);
1221 /* -- device connect -- */
1222 static int sd_probe(struct usb_interface *intf,
1223 const struct usb_device_id *id)
1225 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1229 static struct usb_driver sd_driver = {
1230 .name = MODULE_NAME,
1231 .id_table = device_table,
1233 .disconnect = gspca_disconnect,
1236 /* -- module insert / remove -- */
1237 static int __init sd_mod_init(void)
1239 if (usb_register(&sd_driver) < 0)
1241 PDEBUG(D_PROBE, "registered");
1244 static void __exit sd_mod_exit(void)
1246 usb_deregister(&sd_driver);
1247 PDEBUG(D_PROBE, "deregistered");
1250 module_init(sd_mod_init);
1251 module_exit(sd_mod_exit);