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