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