]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/media/video/gspca/sonixj.c
V4L/DVB (10360): gspca - mars: Bad interface/altsetting since 0a10a0e906be.
[mirror_ubuntu-jammy-kernel.git] / drivers / media / video / gspca / sonixj.c
CommitLineData
6a7eba24
JFM
1/*
2 * Sonix sn9c102p sn9c105 sn9c120 (jpeg) library
3 * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
4 *
5 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#define MODULE_NAME "sonixj"
23
24#include "gspca.h"
36e819db 25#define QUANT_VAL 4 /* quantization table */
6a7eba24
JFM
26#include "jpeg.h"
27
0cae8964
JFM
28#define V4L2_CID_INFRARED (V4L2_CID_PRIVATE_BASE + 0)
29
6a7eba24
JFM
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SONIX JPEG 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
cebf3b67 38 atomic_t avg_lum;
6a7eba24
JFM
39 unsigned int exposure;
40
577cbf49
JFM
41 __u16 brightness;
42 __u8 contrast;
43 __u8 colors;
44 __u8 autogain;
403123d2
JFM
45 __u8 blue;
46 __u8 red;
6c86274f 47 __u8 vflip; /* ov7630 only */
0cae8964 48 __u8 infrared; /* mi0360 only */
6a7eba24 49
577cbf49 50 __s8 ag_cnt;
6a7eba24
JFM
51#define AG_CNT_START 13
52
577cbf49 53 __u8 bridge;
3647fea8
HG
54#define BRIDGE_SN9C102P 0
55#define BRIDGE_SN9C105 1
56#define BRIDGE_SN9C110 2
57#define BRIDGE_SN9C120 3
58#define BRIDGE_SN9C325 4
577cbf49 59 __u8 sensor; /* Type of image sensor chip */
6a7eba24
JFM
60#define SENSOR_HV7131R 0
61#define SENSOR_MI0360 1
62#define SENSOR_MO4000 2
d2d16e90 63#define SENSOR_OM6802 3
6ab0b174
JFM
64#define SENSOR_OV7630 4
65#define SENSOR_OV7648 5
66#define SENSOR_OV7660 6
577cbf49 67 __u8 i2c_base;
6a7eba24
JFM
68};
69
70/* V4L2 controls supported by the driver */
71static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
403123d2
JFM
77static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val);
6a7eba24
JFM
81static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
6c86274f
JFM
83static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
0cae8964
JFM
85static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val);
6a7eba24
JFM
87
88static struct ctrl sd_ctrls[] = {
6a7eba24
JFM
89 {
90 {
91 .id = V4L2_CID_BRIGHTNESS,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Brightness",
94 .minimum = 0,
05b809c7
JFM
95#define BRIGHTNESS_MAX 0xffff
96 .maximum = BRIGHTNESS_MAX,
6a7eba24 97 .step = 1,
b1b056a5 98#define BRIGHTNESS_DEF 0x8000
a5ae2062 99 .default_value = BRIGHTNESS_DEF,
6a7eba24
JFM
100 },
101 .set = sd_setbrightness,
102 .get = sd_getbrightness,
103 },
6a7eba24
JFM
104 {
105 {
106 .id = V4L2_CID_CONTRAST,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Contrast",
109 .minimum = 0,
05b809c7
JFM
110#define CONTRAST_MAX 127
111 .maximum = CONTRAST_MAX,
6a7eba24 112 .step = 1,
a5ae2062
JFM
113#define CONTRAST_DEF 63
114 .default_value = CONTRAST_DEF,
6a7eba24
JFM
115 },
116 .set = sd_setcontrast,
117 .get = sd_getcontrast,
118 },
6a7eba24
JFM
119 {
120 {
121 .id = V4L2_CID_SATURATION,
122 .type = V4L2_CTRL_TYPE_INTEGER,
123 .name = "Color",
124 .minimum = 0,
403123d2 125 .maximum = 40,
6a7eba24 126 .step = 1,
9c5f70f2 127#define COLOR_DEF 32
a5ae2062 128 .default_value = COLOR_DEF,
6a7eba24
JFM
129 },
130 .set = sd_setcolors,
131 .get = sd_getcolors,
132 },
403123d2
JFM
133 {
134 {
135 .id = V4L2_CID_BLUE_BALANCE,
136 .type = V4L2_CTRL_TYPE_INTEGER,
137 .name = "Blue Balance",
138 .minimum = 24,
139 .maximum = 40,
140 .step = 1,
141#define BLUE_BALANCE_DEF 32
142 .default_value = BLUE_BALANCE_DEF,
143 },
144 .set = sd_setblue_balance,
145 .get = sd_getblue_balance,
146 },
147 {
148 {
149 .id = V4L2_CID_RED_BALANCE,
150 .type = V4L2_CTRL_TYPE_INTEGER,
151 .name = "Red Balance",
152 .minimum = 24,
153 .maximum = 40,
154 .step = 1,
155#define RED_BALANCE_DEF 32
156 .default_value = RED_BALANCE_DEF,
157 },
158 .set = sd_setred_balance,
159 .get = sd_getred_balance,
160 },
161#define AUTOGAIN_IDX 5
6a7eba24
JFM
162 {
163 {
164 .id = V4L2_CID_AUTOGAIN,
165 .type = V4L2_CTRL_TYPE_BOOLEAN,
166 .name = "Auto Gain",
167 .minimum = 0,
168 .maximum = 1,
169 .step = 1,
a5ae2062
JFM
170#define AUTOGAIN_DEF 1
171 .default_value = AUTOGAIN_DEF,
6a7eba24
JFM
172 },
173 .set = sd_setautogain,
174 .get = sd_getautogain,
175 },
6c86274f 176/* ov7630 only */
403123d2 177#define VFLIP_IDX 6
6c86274f
JFM
178 {
179 {
180 .id = V4L2_CID_VFLIP,
181 .type = V4L2_CTRL_TYPE_BOOLEAN,
182 .name = "Vflip",
183 .minimum = 0,
184 .maximum = 1,
185 .step = 1,
40e6ec12 186#define VFLIP_DEF 1
6c86274f
JFM
187 .default_value = VFLIP_DEF,
188 },
189 .set = sd_setvflip,
190 .get = sd_getvflip,
191 },
0cae8964 192/* mi0360 only */
403123d2 193#define INFRARED_IDX 7
0cae8964
JFM
194 {
195 {
196 .id = V4L2_CID_INFRARED,
197 .type = V4L2_CTRL_TYPE_BOOLEAN,
198 .name = "Infrared",
199 .minimum = 0,
200 .maximum = 1,
201 .step = 1,
202#define INFRARED_DEF 0
203 .default_value = INFRARED_DEF,
204 },
205 .set = sd_setinfrared,
206 .get = sd_getinfrared,
207 },
6a7eba24
JFM
208};
209
577cbf49
JFM
210/* table of the disabled controls */
211static __u32 ctrl_dis[] = {
212 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
213 /* SENSOR_HV7131R 0 */
214 (1 << VFLIP_IDX),
215 /* SENSOR_MI0360 1 */
216 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
217 /* SENSOR_MO4000 2 */
218 (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
219 /* SENSOR_OM6802 3 */
220 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX),
221 /* SENSOR_OV7630 4 */
222 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
223 /* SENSOR_OV7648 5 */
224 (1 << AUTOGAIN_IDX) | (1 << INFRARED_IDX) | (1 << VFLIP_IDX),
225 /* SENSOR_OV7660 6 */
226};
227
cc611b8a 228static const struct v4l2_pix_format vga_mode[] = {
c2446b3e
JFM
229 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
230 .bytesperline = 160,
5d05294a 231 .sizeimage = 160 * 120 * 4 / 8 + 590,
c2446b3e
JFM
232 .colorspace = V4L2_COLORSPACE_JPEG,
233 .priv = 2},
234 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
235 .bytesperline = 320,
236 .sizeimage = 320 * 240 * 3 / 8 + 590,
237 .colorspace = V4L2_COLORSPACE_JPEG,
238 .priv = 1},
239 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
240 .bytesperline = 640,
241 .sizeimage = 640 * 480 * 3 / 8 + 590,
242 .colorspace = V4L2_COLORSPACE_JPEG,
243 .priv = 0},
6a7eba24
JFM
244};
245
8c2ba441
JFM
246/*Data from sn9c102p+hv7131r */
247static const u8 sn_hv7131[0x1c] = {
8f47a3ce
JFM
248/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
249 0x00, 0x03, 0x64, 0x00, 0x1a, 0x20, 0x20, 0x20,
250/* reg8 reg9 rega regb regc regd rege regf */
251 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10,
252/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
253 0x03, 0x00, 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41,
8c2ba441
JFM
254/* reg18 reg19 reg1a reg1b */
255 0x0a, 0x00, 0x00, 0x00
6a7eba24
JFM
256};
257
8c2ba441 258static const u8 sn_mi0360[0x1c] = {
8f47a3ce
JFM
259/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
260 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20,
261/* reg8 reg9 rega regb regc regd rege regf */
262 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
263/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
264 0x03, 0x00, 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61,
8c2ba441
JFM
265/* reg18 reg19 reg1a reg1b */
266 0x06, 0x00, 0x00, 0x00
6a7eba24
JFM
267};
268
8c2ba441 269static const u8 sn_mo4000[0x1c] = {
8f47a3ce 270/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
8c2ba441 271 0x00, 0x23, 0x60, 0x00, 0x1a, 0x00, 0x20, 0x18,
8f47a3ce
JFM
272/* reg8 reg9 rega regb regc regd rege regf */
273 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
275 0x03, 0x00, 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40,
8c2ba441
JFM
276/* reg18 reg19 reg1a reg1b */
277 0x08, 0x00, 0x00, 0x00
6a7eba24
JFM
278};
279
8c2ba441 280static const u8 sn_om6802[0x1c] = {
d2d16e90
JFM
281/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
282 0x00, 0x23, 0x72, 0x00, 0x1a, 0x34, 0x27, 0x20,
283/* reg8 reg9 rega regb regc regd rege regf */
284 0x80, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
286 0x03, 0x00, 0x51, 0x01, 0x00, 0x28, 0x1e, 0x40,
8c2ba441
JFM
287/* reg18 reg19 reg1a reg1b */
288 0x05, 0x00, 0x00, 0x00
d2d16e90
JFM
289};
290
8c2ba441 291static const u8 sn_ov7630[0x1c] = {
6ab0b174
JFM
292/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
293 0x00, 0x21, 0x40, 0x00, 0x1a, 0x20, 0x1f, 0x20,
294/* reg8 reg9 rega regb regc regd rege regf */
295 0xa1, 0x21, 0x76, 0x21, 0x00, 0x00, 0x00, 0x10,
296/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
297 0x03, 0x00, 0x04, 0x01, 0x0a, 0x28, 0x1e, 0xc2,
8c2ba441
JFM
298/* reg18 reg19 reg1a reg1b */
299 0x0b, 0x00, 0x00, 0x00
6ab0b174
JFM
300};
301
8c2ba441 302static const u8 sn_ov7648[0x1c] = {
8f47a3ce 303/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
6270330a 304 0x00, 0x63, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
8f47a3ce 305/* reg8 reg9 rega regb regc regd rege regf */
6270330a 306 0x81, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
8f47a3ce 307/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
6270330a 308 0x03, 0x00, 0x00, 0x01, 0x00, 0x28, 0x1e, 0x00,
8c2ba441
JFM
309/* reg18 reg19 reg1a reg1b */
310 0x0b, 0x00, 0x00, 0x00
6a7eba24
JFM
311};
312
8c2ba441 313static const u8 sn_ov7660[0x1c] = {
8f47a3ce
JFM
314/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 */
315 0x00, 0x61, 0x40, 0x00, 0x1a, 0x20, 0x20, 0x20,
316/* reg8 reg9 rega regb regc regd rege regf */
317 0x81, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10,
318/* reg10 reg11 reg12 reg13 reg14 reg15 reg16 reg17 */
319 0x03, 0x00, 0x01, 0x01, 0x08, 0x28, 0x1e, 0x20,
8c2ba441
JFM
320/* reg18 reg19 reg1a reg1b */
321 0x07, 0x00, 0x00, 0x00
6a7eba24
JFM
322};
323
324/* sequence specific to the sensors - !! index = SENSOR_xxx */
8c2ba441 325static const u8 *sn_tb[] = {
6a7eba24
JFM
326 sn_hv7131,
327 sn_mi0360,
328 sn_mo4000,
d2d16e90 329 sn_om6802,
6ab0b174 330 sn_ov7630,
6a7eba24
JFM
331 sn_ov7648,
332 sn_ov7660
333};
334
05b809c7 335static const __u8 gamma_def[] = {
6a7eba24
JFM
336 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
337 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
338};
6a7eba24 339
803f9ccf 340/* color matrix and offsets */
a5ae2062 341static const __u8 reg84[] = {
803f9ccf
JFM
342 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, /* YR YG YB gains */
343 0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00, /* UR UG UB */
344 0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f, /* VR VG VB */
345 0x00, 0x00, 0x00 /* YUV offsets */
6a7eba24 346};
a5ae2062 347static const __u8 hv7131r_sensor_init[][8] = {
8c2ba441
JFM
348 {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
349 {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
350 {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
351/* {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
352 {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
353 {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
354/* {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
355
356 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
358 {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
359 {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
360 {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
361 {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
362 {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
363 {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
364
365 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
366 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
367 {0xa1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
368 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
369 {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
370
371 {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
372 {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
373 {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
374 {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
375 {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
a5ae2062 376 {}
6a7eba24 377};
a5ae2062 378static const __u8 mi0360_sensor_init[][8] = {
8c2ba441
JFM
379 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
380 {0xb1, 0x5d, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
381 {0xb1, 0x5d, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
382 {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
383 {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
384 {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
385 {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
386 {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
387 {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
388 {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
389 {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
390 {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
391 {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
392 {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
393 {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
394 {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
395 {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
396 {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
397 {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
398 {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
399 {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
400 {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
401 {0xd1, 0x5d, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
402 {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
403 {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
404 {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
405 {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
406 {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
407 {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
408 {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
409 {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
410 {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
411 {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
412
413 {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
414 {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
415 {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
416 {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
417 {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
418
419 {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
420 {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
421 {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
422 {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
423
424 {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
425 {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
426/* {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
427/* {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
428 {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
429 {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
a5ae2062 430 {}
6a7eba24 431};
a5ae2062 432static const __u8 mo4000_sensor_init[][8] = {
6a7eba24
JFM
433 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
435 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
436 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
437 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
438 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
439 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
440 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
441 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
444 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
445 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
446 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
450 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
451 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
452 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
a5ae2062 453 {}
6a7eba24 454};
d2d16e90
JFM
455static __u8 om6802_sensor_init[][8] = {
456 {0xa0, 0x34, 0x90, 0x05, 0x00, 0x00, 0x00, 0x10},
457 {0xa0, 0x34, 0x49, 0x85, 0x00, 0x00, 0x00, 0x10},
458 {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
459 {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
460/* {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
461 {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
462 /* white balance & auto-exposure */
463/* {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
464 * set color mode */
465/* {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
466 * max AGC value in AE */
467/* {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
468 * preset AGC */
469/* {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
470 * preset brightness */
471/* {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
472 * preset contrast */
473/* {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
474 * preset gamma */
475 {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
476 /* luminance mode (0x4f = AE) */
477 {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
478 /* preset shutter */
479/* {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
480 * auto frame rate */
481/* {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
482
483/* {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10}, */
484/* {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10}, */
485/* {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10}, */
486/* {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10}, */
487 {}
488};
6ab0b174
JFM
489static const __u8 ov7630_sensor_init[][8] = {
490 {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
491 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
492/* win: delay 20ms */
493 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
494 {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
495/* win: delay 20ms */
496 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
05b809c7 497/* win: i2c_r from 00 to 80 */
6ab0b174
JFM
498 {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
499 {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
500 {0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
501 {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
502 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
503 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
504 {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
505 {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
506 {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
507 {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
508 {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
509 {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
510 {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
511 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
512 {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
513 {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
514 {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
515 {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
516 {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
517 {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
518 {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
519 {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
520 {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
521 {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
522 {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
523 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
524/* */
525 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
526 {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
527/*fixme: + 0x12, 0x04*/
6c86274f
JFM
528/* {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10}, * COMN
529 * set by setvflip */
6ab0b174
JFM
530 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
531 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
532 {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
05b809c7 533/* */
6ab0b174
JFM
534 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
535 {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
536 {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
05b809c7 537/* */
6ab0b174 538 {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
91de65ac 539/* {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
6ab0b174
JFM
540 {}
541};
6270330a
JFM
542
543static const __u8 ov7648_sensor_init[][8] = {
544 {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
545 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
546 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
547 {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
548 {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
549 {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
550 {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
551 {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
552 {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
553 {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
554 {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
555 {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
556 {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
557 {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
558 {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
559 {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
560 {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
561 {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
562 {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
563 {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
564 {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
565
566 {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
567/* {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
568/* {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
569 {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10},
570/*...*/
571/* {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
572/* {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10}, jfm done */
573 {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
574 {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
575/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
576/* {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10}, * GAIN - def */
577/* {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10}, * B R - def: 80 */
578/*...*/
579 {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
580/* {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
581/* {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
582/* {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
583/* {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
584/* {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10}, * B R - def: 80 */
585
586 {}
587};
588
a5ae2062 589static const __u8 ov7660_sensor_init[][8] = {
6a7eba24 590 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
60017617 591/* (delay 20ms) */
6a7eba24 592 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
738608ae 593 /* Outformat = rawRGB */
6a7eba24 594 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
738608ae 595 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10},
6a7eba24
JFM
596 /* GAIN BLUE RED VREF */
597 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
598 /* COM 1 BAVE GEAVE AECHH */
599 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
600 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
738608ae 601 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
6a7eba24
JFM
602 /* AECH CLKRC COM7 COM8 */
603 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
604 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
605 /* HSTART HSTOP VSTRT VSTOP */
606 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
607 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
608 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
609 /* BOS GBOS GROS ROS (BGGR offset) */
738608ae
JFM
610/* {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
611 {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
6a7eba24
JFM
612 /* AEW AEB VPT BBIAS */
613 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
614 /* GbBIAS RSVD EXHCH EXHCL */
615 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
616 /* RBIAS ADVFL ASDVFH YAVE */
617 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
618 /* HSYST HSYEN HREF */
619 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
620 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
621 /* ADC ACOM OFON TSLB */
622 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
623 /* COM11 COM12 COM13 COM14 */
624 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
625 /* EDGE COM15 COM16 COM17 */
626 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
627 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
628 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
629 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
630 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
631 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
632 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
633 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
634 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
635 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
636 /* LCC1 LCC2 LCC3 LCC4 */
637 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
738608ae 638 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
6a7eba24 639 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
738608ae 640 /* band gap reference [0:3] DBLV */
6a7eba24
JFM
641 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
642 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
643 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
644 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
645 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
646 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
647 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
648 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
649 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
738608ae 650 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
6a7eba24 651/****** (some exchanges in the win trace) ******/
738608ae 652 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
6a7eba24
JFM
653 /* bits[3..0]reserved */
654 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
655 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
656 /* VREF vertical frame ctrl */
657 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
738608ae
JFM
658 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
659 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
660 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
661 {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
662/* {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
6a7eba24
JFM
663/****** (some exchanges in the win trace) ******/
664 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
738608ae
JFM
665 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
666 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
667 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
668/* {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10}, * RED */
6a7eba24 669/****** (some exchanges in the win trace) ******/
738608ae 670/******!! startsensor KO if changed !!****/
6a7eba24
JFM
671 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
672 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
673 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
674 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
a5ae2062 675 {}
6a7eba24 676};
6a7eba24 677
a5ae2062 678static const __u8 qtable4[] = {
6a7eba24 679 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
8c2ba441
JFM
680 0x06, 0x08, 0x0a, 0x11,
681 0x0a, 0x0a, 0x08, 0x08, 0x0a, 0x15, 0x0f, 0x0f, 0x0c, 0x11, 0x19, 0x15,
6a7eba24 682 0x19, 0x19, 0x17, 0x15,
8c2ba441
JFM
683 0x17, 0x17, 0x1b, 0x1d, 0x25, 0x21, 0x1b, 0x1d, 0x23, 0x1d, 0x17, 0x17,
684 0x21, 0x2e, 0x21, 0x23,
685 0x27, 0x29, 0x2c, 0x2c, 0x2c, 0x19, 0x1f, 0x30, 0x32, 0x2e, 0x29, 0x32,
686 0x25, 0x29, 0x2c, 0x29,
687 0x06, 0x08, 0x08, 0x0a, 0x08, 0x0a, 0x13, 0x0a, 0x0a, 0x13, 0x29, 0x1b,
688 0x17, 0x1b, 0x29, 0x29,
6a7eba24
JFM
689 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
690 0x29, 0x29, 0x29, 0x29,
691 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
692 0x29, 0x29, 0x29, 0x29,
693 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
694 0x29, 0x29, 0x29, 0x29
695};
696
8295d99e 697/* read <len> bytes to gspca_dev->usb_buf */
739570bb
JFM
698static void reg_r(struct gspca_dev *gspca_dev,
699 __u16 value, int len)
6a7eba24 700{
8295d99e
JFM
701#ifdef GSPCA_DEBUG
702 if (len > USB_BUF_SZ) {
703 err("reg_r: buffer overflow");
704 return;
705 }
706#endif
739570bb
JFM
707 usb_control_msg(gspca_dev->dev,
708 usb_rcvctrlpipe(gspca_dev->dev, 0),
6a7eba24
JFM
709 0,
710 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
711 value, 0,
739570bb 712 gspca_dev->usb_buf, len,
6a7eba24 713 500);
60017617 714 PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
6a7eba24
JFM
715}
716
60017617
JFM
717static void reg_w1(struct gspca_dev *gspca_dev,
718 __u16 value,
719 __u8 data)
720{
721 PDEBUG(D_USBO, "reg_w1 [%02x] = %02x", value, data);
722 gspca_dev->usb_buf[0] = data;
723 usb_control_msg(gspca_dev->dev,
724 usb_sndctrlpipe(gspca_dev->dev, 0),
725 0x08,
726 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
727 value,
728 0,
729 gspca_dev->usb_buf, 1,
730 500);
731}
739570bb 732static void reg_w(struct gspca_dev *gspca_dev,
6a7eba24 733 __u16 value,
bf7f0b98 734 const __u8 *buffer,
6a7eba24
JFM
735 int len)
736{
60017617
JFM
737 PDEBUG(D_USBO, "reg_w [%02x] = %02x %02x ..",
738 value, buffer[0], buffer[1]);
8295d99e
JFM
739#ifdef GSPCA_DEBUG
740 if (len > USB_BUF_SZ) {
741 err("reg_w: buffer overflow");
742 return;
bf7f0b98 743 }
8295d99e
JFM
744#endif
745 memcpy(gspca_dev->usb_buf, buffer, len);
746 usb_control_msg(gspca_dev->dev,
747 usb_sndctrlpipe(gspca_dev->dev, 0),
748 0x08,
749 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
750 value, 0,
751 gspca_dev->usb_buf, len,
752 500);
6a7eba24
JFM
753}
754
60017617
JFM
755/* I2C write 1 byte */
756static void i2c_w1(struct gspca_dev *gspca_dev, __u8 reg, __u8 val)
6a7eba24
JFM
757{
758 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 759
60017617
JFM
760 PDEBUG(D_USBO, "i2c_w2 [%02x] = %02x", reg, val);
761 gspca_dev->usb_buf[0] = 0x81 | (2 << 4); /* = a1 */
762 gspca_dev->usb_buf[1] = sd->i2c_base;
763 gspca_dev->usb_buf[2] = reg;
764 gspca_dev->usb_buf[3] = val;
765 gspca_dev->usb_buf[4] = 0;
766 gspca_dev->usb_buf[5] = 0;
767 gspca_dev->usb_buf[6] = 0;
768 gspca_dev->usb_buf[7] = 0x10;
769 usb_control_msg(gspca_dev->dev,
770 usb_sndctrlpipe(gspca_dev->dev, 0),
771 0x08,
772 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
773 0x08, /* value = i2c */
774 0,
775 gspca_dev->usb_buf, 8,
776 500);
6a7eba24
JFM
777}
778
739570bb
JFM
779/* I2C write 8 bytes */
780static void i2c_w8(struct gspca_dev *gspca_dev,
781 const __u8 *buffer)
6a7eba24 782{
60017617
JFM
783 memcpy(gspca_dev->usb_buf, buffer, 8);
784 usb_control_msg(gspca_dev->dev,
785 usb_sndctrlpipe(gspca_dev->dev, 0),
786 0x08,
787 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
788 0x08, 0, /* value, index */
789 gspca_dev->usb_buf, 8,
790 500);
8d768e14 791 msleep(2);
6a7eba24
JFM
792}
793
739570bb
JFM
794/* read 5 bytes in gspca_dev->usb_buf */
795static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
6a7eba24
JFM
796{
797 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24
JFM
798 __u8 mode[8];
799
3647fea8 800 mode[0] = 0x81 | 0x10;
6a7eba24
JFM
801 mode[1] = sd->i2c_base;
802 mode[2] = reg;
803 mode[3] = 0;
804 mode[4] = 0;
805 mode[5] = 0;
806 mode[6] = 0;
807 mode[7] = 0x10;
739570bb 808 i2c_w8(gspca_dev, mode);
60017617 809 msleep(2);
3647fea8 810 mode[0] = 0x81 | (5 << 4) | 0x02;
6a7eba24 811 mode[2] = 0;
739570bb 812 i2c_w8(gspca_dev, mode);
60017617 813 msleep(2);
739570bb 814 reg_r(gspca_dev, 0x0a, 5);
6a7eba24
JFM
815}
816
817static int probesensor(struct gspca_dev *gspca_dev)
818{
60017617 819 i2c_w1(gspca_dev, 0x02, 0); /* sensor wakeup */
6a7eba24 820 msleep(10);
60017617 821 reg_w1(gspca_dev, 0x02, 0x66); /* Gpio on */
6a7eba24 822 msleep(10);
739570bb
JFM
823 i2c_r5(gspca_dev, 0); /* read sensor id */
824 if (gspca_dev->usb_buf[0] == 0x02
825 && gspca_dev->usb_buf[1] == 0x09
826 && gspca_dev->usb_buf[2] == 0x01
827 && gspca_dev->usb_buf[3] == 0x00
828 && gspca_dev->usb_buf[4] == 0x00) {
6a7eba24 829 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
577cbf49 830 return 0;
6a7eba24 831 }
60017617 832 PDEBUG(D_PROBE, "Find Sensor 0x%02x 0x%02x 0x%02x",
739570bb
JFM
833 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
834 gspca_dev->usb_buf[2]);
6a7eba24
JFM
835 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
836 return -ENODEV;
837}
838
839static int configure_gpio(struct gspca_dev *gspca_dev,
a5ae2062 840 const __u8 *sn9c1xx)
6a7eba24
JFM
841{
842 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062
JFM
843 const __u8 *reg9a;
844 static const __u8 reg9a_def[] =
6a7eba24 845 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
a5ae2062 846 static const __u8 reg9a_sn9c325[] =
6a7eba24 847 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
8f47a3ce 848 static const __u8 regd4[] = {0x60, 0x00, 0x00};
6a7eba24 849
60017617 850 reg_w1(gspca_dev, 0xf1, 0x00);
05b809c7 851 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
6a7eba24
JFM
852
853 /* configure gpio */
739570bb
JFM
854 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
855 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
60017617 856 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm len was 3 */
3647fea8
HG
857 switch (sd->bridge) {
858 case BRIDGE_SN9C325:
6a7eba24
JFM
859 reg9a = reg9a_sn9c325;
860 break;
6a7eba24
JFM
861 default:
862 reg9a = reg9a_def;
863 break;
864 }
739570bb 865 reg_w(gspca_dev, 0x9a, reg9a, 6);
6a7eba24 866
8f47a3ce 867 reg_w(gspca_dev, 0xd4, regd4, sizeof regd4); /*fixme:jfm was 60 only*/
6a7eba24 868
739570bb 869 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
6a7eba24 870
d2d16e90
JFM
871 switch (sd->sensor) {
872 case SENSOR_OM6802:
4f30f6cf 873 reg_w1(gspca_dev, 0x02, 0x71);
d2d16e90
JFM
874 reg_w1(gspca_dev, 0x01, 0x42);
875 reg_w1(gspca_dev, 0x17, 0x64);
876 reg_w1(gspca_dev, 0x01, 0x42);
877 break;
05b809c7
JFM
878/*jfm: from win trace */
879 case SENSOR_OV7630:
880 reg_w1(gspca_dev, 0x01, 0x61);
881 reg_w1(gspca_dev, 0x17, 0xe2);
882 reg_w1(gspca_dev, 0x01, 0x60);
883 reg_w1(gspca_dev, 0x01, 0x40);
884 break;
d2d16e90 885 case SENSOR_OV7648:
6270330a
JFM
886 reg_w1(gspca_dev, 0x01, 0x63);
887 reg_w1(gspca_dev, 0x17, 0x20);
60017617 888 reg_w1(gspca_dev, 0x01, 0x42);
6a7eba24 889 break;
91de65ac
JFM
890/*jfm: from win trace */
891 case SENSOR_OV7660:
1432f306
JFM
892 if (sd->bridge == BRIDGE_SN9C120) {
893 reg_w1(gspca_dev, 0x01, 0x61);
894 reg_w1(gspca_dev, 0x17, 0x20);
895 reg_w1(gspca_dev, 0x01, 0x60);
896 reg_w1(gspca_dev, 0x01, 0x40);
897 break;
898 }
899 /* fall thru */
6a7eba24 900 default:
60017617
JFM
901 reg_w1(gspca_dev, 0x01, 0x43);
902 reg_w1(gspca_dev, 0x17, 0x61);
903 reg_w1(gspca_dev, 0x01, 0x42);
d2d16e90
JFM
904 if (sd->sensor == SENSOR_HV7131R) {
905 if (probesensor(gspca_dev) < 0)
906 return -ENODEV;
907 }
908 break;
6a7eba24
JFM
909 }
910 return 0;
911}
912
913static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
914{
915 int i = 0;
a5ae2062 916 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
6a7eba24
JFM
917 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
918
919 while (hv7131r_sensor_init[i][0]) {
739570bb 920 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
6a7eba24
JFM
921 i++;
922 }
739570bb 923 i2c_w8(gspca_dev, SetSensorClk);
6a7eba24
JFM
924}
925
926static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
927{
928 int i = 0;
6a7eba24
JFM
929
930 while (mi0360_sensor_init[i][0]) {
739570bb 931 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
6a7eba24
JFM
932 i++;
933 }
934}
935
936static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
937{
938 int i = 0;
6a7eba24
JFM
939
940 while (mo4000_sensor_init[i][0]) {
739570bb 941 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
6a7eba24
JFM
942 i++;
943 }
944}
945
d2d16e90
JFM
946static void om6802_InitSensor(struct gspca_dev *gspca_dev)
947{
948 int i = 0;
949
950 while (om6802_sensor_init[i][0]) {
951 i2c_w8(gspca_dev, om6802_sensor_init[i]);
952 i++;
953 }
954}
955
6ab0b174
JFM
956static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
957{
958 int i = 0;
959
05b809c7
JFM
960 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
961 i++;
962 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
6ab0b174
JFM
963 i++;
964 msleep(20);
05b809c7
JFM
965 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
966 i++;
967 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
968 i++;
969 msleep(20);
970 i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
971 i++;
972/*jfm:win i2c_r from 00 to 80*/
973
6ab0b174
JFM
974 while (ov7630_sensor_init[i][0]) {
975 i2c_w8(gspca_dev, ov7630_sensor_init[i]);
976 i++;
977 }
978}
979
6a7eba24
JFM
980static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
981{
6a7eba24
JFM
982 int i = 0;
983
6270330a
JFM
984 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
985 i++;
986/* win: dble reset */
987 i2c_w8(gspca_dev, ov7648_sensor_init[i]); /* reset */
988 i++;
989 msleep(20);
990/* win: i2c reg read 00..7f */
6a7eba24 991 while (ov7648_sensor_init[i][0]) {
739570bb 992 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
6a7eba24
JFM
993 i++;
994 }
995}
996
997static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
998{
999 int i = 0;
6a7eba24 1000
60017617
JFM
1001 i2c_w8(gspca_dev, ov7660_sensor_init[i]); /* reset SCCB */
1002 i++;
1003 msleep(20);
6a7eba24 1004 while (ov7660_sensor_init[i][0]) {
739570bb 1005 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
6a7eba24
JFM
1006 i++;
1007 }
1008}
1009
1010/* this function is called at probe time */
1011static int sd_config(struct gspca_dev *gspca_dev,
1012 const struct usb_device_id *id)
1013{
1014 struct sd *sd = (struct sd *) gspca_dev;
1015 struct cam *cam;
6a7eba24
JFM
1016
1017 cam = &gspca_dev->cam;
6a7eba24
JFM
1018 cam->cam_mode = vga_mode;
1019 cam->nmodes = ARRAY_SIZE(vga_mode);
a5ae2062 1020
9d64fdb1
JFM
1021 sd->bridge = id->driver_info >> 16;
1022 sd->sensor = id->driver_info >> 8;
1023 sd->i2c_base = id->driver_info;
1024
a5ae2062
JFM
1025 sd->brightness = BRIGHTNESS_DEF;
1026 sd->contrast = CONTRAST_DEF;
1027 sd->colors = COLOR_DEF;
403123d2
JFM
1028 sd->blue = BLUE_BALANCE_DEF;
1029 sd->red = RED_BALANCE_DEF;
a5ae2062 1030 sd->autogain = AUTOGAIN_DEF;
cebf3b67 1031 sd->ag_cnt = -1;
0cae8964
JFM
1032 sd->vflip = VFLIP_DEF;
1033 sd->infrared = INFRARED_DEF;
cebf3b67 1034
577cbf49 1035 gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
6a7eba24
JFM
1036 return 0;
1037}
1038
012d6b02
JFM
1039/* this function is called at probe and resume time */
1040static int sd_init(struct gspca_dev *gspca_dev)
6a7eba24
JFM
1041{
1042 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 1043 __u8 regGpio[] = { 0x29, 0x74 };
60017617 1044 __u8 regF1;
6a7eba24 1045
3647fea8 1046 /* setup a selector by bridge */
60017617 1047 reg_w1(gspca_dev, 0xf1, 0x01);
739570bb 1048 reg_r(gspca_dev, 0x00, 1);
8f47a3ce
JFM
1049 reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
1050 reg_r(gspca_dev, 0x00, 1); /* get sonix chip id */
739570bb 1051 regF1 = gspca_dev->usb_buf[0];
8f47a3ce 1052 PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
3647fea8
HG
1053 switch (sd->bridge) {
1054 case BRIDGE_SN9C102P:
6a7eba24
JFM
1055 if (regF1 != 0x11)
1056 return -ENODEV;
60017617 1057 reg_w1(gspca_dev, 0x02, regGpio[1]);
6a7eba24 1058 break;
3647fea8 1059 case BRIDGE_SN9C105:
6a7eba24
JFM
1060 if (regF1 != 0x11)
1061 return -ENODEV;
674cbc69 1062 reg_w(gspca_dev, 0x01, regGpio, 2);
6a7eba24 1063 break;
3647fea8 1064 case BRIDGE_SN9C120:
6a7eba24
JFM
1065 if (regF1 != 0x12)
1066 return -ENODEV;
1067 regGpio[1] = 0x70;
674cbc69 1068 reg_w(gspca_dev, 0x01, regGpio, 2);
6a7eba24
JFM
1069 break;
1070 default:
60017617 1071/* case BRIDGE_SN9C110: */
3647fea8 1072/* case BRIDGE_SN9C325: */
6a7eba24
JFM
1073 if (regF1 != 0x12)
1074 return -ENODEV;
60017617 1075 reg_w1(gspca_dev, 0x02, 0x62);
6a7eba24
JFM
1076 break;
1077 }
1078
759aa3c2 1079 reg_w1(gspca_dev, 0xf1, 0x01);
6a7eba24
JFM
1080
1081 return 0;
1082}
1083
1084static unsigned int setexposure(struct gspca_dev *gspca_dev,
1085 unsigned int expo)
1086{
1087 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1088 static const __u8 doit[] = /* update sensor */
6a7eba24 1089 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
a5ae2062 1090 static const __u8 sensorgo[] = /* sensor on */
6a7eba24 1091 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
a5ae2062 1092 static const __u8 gainMo[] =
6a7eba24
JFM
1093 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1094
1095 switch (sd->sensor) {
1096 case SENSOR_HV7131R: {
1097 __u8 Expodoit[] =
1098 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1099
1100 Expodoit[3] = expo >> 16;
1101 Expodoit[4] = expo >> 8;
1102 Expodoit[5] = expo;
739570bb 1103 i2c_w8(gspca_dev, Expodoit);
6a7eba24
JFM
1104 break;
1105 }
1106 case SENSOR_MI0360: {
1107 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1108 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1109
1110 if (expo > 0x0635)
1111 expo = 0x0635;
1112 else if (expo < 0x0001)
1113 expo = 0x0001;
1114 expoMi[3] = expo >> 8;
1115 expoMi[4] = expo;
739570bb
JFM
1116 i2c_w8(gspca_dev, expoMi);
1117 i2c_w8(gspca_dev, doit);
1118 i2c_w8(gspca_dev, sensorgo);
6a7eba24
JFM
1119 break;
1120 }
1121 case SENSOR_MO4000: {
1122 __u8 expoMof[] =
1123 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1124 __u8 expoMo10[] =
1125 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1126
1127 if (expo > 0x1fff)
1128 expo = 0x1fff;
1129 else if (expo < 0x0001)
1130 expo = 0x0001;
1131 expoMof[3] = (expo & 0x03fc) >> 2;
739570bb 1132 i2c_w8(gspca_dev, expoMof);
6a7eba24
JFM
1133 expoMo10[3] = ((expo & 0x1c00) >> 10)
1134 | ((expo & 0x0003) << 4);
739570bb
JFM
1135 i2c_w8(gspca_dev, expoMo10);
1136 i2c_w8(gspca_dev, gainMo);
956e42d2 1137 PDEBUG(D_CONF, "set exposure %d",
6a7eba24
JFM
1138 ((expoMo10[3] & 0x07) << 10)
1139 | (expoMof[3] << 2)
1140 | ((expoMo10[3] & 0x30) >> 4));
1141 break;
1142 }
d2d16e90
JFM
1143 case SENSOR_OM6802: {
1144 __u8 gainOm[] =
1145 { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
1146
1147 if (expo > 0x03ff)
1148 expo = 0x03ff;
1149 if (expo < 0x0001)
1150 expo = 0x0001;
1151 gainOm[3] = expo >> 2;
1152 i2c_w8(gspca_dev, gainOm);
d55b83d3 1153 reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
d2d16e90
JFM
1154 PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
1155 break;
1156 }
6a7eba24
JFM
1157 }
1158 return expo;
1159}
1160
1161static void setbrightness(struct gspca_dev *gspca_dev)
1162{
1163 struct sd *sd = (struct sd *) gspca_dev;
1164 unsigned int expo;
1165 __u8 k2;
1166
b1b056a5 1167 k2 = ((int) sd->brightness - 0x8000) >> 10;
6a7eba24
JFM
1168 switch (sd->sensor) {
1169 case SENSOR_HV7131R:
1170 expo = sd->brightness << 4;
1171 if (expo > 0x002dc6c0)
1172 expo = 0x002dc6c0;
1173 else if (expo < 0x02a0)
1174 expo = 0x02a0;
1175 sd->exposure = setexposure(gspca_dev, expo);
1176 break;
1177 case SENSOR_MI0360:
6a7eba24
JFM
1178 case SENSOR_MO4000:
1179 expo = sd->brightness >> 4;
1180 sd->exposure = setexposure(gspca_dev, expo);
1181 break;
d2d16e90
JFM
1182 case SENSOR_OM6802:
1183 expo = sd->brightness >> 6;
1184 sd->exposure = setexposure(gspca_dev, expo);
b1b056a5 1185 k2 = sd->brightness >> 11;
d2d16e90 1186 break;
6a7eba24
JFM
1187 }
1188
91bd3412 1189 reg_w1(gspca_dev, 0x96, k2); /* color matrix Y offset */
6a7eba24
JFM
1190}
1191
1192static void setcontrast(struct gspca_dev *gspca_dev)
1193{
1194 struct sd *sd = (struct sd *) gspca_dev;
1195 __u8 k2;
577cbf49 1196 __u8 contrast[6];
6a7eba24 1197
91bd3412
JFM
1198 k2 = sd->contrast * 0x30 / (CONTRAST_MAX + 1) + 0x10; /* 10..40 */
1199 contrast[0] = (k2 + 1) / 2; /* red */
577cbf49 1200 contrast[1] = 0;
91bd3412 1201 contrast[2] = k2; /* green */
577cbf49 1202 contrast[3] = 0;
91bd3412 1203 contrast[4] = (k2 + 1) / 5; /* blue */
577cbf49
JFM
1204 contrast[5] = 0;
1205 reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
6a7eba24
JFM
1206}
1207
1208static void setcolors(struct gspca_dev *gspca_dev)
1209{
1210 struct sd *sd = (struct sd *) gspca_dev;
403123d2 1211 int i, v;
bd088835 1212 __u8 reg8a[12]; /* U & V gains */
403123d2
JFM
1213 static __s16 uv[6] = { /* same as reg84 in signed decimal */
1214 -24, -38, 64, /* UR UG UB */
1215 62, -51, -9 /* VR VG VB */
1216 };
1217 for (i = 0; i < 6; i++) {
1218 v = uv[i] * sd->colors / COLOR_DEF;
bd088835
JFM
1219 reg8a[i * 2] = v;
1220 reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
d55b83d3 1221 }
bd088835 1222 reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
403123d2
JFM
1223}
1224
1225static void setredblue(struct gspca_dev *gspca_dev)
1226{
1227 struct sd *sd = (struct sd *) gspca_dev;
1228
1229 reg_w1(gspca_dev, 0x05, sd->red);
9c5f70f2 1230/* reg_w1(gspca_dev, 0x07, 32); */
403123d2 1231 reg_w1(gspca_dev, 0x06, sd->blue);
6a7eba24
JFM
1232}
1233
cebf3b67
JFM
1234static void setautogain(struct gspca_dev *gspca_dev)
1235{
1236 struct sd *sd = (struct sd *) gspca_dev;
1237
f50ba1be
JFM
1238 if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
1239 return;
1240 if (sd->autogain)
1241 sd->ag_cnt = AG_CNT_START;
1242 else
1243 sd->ag_cnt = -1;
cebf3b67
JFM
1244}
1245
6c86274f
JFM
1246static void setvflip(struct sd *sd)
1247{
6c86274f
JFM
1248 i2c_w1(&sd->gspca_dev, 0x75, /* COMN */
1249 sd->vflip ? 0x82 : 0x02);
1250}
1251
0cae8964
JFM
1252static void setinfrared(struct sd *sd)
1253{
1254/*fixme: different sequence for StarCam Clip and StarCam 370i */
1255/* Clip */
1256 i2c_w1(&sd->gspca_dev, 0x02, /* gpio */
1257 sd->infrared ? 0x66 : 0x64);
1258}
1259
6a7eba24 1260/* -- start the camera -- */
72ab97ce 1261static int sd_start(struct gspca_dev *gspca_dev)
6a7eba24
JFM
1262{
1263 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 1264 int i;
8f47a3ce 1265 __u8 reg1, reg17, reg18;
a5ae2062 1266 const __u8 *sn9c1xx;
6a7eba24 1267 int mode;
a5ae2062
JFM
1268 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1269 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
a5ae2062 1270 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
6ab0b174 1271 static const __u8 CE_ov76xx[] =
674cbc69 1272 { 0x32, 0xdd, 0x32, 0xdd };
6a7eba24
JFM
1273
1274 sn9c1xx = sn_tb[(int) sd->sensor];
1275 configure_gpio(gspca_dev, sn9c1xx);
1276
60017617
JFM
1277 reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
1278 reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
1279 reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
1280 reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
1281 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
1282 reg_w1(gspca_dev, 0xd2, 0x6a); /* DC29 */
1283 reg_w1(gspca_dev, 0xd3, 0x50);
1284 reg_w1(gspca_dev, 0xc6, 0x00);
1285 reg_w1(gspca_dev, 0xc7, 0x00);
1286 reg_w1(gspca_dev, 0xc8, 0x50);
1287 reg_w1(gspca_dev, 0xc9, 0x3c);
60017617 1288 reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
6ab0b174
JFM
1289 switch (sd->sensor) {
1290 case SENSOR_OV7630:
1291 reg17 = 0xe2;
1292 break;
1293 case SENSOR_OV7648:
6270330a 1294 reg17 = 0x20;
568788a7 1295 break;
6ab0b174
JFM
1296/*jfm: from win trace */
1297 case SENSOR_OV7660:
1432f306
JFM
1298 if (sd->bridge == BRIDGE_SN9C120) {
1299 reg17 = 0xa0;
1300 break;
1301 }
1302 /* fall thru */
568788a7 1303 default:
8f47a3ce 1304 reg17 = 0x60;
568788a7
JFM
1305 break;
1306 }
8f47a3ce 1307 reg_w1(gspca_dev, 0x17, reg17);
1432f306 1308/* set reg1 was here */
403123d2
JFM
1309 reg_w1(gspca_dev, 0x05, sn9c1xx[5]); /* red */
1310 reg_w1(gspca_dev, 0x07, sn9c1xx[7]); /* green */
1311 reg_w1(gspca_dev, 0x06, sn9c1xx[6]); /* blue */
60017617 1312 reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
05b809c7
JFM
1313 reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
1314 for (i = 0; i < 8; i++)
1315 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
674cbc69 1316 switch (sd->sensor) {
6270330a
JFM
1317 case SENSOR_OV7648:
1318 reg_w1(gspca_dev, 0x9a, 0x0a);
1319 reg_w1(gspca_dev, 0x99, 0x60);
1320 break;
674cbc69 1321 case SENSOR_OV7660:
1432f306
JFM
1322 if (sd->bridge == BRIDGE_SN9C120) {
1323 reg_w1(gspca_dev, 0x9a, 0x05);
1324 break;
1325 }
1326 /* fall thru */
674cbc69 1327 default:
60017617
JFM
1328 reg_w1(gspca_dev, 0x9a, 0x08);
1329 reg_w1(gspca_dev, 0x99, 0x59);
674cbc69
JFM
1330 break;
1331 }
6a7eba24 1332
c2446b3e 1333 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
60017617 1334 if (mode)
1432f306 1335 reg1 = 0x46; /* 320x240: clk 48Mhz, video trf enable */
60017617 1336 else
1432f306
JFM
1337 reg1 = 0x06; /* 640x480: clk 24Mhz, video trf enable */
1338 reg17 = 0x61; /* 0x:20: enable sensor clock */
6a7eba24
JFM
1339 switch (sd->sensor) {
1340 case SENSOR_HV7131R:
1341 hv7131R_InitSensor(gspca_dev);
6a7eba24
JFM
1342 break;
1343 case SENSOR_MI0360:
1344 mi0360_InitSensor(gspca_dev);
6a7eba24
JFM
1345 break;
1346 case SENSOR_MO4000:
1347 mo4000_InitSensor(gspca_dev);
1348 if (mode) {
1349/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1350 reg1 = 0x06; /* clk 24Mz */
1351 } else {
1352 reg17 = 0x22; /* 640 MCKSIZE */
60017617 1353/* reg1 = 0x06; * 640 clk 24Mz (done) */
6a7eba24
JFM
1354 }
1355 break;
d2d16e90
JFM
1356 case SENSOR_OM6802:
1357 om6802_InitSensor(gspca_dev);
d2d16e90
JFM
1358 reg17 = 0x64; /* 640 MCKSIZE */
1359 break;
6ab0b174
JFM
1360 case SENSOR_OV7630:
1361 ov7630_InitSensor(gspca_dev);
6c86274f 1362 setvflip(sd);
6ab0b174 1363 reg17 = 0xe2;
5b064da8 1364 reg1 = 0x44;
6ab0b174 1365 break;
6a7eba24 1366 case SENSOR_OV7648:
60017617 1367 ov7648_InitSensor(gspca_dev);
6270330a
JFM
1368 reg17 = 0x21;
1369/* reg1 = 0x42; * 42 - 46? */
6a7eba24
JFM
1370 break;
1371 default:
1372/* case SENSOR_OV7660: */
1373 ov7660_InitSensor(gspca_dev);
daa5cb42
JFM
1374 if (sd->bridge == BRIDGE_SN9C120) {
1375 if (mode) { /* 320x240 - 160x120 */
1432f306
JFM
1376 reg17 = 0xa2;
1377 reg1 = 0x44; /* 48 Mhz, video trf eneble */
1432f306 1378 }
daa5cb42
JFM
1379 } else {
1380 reg17 = 0x22;
1381 reg1 = 0x06; /* 24 Mhz, video trf eneble
1382 * inverse power down */
6a7eba24
JFM
1383 }
1384 break;
1385 }
739570bb 1386 reg_w(gspca_dev, 0xc0, C0, 6);
8f47a3ce 1387 reg_w(gspca_dev, 0xca, CA, 4);
6ab0b174
JFM
1388 switch (sd->sensor) {
1389 case SENSOR_OV7630:
1390 case SENSOR_OV7648:
674cbc69 1391 case SENSOR_OV7660:
6ab0b174 1392 reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
6a7eba24
JFM
1393 break;
1394 default:
739570bb 1395 reg_w(gspca_dev, 0xce, CE, 4);
6a7eba24
JFM
1396 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1397 break;
1398 }
1399
1400 /* here change size mode 0 -> VGA; 1 -> CIF */
8f47a3ce
JFM
1401 reg18 = sn9c1xx[0x18] | (mode << 4);
1402 reg_w1(gspca_dev, 0x18, reg18 | 0x40);
6a7eba24 1403
739570bb
JFM
1404 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1405 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
6a7eba24 1406
8f47a3ce 1407 reg_w1(gspca_dev, 0x18, reg18);
6a7eba24 1408
60017617 1409 reg_w1(gspca_dev, 0x17, reg17);
1432f306 1410 reg_w1(gspca_dev, 0x01, reg1);
05b809c7 1411 switch (sd->sensor) {
05b809c7 1412 case SENSOR_MI0360:
0cae8964 1413 setinfrared(sd);
05b809c7 1414 break;
79a9098a
JFM
1415 case SENSOR_OV7630:
1416 setvflip(sd);
05b809c7
JFM
1417 break;
1418 }
91bd3412
JFM
1419 setbrightness(gspca_dev);
1420 setcontrast(gspca_dev);
cebf3b67 1421 setautogain(gspca_dev);
72ab97ce 1422 return 0;
6a7eba24
JFM
1423}
1424
1425static void sd_stopN(struct gspca_dev *gspca_dev)
1426{
1427 struct sd *sd = (struct sd *) gspca_dev;
a5ae2062 1428 static const __u8 stophv7131[] =
6a7eba24 1429 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
a5ae2062 1430 static const __u8 stopmi0360[] =
6a7eba24 1431 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
6270330a
JFM
1432 static const __u8 stopov7648[] =
1433 { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
6a7eba24 1434 __u8 data;
a5ae2062 1435 const __u8 *sn9c1xx;
6a7eba24
JFM
1436
1437 data = 0x0b;
1438 switch (sd->sensor) {
1439 case SENSOR_HV7131R:
739570bb 1440 i2c_w8(gspca_dev, stophv7131);
6a7eba24
JFM
1441 data = 0x2b;
1442 break;
1443 case SENSOR_MI0360:
739570bb 1444 i2c_w8(gspca_dev, stopmi0360);
6a7eba24
JFM
1445 data = 0x29;
1446 break;
6a7eba24 1447 case SENSOR_OV7648:
6270330a
JFM
1448 i2c_w8(gspca_dev, stopov7648);
1449 /* fall thru */
1450 case SENSOR_OV7630:
6a7eba24
JFM
1451 data = 0x29;
1452 break;
1453 default:
8f47a3ce 1454/* case SENSOR_MO4000: */
6a7eba24
JFM
1455/* case SENSOR_OV7660: */
1456 break;
1457 }
1458 sn9c1xx = sn_tb[(int) sd->sensor];
60017617
JFM
1459 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1460 reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
1461 reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
1462 reg_w1(gspca_dev, 0x01, data);
759aa3c2 1463 reg_w1(gspca_dev, 0xf1, 0x00);
6a7eba24
JFM
1464}
1465
cebf3b67 1466static void do_autogain(struct gspca_dev *gspca_dev)
6a7eba24
JFM
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
6a7eba24 1469 int delta;
cebf3b67 1470 int expotimes;
6a7eba24
JFM
1471 __u8 luma_mean = 130;
1472 __u8 luma_delta = 20;
1473
cebf3b67
JFM
1474 /* Thanks S., without your advice, autobright should not work :) */
1475 if (sd->ag_cnt < 0)
1476 return;
1477 if (--sd->ag_cnt >= 0)
1478 return;
1479 sd->ag_cnt = AG_CNT_START;
1480
1481 delta = atomic_read(&sd->avg_lum);
1482 PDEBUG(D_FRAM, "mean lum %d", delta);
6a7eba24
JFM
1483 if (delta < luma_mean - luma_delta ||
1484 delta > luma_mean + luma_delta) {
1485 switch (sd->sensor) {
1486 case SENSOR_HV7131R:
1487 expotimes = sd->exposure >> 8;
1488 expotimes += (luma_mean - delta) >> 4;
1489 if (expotimes < 0)
1490 expotimes = 0;
1491 sd->exposure = setexposure(gspca_dev,
1492 (unsigned int) (expotimes << 8));
1493 break;
cebf3b67
JFM
1494 default:
1495/* case SENSOR_MO4000: */
1496/* case SENSOR_MI0360: */
d2d16e90 1497/* case SENSOR_OM6802: */
6a7eba24
JFM
1498 expotimes = sd->exposure;
1499 expotimes += (luma_mean - delta) >> 6;
1500 if (expotimes < 0)
1501 expotimes = 0;
1502 sd->exposure = setexposure(gspca_dev,
1503 (unsigned int) expotimes);
403123d2 1504 setredblue(gspca_dev);
6a7eba24
JFM
1505 break;
1506 }
1507 }
1508}
1509
cebf3b67
JFM
1510/* scan the URB packets */
1511/* This function is run at interrupt level. */
6a7eba24
JFM
1512static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1513 struct gspca_frame *frame, /* target */
a5ae2062 1514 __u8 *data, /* isoc packet */
6a7eba24
JFM
1515 int len) /* iso packet length */
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518 int sof, avg_lum;
1519
1520 sof = len - 64;
1521 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1522
1523 /* end of frame */
1524 gspca_frame_add(gspca_dev, LAST_PACKET,
1525 frame, data, sof + 2);
1526 if (sd->ag_cnt < 0)
1527 return;
6a7eba24
JFM
1528/* w1 w2 w3 */
1529/* w4 w5 w6 */
1530/* w7 w8 */
1531/* w4 */
1532 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1533/* w6 */
1534 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1535/* w2 */
1536 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1537/* w8 */
1538 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1539/* w5 */
1540 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1541 avg_lum >>= 4;
cebf3b67 1542 atomic_set(&sd->avg_lum, avg_lum);
6a7eba24
JFM
1543 return;
1544 }
1545 if (gspca_dev->last_packet_type == LAST_PACKET) {
1546
1547 /* put the JPEG 422 header */
36e819db 1548 jpeg_put_header(gspca_dev, frame, 0x21);
6a7eba24
JFM
1549 }
1550 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1551}
1552
6a7eba24
JFM
1553static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 sd->brightness = val;
91bd3412
JFM
1558 if (gspca_dev->streaming)
1559 setbrightness(gspca_dev);
6a7eba24
JFM
1560 return 0;
1561}
1562
1563static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1564{
1565 struct sd *sd = (struct sd *) gspca_dev;
1566
6a7eba24
JFM
1567 *val = sd->brightness;
1568 return 0;
1569}
1570
1571static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1572{
1573 struct sd *sd = (struct sd *) gspca_dev;
1574
1575 sd->contrast = val;
91bd3412
JFM
1576 if (gspca_dev->streaming)
1577 setcontrast(gspca_dev);
6a7eba24
JFM
1578 return 0;
1579}
1580
1581static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1582{
1583 struct sd *sd = (struct sd *) gspca_dev;
1584
1585 *val = sd->contrast;
1586 return 0;
1587}
1588
1589static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1590{
1591 struct sd *sd = (struct sd *) gspca_dev;
1592
1593 sd->colors = val;
1594 if (gspca_dev->streaming)
1595 setcolors(gspca_dev);
1596 return 0;
1597}
1598
1599static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1600{
1601 struct sd *sd = (struct sd *) gspca_dev;
1602
1603 *val = sd->colors;
1604 return 0;
1605}
1606
403123d2
JFM
1607static int sd_setblue_balance(struct gspca_dev *gspca_dev, __s32 val)
1608{
1609 struct sd *sd = (struct sd *) gspca_dev;
1610
1611 sd->blue = val;
1612 if (gspca_dev->streaming)
1613 setredblue(gspca_dev);
1614 return 0;
1615}
1616
1617static int sd_getblue_balance(struct gspca_dev *gspca_dev, __s32 *val)
1618{
1619 struct sd *sd = (struct sd *) gspca_dev;
1620
1621 *val = sd->blue;
1622 return 0;
1623}
1624
1625static int sd_setred_balance(struct gspca_dev *gspca_dev, __s32 val)
1626{
1627 struct sd *sd = (struct sd *) gspca_dev;
1628
1629 sd->red = val;
1630 if (gspca_dev->streaming)
1631 setredblue(gspca_dev);
1632 return 0;
1633}
1634
1635static int sd_getred_balance(struct gspca_dev *gspca_dev, __s32 *val)
1636{
1637 struct sd *sd = (struct sd *) gspca_dev;
1638
1639 *val = sd->red;
1640 return 0;
1641}
1642
6a7eba24
JFM
1643static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1644{
1645 struct sd *sd = (struct sd *) gspca_dev;
1646
1647 sd->autogain = val;
cebf3b67
JFM
1648 if (gspca_dev->streaming)
1649 setautogain(gspca_dev);
6a7eba24
JFM
1650 return 0;
1651}
1652
1653static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1654{
1655 struct sd *sd = (struct sd *) gspca_dev;
1656
1657 *val = sd->autogain;
1658 return 0;
1659}
1660
6c86274f
JFM
1661static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
1662{
1663 struct sd *sd = (struct sd *) gspca_dev;
1664
1665 sd->vflip = val;
79a9098a
JFM
1666 if (gspca_dev->streaming)
1667 setvflip(sd);
6c86274f
JFM
1668 return 0;
1669}
1670
1671static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
1672{
1673 struct sd *sd = (struct sd *) gspca_dev;
1674
1675 *val = sd->vflip;
1676 return 0;
1677}
1678
0cae8964
JFM
1679static int sd_setinfrared(struct gspca_dev *gspca_dev, __s32 val)
1680{
1681 struct sd *sd = (struct sd *) gspca_dev;
1682
1683 sd->infrared = val;
1684 if (gspca_dev->streaming)
1685 setinfrared(sd);
1686 return 0;
1687}
1688
1689static int sd_getinfrared(struct gspca_dev *gspca_dev, __s32 *val)
1690{
1691 struct sd *sd = (struct sd *) gspca_dev;
1692
1693 *val = sd->infrared;
1694 return 0;
1695}
1696
6a7eba24 1697/* sub-driver description */
a5ae2062 1698static const struct sd_desc sd_desc = {
6a7eba24
JFM
1699 .name = MODULE_NAME,
1700 .ctrls = sd_ctrls,
1701 .nctrls = ARRAY_SIZE(sd_ctrls),
1702 .config = sd_config,
012d6b02 1703 .init = sd_init,
6a7eba24
JFM
1704 .start = sd_start,
1705 .stopN = sd_stopN,
6a7eba24 1706 .pkt_scan = sd_pkt_scan,
cebf3b67 1707 .dq_callback = do_autogain,
6a7eba24
JFM
1708};
1709
1710/* -- module initialisation -- */
9d64fdb1
JFM
1711#define BSI(bridge, sensor, i2c_addr) \
1712 .driver_info = (BRIDGE_ ## bridge << 16) \
1713 | (SENSOR_ ## sensor << 8) \
1714 | (i2c_addr)
a5ae2062 1715static const __devinitdata struct usb_device_id device_table[] = {
222a07ff 1716#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
9d64fdb1 1717 {USB_DEVICE(0x0458, 0x7025), BSI(SN9C120, MI0360, 0x5d)},
7b537391 1718 {USB_DEVICE(0x0458, 0x702e), BSI(SN9C120, OV7660, 0x21)},
a08d81af 1719#endif
9d64fdb1
JFM
1720 {USB_DEVICE(0x045e, 0x00f5), BSI(SN9C105, OV7660, 0x21)},
1721 {USB_DEVICE(0x045e, 0x00f7), BSI(SN9C105, OV7660, 0x21)},
a08d81af 1722#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
9d64fdb1 1723 {USB_DEVICE(0x0471, 0x0327), BSI(SN9C105, MI0360, 0x5d)},
c41492c8 1724#endif
7e21fda1 1725 {USB_DEVICE(0x0471, 0x0328), BSI(SN9C105, MI0360, 0x5d)},
9d64fdb1 1726 {USB_DEVICE(0x0471, 0x0330), BSI(SN9C105, MI0360, 0x5d)},
3319dc98 1727 {USB_DEVICE(0x06f8, 0x3004), BSI(SN9C105, OV7660, 0x21)},
9d64fdb1
JFM
1728 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, HV7131R, 0x11)},
1729/* bw600.inf:
1730 {USB_DEVICE(0x0c45, 0x6040), BSI(SN9C102P, MI0360, 0x5d)}, */
1731/* {USB_DEVICE(0x0c45, 0x603a), BSI(SN9C102P, OV7648, 0x??)}, */
1732/* {USB_DEVICE(0x0c45, 0x607a), BSI(SN9C102P, OV7648, 0x??)}, */
1733 {USB_DEVICE(0x0c45, 0x607c), BSI(SN9C102P, HV7131R, 0x11)},
1734/* {USB_DEVICE(0x0c45, 0x607e), BSI(SN9C102P, OV7630, 0x??)}, */
1735 {USB_DEVICE(0x0c45, 0x60c0), BSI(SN9C105, MI0360, 0x5d)},
1736/* {USB_DEVICE(0x0c45, 0x60c8), BSI(SN9C105, OM6801, 0x??)}, */
1737/* {USB_DEVICE(0x0c45, 0x60cc), BSI(SN9C105, HV7131GP, 0x??)}, */
1738 {USB_DEVICE(0x0c45, 0x60ec), BSI(SN9C105, MO4000, 0x21)},
1739/* {USB_DEVICE(0x0c45, 0x60ef), BSI(SN9C105, ICM105C, 0x??)}, */
1740/* {USB_DEVICE(0x0c45, 0x60fa), BSI(SN9C105, OV7648, 0x??)}, */
1741 {USB_DEVICE(0x0c45, 0x60fb), BSI(SN9C105, OV7660, 0x21)},
1742 {USB_DEVICE(0x0c45, 0x60fc), BSI(SN9C105, HV7131R, 0x11)},
3c41cb77
JFM
1743#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1744 {USB_DEVICE(0x0c45, 0x60fe), BSI(SN9C105, OV7630, 0x21)},
1745#endif
9d64fdb1
JFM
1746/* {USB_DEVICE(0x0c45, 0x6108), BSI(SN9C120, OM6801, 0x??)}, */
1747/* {USB_DEVICE(0x0c45, 0x6122), BSI(SN9C110, ICM105C, 0x??)}, */
1748/* {USB_DEVICE(0x0c45, 0x6123), BSI(SN9C110, SanyoCCD, 0x??)}, */
d2d16e90
JFM
1749 {USB_DEVICE(0x0c45, 0x6128), BSI(SN9C110, OM6802, 0x21)}, /*sn9c325?*/
1750/*bw600.inf:*/
6270330a 1751 {USB_DEVICE(0x0c45, 0x612a), BSI(SN9C120, OV7648, 0x21)}, /*sn9c110?*/
9d64fdb1 1752 {USB_DEVICE(0x0c45, 0x612c), BSI(SN9C110, MO4000, 0x21)},
6ab0b174 1753 {USB_DEVICE(0x0c45, 0x612e), BSI(SN9C110, OV7630, 0x21)},
9d64fdb1 1754/* {USB_DEVICE(0x0c45, 0x612f), BSI(SN9C110, ICM105C, 0x??)}, */
222a07ff 1755#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
9d64fdb1 1756 {USB_DEVICE(0x0c45, 0x6130), BSI(SN9C120, MI0360, 0x5d)},
222a07ff 1757#endif
9d64fdb1 1758 {USB_DEVICE(0x0c45, 0x6138), BSI(SN9C120, MO4000, 0x21)},
821ced29 1759 {USB_DEVICE(0x0c45, 0x613a), BSI(SN9C120, OV7648, 0x21)},
222a07ff 1760#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
9d64fdb1
JFM
1761 {USB_DEVICE(0x0c45, 0x613b), BSI(SN9C120, OV7660, 0x21)},
1762 {USB_DEVICE(0x0c45, 0x613c), BSI(SN9C120, HV7131R, 0x11)},
1763/* {USB_DEVICE(0x0c45, 0x613e), BSI(SN9C120, OV7630, 0x??)}, */
c41492c8 1764#endif
e546f4bb 1765 {USB_DEVICE(0x0c45, 0x6143), BSI(SN9C120, MI0360, 0x5d)},
6a7eba24
JFM
1766 {}
1767};
1768MODULE_DEVICE_TABLE(usb, device_table);
1769
1770/* -- device connect -- */
1771static int sd_probe(struct usb_interface *intf,
1772 const struct usb_device_id *id)
1773{
1774 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1775 THIS_MODULE);
1776}
1777
1778static struct usb_driver sd_driver = {
1779 .name = MODULE_NAME,
1780 .id_table = device_table,
1781 .probe = sd_probe,
1782 .disconnect = gspca_disconnect,
6a709749
JFM
1783#ifdef CONFIG_PM
1784 .suspend = gspca_suspend,
1785 .resume = gspca_resume,
1786#endif
6a7eba24
JFM
1787};
1788
1789/* -- module insert / remove -- */
1790static int __init sd_mod_init(void)
1791{
f69e9529
AK
1792 int ret;
1793 ret = usb_register(&sd_driver);
1794 if (ret < 0)
e6b14849 1795 return ret;
10b0e96e 1796 info("registered");
6a7eba24
JFM
1797 return 0;
1798}
1799static void __exit sd_mod_exit(void)
1800{
1801 usb_deregister(&sd_driver);
1802 info("deregistered");
1803}
1804
1805module_init(sd_mod_init);
1806module_exit(sd_mod_exit);