V4L/DVB (8372): gspca: Small ov6650 fixes.
[linux-2.6.git] / drivers / media / video / gspca / sonixb.c
blobd34d582e5f598f5b4a0354eedb19a6e786d7f220
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 #define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28 static const char version[] = "2.1.8";
30 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32 MODULE_LICENSE("GPL");
34 /* specific webcam descriptor */
35 struct sd {
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 */
40 atomic_t avg_lum;
42 unsigned char gain;
43 unsigned char exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
49 unsigned char fr_h_sz; /* size of frame header */
50 char sensor; /* Type of image sensor chip */
51 #define SENSOR_HV7131R 0
52 #define SENSOR_OV6650 1
53 #define SENSOR_OV7630 2
54 #define SENSOR_OV7630_3 3
55 #define SENSOR_PAS106 4
56 #define SENSOR_PAS202 5
57 #define SENSOR_TAS5110 6
58 #define SENSOR_TAS5130CXX 7
59 char sensor_has_gain;
60 __u8 sensor_addr;
63 #define COMP2 0x8f
64 #define COMP 0xc7 /* 0x87 //0x07 */
65 #define COMP1 0xc9 /* 0x89 //0x09 */
67 #define MCK_INIT 0x63
68 #define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
70 #define SYS_CLK 0x04
72 /* We calculate the autogain at the end of the transfer of a frame, at this
73 moment a frame with the old settings is being transmitted, and a frame is
74 being captured with the old settings. So if we adjust the autogain we must
75 ignore atleast the 2 next frames for the new settings to come into effect
76 before doing any other adjustments */
77 #define AUTOGAIN_IGNORE_FRAMES 3
78 #define AUTOGAIN_DEADZONE 1000
79 #define DESIRED_AVG_LUM 7000
81 /* V4L2 controls supported by the driver */
82 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
84 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
85 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
86 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
87 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
88 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
89 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
90 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
91 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
93 static struct ctrl sd_ctrls[] = {
96 .id = V4L2_CID_BRIGHTNESS,
97 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Brightness",
99 .minimum = 0,
100 .maximum = 255,
101 .step = 1,
102 #define BRIGHTNESS_DEF 127
103 .default_value = BRIGHTNESS_DEF,
105 .set = sd_setbrightness,
106 .get = sd_getbrightness,
110 .id = V4L2_CID_GAIN,
111 .type = V4L2_CTRL_TYPE_INTEGER,
112 .name = "Gain",
113 .minimum = 0,
114 .maximum = 255,
115 .step = 1,
116 #define GAIN_DEF 127
117 #define GAIN_KNEE 200
118 .default_value = GAIN_DEF,
120 .set = sd_setgain,
121 .get = sd_getgain,
125 .id = V4L2_CID_EXPOSURE,
126 .type = V4L2_CTRL_TYPE_INTEGER,
127 .name = "Exposure",
128 #define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
129 #define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
130 .minimum = 0,
131 .maximum = 255,
132 .step = 1,
133 .default_value = EXPOSURE_DEF,
134 .flags = 0,
136 .set = sd_setexposure,
137 .get = sd_getexposure,
141 .id = V4L2_CID_AUTOGAIN,
142 .type = V4L2_CTRL_TYPE_BOOLEAN,
143 .name = "Automatic Gain (and Exposure)",
144 .minimum = 0,
145 .maximum = 1,
146 .step = 1,
147 #define AUTOGAIN_DEF 1
148 .default_value = AUTOGAIN_DEF,
149 .flags = 0,
151 .set = sd_setautogain,
152 .get = sd_getautogain,
156 .id = V4L2_CID_POWER_LINE_FREQUENCY,
157 .type = V4L2_CTRL_TYPE_MENU,
158 .name = "Light frequency filter",
159 .minimum = 0,
160 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
161 .step = 1,
162 #define FREQ_DEF 1
163 .default_value = FREQ_DEF,
165 .set = sd_setfreq,
166 .get = sd_getfreq,
170 static struct v4l2_pix_format vga_mode[] = {
171 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
172 .bytesperline = 160,
173 .sizeimage = 160 * 120,
174 .colorspace = V4L2_COLORSPACE_SRGB,
175 .priv = 2},
176 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
177 .bytesperline = 320,
178 .sizeimage = 320 * 240,
179 .colorspace = V4L2_COLORSPACE_SRGB,
180 .priv = 1},
181 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
182 .bytesperline = 640,
183 .sizeimage = 640 * 480,
184 .colorspace = V4L2_COLORSPACE_SRGB,
185 .priv = 0},
187 static struct v4l2_pix_format sif_mode[] = {
188 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
189 .bytesperline = 176,
190 .sizeimage = 176 * 144,
191 .colorspace = V4L2_COLORSPACE_SRGB,
192 .priv = 1},
193 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
194 .bytesperline = 352,
195 .sizeimage = 352 * 288,
196 .colorspace = V4L2_COLORSPACE_SRGB,
197 .priv = 0},
200 static const __u8 probe_ov7630[] = {0x08, 0x44};
202 static const __u8 initHv7131[] = {
203 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
204 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
206 0x28, 0x1e, 0x60, 0x8a, 0x20,
207 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
209 static const __u8 hv7131_sensor_init[][8] = {
210 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
211 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
212 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
213 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
214 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
216 static const __u8 initOv6650[] = {
217 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
218 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
220 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
222 static const __u8 ov6650_sensor_init[][8] =
224 /* Bright, contrast, etc are set througth SCBB interface.
225 * AVCAP on win2 do not send any data on this controls. */
226 /* Anyway, some registers appears to alter bright and constrat */
228 /* Reset sensor */
229 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
230 /* Set clock register 0x11 low nibble is clock divider */
231 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
232 /* Next some unknown stuff */
233 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
234 /* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
235 * THIS SET GREEN SCREEN
236 * (pixels could be innverted in decode kind of "brg",
237 * but blue wont be there. Avoid this data ... */
238 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
239 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
240 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
241 /* Enable rgb brightness control */
242 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
243 /* HDG: Note windows uses the line below, which sets both register 0x60
244 and 0x61 I believe these registers of the ov6650 are identical as
245 those of the ov7630, because if this is true the windows settings
246 add a bit additional red gain and a lot additional blue gain, which
247 matches my findings that the windows settings make blue much too
248 blue and red a little too red.
249 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
250 /* Some more unknown stuff */
251 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
252 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
255 static const __u8 initOv7630[] = {
256 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
257 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
258 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
259 0x28, 0x1e, /* H & V sizes r15 .. r16 */
260 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
261 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
263 static const __u8 initOv7630_3[] = {
264 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
265 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
266 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
267 0x28, 0x1e, /* H & V sizes r15 .. r16 */
268 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
269 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
270 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
271 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
273 static const __u8 ov7630_sensor_init_com[][8] = {
274 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
275 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
276 /* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
277 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
278 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
279 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
280 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
281 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
282 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
283 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
284 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
285 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
286 /* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
287 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
288 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
289 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
290 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
291 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
292 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
294 static const __u8 ov7630_sensor_init[][8] = {
295 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
296 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
297 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
298 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
299 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
301 static const __u8 ov7630_sensor_init_3[][8] = {
302 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
303 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
306 static const __u8 initPas106[] = {
307 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
308 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
310 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
311 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
313 /* compression 0x86 mckinit1 0x2b */
314 static const __u8 pas106_data[][2] = {
315 {0x02, 0x04}, /* Pixel Clock Divider 6 */
316 {0x03, 0x13}, /* Frame Time MSB */
317 /* {0x03, 0x12}, * Frame Time MSB */
318 {0x04, 0x06}, /* Frame Time LSB */
319 /* {0x04, 0x05}, * Frame Time LSB */
320 {0x05, 0x65}, /* Shutter Time Line Offset */
321 /* {0x05, 0x6d}, * Shutter Time Line Offset */
322 /* {0x06, 0xb1}, * Shutter Time Pixel Offset */
323 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
324 {0x07, 0xc1}, /* Black Level Subtract Sign */
325 /* {0x07, 0x00}, * Black Level Subtract Sign */
326 {0x08, 0x06}, /* Black Level Subtract Level */
327 {0x08, 0x06}, /* Black Level Subtract Level */
328 /* {0x08, 0x01}, * Black Level Subtract Level */
329 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
330 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
331 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
332 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
333 {0x0d, 0x00}, /* Color GainH Pixel */
334 {0x0e, 0x0e}, /* Global Gain */
335 {0x0f, 0x00}, /* Contrast */
336 {0x10, 0x06}, /* H&V synchro polarity */
337 {0x11, 0x06}, /* ?default */
338 {0x12, 0x06}, /* DAC scale */
339 {0x14, 0x02}, /* ?default */
340 {0x13, 0x01}, /* Validate Settings */
342 static const __u8 initPas202[] = {
343 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
344 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
346 0x28, 0x1e, 0x28, 0x89, 0x30,
347 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
349 static const __u8 pas202_sensor_init[][8] = {
350 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
351 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
352 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
353 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
354 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
355 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
356 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
357 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
358 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
359 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
360 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
361 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
363 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
364 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
365 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
366 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
367 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
368 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
369 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
370 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
373 static const __u8 initTas5110[] = {
374 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
375 0x00, 0x00,
376 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
377 0x16, 0x12, 0x60, 0x86, 0x2b,
378 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
380 static const __u8 tas5110_sensor_init[][8] = {
381 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
382 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
383 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
386 static const __u8 initTas5130[] = {
387 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
388 0x00, 0x00,
389 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
390 0x28, 0x1e, 0x60, COMP, MCK_INIT,
391 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
393 static const __u8 tas5130_sensor_init[][8] = {
394 /* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
395 * shutter 0x47 short exposure? */
396 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
397 /* shutter 0x01 long exposure */
398 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
401 /* get one byte in gspca_dev->usb_buf */
402 static void reg_r(struct gspca_dev *gspca_dev,
403 __u16 value)
405 usb_control_msg(gspca_dev->dev,
406 usb_rcvctrlpipe(gspca_dev->dev, 0),
407 0, /* request */
408 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
409 value,
410 0, /* index */
411 gspca_dev->usb_buf, 1,
412 500);
415 static void reg_w(struct gspca_dev *gspca_dev,
416 __u16 value,
417 const __u8 *buffer,
418 int len)
420 #ifdef CONFIG_VIDEO_ADV_DEBUG
421 if (len > sizeof gspca_dev->usb_buf) {
422 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
423 return;
425 #endif
426 memcpy(gspca_dev->usb_buf, buffer, len);
427 usb_control_msg(gspca_dev->dev,
428 usb_sndctrlpipe(gspca_dev->dev, 0),
429 0x08, /* request */
430 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
431 value,
432 0, /* index */
433 gspca_dev->usb_buf, len,
434 500);
437 static void reg_w_big(struct gspca_dev *gspca_dev,
438 __u16 value,
439 const __u8 *buffer,
440 int len)
442 __u8 *tmpbuf;
444 tmpbuf = kmalloc(len, GFP_KERNEL);
445 memcpy(tmpbuf, buffer, len);
446 usb_control_msg(gspca_dev->dev,
447 usb_sndctrlpipe(gspca_dev->dev, 0),
448 0x08, /* request */
449 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
450 value,
451 0, /* index */
452 tmpbuf, len,
453 500);
454 kfree(tmpbuf);
457 static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
459 int retry = 60;
461 /* is i2c ready */
462 reg_w(gspca_dev, 0x08, buffer, 8);
463 while (retry--) {
464 msleep(10);
465 reg_r(gspca_dev, 0x08);
466 if (gspca_dev->usb_buf[0] & 0x04) {
467 if (gspca_dev->usb_buf[0] & 0x08)
468 return -1;
469 return 0;
472 return -1;
475 static void i2c_w_vector(struct gspca_dev *gspca_dev,
476 const __u8 buffer[][8], int len)
478 for (;;) {
479 reg_w(gspca_dev, 0x08, *buffer, 8);
480 len -= 8;
481 if (len <= 0)
482 break;
483 buffer++;
487 static void setbrightness(struct gspca_dev *gspca_dev)
489 struct sd *sd = (struct sd *) gspca_dev;
490 __u8 value;
492 switch (sd->sensor) {
493 case SENSOR_OV6650:
494 case SENSOR_OV7630_3:
495 case SENSOR_OV7630: {
496 __u8 i2cOV[] =
497 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
499 /* change reg 0x06 */
500 i2cOV[1] = sd->sensor_addr;
501 i2cOV[3] = sd->brightness;
502 if (i2c_w(gspca_dev, i2cOV) < 0)
503 goto err;
504 break;
506 case SENSOR_PAS106: {
507 __u8 i2c1[] =
508 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
510 i2c1[3] = sd->brightness >> 3;
511 i2c1[2] = 0x0e;
512 if (i2c_w(gspca_dev, i2c1) < 0)
513 goto err;
514 i2c1[3] = 0x01;
515 i2c1[2] = 0x13;
516 if (i2c_w(gspca_dev, i2c1) < 0)
517 goto err;
518 break;
520 case SENSOR_PAS202: {
521 /* __u8 i2cpexpo1[] =
522 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
523 __u8 i2cpexpo[] =
524 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
525 __u8 i2cp202[] =
526 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
527 static __u8 i2cpdoit[] =
528 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
530 /* change reg 0x10 */
531 i2cpexpo[4] = 0xff - sd->brightness;
532 /* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
533 goto err; */
534 /* if(i2c_w(gspca_dev,i2cpdoit) < 0)
535 goto err; */
536 if (i2c_w(gspca_dev, i2cpexpo) < 0)
537 goto err;
538 if (i2c_w(gspca_dev, i2cpdoit) < 0)
539 goto err;
540 i2cp202[3] = sd->brightness >> 3;
541 if (i2c_w(gspca_dev, i2cp202) < 0)
542 goto err;
543 if (i2c_w(gspca_dev, i2cpdoit) < 0)
544 goto err;
545 break;
547 case SENSOR_TAS5130CXX: {
548 __u8 i2c[] =
549 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
551 value = 0xff - sd->brightness;
552 i2c[4] = value;
553 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
554 if (i2c_w(gspca_dev, i2c) < 0)
555 goto err;
556 break;
558 case SENSOR_TAS5110:
559 /* FIXME figure out howto control brightness on TAS5110 */
560 break;
562 return;
563 err:
564 PDEBUG(D_ERR, "i2c error brightness");
567 static void setsensorgain(struct gspca_dev *gspca_dev)
569 struct sd *sd = (struct sd *) gspca_dev;
570 unsigned char gain = sd->gain;
572 switch (sd->sensor) {
574 case SENSOR_TAS5110: {
575 __u8 i2c[] =
576 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
578 i2c[4] = 255 - gain;
579 if (i2c_w(gspca_dev, i2c) < 0)
580 goto err;
581 break;
584 case SENSOR_OV6650:
585 gain >>= 1;
586 /* fall thru */
587 case SENSOR_OV7630_3: {
588 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
590 i2c[1] = sd->sensor_addr;
591 i2c[3] = gain >> 2;
592 if (i2c_w(gspca_dev, i2c) < 0)
593 goto err;
594 break;
597 return;
598 err:
599 PDEBUG(D_ERR, "i2c error gain");
602 static void setgain(struct gspca_dev *gspca_dev)
604 struct sd *sd = (struct sd *) gspca_dev;
605 __u8 gain;
606 __u8 rgb_value;
608 gain = sd->gain >> 4;
610 /* red and blue gain */
611 rgb_value = gain << 4 | gain;
612 reg_w(gspca_dev, 0x10, &rgb_value, 1);
613 /* green gain */
614 rgb_value = gain;
615 reg_w(gspca_dev, 0x11, &rgb_value, 1);
617 if (sd->sensor_has_gain)
618 setsensorgain(gspca_dev);
621 static void setexposure(struct gspca_dev *gspca_dev)
623 struct sd *sd = (struct sd *) gspca_dev;
625 switch (sd->sensor) {
626 case SENSOR_TAS5110: {
627 __u8 reg;
629 /* register 19's high nibble contains the sn9c10x clock divider
630 The high nibble configures the no fps according to the
631 formula: 60 / high_nibble. With a maximum of 30 fps */
632 reg = 120 * sd->exposure / 1000;
633 if (reg < 2)
634 reg = 2;
635 else if (reg > 15)
636 reg = 15;
637 reg = (reg << 4) | 0x0b;
638 reg_w(gspca_dev, 0x19, &reg, 1);
639 break;
641 case SENSOR_OV6650:
642 case SENSOR_OV7630_3: {
643 /* The ov6650 / ov7630 have 2 registers which both influence
644 exposure, register 11, whose low nibble sets the nr off fps
645 according to: fps = 30 / (low_nibble + 1)
647 The fps configures the maximum exposure setting, but it is
648 possible to use less exposure then what the fps maximum
649 allows by setting register 10. register 10 configures the
650 actual exposure as quotient of the full exposure, with 0
651 being no exposure at all (not very usefull) and reg10_max
652 being max exposure possible at that framerate.
654 The code maps our 0 - 510 ms exposure ctrl to these 2
655 registers, trying to keep fps as high as possible.
657 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
658 int reg10, reg11;
659 /* ov6645 datasheet says reg10_max is 9a, but that uses
660 tline * 2 * reg10 as formula for calculating texpo, the
661 ov6650 probably uses the same formula as the 7730 which uses
662 tline * 4 * reg10, which explains why the reg10max we've
663 found experimentally for the ov6650 is exactly half that of
664 the ov6645. The ov7630 datasheet says the max is 0x41. */
665 const int reg10_max = (sd->sensor == SENSOR_OV6650)
666 ? 0x4d : 0x41;
668 reg11 = (60 * sd->exposure + 999) / 1000;
669 if (reg11 < 1)
670 reg11 = 1;
671 else if (reg11 > 16)
672 reg11 = 16;
674 /* frame exposure time in ms = 1000 * reg11 / 30 ->
675 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
676 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
678 /* Don't allow this to get below 10 when using autogain, the
679 steps become very large (relatively) when below 10 causing
680 the image to oscilate from much too dark, to much too bright
681 and back again. */
682 if (sd->autogain && reg10 < 10)
683 reg10 = 10;
684 else if (reg10 > reg10_max)
685 reg10 = reg10_max;
687 /* Write reg 10 and reg11 low nibble */
688 i2c[1] = sd->sensor_addr;
689 i2c[3] = reg10;
690 i2c[4] |= reg11 - 1;
691 if (sd->sensor == SENSOR_OV7630_3) {
692 __u8 reg76 = reg10 & 0x03;
693 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
694 0x00, 0x00, 0x00, 0x10};
695 reg10 >>= 2;
696 i2c_reg76[3] = reg76;
697 if (i2c_w(gspca_dev, i2c_reg76) < 0)
698 PDEBUG(D_ERR, "i2c error exposure");
700 if (i2c_w(gspca_dev, i2c) < 0)
701 PDEBUG(D_ERR, "i2c error exposure");
702 break;
707 static void setfreq(struct gspca_dev *gspca_dev)
709 struct sd *sd = (struct sd *) gspca_dev;
711 switch (sd->sensor) {
712 case SENSOR_OV6650:
713 case SENSOR_OV7630_3: {
714 /* Framerate adjust register for artificial light 50 hz flicker
715 compensation, identical to ov6630 0x2b register, see ov6630
716 datasheet.
717 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
718 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
719 switch (sd->freq) {
720 default:
721 /* case 0: * no filter*/
722 /* case 2: * 60 hz */
723 i2c[3] = 0;
724 break;
725 case 1: /* 50 hz */
726 i2c[3] = (sd->sensor == SENSOR_OV6650)
727 ? 0x4f : 0x8a;
728 break;
730 i2c[1] = sd->sensor_addr;
731 if (i2c_w(gspca_dev, i2c) < 0)
732 PDEBUG(D_ERR, "i2c error setfreq");
733 break;
739 static void do_autogain(struct gspca_dev *gspca_dev)
741 struct sd *sd = (struct sd *) gspca_dev;
742 int avg_lum = atomic_read(&sd->avg_lum);
744 if (avg_lum == -1)
745 return;
747 if (sd->autogain_ignore_frames > 0)
748 sd->autogain_ignore_frames--;
749 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
750 sd->brightness * DESIRED_AVG_LUM / 127,
751 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
752 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
753 (int)sd->gain, (int)sd->exposure);
754 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
758 /* this function is called at probe time */
759 static int sd_config(struct gspca_dev *gspca_dev,
760 const struct usb_device_id *id)
762 struct sd *sd = (struct sd *) gspca_dev;
763 struct cam *cam;
764 __u16 product;
765 int sif = 0;
767 /* nctrls depends upon the sensor, so we use a per cam copy */
768 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
769 gspca_dev->sd_desc = &sd->sd_desc;
771 sd->fr_h_sz = 12; /* default size of the frame header */
772 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
773 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
774 sd->freq = FREQ_DEF;
776 product = id->idProduct;
777 /* switch (id->idVendor) { */
778 /* case 0x0c45: * Sonix */
779 switch (product) {
780 case 0x6001: /* SN9C102 */
781 case 0x6005: /* SN9C101 */
782 case 0x6007: /* SN9C101 */
783 sd->sensor = SENSOR_TAS5110;
784 sd->sensor_has_gain = 1;
785 sd->sd_desc.nctrls = 4;
786 sd->sd_desc.dq_callback = do_autogain;
787 sif = 1;
788 break;
789 case 0x6009: /* SN9C101 */
790 case 0x600d: /* SN9C101 */
791 case 0x6029: /* SN9C101 */
792 sd->sensor = SENSOR_PAS106;
793 sif = 1;
794 break;
795 case 0x6011: /* SN9C101 - SN9C101G */
796 sd->sensor = SENSOR_OV6650;
797 sd->sensor_has_gain = 1;
798 sd->sensor_addr = 0x60;
799 sd->sd_desc.nctrls = 5;
800 sd->sd_desc.dq_callback = do_autogain;
801 sif = 1;
802 break;
803 case 0x6019: /* SN9C101 */
804 case 0x602c: /* SN9C102 */
805 case 0x602e: /* SN9C102 */
806 sd->sensor = SENSOR_OV7630;
807 sd->sensor_addr = 0x21;
808 break;
809 case 0x60b0: /* SN9C103 */
810 sd->sensor = SENSOR_OV7630_3;
811 sd->sensor_addr = 0x21;
812 sd->fr_h_sz = 18; /* size of frame header */
813 sd->sensor_has_gain = 1;
814 sd->sd_desc.nctrls = 5;
815 sd->sd_desc.dq_callback = do_autogain;
816 sd->autogain = 0;
817 break;
818 case 0x6024: /* SN9C102 */
819 case 0x6025: /* SN9C102 */
820 sd->sensor = SENSOR_TAS5130CXX;
821 break;
822 case 0x6028: /* SN9C102 */
823 sd->sensor = SENSOR_PAS202;
824 break;
825 case 0x602d: /* SN9C102 */
826 sd->sensor = SENSOR_HV7131R;
827 break;
828 case 0x60af: /* SN9C103 */
829 sd->sensor = SENSOR_PAS202;
830 sd->fr_h_sz = 18; /* size of frame header (?) */
831 break;
833 /* break; */
834 /* } */
836 cam = &gspca_dev->cam;
837 cam->dev_name = (char *) id->driver_info;
838 cam->epaddr = 0x01;
839 if (!sif) {
840 cam->cam_mode = vga_mode;
841 cam->nmodes = ARRAY_SIZE(vga_mode);
842 if (sd->sensor == SENSOR_OV7630_3) {
843 /* We only have 320x240 & 640x480 */
844 cam->cam_mode++;
845 cam->nmodes--;
847 } else {
848 cam->cam_mode = sif_mode;
849 cam->nmodes = ARRAY_SIZE(sif_mode);
851 sd->brightness = BRIGHTNESS_DEF;
852 sd->gain = GAIN_DEF;
853 sd->exposure = EXPOSURE_DEF;
854 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
855 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
856 return 0;
859 /* this function is called at open time */
860 static int sd_open(struct gspca_dev *gspca_dev)
862 reg_r(gspca_dev, 0x00);
863 if (gspca_dev->usb_buf[0] != 0x10)
864 return -ENODEV;
865 return 0;
868 static void pas106_i2cinit(struct gspca_dev *gspca_dev)
870 int i;
871 const __u8 *data;
872 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
874 i = ARRAY_SIZE(pas106_data);
875 data = pas106_data[0];
876 while (--i >= 0) {
877 memcpy(&i2c1[2], data, 2);
878 /* copy 2 bytes from the template */
879 if (i2c_w(gspca_dev, i2c1) < 0)
880 PDEBUG(D_ERR, "i2c error pas106");
881 data += 2;
885 /* -- start the camera -- */
886 static void sd_start(struct gspca_dev *gspca_dev)
888 struct sd *sd = (struct sd *) gspca_dev;
889 int mode, l;
890 const __u8 *sn9c10x;
891 __u8 reg01, reg17;
892 __u8 reg17_19[3];
894 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
895 switch (sd->sensor) {
896 case SENSOR_HV7131R:
897 sn9c10x = initHv7131;
898 reg17_19[0] = 0x60;
899 reg17_19[1] = (mode << 4) | 0x8a;
900 reg17_19[2] = 0x20;
901 break;
902 case SENSOR_OV6650:
903 sn9c10x = initOv6650;
904 reg17_19[0] = 0x68;
905 reg17_19[1] = (mode << 4) | 0x8b;
906 reg17_19[2] = 0x20;
907 break;
908 case SENSOR_OV7630:
909 sn9c10x = initOv7630;
910 reg17_19[0] = 0x68;
911 reg17_19[1] = (mode << 4) | COMP2;
912 reg17_19[2] = MCK_INIT1;
913 break;
914 case SENSOR_OV7630_3:
915 sn9c10x = initOv7630_3;
916 reg17_19[0] = 0x68;
917 reg17_19[1] = (mode << 4) | COMP2;
918 reg17_19[2] = MCK_INIT1;
919 break;
920 case SENSOR_PAS106:
921 sn9c10x = initPas106;
922 reg17_19[0] = 0x24; /* 0x28 */
923 reg17_19[1] = (mode << 4) | COMP1;
924 reg17_19[2] = MCK_INIT1;
925 break;
926 case SENSOR_PAS202:
927 sn9c10x = initPas202;
928 reg17_19[0] = mode ? 0x24 : 0x20;
929 reg17_19[1] = (mode << 4) | 0x89;
930 reg17_19[2] = 0x20;
931 break;
932 case SENSOR_TAS5110:
933 sn9c10x = initTas5110;
934 reg17_19[0] = 0x60;
935 reg17_19[1] = (mode << 4) | 0x86;
936 reg17_19[2] = 0x2b; /* 0xf3; */
937 break;
938 default:
939 /* case SENSOR_TAS5130CXX: */
940 sn9c10x = initTas5130;
941 reg17_19[0] = 0x60;
942 reg17_19[1] = (mode << 4) | COMP;
943 reg17_19[2] = mode ? 0x23 : 0x43;
944 break;
946 switch (sd->sensor) {
947 case SENSOR_OV7630:
948 reg01 = 0x06;
949 reg17 = 0x29;
950 l = sizeof initOv7630;
951 break;
952 case SENSOR_OV7630_3:
953 reg01 = 0x44;
954 reg17 = 0x68;
955 l = sizeof initOv7630_3;
956 break;
957 default:
958 reg01 = sn9c10x[0];
959 reg17 = sn9c10x[0x17 - 1];
960 l = 0x1f;
961 break;
964 /* reg 0x01 bit 2 video transfert on */
965 reg_w(gspca_dev, 0x01, &reg01, 1);
966 /* reg 0x17 SensorClk enable inv Clk 0x60 */
967 reg_w(gspca_dev, 0x17, &reg17, 1);
968 /*fixme: for ov7630 102
969 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
970 /* Set the registers from the template */
971 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
972 switch (sd->sensor) {
973 case SENSOR_HV7131R:
974 i2c_w_vector(gspca_dev, hv7131_sensor_init,
975 sizeof hv7131_sensor_init);
976 break;
977 case SENSOR_OV6650:
978 i2c_w_vector(gspca_dev, ov6650_sensor_init,
979 sizeof ov6650_sensor_init);
980 break;
981 case SENSOR_OV7630:
982 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
983 sizeof ov7630_sensor_init_com);
984 msleep(200);
985 i2c_w_vector(gspca_dev, ov7630_sensor_init,
986 sizeof ov7630_sensor_init);
987 break;
988 case SENSOR_OV7630_3:
989 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
990 sizeof ov7630_sensor_init_com);
991 msleep(200);
992 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
993 break;
994 case SENSOR_PAS106:
995 pas106_i2cinit(gspca_dev);
996 break;
997 case SENSOR_PAS202:
998 i2c_w_vector(gspca_dev, pas202_sensor_init,
999 sizeof pas202_sensor_init);
1000 break;
1001 case SENSOR_TAS5110:
1002 i2c_w_vector(gspca_dev, tas5110_sensor_init,
1003 sizeof tas5110_sensor_init);
1004 break;
1005 default:
1006 /* case SENSOR_TAS5130CXX: */
1007 i2c_w_vector(gspca_dev, tas5130_sensor_init,
1008 sizeof tas5130_sensor_init);
1009 break;
1011 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1012 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1013 /* compression register */
1014 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
1015 /* H_start */
1016 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1017 /* V_START */
1018 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1019 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1020 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1021 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
1022 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1023 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
1024 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1025 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1026 /* Enable video transfert */
1027 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1028 /* Compression */
1029 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
1030 msleep(20);
1032 setgain(gspca_dev);
1033 setbrightness(gspca_dev);
1034 setexposure(gspca_dev);
1035 setfreq(gspca_dev);
1037 sd->autogain_ignore_frames = 0;
1038 atomic_set(&sd->avg_lum, -1);
1041 static void sd_stopN(struct gspca_dev *gspca_dev)
1043 __u8 ByteSend;
1045 ByteSend = 0x09; /* 0X00 */
1046 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1049 static void sd_stop0(struct gspca_dev *gspca_dev)
1053 static void sd_close(struct gspca_dev *gspca_dev)
1057 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1058 struct gspca_frame *frame, /* target */
1059 unsigned char *data, /* isoc packet */
1060 int len) /* iso packet length */
1062 int i;
1063 struct sd *sd = (struct sd *) gspca_dev;
1065 /* frames start with:
1066 * ff ff 00 c4 c4 96 synchro
1067 * 00 (unknown)
1068 * xx (frame sequence / size / compression)
1069 * (xx) (idem - extra byte for sn9c103)
1070 * ll mm brightness sum inside auto exposure
1071 * ll mm brightness sum outside auto exposure
1072 * (xx xx xx xx xx) audio values for snc103
1074 if (len > 6 && len < 24) {
1075 for (i = 0; i < len - 6; i++) {
1076 if (data[0 + i] == 0xff
1077 && data[1 + i] == 0xff
1078 && data[2 + i] == 0x00
1079 && data[3 + i] == 0xc4
1080 && data[4 + i] == 0xc4
1081 && data[5 + i] == 0x96) { /* start of frame */
1082 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1083 frame, data, 0);
1084 if (len - i < sd->fr_h_sz) {
1085 atomic_set(&sd->avg_lum, -1);
1086 PDEBUG(D_STREAM, "packet too short to"
1087 " get avg brightness");
1088 } else if (sd->fr_h_sz == 12) {
1089 atomic_set(&sd->avg_lum,
1090 data[i + 8] +
1091 (data[i + 9] << 8));
1092 } else {
1093 atomic_set(&sd->avg_lum,
1094 data[i + 9] +
1095 (data[i + 10] << 8));
1097 data += i + sd->fr_h_sz;
1098 len -= i + sd->fr_h_sz;
1099 gspca_frame_add(gspca_dev, FIRST_PACKET,
1100 frame, data, len);
1101 return;
1105 gspca_frame_add(gspca_dev, INTER_PACKET,
1106 frame, data, len);
1109 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1111 struct sd *sd = (struct sd *) gspca_dev;
1113 sd->brightness = val;
1114 if (gspca_dev->streaming)
1115 setbrightness(gspca_dev);
1116 return 0;
1119 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1121 struct sd *sd = (struct sd *) gspca_dev;
1123 *val = sd->brightness;
1124 return 0;
1127 static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1129 struct sd *sd = (struct sd *) gspca_dev;
1131 sd->gain = val;
1132 if (gspca_dev->streaming)
1133 setgain(gspca_dev);
1134 return 0;
1137 static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1139 struct sd *sd = (struct sd *) gspca_dev;
1141 *val = sd->gain;
1142 return 0;
1145 static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1147 struct sd *sd = (struct sd *) gspca_dev;
1149 sd->exposure = val;
1150 if (gspca_dev->streaming)
1151 setexposure(gspca_dev);
1152 return 0;
1155 static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1157 struct sd *sd = (struct sd *) gspca_dev;
1159 *val = sd->exposure;
1160 return 0;
1163 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1165 struct sd *sd = (struct sd *) gspca_dev;
1167 sd->autogain = val;
1168 /* when switching to autogain set defaults to make sure
1169 we are on a valid point of the autogain gain /
1170 exposure knee graph, and give this change time to
1171 take effect before doing autogain. */
1172 if (sd->autogain) {
1173 sd->exposure = EXPOSURE_DEF;
1174 sd->gain = GAIN_DEF;
1175 if (gspca_dev->streaming) {
1176 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1177 setexposure(gspca_dev);
1178 setgain(gspca_dev);
1182 return 0;
1185 static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1187 struct sd *sd = (struct sd *) gspca_dev;
1189 *val = sd->autogain;
1190 return 0;
1193 static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1195 struct sd *sd = (struct sd *) gspca_dev;
1197 sd->freq = val;
1198 if (gspca_dev->streaming)
1199 setfreq(gspca_dev);
1200 return 0;
1203 static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1205 struct sd *sd = (struct sd *) gspca_dev;
1207 *val = sd->freq;
1208 return 0;
1211 static int sd_querymenu(struct gspca_dev *gspca_dev,
1212 struct v4l2_querymenu *menu)
1214 switch (menu->id) {
1215 case V4L2_CID_POWER_LINE_FREQUENCY:
1216 switch (menu->index) {
1217 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1218 strcpy((char *) menu->name, "NoFliker");
1219 return 0;
1220 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1221 strcpy((char *) menu->name, "50 Hz");
1222 return 0;
1223 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1224 strcpy((char *) menu->name, "60 Hz");
1225 return 0;
1227 break;
1229 return -EINVAL;
1232 /* sub-driver description */
1233 static const struct sd_desc sd_desc = {
1234 .name = MODULE_NAME,
1235 .ctrls = sd_ctrls,
1236 .nctrls = ARRAY_SIZE(sd_ctrls),
1237 .config = sd_config,
1238 .open = sd_open,
1239 .start = sd_start,
1240 .stopN = sd_stopN,
1241 .stop0 = sd_stop0,
1242 .close = sd_close,
1243 .pkt_scan = sd_pkt_scan,
1244 .querymenu = sd_querymenu,
1247 /* -- module initialisation -- */
1248 #define DVNM(name) .driver_info = (kernel_ulong_t) name
1249 static __devinitdata struct usb_device_id device_table[] = {
1250 #ifndef CONFIG_USB_SN9C102
1251 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1252 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1253 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1254 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1255 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1256 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1257 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1258 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1259 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1260 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1261 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1262 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1263 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1264 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1265 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1266 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1267 #endif
1270 MODULE_DEVICE_TABLE(usb, device_table);
1272 /* -- device connect -- */
1273 static int sd_probe(struct usb_interface *intf,
1274 const struct usb_device_id *id)
1276 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1277 THIS_MODULE);
1280 static struct usb_driver sd_driver = {
1281 .name = MODULE_NAME,
1282 .id_table = device_table,
1283 .probe = sd_probe,
1284 .disconnect = gspca_disconnect,
1287 /* -- module insert / remove -- */
1288 static int __init sd_mod_init(void)
1290 if (usb_register(&sd_driver) < 0)
1291 return -1;
1292 PDEBUG(D_PROBE, "v%s registered", version);
1293 return 0;
1295 static void __exit sd_mod_exit(void)
1297 usb_deregister(&sd_driver);
1298 PDEBUG(D_PROBE, "deregistered");
1301 module_init(sd_mod_init);
1302 module_exit(sd_mod_exit);