V4L/DVB (8455): gspca_sonixb sn9c103 + ov7630 autoexposure and cleanup
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / media / video / gspca / sonixb.c
blob4f9c9ecb06e850087e2be9c7d761ef64f4aaef8d
1 /*
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
11 * any later version.
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"
25 #include "gspca.h"
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 */
32 struct sd {
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 */
37 atomic_t avg_lum;
39 unsigned char gain;
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 */
46 unsigned char saturation;
47 unsigned char hue;
48 unsigned char contrast;
50 unsigned char fr_h_sz; /* size of frame header */
51 char sensor; /* Type of image sensor chip */
52 #define SENSOR_HV7131R 0
53 #define SENSOR_OV6650 1
54 #define SENSOR_OV7630 2
55 #define SENSOR_PAS106 3
56 #define SENSOR_PAS202 4
57 #define SENSOR_TAS5110 5
58 #define SENSOR_TAS5130CXX 6
59 char sensor_has_gain;
60 __u8 sensor_addr;
61 __u8 reg11;
64 #define COMP2 0x8f
65 #define COMP 0xc7 /* 0x87 //0x07 */
66 #define COMP1 0xc9 /* 0x89 //0x09 */
68 #define MCK_INIT 0x63
69 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
71 #define SYS_CLK 0x04
73 /* We calculate the autogain at the end of the transfer of a frame, at this
74 moment a frame with the old settings is being transmitted, and a frame is
75 being captured with the old settings. So if we adjust the autogain we must
76 ignore atleast the 2 next frames for the new settings to come into effect
77 before doing any other adjustments */
78 #define AUTOGAIN_IGNORE_FRAMES 3
79 #define AUTOGAIN_DEADZONE 1000
80 #define DESIRED_AVG_LUM 7000
82 /* V4L2 controls supported by the driver */
83 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
84 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
85 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
86 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
87 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
88 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
89 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
90 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
91 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
92 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
93 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
94 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
95 static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
96 static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
97 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
98 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
100 static struct ctrl sd_ctrls[] = {
103 .id = V4L2_CID_BRIGHTNESS,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Brightness",
106 .minimum = 0,
107 .maximum = 255,
108 .step = 1,
109 #define BRIGHTNESS_DEF 127
110 .default_value = BRIGHTNESS_DEF,
112 .set = sd_setbrightness,
113 .get = sd_getbrightness,
117 .id = V4L2_CID_GAIN,
118 .type = V4L2_CTRL_TYPE_INTEGER,
119 .name = "Gain",
120 .minimum = 0,
121 .maximum = 255,
122 .step = 1,
123 #define GAIN_DEF 127
124 #define GAIN_KNEE 200
125 .default_value = GAIN_DEF,
127 .set = sd_setgain,
128 .get = sd_getgain,
132 .id = V4L2_CID_EXPOSURE,
133 .type = V4L2_CTRL_TYPE_INTEGER,
134 .name = "Exposure",
135 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
136 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
137 .minimum = 0,
138 .maximum = 255,
139 .step = 1,
140 .default_value = EXPOSURE_DEF,
141 .flags = 0,
143 .set = sd_setexposure,
144 .get = sd_getexposure,
148 .id = V4L2_CID_AUTOGAIN,
149 .type = V4L2_CTRL_TYPE_BOOLEAN,
150 .name = "Automatic Gain (and Exposure)",
151 .minimum = 0,
152 .maximum = 1,
153 .step = 1,
154 #define AUTOGAIN_DEF 1
155 .default_value = AUTOGAIN_DEF,
156 .flags = 0,
158 .set = sd_setautogain,
159 .get = sd_getautogain,
163 .id = V4L2_CID_POWER_LINE_FREQUENCY,
164 .type = V4L2_CTRL_TYPE_MENU,
165 .name = "Light frequency filter",
166 .minimum = 0,
167 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
168 .step = 1,
169 #define FREQ_DEF 1
170 .default_value = FREQ_DEF,
172 .set = sd_setfreq,
173 .get = sd_getfreq,
177 .id = V4L2_CID_SATURATION,
178 .type = V4L2_CTRL_TYPE_INTEGER,
179 .name = "Saturation",
180 .minimum = 0,
181 .maximum = 255,
182 .step = 1,
183 #define SATURATION_DEF 127
184 .default_value = SATURATION_DEF,
186 .set = sd_setsaturation,
187 .get = sd_getsaturation,
191 .id = V4L2_CID_HUE,
192 .type = V4L2_CTRL_TYPE_INTEGER,
193 .name = "Hue",
194 .minimum = 0,
195 .maximum = 255,
196 .step = 1,
197 #define HUE_DEF 127
198 .default_value = HUE_DEF,
200 .set = sd_sethue,
201 .get = sd_gethue,
205 .id = V4L2_CID_CONTRAST,
206 .type = V4L2_CTRL_TYPE_INTEGER,
207 .name = "Contrast",
208 .minimum = 0,
209 .maximum = 255,
210 .step = 1,
211 #define CONTRAST_DEF 127
212 .default_value = CONTRAST_DEF,
214 .set = sd_setcontrast,
215 .get = sd_getcontrast,
219 static struct v4l2_pix_format vga_mode[] = {
220 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
221 .bytesperline = 160,
222 .sizeimage = 160 * 120,
223 .colorspace = V4L2_COLORSPACE_SRGB,
224 .priv = 2},
225 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
226 .bytesperline = 320,
227 .sizeimage = 320 * 240,
228 .colorspace = V4L2_COLORSPACE_SRGB,
229 .priv = 1},
230 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
231 .bytesperline = 640,
232 .sizeimage = 640 * 480,
233 .colorspace = V4L2_COLORSPACE_SRGB,
234 .priv = 0},
236 static struct v4l2_pix_format sif_mode[] = {
237 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
238 .bytesperline = 176,
239 .sizeimage = 176 * 144,
240 .colorspace = V4L2_COLORSPACE_SRGB,
241 .priv = 1},
242 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
243 .bytesperline = 352,
244 .sizeimage = 352 * 288,
245 .colorspace = V4L2_COLORSPACE_SRGB,
246 .priv = 0},
249 static const __u8 probe_ov7630[] = {0x08, 0x44};
251 static const __u8 initHv7131[] = {
252 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
253 0x00, 0x00,
254 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
255 0x28, 0x1e, 0x60, 0x8a, 0x20,
256 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
258 static const __u8 hv7131_sensor_init[][8] = {
259 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
260 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
261 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
262 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
263 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
265 static const __u8 initOv6650[] = {
266 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
267 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
269 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
271 static const __u8 ov6650_sensor_init[][8] =
273 /* Bright, contrast, etc are set througth SCBB interface.
274 * AVCAP on win2 do not send any data on this controls. */
275 /* Anyway, some registers appears to alter bright and constrat */
277 /* Reset sensor */
278 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
279 /* Set clock register 0x11 low nibble is clock divider */
280 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
281 /* Next some unknown stuff */
282 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
283 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
284 * THIS SET GREEN SCREEN
285 * (pixels could be innverted in decode kind of "brg",
286 * but blue wont be there. Avoid this data ... */
287 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
288 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
289 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
290 /* Enable rgb brightness control */
291 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
292 /* HDG: Note windows uses the line below, which sets both register 0x60
293 and 0x61 I believe these registers of the ov6650 are identical as
294 those of the ov7630, because if this is true the windows settings
295 add a bit additional red gain and a lot additional blue gain, which
296 matches my findings that the windows settings make blue much too
297 blue and red a little too red.
298 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
299 /* Some more unknown stuff */
300 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
301 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
304 static const __u8 initOv7630[] = {
305 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
306 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
307 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
308 0x28, 0x1e, /* H & V sizes r15 .. r16 */
309 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
310 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
312 static const __u8 initOv7630_3[] = {
313 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
314 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
315 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
316 0x28, 0x1e, /* H & V sizes r15 .. r16 */
317 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
318 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
319 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
320 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
322 static const __u8 ov7630_sensor_init[][8] = {
323 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
324 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
325 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
326 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
327 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
328 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
329 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
330 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
331 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
332 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
333 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
334 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
335 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
336 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
337 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
338 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
339 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
340 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
341 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
344 static const __u8 initPas106[] = {
345 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
346 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
348 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
349 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
351 /* compression 0x86 mckinit1 0x2b */
352 static const __u8 pas106_data[][2] = {
353 {0x02, 0x04}, /* Pixel Clock Divider 6 */
354 {0x03, 0x13}, /* Frame Time MSB */
355 /* {0x03, 0x12}, * Frame Time MSB */
356 {0x04, 0x06}, /* Frame Time LSB */
357 /* {0x04, 0x05}, * Frame Time LSB */
358 {0x05, 0x65}, /* Shutter Time Line Offset */
359 /* {0x05, 0x6d}, * Shutter Time Line Offset */
360 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
361 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
362 {0x07, 0xc1}, /* Black Level Subtract Sign */
363 /* {0x07, 0x00}, * Black Level Subtract Sign */
364 {0x08, 0x06}, /* Black Level Subtract Level */
365 {0x08, 0x06}, /* Black Level Subtract Level */
366 /* {0x08, 0x01}, * Black Level Subtract Level */
367 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
368 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
369 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
370 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
371 {0x0d, 0x00}, /* Color GainH Pixel */
372 {0x0e, 0x0e}, /* Global Gain */
373 {0x0f, 0x00}, /* Contrast */
374 {0x10, 0x06}, /* H&V synchro polarity */
375 {0x11, 0x06}, /* ?default */
376 {0x12, 0x06}, /* DAC scale */
377 {0x14, 0x02}, /* ?default */
378 {0x13, 0x01}, /* Validate Settings */
380 static const __u8 initPas202[] = {
381 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
382 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
384 0x28, 0x1e, 0x28, 0x89, 0x30,
385 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
387 static const __u8 pas202_sensor_init[][8] = {
388 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
389 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
390 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
391 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
392 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
393 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
394 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
395 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
396 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
397 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
398 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
399 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
401 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
402 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
403 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
404 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
405 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
406 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
407 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
408 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
411 static const __u8 initTas5110[] = {
412 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
413 0x00, 0x00,
414 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
415 0x16, 0x12, 0x60, 0x86, 0x2b,
416 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
418 static const __u8 tas5110_sensor_init[][8] = {
419 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
420 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
421 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
424 static const __u8 initTas5130[] = {
425 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
426 0x00, 0x00,
427 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
428 0x28, 0x1e, 0x60, COMP, MCK_INIT,
429 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
431 static const __u8 tas5130_sensor_init[][8] = {
432 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
433 * shutter 0x47 short exposure? */
434 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
435 /* shutter 0x01 long exposure */
436 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
439 /* get one byte in gspca_dev->usb_buf */
440 static void reg_r(struct gspca_dev *gspca_dev,
441 __u16 value)
443 usb_control_msg(gspca_dev->dev,
444 usb_rcvctrlpipe(gspca_dev->dev, 0),
445 0, /* request */
446 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
447 value,
448 0, /* index */
449 gspca_dev->usb_buf, 1,
450 500);
453 static void reg_w(struct gspca_dev *gspca_dev,
454 __u16 value,
455 const __u8 *buffer,
456 int len)
458 #ifdef CONFIG_VIDEO_ADV_DEBUG
459 if (len > sizeof gspca_dev->usb_buf) {
460 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
461 return;
463 #endif
464 memcpy(gspca_dev->usb_buf, buffer, len);
465 usb_control_msg(gspca_dev->dev,
466 usb_sndctrlpipe(gspca_dev->dev, 0),
467 0x08, /* request */
468 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
469 value,
470 0, /* index */
471 gspca_dev->usb_buf, len,
472 500);
475 static void reg_w_big(struct gspca_dev *gspca_dev,
476 __u16 value,
477 const __u8 *buffer,
478 int len)
480 __u8 *tmpbuf;
482 tmpbuf = kmalloc(len, GFP_KERNEL);
483 memcpy(tmpbuf, buffer, len);
484 usb_control_msg(gspca_dev->dev,
485 usb_sndctrlpipe(gspca_dev->dev, 0),
486 0x08, /* request */
487 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
488 value,
489 0, /* index */
490 tmpbuf, len,
491 500);
492 kfree(tmpbuf);
495 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
497 int retry = 60;
499 /* is i2c ready */
500 reg_w(gspca_dev, 0x08, buffer, 8);
501 while (retry--) {
502 msleep(10);
503 reg_r(gspca_dev, 0x08);
504 if (gspca_dev->usb_buf[0] & 0x04) {
505 if (gspca_dev->usb_buf[0] & 0x08)
506 return -1;
507 return 0;
510 return -1;
513 static void i2c_w_vector(struct gspca_dev *gspca_dev,
514 const __u8 buffer[][8], int len)
516 for (;;) {
517 reg_w(gspca_dev, 0x08, *buffer, 8);
518 len -= 8;
519 if (len <= 0)
520 break;
521 buffer++;
525 static void setbrightness(struct gspca_dev *gspca_dev)
527 struct sd *sd = (struct sd *) gspca_dev;
528 __u8 value;
530 switch (sd->sensor) {
531 case SENSOR_OV6650:
532 case SENSOR_OV7630: {
533 __u8 i2cOV[] =
534 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
536 /* change reg 0x06 */
537 i2cOV[1] = sd->sensor_addr;
538 i2cOV[3] = sd->brightness;
539 if (i2c_w(gspca_dev, i2cOV) < 0)
540 goto err;
541 break;
543 case SENSOR_PAS106: {
544 __u8 i2c1[] =
545 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
547 i2c1[3] = sd->brightness >> 3;
548 i2c1[2] = 0x0e;
549 if (i2c_w(gspca_dev, i2c1) < 0)
550 goto err;
551 i2c1[3] = 0x01;
552 i2c1[2] = 0x13;
553 if (i2c_w(gspca_dev, i2c1) < 0)
554 goto err;
555 break;
557 case SENSOR_PAS202: {
558 /* __u8 i2cpexpo1[] =
559 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
560 __u8 i2cpexpo[] =
561 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
562 __u8 i2cp202[] =
563 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
564 static __u8 i2cpdoit[] =
565 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
567 /* change reg 0x10 */
568 i2cpexpo[4] = 0xff - sd->brightness;
569 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
570 goto err; */
571 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
572 goto err; */
573 if (i2c_w(gspca_dev, i2cpexpo) < 0)
574 goto err;
575 if (i2c_w(gspca_dev, i2cpdoit) < 0)
576 goto err;
577 i2cp202[3] = sd->brightness >> 3;
578 if (i2c_w(gspca_dev, i2cp202) < 0)
579 goto err;
580 if (i2c_w(gspca_dev, i2cpdoit) < 0)
581 goto err;
582 break;
584 case SENSOR_TAS5130CXX: {
585 __u8 i2c[] =
586 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
588 value = 0xff - sd->brightness;
589 i2c[4] = value;
590 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
591 if (i2c_w(gspca_dev, i2c) < 0)
592 goto err;
593 break;
595 case SENSOR_TAS5110:
596 /* FIXME figure out howto control brightness on TAS5110 */
597 break;
599 return;
600 err:
601 PDEBUG(D_ERR, "i2c error brightness");
604 static void setsensorgain(struct gspca_dev *gspca_dev)
606 struct sd *sd = (struct sd *) gspca_dev;
607 unsigned char gain = sd->gain;
609 switch (sd->sensor) {
611 case SENSOR_TAS5110: {
612 __u8 i2c[] =
613 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
615 i2c[4] = 255 - gain;
616 if (i2c_w(gspca_dev, i2c) < 0)
617 goto err;
618 break;
621 case SENSOR_OV6650:
622 gain >>= 1;
623 /* fall thru */
624 case SENSOR_OV7630: {
625 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
627 i2c[1] = sd->sensor_addr;
628 i2c[3] = gain >> 2;
629 if (i2c_w(gspca_dev, i2c) < 0)
630 goto err;
631 break;
634 return;
635 err:
636 PDEBUG(D_ERR, "i2c error gain");
639 static void setgain(struct gspca_dev *gspca_dev)
641 struct sd *sd = (struct sd *) gspca_dev;
642 __u8 gain;
643 __u8 rgb_value;
645 gain = sd->gain >> 4;
647 /* red and blue gain */
648 rgb_value = gain << 4 | gain;
649 reg_w(gspca_dev, 0x10, &rgb_value, 1);
650 /* green gain */
651 rgb_value = gain;
652 reg_w(gspca_dev, 0x11, &rgb_value, 1);
654 if (sd->sensor_has_gain)
655 setsensorgain(gspca_dev);
658 static void setexposure(struct gspca_dev *gspca_dev)
660 struct sd *sd = (struct sd *) gspca_dev;
662 switch (sd->sensor) {
663 case SENSOR_TAS5110: {
664 __u8 reg;
666 /* register 19's high nibble contains the sn9c10x clock divider
667 The high nibble configures the no fps according to the
668 formula: 60 / high_nibble. With a maximum of 30 fps */
669 reg = 120 * sd->exposure / 1000;
670 if (reg < 2)
671 reg = 2;
672 else if (reg > 15)
673 reg = 15;
674 reg = (reg << 4) | 0x0b;
675 reg_w(gspca_dev, 0x19, &reg, 1);
676 break;
678 case SENSOR_OV6650:
679 case SENSOR_OV7630: {
680 /* The ov6650 / ov7630 have 2 registers which both influence
681 exposure, register 11, whose low nibble sets the nr off fps
682 according to: fps = 30 / (low_nibble + 1)
684 The fps configures the maximum exposure setting, but it is
685 possible to use less exposure then what the fps maximum
686 allows by setting register 10. register 10 configures the
687 actual exposure as quotient of the full exposure, with 0
688 being no exposure at all (not very usefull) and reg10_max
689 being max exposure possible at that framerate.
691 The code maps our 0 - 510 ms exposure ctrl to these 2
692 registers, trying to keep fps as high as possible.
694 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
695 int reg10, reg11, reg10_max;
697 /* ov6645 datasheet says reg10_max is 9a, but that uses
698 tline * 2 * reg10 as formula for calculating texpo, the
699 ov6650 probably uses the same formula as the 7730 which uses
700 tline * 4 * reg10, which explains why the reg10max we've
701 found experimentally for the ov6650 is exactly half that of
702 the ov6645. The ov7630 datasheet says the max is 0x41. */
703 if (sd->sensor == SENSOR_OV6650) {
704 reg10_max = 0x4d;
705 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
706 } else
707 reg10_max = 0x41;
709 reg11 = (60 * sd->exposure + 999) / 1000;
710 if (reg11 < 1)
711 reg11 = 1;
712 else if (reg11 > 16)
713 reg11 = 16;
715 /* frame exposure time in ms = 1000 * reg11 / 30 ->
716 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
717 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
719 /* Don't allow this to get below 10 when using autogain, the
720 steps become very large (relatively) when below 10 causing
721 the image to oscilate from much too dark, to much too bright
722 and back again. */
723 if (sd->autogain && reg10 < 10)
724 reg10 = 10;
725 else if (reg10 > reg10_max)
726 reg10 = reg10_max;
728 /* In 640x480, if the reg11 has less than 3, the image is
729 unstable (not enough bandwidth). */
730 if (gspca_dev->width == 640 && reg11 < 3)
731 reg11 = 3;
733 /* Write reg 10 and reg11 low nibble */
734 i2c[1] = sd->sensor_addr;
735 i2c[3] = reg10;
736 i2c[4] |= reg11 - 1;
738 /* If register 11 didn't change, don't change it */
739 if (sd->reg11 == reg11 )
740 i2c[0] = 0xa0;
742 if (i2c_w(gspca_dev, i2c) == 0)
743 sd->reg11 = reg11;
744 else
745 PDEBUG(D_ERR, "i2c error exposure");
746 break;
751 static void setfreq(struct gspca_dev *gspca_dev)
753 struct sd *sd = (struct sd *) gspca_dev;
755 switch (sd->sensor) {
756 case SENSOR_OV6650:
757 case SENSOR_OV7630: {
758 /* Framerate adjust register for artificial light 50 hz flicker
759 compensation, for the ov6650 this is identical to ov6630
760 0x2b register, see ov6630 datasheet.
761 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
762 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
763 switch (sd->freq) {
764 default:
765 /* case 0: * no filter*/
766 /* case 2: * 60 hz */
767 i2c[3] = 0;
768 break;
769 case 1: /* 50 hz */
770 i2c[3] = (sd->sensor == SENSOR_OV6650)
771 ? 0x4f : 0x8a;
772 break;
774 i2c[1] = sd->sensor_addr;
775 if (i2c_w(gspca_dev, i2c) < 0)
776 PDEBUG(D_ERR, "i2c error setfreq");
777 break;
782 static void setsaturation(struct gspca_dev *gspca_dev)
784 struct sd *sd = (struct sd *) gspca_dev;
786 switch (sd->sensor) {
787 /* case SENSOR_OV6650: */
788 case SENSOR_OV7630: {
789 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
790 i2c[1] = sd->sensor_addr;
791 i2c[3] = sd->saturation & 0xf0;
792 if (i2c_w(gspca_dev, i2c) < 0)
793 PDEBUG(D_ERR, "i2c error setsaturation");
794 else
795 PDEBUG(D_CONF, "saturation set to: %d",
796 (int)sd->saturation);
797 break;
802 static void sethue(struct gspca_dev *gspca_dev)
804 struct sd *sd = (struct sd *) gspca_dev;
806 switch (sd->sensor) {
807 /* case SENSOR_OV6650: */
808 case SENSOR_OV7630: {
809 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
810 i2c[1] = sd->sensor_addr;
811 i2c[3] = 0x20 | (sd->hue >> 3);
812 if (i2c_w(gspca_dev, i2c) < 0)
813 PDEBUG(D_ERR, "i2c error setsaturation");
814 else
815 PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
816 break;
821 static void setcontrast(struct gspca_dev *gspca_dev)
823 struct sd *sd = (struct sd *) gspca_dev;
825 switch (sd->sensor) {
826 /* case SENSOR_OV6650: */
827 case SENSOR_OV7630: {
828 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
829 i2c[1] = sd->sensor_addr;
830 i2c[3] = 0x20 | (sd->contrast >> 3);
831 if (i2c_w(gspca_dev, i2c) < 0)
832 PDEBUG(D_ERR, "i2c error setcontrast");
833 else
834 PDEBUG(D_CONF, "contrast set to: %d",
835 (int)sd->contrast);
836 break;
842 static void do_autogain(struct gspca_dev *gspca_dev)
844 struct sd *sd = (struct sd *) gspca_dev;
845 int avg_lum = atomic_read(&sd->avg_lum);
847 if (avg_lum == -1)
848 return;
850 if (sd->autogain_ignore_frames > 0)
851 sd->autogain_ignore_frames--;
852 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
853 sd->brightness * DESIRED_AVG_LUM / 127,
854 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
855 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
856 (int)sd->gain, (int)sd->exposure);
857 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
861 /* this function is called at probe time */
862 static int sd_config(struct gspca_dev *gspca_dev,
863 const struct usb_device_id *id)
865 struct sd *sd = (struct sd *) gspca_dev;
866 struct cam *cam;
867 __u16 product;
868 int sif = 0;
870 /* nctrls depends upon the sensor, so we use a per cam copy */
871 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
872 gspca_dev->sd_desc = &sd->sd_desc;
874 sd->fr_h_sz = 12; /* default size of the frame header */
875 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
876 product = id->idProduct;
877 /* switch (id->idVendor) { */
878 /* case 0x0c45: * Sonix */
879 switch (product) {
880 case 0x6001: /* SN9C102 */
881 case 0x6005: /* SN9C101 */
882 case 0x6007: /* SN9C101 */
883 sd->sensor = SENSOR_TAS5110;
884 sd->sensor_has_gain = 1;
885 sd->sd_desc.nctrls = 4;
886 sd->sd_desc.dq_callback = do_autogain;
887 sif = 1;
888 break;
889 case 0x6009: /* SN9C101 */
890 case 0x600d: /* SN9C101 */
891 case 0x6029: /* SN9C101 */
892 sd->sensor = SENSOR_PAS106;
893 sif = 1;
894 break;
895 case 0x6011: /* SN9C101 - SN9C101G */
896 sd->sensor = SENSOR_OV6650;
897 sd->sensor_has_gain = 1;
898 sd->sensor_addr = 0x60;
899 sd->sd_desc.nctrls = 5;
900 sd->sd_desc.dq_callback = do_autogain;
901 sif = 1;
902 break;
903 case 0x6019: /* SN9C101 */
904 case 0x602c: /* SN9C102 */
905 case 0x602e: /* SN9C102 */
906 case 0x60b0: /* SN9C103 */
907 sd->sensor = SENSOR_OV7630;
908 sd->sensor_addr = 0x21;
909 sd->sensor_has_gain = 1;
910 sd->sd_desc.nctrls = 5;
911 sd->sd_desc.dq_callback = do_autogain;
912 if (product == 0x60b0)
913 sd->fr_h_sz = 18; /* size of frame header */
914 break;
915 case 0x6024: /* SN9C102 */
916 case 0x6025: /* SN9C102 */
917 sd->sensor = SENSOR_TAS5130CXX;
918 break;
919 case 0x6028: /* SN9C102 */
920 sd->sensor = SENSOR_PAS202;
921 break;
922 case 0x602d: /* SN9C102 */
923 sd->sensor = SENSOR_HV7131R;
924 break;
925 case 0x60af: /* SN9C103 */
926 sd->sensor = SENSOR_PAS202;
927 sd->fr_h_sz = 18; /* size of frame header (?) */
928 break;
930 /* break; */
931 /* } */
933 cam = &gspca_dev->cam;
934 cam->dev_name = (char *) id->driver_info;
935 cam->epaddr = 0x01;
936 if (!sif) {
937 cam->cam_mode = vga_mode;
938 cam->nmodes = ARRAY_SIZE(vga_mode);
939 if (product == 0x60b0) { /* SN9C103 with OV7630 */
940 /* We only have 320x240 & 640x480 */
941 cam->cam_mode++;
942 cam->nmodes--;
944 } else {
945 cam->cam_mode = sif_mode;
946 cam->nmodes = ARRAY_SIZE(sif_mode);
948 sd->brightness = BRIGHTNESS_DEF;
949 sd->gain = GAIN_DEF;
950 sd->exposure = EXPOSURE_DEF;
951 sd->autogain = AUTOGAIN_DEF;
952 sd->freq = FREQ_DEF;
953 sd->contrast = CONTRAST_DEF;
954 sd->saturation = SATURATION_DEF;
955 sd->hue = HUE_DEF;
957 if (product == 0x60b0) /* SN9C103 with OV7630 */
958 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
960 return 0;
963 /* this function is called at open time */
964 static int sd_open(struct gspca_dev *gspca_dev)
966 reg_r(gspca_dev, 0x00);
967 if (gspca_dev->usb_buf[0] != 0x10)
968 return -ENODEV;
969 return 0;
972 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
974 int i;
975 const __u8 *data;
976 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
978 i = ARRAY_SIZE(pas106_data);
979 data = pas106_data[0];
980 while (--i >= 0) {
981 memcpy(&i2c1[2], data, 2);
982 /* copy 2 bytes from the template */
983 if (i2c_w(gspca_dev, i2c1) < 0)
984 PDEBUG(D_ERR, "i2c error pas106");
985 data += 2;
989 /* -- start the camera -- */
990 static void sd_start(struct gspca_dev *gspca_dev)
992 struct sd *sd = (struct sd *) gspca_dev;
993 int mode, l = 0x1f;
994 const __u8 *sn9c10x;
995 __u8 reg01, reg17;
996 __u8 reg17_19[3];
998 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
999 switch (sd->sensor) {
1000 case SENSOR_HV7131R:
1001 sn9c10x = initHv7131;
1002 reg17_19[0] = 0x60;
1003 reg17_19[1] = (mode << 4) | 0x8a;
1004 reg17_19[2] = 0x20;
1005 break;
1006 case SENSOR_OV6650:
1007 sn9c10x = initOv6650;
1008 reg17_19[0] = 0x68;
1009 reg17_19[1] = (mode << 4) | 0x8b;
1010 reg17_19[2] = 0x20;
1011 break;
1012 case SENSOR_OV7630:
1013 if (sd->fr_h_sz == 18) { /* SN9C103 */
1014 sn9c10x = initOv7630_3;
1015 l = sizeof initOv7630_3;
1016 } else
1017 sn9c10x = initOv7630;
1018 reg17_19[0] = 0x68;
1019 reg17_19[1] = (mode << 4) | COMP2;
1020 reg17_19[2] = MCK_INIT1;
1021 break;
1022 case SENSOR_PAS106:
1023 sn9c10x = initPas106;
1024 reg17_19[0] = 0x24; /* 0x28 */
1025 reg17_19[1] = (mode << 4) | COMP1;
1026 reg17_19[2] = MCK_INIT1;
1027 break;
1028 case SENSOR_PAS202:
1029 sn9c10x = initPas202;
1030 reg17_19[0] = mode ? 0x24 : 0x20;
1031 reg17_19[1] = (mode << 4) | 0x89;
1032 reg17_19[2] = 0x20;
1033 break;
1034 case SENSOR_TAS5110:
1035 sn9c10x = initTas5110;
1036 reg17_19[0] = 0x60;
1037 reg17_19[1] = (mode << 4) | 0x86;
1038 reg17_19[2] = 0x2b; /* 0xf3; */
1039 break;
1040 default:
1041 /* case SENSOR_TAS5130CXX: */
1042 sn9c10x = initTas5130;
1043 reg17_19[0] = 0x60;
1044 reg17_19[1] = (mode << 4) | COMP;
1045 reg17_19[2] = mode ? 0x23 : 0x43;
1046 break;
1049 /* Special case for SN9C101/2 with OV 7630 */
1050 /* HDG: is this really necessary we overwrite the values immediately
1051 afterwards with the ones from the template ?? */
1052 if (sd->sensor == SENSOR_OV7630 && sd->fr_h_sz == 12) {
1053 reg01 = 0x06;
1054 reg17 = 0x29;
1055 } else {
1056 reg01 = sn9c10x[0];
1057 reg17 = sn9c10x[0x17 - 1];
1060 /* reg 0x01 bit 2 video transfert on */
1061 reg_w(gspca_dev, 0x01, &reg01, 1);
1062 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1063 reg_w(gspca_dev, 0x17, &reg17, 1);
1064 /* Set the registers from the template */
1065 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
1066 switch (sd->sensor) {
1067 case SENSOR_HV7131R:
1068 i2c_w_vector(gspca_dev, hv7131_sensor_init,
1069 sizeof hv7131_sensor_init);
1070 break;
1071 case SENSOR_OV6650:
1072 i2c_w_vector(gspca_dev, ov6650_sensor_init,
1073 sizeof ov6650_sensor_init);
1074 break;
1075 case SENSOR_OV7630:
1076 i2c_w_vector(gspca_dev, ov7630_sensor_init,
1077 sizeof ov7630_sensor_init);
1078 if (sd->fr_h_sz == 18) { /* SN9C103 */
1079 const __u8 i2c[] = { 0xa0, 0x21, 0x13, 0x80, 0x00,
1080 0x00, 0x00, 0x10 };
1081 i2c_w(gspca_dev, i2c);
1083 break;
1084 case SENSOR_PAS106:
1085 pas106_i2cinit(gspca_dev);
1086 break;
1087 case SENSOR_PAS202:
1088 i2c_w_vector(gspca_dev, pas202_sensor_init,
1089 sizeof pas202_sensor_init);
1090 break;
1091 case SENSOR_TAS5110:
1092 i2c_w_vector(gspca_dev, tas5110_sensor_init,
1093 sizeof tas5110_sensor_init);
1094 break;
1095 default:
1096 /* case SENSOR_TAS5130CXX: */
1097 i2c_w_vector(gspca_dev, tas5130_sensor_init,
1098 sizeof tas5130_sensor_init);
1099 break;
1101 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1102 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1103 /* compression register */
1104 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
1105 /* H_start */
1106 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1107 /* V_START */
1108 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1109 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1110 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1111 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
1112 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1113 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
1114 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1115 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1116 /* Enable video transfert */
1117 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1118 /* Compression */
1119 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
1120 msleep(20);
1122 sd->reg11 = -1;
1124 setgain(gspca_dev);
1125 setbrightness(gspca_dev);
1126 setexposure(gspca_dev);
1127 setfreq(gspca_dev);
1128 setsaturation(gspca_dev);
1129 sethue(gspca_dev);
1130 setcontrast(gspca_dev);
1132 sd->frames_to_drop = 0;
1133 sd->autogain_ignore_frames = 0;
1134 atomic_set(&sd->avg_lum, -1);
1137 static void sd_stopN(struct gspca_dev *gspca_dev)
1139 __u8 ByteSend;
1141 ByteSend = 0x09; /* 0X00 */
1142 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1145 static void sd_stop0(struct gspca_dev *gspca_dev)
1149 static void sd_close(struct gspca_dev *gspca_dev)
1153 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1154 struct gspca_frame *frame, /* target */
1155 unsigned char *data, /* isoc packet */
1156 int len) /* iso packet length */
1158 int i;
1159 struct sd *sd = (struct sd *) gspca_dev;
1161 /* frames start with:
1162 * ff ff 00 c4 c4 96 synchro
1163 * 00 (unknown)
1164 * xx (frame sequence / size / compression)
1165 * (xx) (idem - extra byte for sn9c103)
1166 * ll mm brightness sum inside auto exposure
1167 * ll mm brightness sum outside auto exposure
1168 * (xx xx xx xx xx) audio values for snc103
1170 if (len > 6 && len < 24) {
1171 for (i = 0; i < len - 6; i++) {
1172 if (data[0 + i] == 0xff
1173 && data[1 + i] == 0xff
1174 && data[2 + i] == 0x00
1175 && data[3 + i] == 0xc4
1176 && data[4 + i] == 0xc4
1177 && data[5 + i] == 0x96) { /* start of frame */
1178 int lum = -1;
1179 int pkt_type = LAST_PACKET;
1181 if (len - i < sd->fr_h_sz) {
1182 PDEBUG(D_STREAM, "packet too short to"
1183 " get avg brightness");
1184 } else if (sd->fr_h_sz == 12) {
1185 lum = data[i + 8] + (data[i + 9] << 8);
1186 } else {
1187 lum = data[i + 9] +
1188 (data[i + 10] << 8);
1190 if (lum == 0) {
1191 lum = -1;
1192 sd->frames_to_drop = 2;
1194 atomic_set(&sd->avg_lum, lum);
1196 if (sd->frames_to_drop) {
1197 sd->frames_to_drop--;
1198 pkt_type = DISCARD_PACKET;
1201 frame = gspca_frame_add(gspca_dev, pkt_type,
1202 frame, data, 0);
1203 data += i + sd->fr_h_sz;
1204 len -= i + sd->fr_h_sz;
1205 gspca_frame_add(gspca_dev, FIRST_PACKET,
1206 frame, data, len);
1207 return;
1211 gspca_frame_add(gspca_dev, INTER_PACKET,
1212 frame, data, len);
1215 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1217 struct sd *sd = (struct sd *) gspca_dev;
1219 sd->brightness = val;
1220 if (gspca_dev->streaming)
1221 setbrightness(gspca_dev);
1222 return 0;
1225 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1227 struct sd *sd = (struct sd *) gspca_dev;
1229 *val = sd->brightness;
1230 return 0;
1233 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1235 struct sd *sd = (struct sd *) gspca_dev;
1237 sd->gain = val;
1238 if (gspca_dev->streaming)
1239 setgain(gspca_dev);
1240 return 0;
1243 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1245 struct sd *sd = (struct sd *) gspca_dev;
1247 *val = sd->gain;
1248 return 0;
1251 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1253 struct sd *sd = (struct sd *) gspca_dev;
1255 sd->exposure = val;
1256 if (gspca_dev->streaming)
1257 setexposure(gspca_dev);
1258 return 0;
1261 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1263 struct sd *sd = (struct sd *) gspca_dev;
1265 *val = sd->exposure;
1266 return 0;
1269 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1271 struct sd *sd = (struct sd *) gspca_dev;
1273 sd->autogain = val;
1274 /* when switching to autogain set defaults to make sure
1275 we are on a valid point of the autogain gain /
1276 exposure knee graph, and give this change time to
1277 take effect before doing autogain. */
1278 if (sd->autogain) {
1279 sd->exposure = EXPOSURE_DEF;
1280 sd->gain = GAIN_DEF;
1281 if (gspca_dev->streaming) {
1282 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1283 setexposure(gspca_dev);
1284 setgain(gspca_dev);
1288 return 0;
1291 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1293 struct sd *sd = (struct sd *) gspca_dev;
1295 *val = sd->autogain;
1296 return 0;
1299 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1301 struct sd *sd = (struct sd *) gspca_dev;
1303 sd->freq = val;
1304 if (gspca_dev->streaming)
1305 setfreq(gspca_dev);
1306 return 0;
1309 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1311 struct sd *sd = (struct sd *) gspca_dev;
1313 *val = sd->freq;
1314 return 0;
1317 static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1319 struct sd *sd = (struct sd *) gspca_dev;
1321 sd->saturation = val;
1322 if (gspca_dev->streaming)
1323 setsaturation(gspca_dev);
1324 return 0;
1327 static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1329 struct sd *sd = (struct sd *) gspca_dev;
1331 *val = sd->saturation;
1332 return 0;
1335 static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
1337 struct sd *sd = (struct sd *) gspca_dev;
1339 sd->hue = val;
1340 if (gspca_dev->streaming)
1341 sethue(gspca_dev);
1342 return 0;
1345 static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
1347 struct sd *sd = (struct sd *) gspca_dev;
1349 *val = sd->hue;
1350 return 0;
1353 static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1355 struct sd *sd = (struct sd *) gspca_dev;
1357 sd->contrast = val;
1358 if (gspca_dev->streaming)
1359 setcontrast(gspca_dev);
1360 return 0;
1363 static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1365 struct sd *sd = (struct sd *) gspca_dev;
1367 *val = sd->contrast;
1368 return 0;
1371 static int sd_querymenu(struct gspca_dev *gspca_dev,
1372 struct v4l2_querymenu *menu)
1374 switch (menu->id) {
1375 case V4L2_CID_POWER_LINE_FREQUENCY:
1376 switch (menu->index) {
1377 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1378 strcpy((char *) menu->name, "NoFliker");
1379 return 0;
1380 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1381 strcpy((char *) menu->name, "50 Hz");
1382 return 0;
1383 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1384 strcpy((char *) menu->name, "60 Hz");
1385 return 0;
1387 break;
1389 return -EINVAL;
1392 /* sub-driver description */
1393 static const struct sd_desc sd_desc = {
1394 .name = MODULE_NAME,
1395 .ctrls = sd_ctrls,
1396 .nctrls = ARRAY_SIZE(sd_ctrls),
1397 .config = sd_config,
1398 .open = sd_open,
1399 .start = sd_start,
1400 .stopN = sd_stopN,
1401 .stop0 = sd_stop0,
1402 .close = sd_close,
1403 .pkt_scan = sd_pkt_scan,
1404 .querymenu = sd_querymenu,
1407 /* -- module initialisation -- */
1408 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1409 static __devinitdata struct usb_device_id device_table[] = {
1410 #ifndef CONFIG_USB_SN9C102
1411 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1412 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1413 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1414 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1415 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1416 #endif
1417 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1418 #ifndef CONFIG_USB_SN9C102
1419 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1420 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1421 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1422 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1423 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1424 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1425 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1426 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1427 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1428 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1429 #endif
1432 MODULE_DEVICE_TABLE(usb, device_table);
1434 /* -- device connect -- */
1435 static int sd_probe(struct usb_interface *intf,
1436 const struct usb_device_id *id)
1438 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1439 THIS_MODULE);
1442 static struct usb_driver sd_driver = {
1443 .name = MODULE_NAME,
1444 .id_table = device_table,
1445 .probe = sd_probe,
1446 .disconnect = gspca_disconnect,
1449 /* -- module insert / remove -- */
1450 static int __init sd_mod_init(void)
1452 if (usb_register(&sd_driver) < 0)
1453 return -1;
1454 PDEBUG(D_PROBE, "registered");
1455 return 0;
1457 static void __exit sd_mod_exit(void)
1459 usb_deregister(&sd_driver);
1460 PDEBUG(D_PROBE, "deregistered");
1463 module_init(sd_mod_init);
1464 module_exit(sd_mod_exit);