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