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