2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #define MODULE_NAME "sonixb"
27 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28 static const char version[] = "2.1.7";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
36 struct gspca_dev gspca_dev; /* !! must be the first item */
38 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
39 sensor, so we use a per cam copy */
43 unsigned short exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
48 unsigned char fr_h_sz; /* size of frame header */
49 char sensor; /* Type of image sensor chip */
51 #define SENSOR_HV7131R 0
52 #define SENSOR_OV6650 1
53 #define SENSOR_OV7630 2
54 #define SENSOR_OV7630_3 3
55 #define SENSOR_PAS106 4
56 #define SENSOR_PAS202 5
57 #define SENSOR_TAS5110 6
58 #define SENSOR_TAS5130CXX 7
62 #define COMP 0xc7 /* 0x87 //0x07 */
63 #define COMP1 0xc9 /* 0x89 //0x09 */
66 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
70 /* We calculate the autogain at the end of the transfer of a frame, at this
71 moment a frame with the old settings is being transmitted, and a frame is
72 being captured with the old settings. So if we adjust the autogain we must
73 ignore atleast the 2 next frames for the new settings to come into effect
74 before doing any other adjustments */
75 #define AUTOGAIN_IGNORE_FRAMES 3
76 #define AUTOGAIN_DEADZONE 500
77 #define DESIRED_AVG_LUM 7000
79 /* V4L2 controls supported by the driver */
80 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
81 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
82 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
89 static struct ctrl sd_ctrls[] = {
92 .id = V4L2_CID_BRIGHTNESS,
93 .type = V4L2_CTRL_TYPE_INTEGER,
98 #define BRIGHTNESS_DEF 127
99 .default_value = BRIGHTNESS_DEF,
101 .set = sd_setbrightness,
102 .get = sd_getbrightness,
107 .type = V4L2_CTRL_TYPE_INTEGER,
113 #define GAIN_KNEE 400
114 .default_value = GAIN_DEF,
121 .id = V4L2_CID_EXPOSURE,
122 .type = V4L2_CTRL_TYPE_INTEGER,
124 #define EXPOSURE_DEF 0
125 #define EXPOSURE_KNEE 353 /* 10 fps */
129 .default_value = EXPOSURE_DEF,
132 .set = sd_setexposure,
133 .get = sd_getexposure,
137 .id = V4L2_CID_AUTOGAIN,
138 .type = V4L2_CTRL_TYPE_BOOLEAN,
139 .name = "Automatic Gain (and Exposure)",
143 #define AUTOGAIN_DEF 1
144 .default_value = AUTOGAIN_DEF,
147 .set = sd_setautogain,
148 .get = sd_getautogain,
152 static struct v4l2_pix_format vga_mode[] = {
153 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
155 .sizeimage = 160 * 120,
156 .colorspace = V4L2_COLORSPACE_SRGB,
158 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
160 .sizeimage = 320 * 240,
161 .colorspace = V4L2_COLORSPACE_SRGB,
163 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
165 .sizeimage = 640 * 480,
166 .colorspace = V4L2_COLORSPACE_SRGB,
169 static struct v4l2_pix_format sif_mode[] = {
170 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
172 .sizeimage = 176 * 144,
173 .colorspace = V4L2_COLORSPACE_SRGB,
175 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .sizeimage = 352 * 288,
178 .colorspace = V4L2_COLORSPACE_SRGB,
182 static const __u8 probe_ov7630[] = {0x08, 0x44};
184 static const __u8 initHv7131[] = {
185 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
188 0x28, 0x1e, 0x60, 0x8a, 0x20,
189 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
191 static const __u8 hv7131_sensor_init[][8] = {
192 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
193 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
194 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
195 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
196 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
198 static const __u8 initOv6650[] = {
199 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
200 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
202 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
204 static const __u8 ov6650_sensor_init[][8] =
206 /* Bright, contrast, etc are set througth SCBB interface.
207 * AVCAP on win2 do not send any data on this controls. */
208 /* Anyway, some registers appears to alter bright and constrat */
211 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
212 /* Set clock register 0x11 low nibble is clock divider */
213 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
214 /* Next some unknown stuff */
215 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
216 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
217 * THIS SET GREEN SCREEN
218 * (pixels could be innverted in decode kind of "brg",
219 * but blue wont be there. Avoid this data ... */
220 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
221 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
222 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
223 /* Disable autobright ? */
224 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10},
225 /* Some more unknown stuff */
226 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
227 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
228 {0xa0, 0x60, 0x10, 0x57, 0x99, 0x04, 0x94, 0x16},
229 /* Framerate adjust register for artificial light 50 hz flicker
230 compensation, identical to ov6630 0x2b register, see 6630 datasheet.
231 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
232 {0xa0, 0x60, 0x2b, 0x4f, 0x99, 0x04, 0x94, 0x15},
235 static const __u8 initOv7630[] = {
236 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
237 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
238 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
239 0x28, 0x1e, /* H & V sizes r15 .. r16 */
240 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
241 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
243 static const __u8 initOv7630_3[] = {
244 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
245 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
246 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
247 0x16, 0x12, /* H & V sizes r15 .. r16 */
248 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
249 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
250 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
251 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
253 static const __u8 ov7630_sensor_init_com[][8] = {
254 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
255 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
256 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
257 {0xd0, 0x21, 0x12, 0x78, 0x00, 0x80, 0x34, 0x10}, /* jfm */
258 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
259 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
260 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
261 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
262 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
263 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
264 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
265 /* {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10}, jfm */
266 {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, /* jfm */
267 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
268 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
269 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
270 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
271 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
272 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
274 static const __u8 ov7630_sensor_init[][8] = {
275 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
276 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
277 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
278 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
279 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
281 static const __u8 ov7630_sensor_init_3[][8] = {
282 {0xa0, 0x21, 0x10, 0x83, 0xbd, 0x06, 0xf6, 0x16}, /* exposure */
283 {0xa0, 0x21, 0x76, 0x00, 0xbd, 0x06, 0xf6, 0x16},
284 {0xa0, 0x21, 0x11, 0x00, 0xbd, 0x06, 0xf6, 0x16},
285 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
286 /* {0xb0, 0x21, 0x2a, 0xc0, 0x3c, 0x06, 0xf6, 0x1d},
287 * a0 1c,a0 1f,c0 3c frame rate ?line interval from ov6630 */
288 /* {0xb0, 0x21, 0x2a, 0xa0, 0x1f, 0x06, 0xf6, 0x1d}, * from win */
289 {0xb0, 0x21, 0x2a, 0x80, 0x60, 0x06, 0xf6, 0x1d},
292 static const __u8 initPas106[] = {
293 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
296 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
297 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
299 /* compression 0x86 mckinit1 0x2b */
300 static const __u8 pas106_data[][2] = {
301 {0x02, 0x04}, /* Pixel Clock Divider 6 */
302 {0x03, 0x13}, /* Frame Time MSB */
303 /* {0x03, 0x12}, * Frame Time MSB */
304 {0x04, 0x06}, /* Frame Time LSB */
305 /* {0x04, 0x05}, * Frame Time LSB */
306 {0x05, 0x65}, /* Shutter Time Line Offset */
307 /* {0x05, 0x6d}, * Shutter Time Line Offset */
308 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
309 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
310 {0x07, 0xc1}, /* Black Level Subtract Sign */
311 /* {0x07, 0x00}, * Black Level Subtract Sign */
312 {0x08, 0x06}, /* Black Level Subtract Level */
313 {0x08, 0x06}, /* Black Level Subtract Level */
314 /* {0x08, 0x01}, * Black Level Subtract Level */
315 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
316 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
317 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
318 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
319 {0x0d, 0x00}, /* Color GainH Pixel */
320 {0x0e, 0x0e}, /* Global Gain */
321 {0x0f, 0x00}, /* Contrast */
322 {0x10, 0x06}, /* H&V synchro polarity */
323 {0x11, 0x06}, /* ?default */
324 {0x12, 0x06}, /* DAC scale */
325 {0x14, 0x02}, /* ?default */
326 {0x13, 0x01}, /* Validate Settings */
328 static const __u8 initPas202[] = {
329 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
332 0x28, 0x1e, 0x28, 0x89, 0x30,
333 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
335 static const __u8 pas202_sensor_init[][8] = {
336 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
337 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
338 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
339 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
340 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
341 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
342 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
343 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
344 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
345 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
346 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
347 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
349 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
350 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
351 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
352 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
353 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
354 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
355 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
356 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
359 static const __u8 initTas5110[] = {
360 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
362 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
363 0x16, 0x12, 0x60, 0x86, 0x2b,
364 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
366 static const __u8 tas5110_sensor_init[][8] = {
367 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
368 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
369 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
372 static const __u8 initTas5130[] = {
373 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
375 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
376 0x28, 0x1e, 0x60, COMP, MCK_INIT,
377 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
379 static const __u8 tas5130_sensor_init[][8] = {
380 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
381 * shutter 0x47 short exposure? */
382 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
383 /* shutter 0x01 long exposure */
384 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
387 /* get one byte in gspca_dev->usb_buf */
388 static void reg_r(struct gspca_dev *gspca_dev,
391 usb_control_msg(gspca_dev->dev,
392 usb_rcvctrlpipe(gspca_dev->dev, 0),
394 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
397 gspca_dev->usb_buf, 1,
401 static void reg_w(struct gspca_dev *gspca_dev,
406 #ifdef CONFIG_VIDEO_ADV_DEBUG
407 if (len > sizeof gspca_dev->usb_buf) {
408 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
412 memcpy(gspca_dev->usb_buf, buffer, len);
413 usb_control_msg(gspca_dev->dev,
414 usb_sndctrlpipe(gspca_dev->dev, 0),
416 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
419 gspca_dev->usb_buf, len,
423 static void reg_w_big(struct gspca_dev *gspca_dev,
430 tmpbuf = kmalloc(len, GFP_KERNEL);
431 memcpy(tmpbuf, buffer, len);
432 usb_control_msg(gspca_dev->dev,
433 usb_sndctrlpipe(gspca_dev->dev, 0),
435 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
443 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
448 reg_w(gspca_dev, 0x08, buffer, 8);
451 reg_r(gspca_dev, 0x08);
452 if (gspca_dev->usb_buf[0] == 4)
458 static void i2c_w_vector(struct gspca_dev *gspca_dev,
459 const __u8 buffer[][8], int len)
462 reg_w(gspca_dev, 0x08, *buffer, 8);
470 static void setbrightness(struct gspca_dev *gspca_dev)
472 struct sd *sd = (struct sd *) gspca_dev;
475 switch (sd->sensor) {
476 case SENSOR_OV6650: {
478 {0xa0, 0x60, 0x06, 0x11, 0x99, 0x04, 0x94, 0x15};
480 i2cOV6650[3] = sd->brightness;
481 if (i2c_w(gspca_dev, i2cOV6650) < 0)
485 case SENSOR_OV7630: {
487 {0xa0, 0x21, 0x06, 0x36, 0xbd, 0x06, 0xf6, 0x16};
489 /* change reg 0x06 */
490 i2cOV[3] = sd->brightness;
491 if (i2c_w(gspca_dev, i2cOV) < 0)
495 case SENSOR_PAS106: {
497 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
499 i2c1[3] = sd->brightness >> 3;
501 if (i2c_w(gspca_dev, i2c1) < 0)
505 if (i2c_w(gspca_dev, i2c1) < 0)
509 case SENSOR_PAS202: {
510 /* __u8 i2cpexpo1[] =
511 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
513 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
515 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
516 static __u8 i2cpdoit[] =
517 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
519 /* change reg 0x10 */
520 i2cpexpo[4] = 0xff - sd->brightness;
521 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
523 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
525 if (i2c_w(gspca_dev, i2cpexpo) < 0)
527 if (i2c_w(gspca_dev, i2cpdoit) < 0)
529 i2cp202[3] = sd->brightness >> 3;
530 if (i2c_w(gspca_dev, i2cp202) < 0)
532 if (i2c_w(gspca_dev, i2cpdoit) < 0)
536 case SENSOR_TAS5130CXX: {
538 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
540 value = 0xff - sd->brightness;
542 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
543 if (i2c_w(gspca_dev, i2c) < 0)
548 /* FIXME figure out howto control brightness on TAS5110 */
553 PDEBUG(D_ERR, "i2c error brightness");
556 static void setsensorgain(struct gspca_dev *gspca_dev)
558 struct sd *sd = (struct sd *) gspca_dev;
561 gain = (sd->gain + 1) >> 1;
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)
576 case SENSOR_OV6650: {
577 __u8 i2c[] = {0xa0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
579 if (i2c_w(gspca_dev, i2c) < 0)
586 PDEBUG(D_ERR, "i2c error gain");
589 static void setgain(struct gspca_dev *gspca_dev)
591 struct sd *sd = (struct sd *) gspca_dev;
595 gain = sd->gain >> 5;
597 /* red and blue gain */
598 rgb_value = gain << 4 | gain;
599 reg_w(gspca_dev, 0x10, &rgb_value, 1);
602 reg_w(gspca_dev, 0x11, &rgb_value, 1);
604 if (sd->sensor_has_gain)
605 setsensorgain(gspca_dev);
608 static void setexposure(struct gspca_dev *gspca_dev)
610 struct sd *sd = (struct sd *) gspca_dev;
611 /* translate 0 - 255 to a number of fps in a 30 - 1 scale */
612 int fps = 30 - sd->exposure * 29 / 511;
614 switch (sd->sensor) {
615 case SENSOR_TAS5110: {
618 /* register 19's high nibble contains the sn9c10x clock divider
619 The high nibble configures the no fps according to the
620 formula: 60 / high_nibble. With a maximum of 30 fps */
624 reg = (reg << 4) | 0x0b;
625 reg_w(gspca_dev, 0x19, ®, 1);
628 case SENSOR_OV6650: {
629 __u8 i2c[] = {0xa0, 0x60, 0x11, 0xc0, 0x00, 0x00, 0x00, 0x10};
630 i2c[3] = 30 / fps - 1;
634 if (i2c_w(gspca_dev, i2c) < 0)
635 PDEBUG(D_ERR, "i2c error exposure");
642 static void do_autogain(struct gspca_dev *gspca_dev)
644 struct sd *sd = (struct sd *) gspca_dev;
645 int avg_lum = atomic_read(&sd->avg_lum);
650 if (sd->autogain_ignore_frames > 0)
651 sd->autogain_ignore_frames--;
652 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
653 sd->brightness * DESIRED_AVG_LUM / 127,
654 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE))
655 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
658 /* this function is called at probe time */
659 static int sd_config(struct gspca_dev *gspca_dev,
660 const struct usb_device_id *id)
662 struct sd *sd = (struct sd *) gspca_dev;
667 /* nctrls depends upon the sensor, so we use a per cam copy */
668 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
669 gspca_dev->sd_desc = &sd->sd_desc;
671 sd->fr_h_sz = 12; /* default size of the frame header */
672 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
674 product = id->idProduct;
675 /* switch (id->idVendor) { */
676 /* case 0x0c45: * Sonix */
678 case 0x6001: /* SN9C102 */
679 case 0x6005: /* SN9C101 */
680 case 0x6007: /* SN9C101 */
681 sd->sensor = SENSOR_TAS5110;
682 sd->sensor_has_gain = 1;
683 sd->sd_desc.nctrls = 4;
684 sd->sd_desc.dq_callback = do_autogain;
687 case 0x6009: /* SN9C101 */
688 case 0x600d: /* SN9C101 */
689 case 0x6029: /* SN9C101 */
690 sd->sensor = SENSOR_PAS106;
693 case 0x6011: /* SN9C101 - SN9C101G */
694 sd->sensor = SENSOR_OV6650;
695 sd->sensor_has_gain = 1;
696 sd->sd_desc.nctrls = 4;
697 sd->sd_desc.dq_callback = do_autogain;
700 case 0x6019: /* SN9C101 */
701 case 0x602c: /* SN9C102 */
702 case 0x602e: /* SN9C102 */
703 sd->sensor = SENSOR_OV7630;
705 case 0x60b0: /* SN9C103 */
706 sd->sensor = SENSOR_OV7630_3;
707 sd->fr_h_sz = 18; /* size of frame header */
709 case 0x6024: /* SN9C102 */
710 case 0x6025: /* SN9C102 */
711 sd->sensor = SENSOR_TAS5130CXX;
713 case 0x6028: /* SN9C102 */
714 sd->sensor = SENSOR_PAS202;
716 case 0x602d: /* SN9C102 */
717 sd->sensor = SENSOR_HV7131R;
719 case 0x60af: /* SN9C103 */
720 sd->sensor = SENSOR_PAS202;
721 sd->fr_h_sz = 18; /* size of frame header (?) */
727 cam = &gspca_dev->cam;
728 cam->dev_name = (char *) id->driver_info;
731 cam->cam_mode = vga_mode;
732 cam->nmodes = ARRAY_SIZE(vga_mode);
734 cam->cam_mode = sif_mode;
735 cam->nmodes = ARRAY_SIZE(sif_mode);
737 sd->brightness = BRIGHTNESS_DEF;
739 sd->exposure = EXPOSURE_DEF;
740 sd->autogain = AUTOGAIN_DEF;
741 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
742 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
746 /* this function is called at open time */
747 static int sd_open(struct gspca_dev *gspca_dev)
749 reg_r(gspca_dev, 0x00);
750 if (gspca_dev->usb_buf[0] != 0x10)
755 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
759 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
761 i = ARRAY_SIZE(pas106_data);
762 data = pas106_data[0];
764 memcpy(&i2c1[2], data, 2);
765 /* copy 2 bytes from the template */
766 if (i2c_w(gspca_dev, i2c1) < 0)
767 PDEBUG(D_ERR, "i2c error pas106");
772 /* -- start the camera -- */
773 static void sd_start(struct gspca_dev *gspca_dev)
775 struct sd *sd = (struct sd *) gspca_dev;
780 static const __u8 reg15[2] = { 0x28, 0x1e };
782 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
783 switch (sd->sensor) {
785 sn9c10x = initHv7131;
787 reg17_19[1] = (mode << 4) | 0x8a;
791 sn9c10x = initOv6650;
793 reg17_19[1] = (mode << 4) | 0x8b;
797 sn9c10x = initOv7630;
799 reg17_19[1] = (mode << 4) | COMP2;
800 reg17_19[2] = MCK_INIT1;
802 case SENSOR_OV7630_3:
803 sn9c10x = initOv7630_3;
805 reg17_19[1] = (mode << 4) | COMP2;
806 reg17_19[2] = MCK_INIT1;
809 sn9c10x = initPas106;
810 reg17_19[0] = 0x24; /* 0x28 */
811 reg17_19[1] = (mode << 4) | COMP1;
812 reg17_19[2] = MCK_INIT1;
815 sn9c10x = initPas202;
816 reg17_19[0] = mode ? 0x24 : 0x20;
817 reg17_19[1] = (mode << 4) | 0x89;
821 sn9c10x = initTas5110;
823 reg17_19[1] = (mode << 4) | 0x86;
824 reg17_19[2] = 0x2b; /* 0xf3; */
827 /* case SENSOR_TAS5130CXX: */
828 sn9c10x = initTas5130;
830 reg17_19[1] = (mode << 4) | COMP;
831 reg17_19[2] = mode ? 0x23 : 0x43;
834 switch (sd->sensor) {
840 case SENSOR_OV7630_3:
843 l = sizeof initOv7630_3;
847 reg17 = sn9c10x[0x17 - 1];
852 /* reg 0x01 bit 2 video transfert on */
853 reg_w(gspca_dev, 0x01, ®01, 1);
854 /* reg 0x17 SensorClk enable inv Clk 0x60 */
855 reg_w(gspca_dev, 0x17, ®17, 1);
856 /*fixme: for ov7630 102
857 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
858 /* Set the registers from the template */
859 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
860 switch (sd->sensor) {
862 i2c_w_vector(gspca_dev, hv7131_sensor_init,
863 sizeof hv7131_sensor_init);
866 i2c_w_vector(gspca_dev, ov6650_sensor_init,
867 sizeof ov6650_sensor_init);
870 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
871 sizeof ov7630_sensor_init_com);
873 i2c_w_vector(gspca_dev, ov7630_sensor_init,
874 sizeof ov7630_sensor_init);
876 case SENSOR_OV7630_3:
877 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
878 sizeof ov7630_sensor_init_com);
880 i2c_w_vector(gspca_dev, ov7630_sensor_init_3,
881 sizeof ov7630_sensor_init_3);
884 pas106_i2cinit(gspca_dev);
887 i2c_w_vector(gspca_dev, pas202_sensor_init,
888 sizeof pas202_sensor_init);
891 i2c_w_vector(gspca_dev, tas5110_sensor_init,
892 sizeof tas5110_sensor_init);
895 /* case SENSOR_TAS5130CXX: */
896 i2c_w_vector(gspca_dev, tas5130_sensor_init,
897 sizeof tas5130_sensor_init);
900 /* H_size V_size 0x28, 0x1e maybe 640x480 */
901 reg_w(gspca_dev, 0x15, reg15, 2);
902 /* compression register */
903 reg_w(gspca_dev, 0x18, ®17_19[1], 1);
904 if (sd->sensor != SENSOR_OV7630_3) {
906 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
908 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
910 /* reset 0x17 SensorClk enable inv Clk 0x60 */
911 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
912 reg_w(gspca_dev, 0x17, ®17_19[0], 1);
913 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
914 if (sd->sensor != SENSOR_OV7630_3)
915 reg_w(gspca_dev, 0x19, ®17_19[2], 1);
916 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
917 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
918 /* Enable video transfert */
919 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
921 reg_w(gspca_dev, 0x18, ®17_19[1], 2);
925 setbrightness(gspca_dev);
926 setexposure(gspca_dev);
928 sd->autogain_ignore_frames = 0;
929 atomic_set(&sd->avg_lum, -1);
932 static void sd_stopN(struct gspca_dev *gspca_dev)
936 ByteSend = 0x09; /* 0X00 */
937 reg_w(gspca_dev, 0x01, &ByteSend, 1);
940 static void sd_stop0(struct gspca_dev *gspca_dev)
944 static void sd_close(struct gspca_dev *gspca_dev)
948 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
949 struct gspca_frame *frame, /* target */
950 unsigned char *data, /* isoc packet */
951 int len) /* iso packet length */
954 struct sd *sd = (struct sd *) gspca_dev;
956 if (len > 6 && len < 24) {
957 for (i = 0; i < len - 6; i++) {
958 if (data[0 + i] == 0xff
959 && data[1 + i] == 0xff
960 && data[2 + i] == 0x00
961 && data[3 + i] == 0xc4
962 && data[4 + i] == 0xc4
963 && data[5 + i] == 0x96) { /* start of frame */
964 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
966 if (i < (len - 10)) {
967 atomic_set(&sd->avg_lum, data[i + 8] +
970 atomic_set(&sd->avg_lum, -1);
971 #ifdef CONFIG_VIDEO_ADV_DEBUG
972 PDEBUG(D_STREAM, "packet too short to "
973 "get avg brightness");
976 data += i + sd->fr_h_sz;
977 len -= i + sd->fr_h_sz;
978 gspca_frame_add(gspca_dev, FIRST_PACKET,
984 gspca_frame_add(gspca_dev, INTER_PACKET,
988 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
990 struct sd *sd = (struct sd *) gspca_dev;
992 sd->brightness = val;
993 if (gspca_dev->streaming)
994 setbrightness(gspca_dev);
998 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1000 struct sd *sd = (struct sd *) gspca_dev;
1002 *val = sd->brightness;
1006 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1008 struct sd *sd = (struct sd *) gspca_dev;
1011 if (gspca_dev->streaming)
1016 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1018 struct sd *sd = (struct sd *) gspca_dev;
1024 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1026 struct sd *sd = (struct sd *) gspca_dev;
1029 if (gspca_dev->streaming)
1030 setexposure(gspca_dev);
1034 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1036 struct sd *sd = (struct sd *) gspca_dev;
1038 *val = sd->exposure;
1042 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1044 struct sd *sd = (struct sd *) gspca_dev;
1047 /* when switching to autogain set defaults to make sure
1048 we are on a valid point of the autogain gain /
1049 exposure knee graph, and give this change time to
1050 take effect before doing autogain. */
1052 sd->exposure = EXPOSURE_DEF;
1053 sd->gain = GAIN_DEF;
1054 if (gspca_dev->streaming) {
1055 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1056 setexposure(gspca_dev);
1064 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1066 struct sd *sd = (struct sd *) gspca_dev;
1068 *val = sd->autogain;
1072 /* sub-driver description */
1073 static const struct sd_desc sd_desc = {
1074 .name = MODULE_NAME,
1076 .nctrls = ARRAY_SIZE(sd_ctrls),
1077 .config = sd_config,
1083 .pkt_scan = sd_pkt_scan,
1086 /* -- module initialisation -- */
1087 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1088 static __devinitdata struct usb_device_id device_table[] = {
1089 #ifndef CONFIG_USB_SN9C102
1090 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1091 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1092 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1093 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1094 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1095 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1096 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1097 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1098 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1099 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1100 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1101 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1102 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1103 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1104 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1105 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1109 MODULE_DEVICE_TABLE(usb, device_table);
1111 /* -- device connect -- */
1112 static int sd_probe(struct usb_interface *intf,
1113 const struct usb_device_id *id)
1115 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1119 static struct usb_driver sd_driver = {
1120 .name = MODULE_NAME,
1121 .id_table = device_table,
1123 .disconnect = gspca_disconnect,
1126 /* -- module insert / remove -- */
1127 static int __init sd_mod_init(void)
1129 if (usb_register(&sd_driver) < 0)
1131 PDEBUG(D_PROBE, "v%s registered", version);
1134 static void __exit sd_mod_exit(void)
1136 usb_deregister(&sd_driver);
1137 PDEBUG(D_PROBE, "deregistered");
1140 module_init(sd_mod_init);
1141 module_exit(sd_mod_exit);