aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sonixb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sonixb.c')
-rw-r--r--drivers/media/video/gspca/sonixb.c1278
1 files changed, 1278 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
new file mode 100644
index 000000000000..6c69bc7778fc
--- /dev/null
+++ b/drivers/media/video/gspca/sonixb.c
@@ -0,0 +1,1278 @@
1/*
2 * sonix sn9c102 (bayer) library
3 * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
4 * Add Pas106 Stefano Mozzi (C) 2004
5 *
6 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
7 *
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.
12 *
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.
17 *
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
21 */
22
23/* Some documentation on known sonixb registers:
24
25Reg Use
260x10 high nibble red gain low nibble blue gain
270x11 low nibble green gain
280x12 hstart
290x13 vstart
300x15 hsize (hsize = register-value * 16)
310x16 vsize (vsize = register-value * 16)
320x17 bit 0 toggle compression quality (according to sn9c102 driver)
330x18 bit 7 enables compression, bit 4-5 set image down scaling:
34 00 scale 1, 01 scale 1/2, 10, scale 1/4
350x19 high-nibble is sensor clock divider, changes exposure on sensors which
36 use a clock generated by the bridge. Some sensors have their own clock.
370x1c auto_exposure area (for avg_lum) startx (startx = register-value * 32)
380x1d auto_exposure area (for avg_lum) starty (starty = register-value * 32)
390x1e auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
400x1f auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
41*/
42
43#define MODULE_NAME "sonixb"
44
45#include "gspca.h"
46
47MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
48MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
49MODULE_LICENSE("GPL");
50
51/* specific webcam descriptor */
52struct sd {
53 struct gspca_dev gspca_dev; /* !! must be the first item */
54 atomic_t avg_lum;
55 int prev_avg_lum;
56
57 unsigned char gain;
58 unsigned char exposure;
59 unsigned char brightness;
60 unsigned char autogain;
61 unsigned char autogain_ignore_frames;
62 unsigned char frames_to_drop;
63 unsigned char freq; /* light freq filter setting */
64
65 __u8 bridge; /* Type of bridge */
66#define BRIDGE_101 0
67#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
68#define BRIDGE_103 1
69
70 __u8 sensor; /* Type of image sensor chip */
71#define SENSOR_HV7131R 0
72#define SENSOR_OV6650 1
73#define SENSOR_OV7630 2
74#define SENSOR_PAS106 3
75#define SENSOR_PAS202 4
76#define SENSOR_TAS5110 5
77#define SENSOR_TAS5130CXX 6
78 __u8 reg11;
79};
80
81typedef const __u8 sensor_init_t[8];
82
83struct sensor_data {
84 const __u8 *bridge_init[2];
85 int bridge_init_size[2];
86 sensor_init_t *sensor_init;
87 int sensor_init_size;
88 sensor_init_t *sensor_bridge_init[2];
89 int sensor_bridge_init_size[2];
90 int flags;
91 unsigned ctrl_dis;
92 __u8 sensor_addr;
93};
94
95/* sensor_data flags */
96#define F_GAIN 0x01 /* has gain */
97#define F_SIF 0x02 /* sif or vga */
98
99/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
100#define MODE_RAW 0x10 /* raw bayer mode */
101#define MODE_REDUCED_SIF 0x20 /* vga mode (320x240 / 160x120) on sif cam */
102
103/* ctrl_dis helper macros */
104#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX))
105#define NO_FREQ (1 << FREQ_IDX)
106#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
107
108#define COMP2 0x8f
109#define COMP 0xc7 /* 0x87 //0x07 */
110#define COMP1 0xc9 /* 0x89 //0x09 */
111
112#define MCK_INIT 0x63
113#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
114
115#define SYS_CLK 0x04
116
117#define SENS(bridge_1, bridge_3, sensor, sensor_1, \
118 sensor_3, _flags, _ctrl_dis, _sensor_addr) \
119{ \
120 .bridge_init = { bridge_1, bridge_3 }, \
121 .bridge_init_size = { sizeof(bridge_1), sizeof(bridge_3) }, \
122 .sensor_init = sensor, \
123 .sensor_init_size = sizeof(sensor), \
124 .sensor_bridge_init = { sensor_1, sensor_3,}, \
125 .sensor_bridge_init_size = { sizeof(sensor_1), sizeof(sensor_3)}, \
126 .flags = _flags, .ctrl_dis = _ctrl_dis, .sensor_addr = _sensor_addr \
127}
128
129/* We calculate the autogain at the end of the transfer of a frame, at this
130 moment a frame with the old settings is being transmitted, and a frame is
131 being captured with the old settings. So if we adjust the autogain we must
132 ignore atleast the 2 next frames for the new settings to come into effect
133 before doing any other adjustments */
134#define AUTOGAIN_IGNORE_FRAMES 3
135#define AUTOGAIN_DEADZONE 1000
136#define DESIRED_AVG_LUM 7000
137
138/* V4L2 controls supported by the driver */
139static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
140static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
141static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
142static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
143static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
144static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
145static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
146static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
147static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
148static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
149
150static struct ctrl sd_ctrls[] = {
151#define BRIGHTNESS_IDX 0
152 {
153 {
154 .id = V4L2_CID_BRIGHTNESS,
155 .type = V4L2_CTRL_TYPE_INTEGER,
156 .name = "Brightness",
157 .minimum = 0,
158 .maximum = 255,
159 .step = 1,
160#define BRIGHTNESS_DEF 127
161 .default_value = BRIGHTNESS_DEF,
162 },
163 .set = sd_setbrightness,
164 .get = sd_getbrightness,
165 },
166#define GAIN_IDX 1
167 {
168 {
169 .id = V4L2_CID_GAIN,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "Gain",
172 .minimum = 0,
173 .maximum = 255,
174 .step = 1,
175#define GAIN_DEF 127
176#define GAIN_KNEE 200
177 .default_value = GAIN_DEF,
178 },
179 .set = sd_setgain,
180 .get = sd_getgain,
181 },
182#define EXPOSURE_IDX 2
183 {
184 {
185 .id = V4L2_CID_EXPOSURE,
186 .type = V4L2_CTRL_TYPE_INTEGER,
187 .name = "Exposure",
188#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
189#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
190 .minimum = 0,
191 .maximum = 255,
192 .step = 1,
193 .default_value = EXPOSURE_DEF,
194 .flags = 0,
195 },
196 .set = sd_setexposure,
197 .get = sd_getexposure,
198 },
199#define AUTOGAIN_IDX 3
200 {
201 {
202 .id = V4L2_CID_AUTOGAIN,
203 .type = V4L2_CTRL_TYPE_BOOLEAN,
204 .name = "Automatic Gain (and Exposure)",
205 .minimum = 0,
206 .maximum = 1,
207 .step = 1,
208#define AUTOGAIN_DEF 1
209 .default_value = AUTOGAIN_DEF,
210 .flags = 0,
211 },
212 .set = sd_setautogain,
213 .get = sd_getautogain,
214 },
215#define FREQ_IDX 4
216 {
217 {
218 .id = V4L2_CID_POWER_LINE_FREQUENCY,
219 .type = V4L2_CTRL_TYPE_MENU,
220 .name = "Light frequency filter",
221 .minimum = 0,
222 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
223 .step = 1,
224#define FREQ_DEF 1
225 .default_value = FREQ_DEF,
226 },
227 .set = sd_setfreq,
228 .get = sd_getfreq,
229 },
230};
231
232static struct v4l2_pix_format vga_mode[] = {
233 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
234 .bytesperline = 160,
235 .sizeimage = 160 * 120,
236 .colorspace = V4L2_COLORSPACE_SRGB,
237 .priv = 2 | MODE_RAW},
238 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
239 .bytesperline = 160,
240 .sizeimage = 160 * 120 * 5 / 4,
241 .colorspace = V4L2_COLORSPACE_SRGB,
242 .priv = 2},
243 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
244 .bytesperline = 320,
245 .sizeimage = 320 * 240 * 5 / 4,
246 .colorspace = V4L2_COLORSPACE_SRGB,
247 .priv = 1},
248 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
249 .bytesperline = 640,
250 .sizeimage = 640 * 480 * 5 / 4,
251 .colorspace = V4L2_COLORSPACE_SRGB,
252 .priv = 0},
253};
254static struct v4l2_pix_format sif_mode[] = {
255 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
256 .bytesperline = 160,
257 .sizeimage = 160 * 120,
258 .colorspace = V4L2_COLORSPACE_SRGB,
259 .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
260 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
261 .bytesperline = 160,
262 .sizeimage = 160 * 120 * 5 / 4,
263 .colorspace = V4L2_COLORSPACE_SRGB,
264 .priv = 1 | MODE_REDUCED_SIF},
265 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
266 .bytesperline = 176,
267 .sizeimage = 176 * 144,
268 .colorspace = V4L2_COLORSPACE_SRGB,
269 .priv = 1 | MODE_RAW},
270 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
271 .bytesperline = 176,
272 .sizeimage = 176 * 144 * 5 / 4,
273 .colorspace = V4L2_COLORSPACE_SRGB,
274 .priv = 1},
275 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
276 .bytesperline = 320,
277 .sizeimage = 320 * 240 * 5 / 4,
278 .colorspace = V4L2_COLORSPACE_SRGB,
279 .priv = 0 | MODE_REDUCED_SIF},
280 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
281 .bytesperline = 352,
282 .sizeimage = 352 * 288 * 5 / 4,
283 .colorspace = V4L2_COLORSPACE_SRGB,
284 .priv = 0},
285};
286
287static const __u8 initHv7131[] = {
288 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
289 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
291 0x28, 0x1e, 0x60, 0x8a, 0x20,
292 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
293};
294static const __u8 hv7131_sensor_init[][8] = {
295 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
296 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
297 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
298 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
299 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
300};
301static const __u8 initOv6650[] = {
302 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
303 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
305 0x10, 0x1d, 0x10, 0x02, 0x02, 0x09, 0x07
306};
307static const __u8 ov6650_sensor_init[][8] =
308{
309 /* Bright, contrast, etc are set througth SCBB interface.
310 * AVCAP on win2 do not send any data on this controls. */
311 /* Anyway, some registers appears to alter bright and constrat */
312
313 /* Reset sensor */
314 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
315 /* Set clock register 0x11 low nibble is clock divider */
316 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
317 /* Next some unknown stuff */
318 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
319/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
320 * THIS SET GREEN SCREEN
321 * (pixels could be innverted in decode kind of "brg",
322 * but blue wont be there. Avoid this data ... */
323 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
324 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
325 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
326 /* Enable rgb brightness control */
327 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
328 /* HDG: Note windows uses the line below, which sets both register 0x60
329 and 0x61 I believe these registers of the ov6650 are identical as
330 those of the ov7630, because if this is true the windows settings
331 add a bit additional red gain and a lot additional blue gain, which
332 matches my findings that the windows settings make blue much too
333 blue and red a little too red.
334 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
335 /* Some more unknown stuff */
336 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
337 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
338};
339
340static const __u8 initOv7630[] = {
341 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
342 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
343 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
344 0x28, 0x1e, /* H & V sizes r15 .. r16 */
345 0x68, COMP2, MCK_INIT1, /* r17 .. r19 */
346 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
347};
348static const __u8 initOv7630_3[] = {
349 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
350 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
351 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
352 0x28, 0x1e, /* H & V sizes r15 .. r16 */
353 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
354 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
355 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
356 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
357};
358static const __u8 ov7630_sensor_init[][8] = {
359 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
360 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
361/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
362 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
363 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
364 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
365 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
366 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
367 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
368 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
369 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
370 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
371/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
372 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
373 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
374 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
375 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
376 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
377 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
378};
379
380static const __u8 ov7630_sensor_init_3[][8] = {
381 {0xa0, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
382};
383
384static const __u8 initPas106[] = {
385 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
386 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
388 0x16, 0x12, 0x24, COMP1, MCK_INIT1,
389 0x18, 0x10, 0x02, 0x02, 0x09, 0x07
390};
391/* compression 0x86 mckinit1 0x2b */
392static const __u8 pas106_sensor_init[][8] = {
393 /* Pixel Clock Divider 6 */
394 { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
395 /* Frame Time MSB (also seen as 0x12) */
396 { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
397 /* Frame Time LSB (also seen as 0x05) */
398 { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
399 /* Shutter Time Line Offset (also seen as 0x6d) */
400 { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
401 /* Shutter Time Pixel Offset (also seen as 0xb1) */
402 { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
403 /* Black Level Subtract Sign (also seen 0x00) */
404 { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
405 /* Black Level Subtract Level (also seen 0x01) */
406 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
407 { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
408 /* Color Gain B Pixel 5 a */
409 { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
410 /* Color Gain G1 Pixel 1 5 */
411 { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
412 /* Color Gain G2 Pixel 1 0 5 */
413 { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
414 /* Color Gain R Pixel 3 1 */
415 { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
416 /* Color GainH Pixel */
417 { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
418 /* Global Gain */
419 { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
420 /* Contrast */
421 { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
422 /* H&V synchro polarity */
423 { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
424 /* ?default */
425 { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
426 /* DAC scale */
427 { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
428 /* ?default */
429 { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
430 /* Validate Settings */
431 { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
432};
433
434static const __u8 initPas202[] = {
435 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
436 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
438 0x28, 0x1e, 0x28, 0x89, 0x20,
439 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
440};
441static const __u8 pas202_sensor_init[][8] = {
442 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
443 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
444 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
445 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
446 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
447 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
448 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
449 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
450 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
451 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
452 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
453 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
454
455 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
456 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
457 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
458 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
459 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
460 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
461 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
462 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
463};
464
465static const __u8 initTas5110[] = {
466 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
467 0x00, 0x00,
468 0x00, 0x01, 0x00, 0x45, 0x09, 0x0a,
469 0x16, 0x12, 0x60, 0x86, 0x2b,
470 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
471};
472static const __u8 tas5110_sensor_init[][8] = {
473 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
474 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
475 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
476};
477
478static const __u8 initTas5130[] = {
479 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
480 0x00, 0x00,
481 0x00, 0x01, 0x00, 0x68, 0x0c, 0x0a,
482 0x28, 0x1e, 0x60, COMP, MCK_INIT,
483 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
484};
485static const __u8 tas5130_sensor_init[][8] = {
486/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
487 * shutter 0x47 short exposure? */
488 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
489 /* shutter 0x01 long exposure */
490 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
491};
492
493static struct sensor_data sensor_data[] = {
494SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0),
495SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
496SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
497 F_GAIN, 0, 0x21),
498SENS(initPas106, NULL, pas106_sensor_init, NULL, NULL, F_SIF, NO_EXPO|NO_FREQ,
499 0),
500SENS(initPas202, initPas202, pas202_sensor_init, NULL, NULL, 0,
501 NO_EXPO|NO_FREQ, 0),
502SENS(initTas5110, NULL, tas5110_sensor_init, NULL, NULL, F_GAIN|F_SIF,
503 NO_BRIGHTNESS|NO_FREQ, 0),
504SENS(initTas5130, NULL, tas5130_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ,
505 0),
506};
507
508/* get one byte in gspca_dev->usb_buf */
509static void reg_r(struct gspca_dev *gspca_dev,
510 __u16 value)
511{
512 usb_control_msg(gspca_dev->dev,
513 usb_rcvctrlpipe(gspca_dev->dev, 0),
514 0, /* request */
515 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
516 value,
517 0, /* index */
518 gspca_dev->usb_buf, 1,
519 500);
520}
521
522static void reg_w(struct gspca_dev *gspca_dev,
523 __u16 value,
524 const __u8 *buffer,
525 int len)
526{
527#ifdef GSPCA_DEBUG
528 if (len > USB_BUF_SZ) {
529 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
530 return;
531 }
532#endif
533 memcpy(gspca_dev->usb_buf, buffer, len);
534 usb_control_msg(gspca_dev->dev,
535 usb_sndctrlpipe(gspca_dev->dev, 0),
536 0x08, /* request */
537 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
538 value,
539 0, /* index */
540 gspca_dev->usb_buf, len,
541 500);
542}
543
544static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
545{
546 int retry = 60;
547
548 /* is i2c ready */
549 reg_w(gspca_dev, 0x08, buffer, 8);
550 while (retry--) {
551 msleep(10);
552 reg_r(gspca_dev, 0x08);
553 if (gspca_dev->usb_buf[0] & 0x04) {
554 if (gspca_dev->usb_buf[0] & 0x08)
555 return -1;
556 return 0;
557 }
558 }
559 return -1;
560}
561
562static void i2c_w_vector(struct gspca_dev *gspca_dev,
563 const __u8 buffer[][8], int len)
564{
565 for (;;) {
566 reg_w(gspca_dev, 0x08, *buffer, 8);
567 len -= 8;
568 if (len <= 0)
569 break;
570 buffer++;
571 }
572}
573
574static void setbrightness(struct gspca_dev *gspca_dev)
575{
576 struct sd *sd = (struct sd *) gspca_dev;
577 __u8 value;
578
579 switch (sd->sensor) {
580 case SENSOR_OV6650:
581 case SENSOR_OV7630: {
582 __u8 i2cOV[] =
583 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
584
585 /* change reg 0x06 */
586 i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
587 i2cOV[3] = sd->brightness;
588 if (i2c_w(gspca_dev, i2cOV) < 0)
589 goto err;
590 break;
591 }
592 case SENSOR_PAS106: {
593 __u8 i2c1[] =
594 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
595
596 i2c1[3] = sd->brightness >> 3;
597 i2c1[2] = 0x0e;
598 if (i2c_w(gspca_dev, i2c1) < 0)
599 goto err;
600 i2c1[3] = 0x01;
601 i2c1[2] = 0x13;
602 if (i2c_w(gspca_dev, i2c1) < 0)
603 goto err;
604 break;
605 }
606 case SENSOR_PAS202: {
607 /* __u8 i2cpexpo1[] =
608 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
609 __u8 i2cpexpo[] =
610 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
611 __u8 i2cp202[] =
612 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
613 static __u8 i2cpdoit[] =
614 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
615
616 /* change reg 0x10 */
617 i2cpexpo[4] = 0xff - sd->brightness;
618/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
619 goto err; */
620/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
621 goto err; */
622 if (i2c_w(gspca_dev, i2cpexpo) < 0)
623 goto err;
624 if (i2c_w(gspca_dev, i2cpdoit) < 0)
625 goto err;
626 i2cp202[3] = sd->brightness >> 3;
627 if (i2c_w(gspca_dev, i2cp202) < 0)
628 goto err;
629 if (i2c_w(gspca_dev, i2cpdoit) < 0)
630 goto err;
631 break;
632 }
633 case SENSOR_TAS5130CXX: {
634 __u8 i2c[] =
635 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
636
637 value = 0xff - sd->brightness;
638 i2c[4] = value;
639 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
640 if (i2c_w(gspca_dev, i2c) < 0)
641 goto err;
642 break;
643 }
644 }
645 return;
646err:
647 PDEBUG(D_ERR, "i2c error brightness");
648}
649
650static void setsensorgain(struct gspca_dev *gspca_dev)
651{
652 struct sd *sd = (struct sd *) gspca_dev;
653 unsigned char gain = sd->gain;
654
655 switch (sd->sensor) {
656
657 case SENSOR_TAS5110: {
658 __u8 i2c[] =
659 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
660
661 i2c[4] = 255 - gain;
662 if (i2c_w(gspca_dev, i2c) < 0)
663 goto err;
664 break;
665 }
666
667 case SENSOR_OV6650:
668 gain >>= 1;
669 /* fall thru */
670 case SENSOR_OV7630: {
671 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
672
673 i2c[1] = sensor_data[sd->sensor].sensor_addr;
674 i2c[3] = gain >> 2;
675 if (i2c_w(gspca_dev, i2c) < 0)
676 goto err;
677 break;
678 }
679 }
680 return;
681err:
682 PDEBUG(D_ERR, "i2c error gain");
683}
684
685static void setgain(struct gspca_dev *gspca_dev)
686{
687 struct sd *sd = (struct sd *) gspca_dev;
688 __u8 gain;
689 __u8 rgb_value;
690
691 gain = sd->gain >> 4;
692
693 /* red and blue gain */
694 rgb_value = gain << 4 | gain;
695 reg_w(gspca_dev, 0x10, &rgb_value, 1);
696 /* green gain */
697 rgb_value = gain;
698 reg_w(gspca_dev, 0x11, &rgb_value, 1);
699
700 if (sensor_data[sd->sensor].flags & F_GAIN)
701 setsensorgain(gspca_dev);
702}
703
704static void setexposure(struct gspca_dev *gspca_dev)
705{
706 struct sd *sd = (struct sd *) gspca_dev;
707
708 switch (sd->sensor) {
709 case SENSOR_TAS5110: {
710 __u8 reg;
711
712 /* register 19's high nibble contains the sn9c10x clock divider
713 The high nibble configures the no fps according to the
714 formula: 60 / high_nibble. With a maximum of 30 fps */
715 reg = 120 * sd->exposure / 1000;
716 if (reg < 2)
717 reg = 2;
718 else if (reg > 15)
719 reg = 15;
720 reg = (reg << 4) | 0x0b;
721 reg_w(gspca_dev, 0x19, &reg, 1);
722 break;
723 }
724 case SENSOR_OV6650:
725 case SENSOR_OV7630: {
726 /* The ov6650 / ov7630 have 2 registers which both influence
727 exposure, register 11, whose low nibble sets the nr off fps
728 according to: fps = 30 / (low_nibble + 1)
729
730 The fps configures the maximum exposure setting, but it is
731 possible to use less exposure then what the fps maximum
732 allows by setting register 10. register 10 configures the
733 actual exposure as quotient of the full exposure, with 0
734 being no exposure at all (not very usefull) and reg10_max
735 being max exposure possible at that framerate.
736
737 The code maps our 0 - 510 ms exposure ctrl to these 2
738 registers, trying to keep fps as high as possible.
739 */
740 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
741 int reg10, reg11, reg10_max;
742
743 /* ov6645 datasheet says reg10_max is 9a, but that uses
744 tline * 2 * reg10 as formula for calculating texpo, the
745 ov6650 probably uses the same formula as the 7730 which uses
746 tline * 4 * reg10, which explains why the reg10max we've
747 found experimentally for the ov6650 is exactly half that of
748 the ov6645. The ov7630 datasheet says the max is 0x41. */
749 if (sd->sensor == SENSOR_OV6650) {
750 reg10_max = 0x4d;
751 i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
752 } else
753 reg10_max = 0x41;
754
755 reg11 = (60 * sd->exposure + 999) / 1000;
756 if (reg11 < 1)
757 reg11 = 1;
758 else if (reg11 > 16)
759 reg11 = 16;
760
761 /* In 640x480, if the reg11 has less than 3, the image is
762 unstable (not enough bandwidth). */
763 if (gspca_dev->width == 640 && reg11 < 3)
764 reg11 = 3;
765
766 /* frame exposure time in ms = 1000 * reg11 / 30 ->
767 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
768 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
769
770 /* Don't allow this to get below 10 when using autogain, the
771 steps become very large (relatively) when below 10 causing
772 the image to oscilate from much too dark, to much too bright
773 and back again. */
774 if (sd->autogain && reg10 < 10)
775 reg10 = 10;
776 else if (reg10 > reg10_max)
777 reg10 = reg10_max;
778
779 /* Write reg 10 and reg11 low nibble */
780 i2c[1] = sensor_data[sd->sensor].sensor_addr;
781 i2c[3] = reg10;
782 i2c[4] |= reg11 - 1;
783
784 /* If register 11 didn't change, don't change it */
785 if (sd->reg11 == reg11 )
786 i2c[0] = 0xa0;
787
788 if (i2c_w(gspca_dev, i2c) == 0)
789 sd->reg11 = reg11;
790 else
791 PDEBUG(D_ERR, "i2c error exposure");
792 break;
793 }
794 }
795}
796
797static void setfreq(struct gspca_dev *gspca_dev)
798{
799 struct sd *sd = (struct sd *) gspca_dev;
800
801 switch (sd->sensor) {
802 case SENSOR_OV6650:
803 case SENSOR_OV7630: {
804 /* Framerate adjust register for artificial light 50 hz flicker
805 compensation, for the ov6650 this is identical to ov6630
806 0x2b register, see ov6630 datasheet.
807 0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
808 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
809 switch (sd->freq) {
810 default:
811/* case 0: * no filter*/
812/* case 2: * 60 hz */
813 i2c[3] = 0;
814 break;
815 case 1: /* 50 hz */
816 i2c[3] = (sd->sensor == SENSOR_OV6650)
817 ? 0x4f : 0x8a;
818 break;
819 }
820 i2c[1] = sensor_data[sd->sensor].sensor_addr;
821 if (i2c_w(gspca_dev, i2c) < 0)
822 PDEBUG(D_ERR, "i2c error setfreq");
823 break;
824 }
825 }
826}
827
828static void do_autogain(struct gspca_dev *gspca_dev)
829{
830 struct sd *sd = (struct sd *) gspca_dev;
831 int avg_lum = atomic_read(&sd->avg_lum);
832
833 if (avg_lum == -1)
834 return;
835
836 if (sd->autogain_ignore_frames > 0)
837 sd->autogain_ignore_frames--;
838 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
839 sd->brightness * DESIRED_AVG_LUM / 127,
840 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
841 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
842 (int)sd->gain, (int)sd->exposure);
843 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
844 }
845}
846
847/* this function is called at probe time */
848static int sd_config(struct gspca_dev *gspca_dev,
849 const struct usb_device_id *id)
850{
851 struct sd *sd = (struct sd *) gspca_dev;
852 struct cam *cam;
853
854 reg_r(gspca_dev, 0x00);
855 if (gspca_dev->usb_buf[0] != 0x10)
856 return -ENODEV;
857
858 /* copy the webcam info from the device id */
859 sd->sensor = id->driver_info >> 8;
860 sd->bridge = id->driver_info & 0xff;
861 gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
862
863 cam = &gspca_dev->cam;
864 cam->epaddr = 0x01;
865 if (!(sensor_data[sd->sensor].flags & F_SIF)) {
866 cam->cam_mode = vga_mode;
867 cam->nmodes = ARRAY_SIZE(vga_mode);
868 } else {
869 cam->cam_mode = sif_mode;
870 cam->nmodes = ARRAY_SIZE(sif_mode);
871 }
872 sd->brightness = BRIGHTNESS_DEF;
873 sd->gain = GAIN_DEF;
874 sd->exposure = EXPOSURE_DEF;
875 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
876 sd->autogain = 0; /* Disable do_autogain callback */
877 else
878 sd->autogain = AUTOGAIN_DEF;
879 sd->freq = FREQ_DEF;
880
881 return 0;
882}
883
884/* this function is called at probe and resume time */
885static int sd_init(struct gspca_dev *gspca_dev)
886{
887 const __u8 stop = 0x09; /* Disable stream turn of LED */
888
889 reg_w(gspca_dev, 0x01, &stop, 1);
890
891 return 0;
892}
893
894/* -- start the camera -- */
895static int sd_start(struct gspca_dev *gspca_dev)
896{
897 struct sd *sd = (struct sd *) gspca_dev;
898 struct cam *cam = &gspca_dev->cam;
899 int mode, l;
900 const __u8 *sn9c10x;
901 __u8 reg12_19[8];
902
903 mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
904 sn9c10x = sensor_data[sd->sensor].bridge_init[sd->bridge];
905 l = sensor_data[sd->sensor].bridge_init_size[sd->bridge];
906 memcpy(reg12_19, &sn9c10x[0x12 - 1], 8);
907 reg12_19[6] = sn9c10x[0x18 - 1] | (mode << 4);
908 /* Special cases where reg 17 and or 19 value depends on mode */
909 switch (sd->sensor) {
910 case SENSOR_PAS202:
911 reg12_19[5] = mode ? 0x24 : 0x20;
912 break;
913 case SENSOR_TAS5130CXX:
914 /* probably not mode specific at all most likely the upper
915 nibble of 0x19 is exposure (clock divider) just as with
916 the tas5110, we need someone to test this. */
917 reg12_19[7] = mode ? 0x23 : 0x43;
918 break;
919 }
920 /* Disable compression when the raw bayer format has been selected */
921 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
922 reg12_19[6] &= ~0x80;
923
924 /* Vga mode emulation on SIF sensor? */
925 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
926 reg12_19[0] += 16; /* 0x12: hstart adjust */
927 reg12_19[1] += 24; /* 0x13: vstart adjust */
928 reg12_19[3] = 320 / 16; /* 0x15: hsize */
929 reg12_19[4] = 240 / 16; /* 0x16: vsize */
930 }
931
932 /* reg 0x01 bit 2 video transfert on */
933 reg_w(gspca_dev, 0x01, &sn9c10x[0x01 - 1], 1);
934 /* reg 0x17 SensorClk enable inv Clk 0x60 */
935 reg_w(gspca_dev, 0x17, &sn9c10x[0x17 - 1], 1);
936 /* Set the registers from the template */
937 reg_w(gspca_dev, 0x01, sn9c10x, l);
938
939 /* Init the sensor */
940 i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
941 sensor_data[sd->sensor].sensor_init_size);
942 if (sensor_data[sd->sensor].sensor_bridge_init[sd->bridge])
943 i2c_w_vector(gspca_dev,
944 sensor_data[sd->sensor].sensor_bridge_init[sd->bridge],
945 sensor_data[sd->sensor].sensor_bridge_init_size[
946 sd->bridge]);
947
948 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
949 reg_w(gspca_dev, 0x15, &reg12_19[3], 2);
950 /* compression register */
951 reg_w(gspca_dev, 0x18, &reg12_19[6], 1);
952 /* H_start */
953 reg_w(gspca_dev, 0x12, &reg12_19[0], 1);
954 /* V_START */
955 reg_w(gspca_dev, 0x13, &reg12_19[1], 1);
956 /* reset 0x17 SensorClk enable inv Clk 0x60 */
957 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
958 reg_w(gspca_dev, 0x17, &reg12_19[5], 1);
959 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
960 reg_w(gspca_dev, 0x19, &reg12_19[7], 1);
961 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
962 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
963 /* Enable video transfert */
964 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
965 /* Compression */
966 reg_w(gspca_dev, 0x18, &reg12_19[6], 2);
967 msleep(20);
968
969 sd->reg11 = -1;
970
971 setgain(gspca_dev);
972 setbrightness(gspca_dev);
973 setexposure(gspca_dev);
974 setfreq(gspca_dev);
975
976 sd->frames_to_drop = 0;
977 sd->autogain_ignore_frames = 0;
978 atomic_set(&sd->avg_lum, -1);
979 return 0;
980}
981
982static void sd_stopN(struct gspca_dev *gspca_dev)
983{
984 sd_init(gspca_dev);
985}
986
987static void sd_pkt_scan(struct gspca_dev *gspca_dev,
988 struct gspca_frame *frame, /* target */
989 unsigned char *data, /* isoc packet */
990 int len) /* iso packet length */
991{
992 int i;
993 struct sd *sd = (struct sd *) gspca_dev;
994 struct cam *cam = &gspca_dev->cam;
995
996 /* frames start with:
997 * ff ff 00 c4 c4 96 synchro
998 * 00 (unknown)
999 * xx (frame sequence / size / compression)
1000 * (xx) (idem - extra byte for sn9c103)
1001 * ll mm brightness sum inside auto exposure
1002 * ll mm brightness sum outside auto exposure
1003 * (xx xx xx xx xx) audio values for snc103
1004 */
1005 if (len > 6 && len < 24) {
1006 for (i = 0; i < len - 6; i++) {
1007 if (data[0 + i] == 0xff
1008 && data[1 + i] == 0xff
1009 && data[2 + i] == 0x00
1010 && data[3 + i] == 0xc4
1011 && data[4 + i] == 0xc4
1012 && data[5 + i] == 0x96) { /* start of frame */
1013 int lum = -1;
1014 int pkt_type = LAST_PACKET;
1015 int fr_h_sz = (sd->bridge == BRIDGE_103) ?
1016 18 : 12;
1017
1018 if (len - i < fr_h_sz) {
1019 PDEBUG(D_STREAM, "packet too short to"
1020 " get avg brightness");
1021 } else if (sd->bridge == BRIDGE_103) {
1022 lum = data[i + 9] +
1023 (data[i + 10] << 8);
1024 } else {
1025 lum = data[i + 8] + (data[i + 9] << 8);
1026 }
1027 /* When exposure changes midway a frame we
1028 get a lum of 0 in this case drop 2 frames
1029 as the frames directly after an exposure
1030 change have an unstable image. Sometimes lum
1031 *really* is 0 (cam used in low light with
1032 low exposure setting), so do not drop frames
1033 if the previous lum was 0 too. */
1034 if (lum == 0 && sd->prev_avg_lum != 0) {
1035 lum = -1;
1036 sd->frames_to_drop = 2;
1037 sd->prev_avg_lum = 0;
1038 } else
1039 sd->prev_avg_lum = lum;
1040 atomic_set(&sd->avg_lum, lum);
1041
1042 if (sd->frames_to_drop) {
1043 sd->frames_to_drop--;
1044 pkt_type = DISCARD_PACKET;
1045 }
1046
1047 frame = gspca_frame_add(gspca_dev, pkt_type,
1048 frame, data, 0);
1049 data += i + fr_h_sz;
1050 len -= i + fr_h_sz;
1051 gspca_frame_add(gspca_dev, FIRST_PACKET,
1052 frame, data, len);
1053 return;
1054 }
1055 }
1056 }
1057
1058 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1059 /* In raw mode we sometimes get some garbage after the frame
1060 ignore this */
1061 int used = frame->data_end - frame->data;
1062 int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
1063
1064 if (used + len > size)
1065 len = size - used;
1066 }
1067
1068 gspca_frame_add(gspca_dev, INTER_PACKET,
1069 frame, data, len);
1070}
1071
1072static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1073{
1074 struct sd *sd = (struct sd *) gspca_dev;
1075
1076 sd->brightness = val;
1077 if (gspca_dev->streaming)
1078 setbrightness(gspca_dev);
1079 return 0;
1080}
1081
1082static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1083{
1084 struct sd *sd = (struct sd *) gspca_dev;
1085
1086 *val = sd->brightness;
1087 return 0;
1088}
1089
1090static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1091{
1092 struct sd *sd = (struct sd *) gspca_dev;
1093
1094 sd->gain = val;
1095 if (gspca_dev->streaming)
1096 setgain(gspca_dev);
1097 return 0;
1098}
1099
1100static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1101{
1102 struct sd *sd = (struct sd *) gspca_dev;
1103
1104 *val = sd->gain;
1105 return 0;
1106}
1107
1108static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1109{
1110 struct sd *sd = (struct sd *) gspca_dev;
1111
1112 sd->exposure = val;
1113 if (gspca_dev->streaming)
1114 setexposure(gspca_dev);
1115 return 0;
1116}
1117
1118static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1119{
1120 struct sd *sd = (struct sd *) gspca_dev;
1121
1122 *val = sd->exposure;
1123 return 0;
1124}
1125
1126static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1127{
1128 struct sd *sd = (struct sd *) gspca_dev;
1129
1130 sd->autogain = val;
1131 /* when switching to autogain set defaults to make sure
1132 we are on a valid point of the autogain gain /
1133 exposure knee graph, and give this change time to
1134 take effect before doing autogain. */
1135 if (sd->autogain) {
1136 sd->exposure = EXPOSURE_DEF;
1137 sd->gain = GAIN_DEF;
1138 if (gspca_dev->streaming) {
1139 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1140 setexposure(gspca_dev);
1141 setgain(gspca_dev);
1142 }
1143 }
1144
1145 return 0;
1146}
1147
1148static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1149{
1150 struct sd *sd = (struct sd *) gspca_dev;
1151
1152 *val = sd->autogain;
1153 return 0;
1154}
1155
1156static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1157{
1158 struct sd *sd = (struct sd *) gspca_dev;
1159
1160 sd->freq = val;
1161 if (gspca_dev->streaming)
1162 setfreq(gspca_dev);
1163 return 0;
1164}
1165
1166static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1167{
1168 struct sd *sd = (struct sd *) gspca_dev;
1169
1170 *val = sd->freq;
1171 return 0;
1172}
1173
1174static int sd_querymenu(struct gspca_dev *gspca_dev,
1175 struct v4l2_querymenu *menu)
1176{
1177 switch (menu->id) {
1178 case V4L2_CID_POWER_LINE_FREQUENCY:
1179 switch (menu->index) {
1180 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1181 strcpy((char *) menu->name, "NoFliker");
1182 return 0;
1183 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1184 strcpy((char *) menu->name, "50 Hz");
1185 return 0;
1186 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1187 strcpy((char *) menu->name, "60 Hz");
1188 return 0;
1189 }
1190 break;
1191 }
1192 return -EINVAL;
1193}
1194
1195/* sub-driver description */
1196static const struct sd_desc sd_desc = {
1197 .name = MODULE_NAME,
1198 .ctrls = sd_ctrls,
1199 .nctrls = ARRAY_SIZE(sd_ctrls),
1200 .config = sd_config,
1201 .init = sd_init,
1202 .start = sd_start,
1203 .stopN = sd_stopN,
1204 .pkt_scan = sd_pkt_scan,
1205 .querymenu = sd_querymenu,
1206 .dq_callback = do_autogain,
1207};
1208
1209/* -- module initialisation -- */
1210#define SB(sensor, bridge) \
1211 .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
1212
1213
1214static __devinitdata struct usb_device_id device_table[] = {
1215 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110, 102)}, /* TAS5110C1B */
1216 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110, 101)}, /* TAS5110C1B */
1217#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1218 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110, 101)}, /* TAS5110D */
1219 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1220 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
1221#endif
1222 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
1223#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1224 {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
1225 {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
1226 {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
1227 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1228 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1229 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
1230#endif
1231 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
1232#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1233 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1234#endif
1235 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1236#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1237 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
1238#endif
1239 {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
1240 {}
1241};
1242MODULE_DEVICE_TABLE(usb, device_table);
1243
1244/* -- device connect -- */
1245static int sd_probe(struct usb_interface *intf,
1246 const struct usb_device_id *id)
1247{
1248 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1249 THIS_MODULE);
1250}
1251
1252static struct usb_driver sd_driver = {
1253 .name = MODULE_NAME,
1254 .id_table = device_table,
1255 .probe = sd_probe,
1256 .disconnect = gspca_disconnect,
1257#ifdef CONFIG_PM
1258 .suspend = gspca_suspend,
1259 .resume = gspca_resume,
1260#endif
1261};
1262
1263/* -- module insert / remove -- */
1264static int __init sd_mod_init(void)
1265{
1266 if (usb_register(&sd_driver) < 0)
1267 return -1;
1268 PDEBUG(D_PROBE, "registered");
1269 return 0;
1270}
1271static void __exit sd_mod_exit(void)
1272{
1273 usb_deregister(&sd_driver);
1274 PDEBUG(D_PROBE, "deregistered");
1275}
1276
1277module_init(sd_mod_init);
1278module_exit(sd_mod_exit);