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