aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r--drivers/media/video/gspca/Kconfig13
-rw-r--r--drivers/media/video/gspca/Makefile29
-rw-r--r--drivers/media/video/gspca/conex.c1051
-rw-r--r--drivers/media/video/gspca/etoms.c956
-rw-r--r--drivers/media/video/gspca/gspca.c1905
-rw-r--r--drivers/media/video/gspca/gspca.h176
-rw-r--r--drivers/media/video/gspca/jpeg.h301
-rw-r--r--drivers/media/video/gspca/mars.c464
-rw-r--r--drivers/media/video/gspca/ov519.c2186
-rw-r--r--drivers/media/video/gspca/pac207.c622
-rw-r--r--drivers/media/video/gspca/pac7311.c760
-rw-r--r--drivers/media/video/gspca/sonixb.c1477
-rw-r--r--drivers/media/video/gspca/sonixj.c1671
-rw-r--r--drivers/media/video/gspca/spca500.c1216
-rw-r--r--drivers/media/video/gspca/spca501.c2229
-rw-r--r--drivers/media/video/gspca/spca505.c951
-rw-r--r--drivers/media/video/gspca/spca506.c847
-rw-r--r--drivers/media/video/gspca/spca508.c1791
-rw-r--r--drivers/media/video/gspca/spca561.c1052
-rw-r--r--drivers/media/video/gspca/stk014.c592
-rw-r--r--drivers/media/video/gspca/sunplus.c1677
-rw-r--r--drivers/media/video/gspca/t613.c1038
-rw-r--r--drivers/media/video/gspca/tv8532.c670
-rw-r--r--drivers/media/video/gspca/vc032x.c1818
-rw-r--r--drivers/media/video/gspca/zc3xx-reg.h261
-rw-r--r--drivers/media/video/gspca/zc3xx.c7623
26 files changed, 33376 insertions, 0 deletions
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
new file mode 100644
index 000000000000..42b90742b40b
--- /dev/null
+++ b/drivers/media/video/gspca/Kconfig
@@ -0,0 +1,13 @@
1config USB_GSPCA
2 tristate "USB GSPCA driver"
3 depends on VIDEO_V4L2
4 ---help---
5 Say Y here if you want support for various USB webcams.
6
7 See <file:Documentation/video4linux/gspca.txt> for more info.
8
9 This driver uses the Video For Linux API. You must say Y or M to
10 "Video For Linux" to use this driver.
11
12 To compile this driver as modules, choose M here: the
13 modules will be called gspca_xxxx.
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
new file mode 100644
index 000000000000..e68a8965297a
--- /dev/null
+++ b/drivers/media/video/gspca/Makefile
@@ -0,0 +1,29 @@
1obj-$(CONFIG_USB_GSPCA) += gspca_main.o \
2 gspca_conex.o gspca_etoms.o gspca_mars.o \
3 gspca_ov519.o gspca_pac207.o gspca_pac7311.o \
4 gspca_sonixb.o gspca_sonixj.o gspca_spca500.o gspca_spca501.o \
5 gspca_spca505.o gspca_spca506.o gspca_spca508.o gspca_spca561.o \
6 gspca_sunplus.o gspca_stk014.o gspca_t613.o gspca_tv8532.o \
7 gspca_vc032x.o gspca_zc3xx.o
8
9gspca_main-objs := gspca.o
10gspca_conex-objs := conex.o
11gspca_etoms-objs := etoms.o
12gspca_mars-objs := mars.o
13gspca_ov519-objs := ov519.o
14gspca_pac207-objs := pac207.o
15gspca_pac7311-objs := pac7311.o
16gspca_sonixb-objs := sonixb.o
17gspca_sonixj-objs := sonixj.o
18gspca_spca500-objs := spca500.o
19gspca_spca501-objs := spca501.o
20gspca_spca505-objs := spca505.o
21gspca_spca506-objs := spca506.o
22gspca_spca508-objs := spca508.o
23gspca_spca561-objs := spca561.o
24gspca_stk014-objs := stk014.o
25gspca_sunplus-objs := sunplus.o
26gspca_t613-objs := t613.o
27gspca_tv8532-objs := tv8532.o
28gspca_vc032x-objs := vc032x.o
29gspca_zc3xx-objs := zc3xx.o
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
new file mode 100644
index 000000000000..013d593b0c67
--- /dev/null
+++ b/drivers/media/video/gspca/conex.c
@@ -0,0 +1,1051 @@
1/*
2 * Connexant Cx11646 library
3 * Copyright (C) 2004 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 "conex"
23
24#include "gspca.h"
25#define CONEX_CAM 1 /* special JPEG header */
26#include "jpeg.h"
27
28#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29static const char version[] = "2.1.7";
30
31MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42
43 unsigned char qindex;
44};
45
46/* V4L2 controls supported by the driver */
47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53
54static struct ctrl sd_ctrls[] = {
55 {
56 {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
59 .name = "Brightness",
60 .minimum = 0,
61 .maximum = 255,
62 .step = 1,
63#define BRIGHTNESS_DEF 0xd4
64 .default_value = BRIGHTNESS_DEF,
65 },
66 .set = sd_setbrightness,
67 .get = sd_getbrightness,
68 },
69 {
70 {
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Contrast",
74 .minimum = 0x0a,
75 .maximum = 0x1f,
76 .step = 1,
77#define CONTRAST_DEF 0x0c
78 .default_value = CONTRAST_DEF,
79 },
80 .set = sd_setcontrast,
81 .get = sd_getcontrast,
82 },
83 {
84 {
85 .id = V4L2_CID_SATURATION,
86 .type = V4L2_CTRL_TYPE_INTEGER,
87 .name = "Color",
88 .minimum = 0,
89 .maximum = 7,
90 .step = 1,
91#define COLOR_DEF 3
92 .default_value = COLOR_DEF,
93 },
94 .set = sd_setcolors,
95 .get = sd_getcolors,
96 },
97};
98
99static struct v4l2_pix_format vga_mode[] = {
100 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
101 .bytesperline = 176,
102 .sizeimage = 176 * 144 * 3 / 8 + 590,
103 .colorspace = V4L2_COLORSPACE_JPEG,
104 .priv = 3},
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
109 .priv = 2},
110 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
111 .bytesperline = 352,
112 .sizeimage = 352 * 288 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
114 .priv = 1},
115 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
116 .bytesperline = 640,
117 .sizeimage = 640 * 480 * 3 / 8 + 590,
118 .colorspace = V4L2_COLORSPACE_JPEG,
119 .priv = 0},
120};
121
122/* the read bytes are found in gspca_dev->usb_buf */
123static void reg_r(struct gspca_dev *gspca_dev,
124 __u16 index,
125 __u16 len)
126{
127 struct usb_device *dev = gspca_dev->dev;
128
129#ifdef CONFIG_VIDEO_ADV_DEBUG
130 if (len > sizeof gspca_dev->usb_buf) {
131 err("reg_r: buffer overflow");
132 return;
133 }
134#endif
135 usb_control_msg(dev,
136 usb_rcvctrlpipe(dev, 0),
137 0,
138 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
139 0,
140 index, gspca_dev->usb_buf, len,
141 500);
142 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
143 index, gspca_dev->usb_buf[0]);
144}
145
146/* the bytes to write are in gspca_dev->usb_buf */
147static void reg_w_val(struct gspca_dev *gspca_dev,
148 __u16 index,
149 __u8 val)
150{
151 struct usb_device *dev = gspca_dev->dev;
152
153 gspca_dev->usb_buf[0] = val;
154 usb_control_msg(dev,
155 usb_sndctrlpipe(dev, 0),
156 0,
157 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
158 0,
159 index, gspca_dev->usb_buf, 1, 500);
160}
161
162static void reg_w(struct gspca_dev *gspca_dev,
163 __u16 index,
164 const __u8 *buffer,
165 __u16 len)
166{
167 struct usb_device *dev = gspca_dev->dev;
168
169#ifdef CONFIG_VIDEO_ADV_DEBUG
170 if (len > sizeof gspca_dev->usb_buf) {
171 err("reg_w: buffer overflow");
172 return;
173 }
174 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
175#endif
176 memcpy(gspca_dev->usb_buf, buffer, len);
177 usb_control_msg(dev,
178 usb_sndctrlpipe(dev, 0),
179 0,
180 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
181 0,
182 index, gspca_dev->usb_buf, len, 500);
183}
184
185static const __u8 cx_sensor_init[][4] = {
186 {0x88, 0x11, 0x01, 0x01},
187 {0x88, 0x12, 0x70, 0x01},
188 {0x88, 0x0f, 0x00, 0x01},
189 {0x88, 0x05, 0x01, 0x01},
190 {}
191};
192
193static const __u8 cx11646_fw1[][3] = {
194 {0x00, 0x02, 0x00},
195 {0x01, 0x43, 0x00},
196 {0x02, 0xA7, 0x00},
197 {0x03, 0x8B, 0x01},
198 {0x04, 0xE9, 0x02},
199 {0x05, 0x08, 0x04},
200 {0x06, 0x08, 0x05},
201 {0x07, 0x07, 0x06},
202 {0x08, 0xE7, 0x06},
203 {0x09, 0xC6, 0x07},
204 {0x0A, 0x86, 0x08},
205 {0x0B, 0x46, 0x09},
206 {0x0C, 0x05, 0x0A},
207 {0x0D, 0xA5, 0x0A},
208 {0x0E, 0x45, 0x0B},
209 {0x0F, 0xE5, 0x0B},
210 {0x10, 0x85, 0x0C},
211 {0x11, 0x25, 0x0D},
212 {0x12, 0xC4, 0x0D},
213 {0x13, 0x45, 0x0E},
214 {0x14, 0xE4, 0x0E},
215 {0x15, 0x64, 0x0F},
216 {0x16, 0xE4, 0x0F},
217 {0x17, 0x64, 0x10},
218 {0x18, 0xE4, 0x10},
219 {0x19, 0x64, 0x11},
220 {0x1A, 0xE4, 0x11},
221 {0x1B, 0x64, 0x12},
222 {0x1C, 0xE3, 0x12},
223 {0x1D, 0x44, 0x13},
224 {0x1E, 0xC3, 0x13},
225 {0x1F, 0x24, 0x14},
226 {0x20, 0xA3, 0x14},
227 {0x21, 0x04, 0x15},
228 {0x22, 0x83, 0x15},
229 {0x23, 0xE3, 0x15},
230 {0x24, 0x43, 0x16},
231 {0x25, 0xA4, 0x16},
232 {0x26, 0x23, 0x17},
233 {0x27, 0x83, 0x17},
234 {0x28, 0xE3, 0x17},
235 {0x29, 0x43, 0x18},
236 {0x2A, 0xA3, 0x18},
237 {0x2B, 0x03, 0x19},
238 {0x2C, 0x63, 0x19},
239 {0x2D, 0xC3, 0x19},
240 {0x2E, 0x22, 0x1A},
241 {0x2F, 0x63, 0x1A},
242 {0x30, 0xC3, 0x1A},
243 {0x31, 0x23, 0x1B},
244 {0x32, 0x83, 0x1B},
245 {0x33, 0xE2, 0x1B},
246 {0x34, 0x23, 0x1C},
247 {0x35, 0x83, 0x1C},
248 {0x36, 0xE2, 0x1C},
249 {0x37, 0x23, 0x1D},
250 {0x38, 0x83, 0x1D},
251 {0x39, 0xE2, 0x1D},
252 {0x3A, 0x23, 0x1E},
253 {0x3B, 0x82, 0x1E},
254 {0x3C, 0xC3, 0x1E},
255 {0x3D, 0x22, 0x1F},
256 {0x3E, 0x63, 0x1F},
257 {0x3F, 0xC1, 0x1F},
258 {}
259};
260static void cx11646_fw(struct gspca_dev*gspca_dev)
261{
262 int i = 0;
263
264 reg_w_val(gspca_dev, 0x006a, 0x02);
265 while (cx11646_fw1[i][1]) {
266 reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
267 i++;
268 }
269 reg_w_val(gspca_dev, 0x006a, 0x00);
270}
271
272static const __u8 cxsensor[] = {
273 0x88, 0x12, 0x70, 0x01,
274 0x88, 0x0d, 0x02, 0x01,
275 0x88, 0x0f, 0x00, 0x01,
276 0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
277 0x88, 0x02, 0x10, 0x01,
278 0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
279 0x88, 0x0B, 0x00, 0x01,
280 0x88, 0x0A, 0x0A, 0x01,
281 0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
282 0x88, 0x05, 0x01, 0x01,
283 0xA1, 0x18, 0x00, 0x01,
284 0x00
285};
286
287static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
288static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
289static const __u8 reg10[] = { 0xb1, 0xb1 };
290static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e }; /* 640 */
291static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
292 /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
293static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
294 /* 320{0x04,0x0c,0x05,0x0f}; //320 */
295static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 }; /* 176 */
296static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
297
298static void cx_sensor(struct gspca_dev*gspca_dev)
299{
300 int i = 0;
301 int length;
302 const __u8 *ptsensor = cxsensor;
303
304 reg_w(gspca_dev, 0x0020, reg20, 8);
305 reg_w(gspca_dev, 0x0028, reg28, 8);
306 reg_w(gspca_dev, 0x0010, reg10, 8);
307 reg_w_val(gspca_dev, 0x0092, 0x03);
308
309 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
310 case 0:
311 reg_w(gspca_dev, 0x0071, reg71a, 4);
312 break;
313 case 1:
314 reg_w(gspca_dev, 0x0071, reg71b, 4);
315 break;
316 default:
317/* case 2: */
318 reg_w(gspca_dev, 0x0071, reg71c, 4);
319 break;
320 case 3:
321 reg_w(gspca_dev, 0x0071, reg71d, 4);
322 break;
323 }
324 reg_w(gspca_dev, 0x007b, reg7b, 6);
325 reg_w_val(gspca_dev, 0x00f8, 0x00);
326 reg_w(gspca_dev, 0x0010, reg10, 8);
327 reg_w_val(gspca_dev, 0x0098, 0x41);
328 for (i = 0; i < 11; i++) {
329 if (i == 3 || i == 5 || i == 8)
330 length = 8;
331 else
332 length = 4;
333 reg_w(gspca_dev, 0x00e5, ptsensor, length);
334 if (length == 4)
335 reg_r(gspca_dev, 0x00e8, 1);
336 else
337 reg_r(gspca_dev, 0x00e8, length);
338 ptsensor += length;
339 }
340 reg_r(gspca_dev, 0x00e7, 8);
341}
342
343static const __u8 cx_inits_176[] = {
344 0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
345 0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
346 0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
347 0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
348 0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
349 0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
350 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
351};
352static const __u8 cx_inits_320[] = {
353 0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
354 0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
355 0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
356 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
357 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
358 0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
359 0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
360};
361static const __u8 cx_inits_352[] = {
362 0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
363 0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
364 0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
365 0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
366 0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
367 0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
368 0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
369};
370static const __u8 cx_inits_640[] = {
371 0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
372 0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
373 0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
374 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
375 0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
376 0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
377 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
378};
379
380static void cx11646_initsize(struct gspca_dev *gspca_dev)
381{
382 const __u8 *cxinit;
383 static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
384 static const __u8 reg17[] =
385 { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
386
387 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
388 case 0:
389 cxinit = cx_inits_640;
390 break;
391 case 1:
392 cxinit = cx_inits_352;
393 break;
394 default:
395/* case 2: */
396 cxinit = cx_inits_320;
397 break;
398 case 3:
399 cxinit = cx_inits_176;
400 break;
401 }
402 reg_w_val(gspca_dev, 0x009a, 0x01);
403 reg_w_val(gspca_dev, 0x0010, 0x10);
404 reg_w(gspca_dev, 0x0012, reg12, 5);
405 reg_w(gspca_dev, 0x0017, reg17, 8);
406 reg_w_val(gspca_dev, 0x00c0, 0x00);
407 reg_w_val(gspca_dev, 0x00c1, 0x04);
408 reg_w_val(gspca_dev, 0x00c2, 0x04);
409
410 reg_w(gspca_dev, 0x0061, cxinit, 8);
411 cxinit += 8;
412 reg_w(gspca_dev, 0x00ca, cxinit, 8);
413 cxinit += 8;
414 reg_w(gspca_dev, 0x00d2, cxinit, 8);
415 cxinit += 8;
416 reg_w(gspca_dev, 0x00da, cxinit, 6);
417 cxinit += 8;
418 reg_w(gspca_dev, 0x0041, cxinit, 8);
419 cxinit += 8;
420 reg_w(gspca_dev, 0x0049, cxinit, 8);
421 cxinit += 8;
422 reg_w(gspca_dev, 0x0051, cxinit, 2);
423
424 reg_r(gspca_dev, 0x0010, 1);
425}
426
427static const __u8 cx_jpeg_init[][8] = {
428 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15}, /* 1 */
429 {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
430 {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
431 {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
432 {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
433 {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
434 {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
435 {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
436 {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
437 {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
438 {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
439 {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
440 {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
441 {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
442 {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
443 {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
444 {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
445 {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
446 {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
447 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
448 {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
449 {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
450 {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
451 {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
452 {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
453 {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
454 {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
455 {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
456 {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
457 {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
458 {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
459 {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
460 {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
461 {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
462 {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
463 {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
464 {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
465 {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
466 {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
467 {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
468 {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
469 {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
470 {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
471 {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
472 {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
473 {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
474 {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
475 {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
476 {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
477 {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
478 {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
479 {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
480 {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
481 {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
482 {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
483 {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
484 {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
485 {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
486 {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
487 {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
488 {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
489 {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
490 {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
491 {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
492 {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
493 {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
494 {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
495 {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
496 {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
497 {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
498 {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
499 {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
500 {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
501 {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
502 {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
503 {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
504 {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
505 {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
506 {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00} /* 79 */
507};
508
509
510static const __u8 cxjpeg_640[][8] = {
511 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10}, /* 1 */
512 {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
513 {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
514 {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
515 {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
516 {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
517 {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
518 {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
519 {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
520 {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
521 {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
522 {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
523 {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
524 {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
525 {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
526 {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
527 {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
528 {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
529 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
530 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
531 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
532 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
533 {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
534 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
535 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
536 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
537 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
538};
539static const __u8 cxjpeg_352[][8] = {
540 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
541 {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
542 {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
543 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
544 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
545 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
546 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
547 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
548 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
549 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
550 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
551 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
552 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
553 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
554 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
555 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
556 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
557 {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
558 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
559 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
560 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
561 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
562 {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
563 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
564 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
565 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
566 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
567};
568static const __u8 cxjpeg_320[][8] = {
569 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
570 {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
571 {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
572 {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
573 {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
574 {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
575 {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
576 {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
577 {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
578 {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
579 {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
580 {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
581 {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
582 {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
583 {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
584 {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
585 {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
586 {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
587 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
588 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
589 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
590 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
591 {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
592 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
593 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
594 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
595 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 27 */
596};
597static const __u8 cxjpeg_176[][8] = {
598 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
599 {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
600 {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
601 {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
602 {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
603 {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
604 {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
605 {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
606 {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
607 {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
608 {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
609 {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
610 {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
611 {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
612 {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
613 {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
614 {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
615 {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
616 {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
617 {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
618 {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
619 {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
620 {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
621 {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
622 {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
623 {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
624 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
625};
626/* 640 take with the zcx30x part */
627static const __u8 cxjpeg_qtable[][8] = {
628 {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
629 {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
630 {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
631 {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
632 {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
633 {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
634 {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
635 {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
636 {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
637 {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
638 {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
639 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
640 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
641 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
642 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
643 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
644 {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
645 {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} /* 18 */
646};
647
648
649static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
650{
651 int i;
652 int length;
653
654 reg_w_val(gspca_dev, 0x00c0, 0x01);
655 reg_w_val(gspca_dev, 0x00c3, 0x00);
656 reg_w_val(gspca_dev, 0x00c0, 0x00);
657 reg_r(gspca_dev, 0x0001, 1);
658 length = 8;
659 for (i = 0; i < 79; i++) {
660 if (i == 78)
661 length = 6;
662 reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
663 }
664 reg_r(gspca_dev, 0x0002, 1);
665 reg_w_val(gspca_dev, 0x0055, 0x14);
666}
667
668static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
669static const __u8 regE5_8[] =
670 { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
671static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
672static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
673static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
674static const __u8 reg51[] = { 0x77, 0x03 };
675#define reg70 0x03
676
677static void cx11646_jpeg(struct gspca_dev*gspca_dev)
678{
679 int i;
680 int length;
681 __u8 Reg55;
682 int retry;
683
684 reg_w_val(gspca_dev, 0x00c0, 0x01);
685 reg_w_val(gspca_dev, 0x00c3, 0x00);
686 reg_w_val(gspca_dev, 0x00c0, 0x00);
687 reg_r(gspca_dev, 0x0001, 1);
688 length = 8;
689 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
690 case 0:
691 for (i = 0; i < 27; i++) {
692 if (i == 26)
693 length = 2;
694 reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
695 }
696 Reg55 = 0x28;
697 break;
698 case 1:
699 for (i = 0; i < 27; i++) {
700 if (i == 26)
701 length = 2;
702 reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
703 }
704 Reg55 = 0x16;
705 break;
706 default:
707/* case 2: */
708 for (i = 0; i < 27; i++) {
709 if (i == 26)
710 length = 2;
711 reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
712 }
713 Reg55 = 0x14;
714 break;
715 case 3:
716 for (i = 0; i < 27; i++) {
717 if (i == 26)
718 length = 2;
719 reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
720 }
721 Reg55 = 0x0B;
722 break;
723 }
724
725 reg_r(gspca_dev, 0x0002, 1);
726 reg_w_val(gspca_dev, 0x0055, Reg55);
727 reg_r(gspca_dev, 0x0002, 1);
728 reg_w(gspca_dev, 0x0010, reg10, 2);
729 reg_w_val(gspca_dev, 0x0054, 0x02);
730 reg_w_val(gspca_dev, 0x0054, 0x01);
731 reg_w_val(gspca_dev, 0x0000, 0x94);
732 reg_w_val(gspca_dev, 0x0053, 0xc0);
733 reg_w_val(gspca_dev, 0x00fc, 0xe1);
734 reg_w_val(gspca_dev, 0x0000, 0x00);
735 /* wait for completion */
736 retry = 50;
737 while (retry--) {
738 reg_r(gspca_dev, 0x0002, 1);
739 /* 0x07 until 0x00 */
740 if (gspca_dev->usb_buf[0] == 0x00)
741 break;
742 reg_w_val(gspca_dev, 0x0053, 0x00);
743 }
744 if (retry == 0)
745 PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
746 /* send the qtable now */
747 reg_r(gspca_dev, 0x0001, 1); /* -> 0x18 */
748 length = 8;
749 for (i = 0; i < 18; i++) {
750 if (i == 17)
751 length = 2;
752 reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
753
754 }
755 reg_r(gspca_dev, 0x0002, 1); /* 0x00 */
756 reg_r(gspca_dev, 0x0053, 1); /* 0x00 */
757 reg_w_val(gspca_dev, 0x0054, 0x02);
758 reg_w_val(gspca_dev, 0x0054, 0x01);
759 reg_w_val(gspca_dev, 0x0000, 0x94);
760 reg_w_val(gspca_dev, 0x0053, 0xc0);
761
762 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
763 reg_r(gspca_dev, 0x0038, 1); /* 0x40 */
764 reg_r(gspca_dev, 0x001f, 1); /* 0x38 */
765 reg_w(gspca_dev, 0x0012, reg12, 5);
766 reg_w(gspca_dev, 0x00e5, regE5_8, 8);
767 reg_r(gspca_dev, 0x00e8, 8);
768 reg_w(gspca_dev, 0x00e5, regE5a, 4);
769 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
770 reg_w_val(gspca_dev, 0x009a, 0x01);
771 reg_w(gspca_dev, 0x00e5, regE5b, 4);
772 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
773 reg_w(gspca_dev, 0x00e5, regE5c, 4);
774 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
775
776 reg_w(gspca_dev, 0x0051, reg51, 2);
777 reg_w(gspca_dev, 0x0010, reg10, 2);
778 reg_w_val(gspca_dev, 0x0070, reg70);
779}
780
781static void cx11646_init1(struct gspca_dev *gspca_dev)
782{
783 int i = 0;
784
785 reg_w_val(gspca_dev, 0x0010, 0x00);
786 reg_w_val(gspca_dev, 0x0053, 0x00);
787 reg_w_val(gspca_dev, 0x0052, 0x00);
788 reg_w_val(gspca_dev, 0x009b, 0x2f);
789 reg_w_val(gspca_dev, 0x009c, 0x10);
790 reg_r(gspca_dev, 0x0098, 1);
791 reg_w_val(gspca_dev, 0x0098, 0x40);
792 reg_r(gspca_dev, 0x0099, 1);
793 reg_w_val(gspca_dev, 0x0099, 0x07);
794 reg_w_val(gspca_dev, 0x0039, 0x40);
795 reg_w_val(gspca_dev, 0x003c, 0xff);
796 reg_w_val(gspca_dev, 0x003f, 0x1f);
797 reg_w_val(gspca_dev, 0x003d, 0x40);
798/* reg_w_val(gspca_dev, 0x003d, 0x60); */
799 reg_r(gspca_dev, 0x0099, 1); /* ->0x07 */
800
801 while (cx_sensor_init[i][0]) {
802 reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
803 reg_r(gspca_dev, 0x00e8, 1); /* -> 0x00 */
804 if (i == 1) {
805 reg_w_val(gspca_dev, 0x00ed, 0x01);
806 reg_r(gspca_dev, 0x00ed, 1); /* -> 0x01 */
807 }
808 i++;
809 }
810 reg_w_val(gspca_dev, 0x00c3, 0x00);
811}
812
813/* this function is called at probe time */
814static int sd_config(struct gspca_dev *gspca_dev,
815 const struct usb_device_id *id)
816{
817 struct sd *sd = (struct sd *) gspca_dev;
818 struct cam *cam;
819
820 cam = &gspca_dev->cam;
821 cam->dev_name = (char *) id->driver_info;
822 cam->epaddr = 0x01;
823 cam->cam_mode = vga_mode;
824 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
825
826 sd->qindex = 0; /* set the quantization */
827 sd->brightness = BRIGHTNESS_DEF;
828 sd->contrast = CONTRAST_DEF;
829 sd->colors = COLOR_DEF;
830 return 0;
831}
832
833/* this function is called at open time */
834static int sd_open(struct gspca_dev *gspca_dev)
835{
836 cx11646_init1(gspca_dev);
837 cx11646_initsize(gspca_dev);
838 cx11646_fw(gspca_dev);
839 cx_sensor(gspca_dev);
840 cx11646_jpegInit(gspca_dev);
841 return 0;
842}
843
844static void sd_start(struct gspca_dev *gspca_dev)
845{
846 cx11646_initsize(gspca_dev);
847 cx11646_fw(gspca_dev);
848 cx_sensor(gspca_dev);
849 cx11646_jpeg(gspca_dev);
850}
851
852static void sd_stopN(struct gspca_dev *gspca_dev)
853{
854}
855
856static void sd_stop0(struct gspca_dev *gspca_dev)
857{
858 int retry = 50;
859
860 reg_w_val(gspca_dev, 0x0000, 0x00);
861 reg_r(gspca_dev, 0x0002, 1);
862 reg_w_val(gspca_dev, 0x0053, 0x00);
863
864 while (retry--) {
865/* reg_r(gspca_dev, 0x0002, 1);*/
866 reg_r(gspca_dev, 0x0053, 1);
867 if (gspca_dev->usb_buf[0] == 0)
868 break;
869 }
870 reg_w_val(gspca_dev, 0x0000, 0x00);
871 reg_r(gspca_dev, 0x0002, 1);
872
873 reg_w_val(gspca_dev, 0x0010, 0x00);
874 reg_r(gspca_dev, 0x0033, 1);
875 reg_w_val(gspca_dev, 0x00fc, 0xe0);
876}
877
878static void sd_close(struct gspca_dev *gspca_dev)
879{
880}
881
882static void sd_pkt_scan(struct gspca_dev *gspca_dev,
883 struct gspca_frame *frame, /* target */
884 __u8 *data, /* isoc packet */
885 int len) /* iso packet length */
886{
887 if (data[0] == 0xff && data[1] == 0xd8) {
888
889 /* start of frame */
890 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
891 data, 0);
892
893 /* put the JPEG header in the new frame */
894 jpeg_put_header(gspca_dev, frame,
895 ((struct sd *) gspca_dev)->qindex,
896 0x22);
897 data += 2;
898 len -= 2;
899 }
900 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
901}
902
903static void setbrightness(struct gspca_dev*gspca_dev)
904{
905 struct sd *sd = (struct sd *) gspca_dev;
906 __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
907 __u8 reg51c[2];
908 __u8 bright;
909 __u8 colors;
910
911 bright = sd->brightness;
912 regE5cbx[2] = bright;
913 reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
914 reg_r(gspca_dev, 0x00e8, 8);
915 reg_w(gspca_dev, 0x00e5, regE5c, 4);
916 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
917
918 colors = sd->colors;
919 reg51c[0] = 0x77;
920 reg51c[1] = colors;
921 reg_w(gspca_dev, 0x0051, reg51c, 2);
922 reg_w(gspca_dev, 0x0010, reg10, 2);
923 reg_w_val(gspca_dev, 0x0070, reg70);
924}
925
926static void setcontrast(struct gspca_dev*gspca_dev)
927{
928 struct sd *sd = (struct sd *) gspca_dev;
929 __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 }; /* seem MSB */
930/* __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01}; * LSB */
931 __u8 reg51c[2];
932
933 regE5acx[2] = sd->contrast;
934 reg_w(gspca_dev, 0x00e5, regE5acx, 4);
935 reg_r(gspca_dev, 0x00e8, 1); /* 0x00 */
936 reg51c[0] = 0x77;
937 reg51c[1] = sd->colors;
938 reg_w(gspca_dev, 0x0051, reg51c, 2);
939 reg_w(gspca_dev, 0x0010, reg10, 2);
940 reg_w_val(gspca_dev, 0x0070, reg70);
941}
942
943static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
944{
945 struct sd *sd = (struct sd *) gspca_dev;
946
947 sd->brightness = val;
948 if (gspca_dev->streaming)
949 setbrightness(gspca_dev);
950 return 0;
951}
952
953static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
954{
955 struct sd *sd = (struct sd *) gspca_dev;
956
957 *val = sd->brightness;
958 return 0;
959}
960
961static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
962{
963 struct sd *sd = (struct sd *) gspca_dev;
964
965 sd->contrast = val;
966 if (gspca_dev->streaming)
967 setcontrast(gspca_dev);
968 return 0;
969}
970
971static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
972{
973 struct sd *sd = (struct sd *) gspca_dev;
974
975 *val = sd->contrast;
976 return 0;
977}
978
979static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
980{
981 struct sd *sd = (struct sd *) gspca_dev;
982
983 sd->colors = val;
984 if (gspca_dev->streaming) {
985 setbrightness(gspca_dev);
986 setcontrast(gspca_dev);
987 }
988 return 0;
989}
990
991static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
992{
993 struct sd *sd = (struct sd *) gspca_dev;
994
995 *val = sd->colors;
996 return 0;
997}
998
999/* sub-driver description */
1000static struct sd_desc sd_desc = {
1001 .name = MODULE_NAME,
1002 .ctrls = sd_ctrls,
1003 .nctrls = ARRAY_SIZE(sd_ctrls),
1004 .config = sd_config,
1005 .open = sd_open,
1006 .start = sd_start,
1007 .stopN = sd_stopN,
1008 .stop0 = sd_stop0,
1009 .close = sd_close,
1010 .pkt_scan = sd_pkt_scan,
1011};
1012
1013/* -- module initialisation -- */
1014#define DVNM(name) .driver_info = (kernel_ulong_t) name
1015static __devinitdata struct usb_device_id device_table[] = {
1016 {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
1017 {}
1018};
1019MODULE_DEVICE_TABLE(usb, device_table);
1020
1021/* -- device connect -- */
1022static int sd_probe(struct usb_interface *intf,
1023 const struct usb_device_id *id)
1024{
1025 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1026 THIS_MODULE);
1027}
1028
1029static struct usb_driver sd_driver = {
1030 .name = MODULE_NAME,
1031 .id_table = device_table,
1032 .probe = sd_probe,
1033 .disconnect = gspca_disconnect,
1034};
1035
1036/* -- module insert / remove -- */
1037static int __init sd_mod_init(void)
1038{
1039 if (usb_register(&sd_driver) < 0)
1040 return -1;
1041 PDEBUG(D_PROBE, "v%s registered", version);
1042 return 0;
1043}
1044static void __exit sd_mod_exit(void)
1045{
1046 usb_deregister(&sd_driver);
1047 PDEBUG(D_PROBE, "deregistered");
1048}
1049
1050module_init(sd_mod_init);
1051module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
new file mode 100644
index 000000000000..8ab4ea7201a9
--- /dev/null
+++ b/drivers/media/video/gspca/etoms.c
@@ -0,0 +1,956 @@
1/*
2 * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004)
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "etoms"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("Etoms USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 unsigned char brightness;
37 unsigned char contrast;
38 unsigned char colors;
39 unsigned char autogain;
40
41 char sensor;
42#define SENSOR_PAS106 0
43#define SENSOR_TAS5130CXX 1
44 signed char ag_cnt;
45#define AG_CNT_START 13
46};
47
48/* V4L2 controls supported by the driver */
49static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
55static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
57
58static struct ctrl sd_ctrls[] = {
59 {
60 {
61 .id = V4L2_CID_BRIGHTNESS,
62 .type = V4L2_CTRL_TYPE_INTEGER,
63 .name = "Brightness",
64 .minimum = 1,
65 .maximum = 127,
66 .step = 1,
67#define BRIGHTNESS_DEF 63
68 .default_value = BRIGHTNESS_DEF,
69 },
70 .set = sd_setbrightness,
71 .get = sd_getbrightness,
72 },
73 {
74 {
75 .id = V4L2_CID_CONTRAST,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Contrast",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81#define CONTRAST_DEF 127
82 .default_value = CONTRAST_DEF,
83 },
84 .set = sd_setcontrast,
85 .get = sd_getcontrast,
86 },
87 {
88 {
89 .id = V4L2_CID_SATURATION,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Color",
92 .minimum = 0,
93 .maximum = 15,
94 .step = 1,
95#define COLOR_DEF 7
96 .default_value = COLOR_DEF,
97 },
98 .set = sd_setcolors,
99 .get = sd_getcolors,
100 },
101 {
102 {
103 .id = V4L2_CID_AUTOGAIN,
104 .type = V4L2_CTRL_TYPE_BOOLEAN,
105 .name = "Auto Gain",
106 .minimum = 0,
107 .maximum = 1,
108 .step = 1,
109#define AUTOGAIN_DEF 1
110 .default_value = AUTOGAIN_DEF,
111 },
112 .set = sd_setautogain,
113 .get = sd_getautogain,
114 },
115};
116
117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240,
121 .colorspace = V4L2_COLORSPACE_SRGB,
122 .priv = 1},
123/* {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480,
126 .colorspace = V4L2_COLORSPACE_SRGB,
127 .priv = 0}, */
128};
129
130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144,
134 .colorspace = V4L2_COLORSPACE_SRGB,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 0},
141};
142
143#define ETOMS_ALT_SIZE_1000 12
144
145#define ET_GPIO_DIR_CTRL 0x04 /* Control IO bit[0..5] (0 in 1 out) */
146#define ET_GPIO_OUT 0x05 /* Only IO data */
147#define ET_GPIO_IN 0x06 /* Read Only IO data */
148#define ET_RESET_ALL 0x03
149#define ET_ClCK 0x01
150#define ET_CTRL 0x02 /* enable i2c OutClck Powerdown mode */
151
152#define ET_COMP 0x12 /* Compression register */
153#define ET_MAXQt 0x13
154#define ET_MINQt 0x14
155#define ET_COMP_VAL0 0x02
156#define ET_COMP_VAL1 0x03
157
158#define ET_REG1d 0x1d
159#define ET_REG1e 0x1e
160#define ET_REG1f 0x1f
161#define ET_REG20 0x20
162#define ET_REG21 0x21
163#define ET_REG22 0x22
164#define ET_REG23 0x23
165#define ET_REG24 0x24
166#define ET_REG25 0x25
167/* base registers for luma calculation */
168#define ET_LUMA_CENTER 0x39
169
170#define ET_G_RED 0x4d
171#define ET_G_GREEN1 0x4e
172#define ET_G_BLUE 0x4f
173#define ET_G_GREEN2 0x50
174#define ET_G_GR_H 0x51
175#define ET_G_GB_H 0x52
176
177#define ET_O_RED 0x34
178#define ET_O_GREEN1 0x35
179#define ET_O_BLUE 0x36
180#define ET_O_GREEN2 0x37
181
182#define ET_SYNCHRO 0x68
183#define ET_STARTX 0x69
184#define ET_STARTY 0x6a
185#define ET_WIDTH_LOW 0x6b
186#define ET_HEIGTH_LOW 0x6c
187#define ET_W_H_HEIGTH 0x6d
188
189#define ET_REG6e 0x6e /* OBW */
190#define ET_REG6f 0x6f /* OBW */
191#define ET_REG70 0x70 /* OBW_AWB */
192#define ET_REG71 0x71 /* OBW_AWB */
193#define ET_REG72 0x72 /* OBW_AWB */
194#define ET_REG73 0x73 /* Clkdelay ns */
195#define ET_REG74 0x74 /* test pattern */
196#define ET_REG75 0x75 /* test pattern */
197
198#define ET_I2C_CLK 0x8c
199#define ET_PXL_CLK 0x60
200
201#define ET_I2C_BASE 0x89
202#define ET_I2C_COUNT 0x8a
203#define ET_I2C_PREFETCH 0x8b
204#define ET_I2C_REG 0x88
205#define ET_I2C_DATA7 0x87
206#define ET_I2C_DATA6 0x86
207#define ET_I2C_DATA5 0x85
208#define ET_I2C_DATA4 0x84
209#define ET_I2C_DATA3 0x83
210#define ET_I2C_DATA2 0x82
211#define ET_I2C_DATA1 0x81
212#define ET_I2C_DATA0 0x80
213
214#define PAS106_REG2 0x02 /* pxlClk = systemClk/(reg2) */
215#define PAS106_REG3 0x03 /* line/frame H [11..4] */
216#define PAS106_REG4 0x04 /* line/frame L [3..0] */
217#define PAS106_REG5 0x05 /* exposure time line offset(default 5) */
218#define PAS106_REG6 0x06 /* exposure time pixel offset(default 6) */
219#define PAS106_REG7 0x07 /* signbit Dac (default 0) */
220#define PAS106_REG9 0x09
221#define PAS106_REG0e 0x0e /* global gain [4..0](default 0x0e) */
222#define PAS106_REG13 0x13 /* end i2c write */
223
224static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
225
226static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
227
228static const __u8 I2c3[] = { 0x12, 0x05 };
229
230static const __u8 I2c4[] = { 0x41, 0x08 };
231
232/* read 'len' bytes to gspca_dev->usb_buf */
233static void reg_r(struct gspca_dev *gspca_dev,
234 __u16 index,
235 __u16 len)
236{
237 struct usb_device *dev = gspca_dev->dev;
238
239#ifdef CONFIG_VIDEO_ADV_DEBUG
240 if (len > sizeof gspca_dev->usb_buf) {
241 err("reg_r: buffer overflow");
242 return;
243 }
244#endif
245 usb_control_msg(dev,
246 usb_rcvctrlpipe(dev, 0),
247 0,
248 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
249 0,
250 index, gspca_dev->usb_buf, len, 500);
251 PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
252 index, gspca_dev->usb_buf[0]);
253}
254
255static void reg_w_val(struct gspca_dev *gspca_dev,
256 __u16 index,
257 __u8 val)
258{
259 struct usb_device *dev = gspca_dev->dev;
260
261 gspca_dev->usb_buf[0] = val;
262 usb_control_msg(dev,
263 usb_sndctrlpipe(dev, 0),
264 0,
265 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
266 0,
267 index, gspca_dev->usb_buf, 1, 500);
268}
269
270static void reg_w(struct gspca_dev *gspca_dev,
271 __u16 index,
272 const __u8 *buffer,
273 __u16 len)
274{
275 struct usb_device *dev = gspca_dev->dev;
276
277#ifdef CONFIG_VIDEO_ADV_DEBUG
278 if (len > sizeof gspca_dev->usb_buf) {
279 err("reg_w: buffer overflow");
280 return;
281 }
282 PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
283#endif
284 memcpy(gspca_dev->usb_buf, buffer, len);
285 usb_control_msg(dev,
286 usb_sndctrlpipe(dev, 0),
287 0,
288 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
289 0, index, gspca_dev->usb_buf, len, 500);
290}
291
292static int i2c_w(struct gspca_dev *gspca_dev,
293 __u8 reg,
294 const __u8 *buffer,
295 int len, __u8 mode)
296{
297 /* buffer should be [D0..D7] */
298 __u8 ptchcount;
299
300 /* set the base address */
301 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
302 /* sensor base for the pas106 */
303 /* set count and prefetch */
304 ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
305 reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
306 /* set the register base */
307 reg_w_val(gspca_dev, ET_I2C_REG, reg);
308 while (--len >= 0)
309 reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
310 return 0;
311}
312
313static int i2c_r(struct gspca_dev *gspca_dev,
314 __u8 reg)
315{
316 /* set the base address */
317 reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
318 /* sensor base for the pas106 */
319 /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
320 reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
321 reg_w_val(gspca_dev, ET_I2C_REG, reg); /* set the register base */
322 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02); /* prefetch */
323 reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
324 reg_r(gspca_dev, ET_I2C_DATA0, 1); /* read one byte */
325 return 0;
326}
327
328static int Et_WaitStatus(struct gspca_dev *gspca_dev)
329{
330 int retry = 10;
331
332 while (retry--) {
333 reg_r(gspca_dev, ET_ClCK, 1);
334 if (gspca_dev->usb_buf[0] != 0)
335 return 1;
336 }
337 return 0;
338}
339
340static int et_video(struct gspca_dev *gspca_dev,
341 int on)
342{
343 int ret;
344
345 reg_w_val(gspca_dev, ET_GPIO_OUT,
346 on ? 0x10 /* startvideo - set Bit5 */
347 : 0); /* stopvideo */
348 ret = Et_WaitStatus(gspca_dev);
349 if (ret != 0)
350 PDEBUG(D_ERR, "timeout video on/off");
351 return ret;
352}
353
354static void Et_init2(struct gspca_dev *gspca_dev)
355{
356 __u8 value;
357 static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
358
359 PDEBUG(D_STREAM, "Open Init2 ET");
360 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
361 reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
362 reg_r(gspca_dev, ET_GPIO_IN, 1);
363 reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
364 reg_w_val(gspca_dev, ET_CTRL, 0x1b);
365
366 /* compression et subsampling */
367 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
368 value = ET_COMP_VAL1; /* 320 */
369 else
370 value = ET_COMP_VAL0; /* 640 */
371 reg_w_val(gspca_dev, ET_COMP, value);
372 reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
373 reg_w_val(gspca_dev, ET_MINQt, 0x04);
374 /* undocumented registers */
375 reg_w_val(gspca_dev, ET_REG1d, 0xff);
376 reg_w_val(gspca_dev, ET_REG1e, 0xff);
377 reg_w_val(gspca_dev, ET_REG1f, 0xff);
378 reg_w_val(gspca_dev, ET_REG20, 0x35);
379 reg_w_val(gspca_dev, ET_REG21, 0x01);
380 reg_w_val(gspca_dev, ET_REG22, 0x00);
381 reg_w_val(gspca_dev, ET_REG23, 0xff);
382 reg_w_val(gspca_dev, ET_REG24, 0xff);
383 reg_w_val(gspca_dev, ET_REG25, 0x0f);
384 /* colors setting */
385 reg_w_val(gspca_dev, 0x30, 0x11); /* 0x30 */
386 reg_w_val(gspca_dev, 0x31, 0x40);
387 reg_w_val(gspca_dev, 0x32, 0x00);
388 reg_w_val(gspca_dev, ET_O_RED, 0x00); /* 0x34 */
389 reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
390 reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
391 reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
392 /*************/
393 reg_w_val(gspca_dev, ET_G_RED, 0x80); /* 0x4d */
394 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
395 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
396 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
397 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
398 reg_w_val(gspca_dev, ET_G_GB_H, 0x00); /* 0x52 */
399 /* Window control registers */
400 reg_w_val(gspca_dev, 0x61, 0x80); /* use cmc_out */
401 reg_w_val(gspca_dev, 0x62, 0x02);
402 reg_w_val(gspca_dev, 0x63, 0x03);
403 reg_w_val(gspca_dev, 0x64, 0x14);
404 reg_w_val(gspca_dev, 0x65, 0x0e);
405 reg_w_val(gspca_dev, 0x66, 0x02);
406 reg_w_val(gspca_dev, 0x67, 0x02);
407
408 /**************************************/
409 reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f); /* 0x68 */
410 reg_w_val(gspca_dev, ET_STARTX, 0x69); /* 0x6a //0x69 */
411 reg_w_val(gspca_dev, ET_STARTY, 0x0d); /* 0x0d //0x0c */
412 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
413 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
414 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60); /* 6d */
415 reg_w_val(gspca_dev, ET_REG6e, 0x86);
416 reg_w_val(gspca_dev, ET_REG6f, 0x01);
417 reg_w_val(gspca_dev, ET_REG70, 0x26);
418 reg_w_val(gspca_dev, ET_REG71, 0x7a);
419 reg_w_val(gspca_dev, ET_REG72, 0x01);
420 /* Clock Pattern registers ***************** */
421 reg_w_val(gspca_dev, ET_REG73, 0x00);
422 reg_w_val(gspca_dev, ET_REG74, 0x18); /* 0x28 */
423 reg_w_val(gspca_dev, ET_REG75, 0x0f); /* 0x01 */
424 /**********************************************/
425 reg_w_val(gspca_dev, 0x8a, 0x20);
426 reg_w_val(gspca_dev, 0x8d, 0x0f);
427 reg_w_val(gspca_dev, 0x8e, 0x08);
428 /**************************************/
429 reg_w_val(gspca_dev, 0x03, 0x08);
430 reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
431 reg_w_val(gspca_dev, 0x81, 0xff);
432 reg_w_val(gspca_dev, 0x80, 0x00);
433 reg_w_val(gspca_dev, 0x81, 0xff);
434 reg_w_val(gspca_dev, 0x80, 0x20);
435 reg_w_val(gspca_dev, 0x03, 0x01);
436 reg_w_val(gspca_dev, 0x03, 0x00);
437 reg_w_val(gspca_dev, 0x03, 0x08);
438 /********************************************/
439
440/* reg_r(gspca_dev, ET_I2C_BASE, 1);
441 always 0x40 as the pas106 ??? */
442 /* set the sensor */
443 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
444 value = 0x04; /* 320 */
445 else /* 640 */
446 value = 0x1e; /* 0x17 * setting PixelClock
447 * 0x03 mean 24/(3+1) = 6 Mhz
448 * 0x05 -> 24/(5+1) = 4 Mhz
449 * 0x0b -> 24/(11+1) = 2 Mhz
450 * 0x17 -> 24/(23+1) = 1 Mhz
451 */
452 reg_w_val(gspca_dev, ET_PXL_CLK, value);
453 /* now set by fifo the FormatLine setting */
454 reg_w(gspca_dev, 0x62, FormLine, 6);
455
456 /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
457 reg_w_val(gspca_dev, 0x81, 0x47); /* 0x47; */
458 reg_w_val(gspca_dev, 0x80, 0x40); /* 0x40; */
459 /* Pedro change */
460 /* Brightness change Brith+ decrease value */
461 /* Brigth- increase value */
462 /* original value = 0x70; */
463 reg_w_val(gspca_dev, 0x81, 0x30); /* 0x20; - set brightness */
464 reg_w_val(gspca_dev, 0x80, 0x20); /* 0x20; */
465}
466
467static void setcolors(struct gspca_dev *gspca_dev)
468{
469 struct sd *sd = (struct sd *) gspca_dev;
470 __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
471 __u8 i2cflags = 0x01;
472 /* __u8 green = 0; */
473 __u8 colors = sd->colors;
474
475 I2cc[3] = colors; /* red */
476 I2cc[0] = 15 - colors; /* blue */
477 /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
478 /* I2cc[1] = I2cc[2] = green; */
479 if (sd->sensor == SENSOR_PAS106) {
480 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
481 i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
482 }
483/* PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
484 I2cc[3], I2cc[0], green); */
485}
486
487static void getcolors(struct gspca_dev *gspca_dev)
488{
489 struct sd *sd = (struct sd *) gspca_dev;
490
491 if (sd->sensor == SENSOR_PAS106) {
492/* i2c_r(gspca_dev, PAS106_REG9); * blue */
493 i2c_r(gspca_dev, PAS106_REG9 + 3); /* red */
494 sd->colors = gspca_dev->usb_buf[0] & 0x0f;
495 }
496}
497
498static void Et_init1(struct gspca_dev *gspca_dev)
499{
500 __u8 value;
501/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
502 __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
503 /* try 1/120 0x6d 0xcd 0x40 */
504/* __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
505 * 1/60000 hmm ?? */
506
507 PDEBUG(D_STREAM, "Open Init1 ET");
508 reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
509 reg_r(gspca_dev, ET_GPIO_IN, 1);
510 reg_w_val(gspca_dev, ET_RESET_ALL, 1);
511 reg_w_val(gspca_dev, ET_RESET_ALL, 0);
512 reg_w_val(gspca_dev, ET_ClCK, 0x10);
513 reg_w_val(gspca_dev, ET_CTRL, 0x19);
514 /* compression et subsampling */
515 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
516 value = ET_COMP_VAL1;
517 else
518 value = ET_COMP_VAL0;
519 PDEBUG(D_STREAM, "Open mode %d Compression %d",
520 gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
521 value);
522 reg_w_val(gspca_dev, ET_COMP, value);
523 reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
524 reg_w_val(gspca_dev, ET_MINQt, 0x02);
525 /* undocumented registers */
526 reg_w_val(gspca_dev, ET_REG1d, 0xff);
527 reg_w_val(gspca_dev, ET_REG1e, 0xff);
528 reg_w_val(gspca_dev, ET_REG1f, 0xff);
529 reg_w_val(gspca_dev, ET_REG20, 0x35);
530 reg_w_val(gspca_dev, ET_REG21, 0x01);
531 reg_w_val(gspca_dev, ET_REG22, 0x00);
532 reg_w_val(gspca_dev, ET_REG23, 0xf7);
533 reg_w_val(gspca_dev, ET_REG24, 0xff);
534 reg_w_val(gspca_dev, ET_REG25, 0x07);
535 /* colors setting */
536 reg_w_val(gspca_dev, ET_G_RED, 0x80);
537 reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
538 reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
539 reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
540 reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
541 reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
542 /* Window control registers */
543 reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
544 reg_w_val(gspca_dev, ET_STARTX, 0x56); /* 0x56 */
545 reg_w_val(gspca_dev, ET_STARTY, 0x05); /* 0x04 */
546 reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
547 reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
548 reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
549 reg_w_val(gspca_dev, ET_REG6e, 0x86);
550 reg_w_val(gspca_dev, ET_REG6f, 0x01);
551 reg_w_val(gspca_dev, ET_REG70, 0x86);
552 reg_w_val(gspca_dev, ET_REG71, 0x14);
553 reg_w_val(gspca_dev, ET_REG72, 0x00);
554 /* Clock Pattern registers */
555 reg_w_val(gspca_dev, ET_REG73, 0x00);
556 reg_w_val(gspca_dev, ET_REG74, 0x00);
557 reg_w_val(gspca_dev, ET_REG75, 0x0a);
558 reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
559 reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
560 /* set the sensor */
561 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
562 I2c0[0] = 0x06;
563 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
564 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
565 value = 0x06;
566 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
567 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
568 /* value = 0x1f; */
569 value = 0x04;
570 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
571 } else {
572 I2c0[0] = 0x0a;
573
574 i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
575 i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
576 value = 0x0a;
577 i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
578 i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
579 value = 0x04;
580 /* value = 0x10; */
581 i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
582 /* bit 2 enable bit 1:2 select 0 1 2 3
583 value = 0x07; * curve 0 *
584 i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
585 */
586 }
587
588/* value = 0x01; */
589/* value = 0x22; */
590/* i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
591 /* magnetude and sign bit for DAC */
592 i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
593 /* now set by fifo the whole colors setting */
594 reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
595 getcolors(gspca_dev);
596 setcolors(gspca_dev);
597}
598
599/* this function is called at probe time */
600static int sd_config(struct gspca_dev *gspca_dev,
601 const struct usb_device_id *id)
602{
603 struct sd *sd = (struct sd *) gspca_dev;
604 struct cam *cam;
605 __u16 vendor;
606 __u16 product;
607
608 vendor = id->idVendor;
609 product = id->idProduct;
610/* switch (vendor) { */
611/* case 0x102c: * Etoms */
612 switch (product) {
613 case 0x6151:
614 sd->sensor = SENSOR_PAS106; /* Etoms61x151 */
615 break;
616 case 0x6251:
617 sd->sensor = SENSOR_TAS5130CXX; /* Etoms61x251 */
618 break;
619/* } */
620/* break; */
621 }
622 cam = &gspca_dev->cam;
623 cam->dev_name = (char *) id->driver_info;
624 cam->epaddr = 1;
625 if (sd->sensor == SENSOR_PAS106) {
626 cam->cam_mode = sif_mode;
627 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
628 } else {
629 cam->cam_mode = vga_mode;
630 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
631 }
632 sd->brightness = BRIGHTNESS_DEF;
633 sd->contrast = CONTRAST_DEF;
634 sd->colors = COLOR_DEF;
635 sd->autogain = AUTOGAIN_DEF;
636 return 0;
637}
638
639/* this function is called at open time */
640static int sd_open(struct gspca_dev *gspca_dev)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643
644 if (sd->sensor == SENSOR_PAS106)
645 Et_init1(gspca_dev);
646 else
647 Et_init2(gspca_dev);
648 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
649 et_video(gspca_dev, 0); /* video off */
650 return 0;
651}
652
653/* -- start the camera -- */
654static void sd_start(struct gspca_dev *gspca_dev)
655{
656 struct sd *sd = (struct sd *) gspca_dev;
657
658 if (sd->sensor == SENSOR_PAS106)
659 Et_init1(gspca_dev);
660 else
661 Et_init2(gspca_dev);
662
663 reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
664 et_video(gspca_dev, 1); /* video on */
665}
666
667static void sd_stopN(struct gspca_dev *gspca_dev)
668{
669 et_video(gspca_dev, 0); /* video off */
670}
671
672static void sd_stop0(struct gspca_dev *gspca_dev)
673{
674}
675
676static void sd_close(struct gspca_dev *gspca_dev)
677{
678}
679
680static void setbrightness(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 int i;
684 __u8 brightness = sd->brightness;
685
686 for (i = 0; i < 4; i++)
687 reg_w_val(gspca_dev, ET_O_RED + i, brightness);
688}
689
690static void getbrightness(struct gspca_dev *gspca_dev)
691{
692 struct sd *sd = (struct sd *) gspca_dev;
693 int i;
694 int brightness = 0;
695
696 for (i = 0; i < 4; i++) {
697 reg_r(gspca_dev, ET_O_RED + i, 1);
698 brightness += gspca_dev->usb_buf[0];
699 }
700 sd->brightness = brightness >> 3;
701}
702
703static void setcontrast(struct gspca_dev *gspca_dev)
704{
705 struct sd *sd = (struct sd *) gspca_dev;
706 __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
707 __u8 contrast = sd->contrast;
708
709 memset(RGBG, contrast, sizeof(RGBG) - 2);
710 reg_w(gspca_dev, ET_G_RED, RGBG, 6);
711}
712
713static void getcontrast(struct gspca_dev *gspca_dev)
714{
715 struct sd *sd = (struct sd *) gspca_dev;
716 int i;
717 int contrast = 0;
718
719 for (i = 0; i < 4; i++) {
720 reg_r(gspca_dev, ET_G_RED + i, 1);
721 contrast += gspca_dev->usb_buf[0];
722 }
723 sd->contrast = contrast >> 2;
724}
725
726static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729
730 if (sd->sensor == SENSOR_PAS106) {
731 i2c_r(gspca_dev, PAS106_REG0e);
732 PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
733 return gspca_dev->usb_buf[0];
734 }
735 return 0x1f;
736}
737
738static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741
742 if (sd->sensor == SENSOR_PAS106) {
743 __u8 i2cflags = 0x01;
744
745 i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
746 i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
747 }
748}
749
750#define BLIMIT(bright) \
751 (__u8)((bright > 0x1f)?0x1f:((bright < 4)?3:bright))
752#define LIMIT(color) \
753 (unsigned char)((color > 0xff)?0xff:((color < 0)?0:color))
754
755static void setautogain(struct gspca_dev *gspca_dev)
756{
757 __u8 luma = 0;
758 __u8 luma_mean = 128;
759 __u8 luma_delta = 20;
760 __u8 spring = 4;
761 int Gbright = 0;
762 __u8 r, g, b;
763
764 Gbright = Et_getgainG(gspca_dev);
765 reg_r(gspca_dev, ET_LUMA_CENTER, 4);
766 g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
767 r = gspca_dev->usb_buf[1];
768 b = gspca_dev->usb_buf[2];
769 r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
770 b = ((b << 7) >> 10);
771 g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
772 luma = LIMIT(r + g + b);
773 PDEBUG(D_FRAM, "Etoms luma G %d", luma);
774 if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
775 Gbright += (luma_mean - luma) >> spring;
776 Gbright = BLIMIT(Gbright);
777 PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
778 Et_setgainG(gspca_dev, (__u8) Gbright);
779 }
780}
781
782#undef BLIMIT
783#undef LIMIT
784
785static void sd_pkt_scan(struct gspca_dev *gspca_dev,
786 struct gspca_frame *frame, /* target */
787 __u8 *data, /* isoc packet */
788 int len) /* iso packet length */
789{
790 struct sd *sd;
791 int seqframe;
792
793 seqframe = data[0] & 0x3f;
794 len = (int) (((data[0] & 0xc0) << 2) | data[1]);
795 if (seqframe == 0x3f) {
796 PDEBUG(D_FRAM,
797 "header packet found datalength %d !!", len);
798 PDEBUG(D_FRAM, "G %d R %d G %d B %d",
799 data[2], data[3], data[4], data[5]);
800 data += 30;
801 /* don't change datalength as the chips provided it */
802 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
803 data, 0);
804 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
805 sd = (struct sd *) gspca_dev;
806 if (sd->ag_cnt >= 0) {
807 if (--sd->ag_cnt < 0) {
808 sd->ag_cnt = AG_CNT_START;
809 setautogain(gspca_dev);
810 }
811 }
812 return;
813 }
814 if (len) {
815 data += 8;
816 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
817 } else { /* Drop Packet */
818 gspca_dev->last_packet_type = DISCARD_PACKET;
819 }
820}
821
822static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
823{
824 struct sd *sd = (struct sd *) gspca_dev;
825
826 sd->brightness = val;
827 if (gspca_dev->streaming)
828 setbrightness(gspca_dev);
829 return 0;
830}
831
832static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
833{
834 struct sd *sd = (struct sd *) gspca_dev;
835
836 getbrightness(gspca_dev);
837 *val = sd->brightness;
838 return 0;
839}
840
841static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
842{
843 struct sd *sd = (struct sd *) gspca_dev;
844
845 sd->contrast = val;
846 if (gspca_dev->streaming)
847 setcontrast(gspca_dev);
848 return 0;
849}
850
851static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
852{
853 struct sd *sd = (struct sd *) gspca_dev;
854
855 getcontrast(gspca_dev);
856 *val = sd->contrast;
857 return 0;
858}
859
860static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
861{
862 struct sd *sd = (struct sd *) gspca_dev;
863
864 sd->colors = val;
865 if (gspca_dev->streaming)
866 setcolors(gspca_dev);
867 return 0;
868}
869
870static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 getcolors(gspca_dev);
875 *val = sd->colors;
876 return 0;
877}
878
879static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
880{
881 struct sd *sd = (struct sd *) gspca_dev;
882
883 sd->autogain = val;
884 if (val)
885 sd->ag_cnt = AG_CNT_START;
886 else
887 sd->ag_cnt = -1;
888 return 0;
889}
890
891static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
892{
893 struct sd *sd = (struct sd *) gspca_dev;
894
895 *val = sd->autogain;
896 return 0;
897}
898
899/* sub-driver description */
900static struct sd_desc sd_desc = {
901 .name = MODULE_NAME,
902 .ctrls = sd_ctrls,
903 .nctrls = ARRAY_SIZE(sd_ctrls),
904 .config = sd_config,
905 .open = sd_open,
906 .start = sd_start,
907 .stopN = sd_stopN,
908 .stop0 = sd_stop0,
909 .close = sd_close,
910 .pkt_scan = sd_pkt_scan,
911};
912
913/* -- module initialisation -- */
914#define DVNM(name) .driver_info = (kernel_ulong_t) name
915static __devinitdata struct usb_device_id device_table[] = {
916#ifndef CONFIG_USB_ET61X251
917 {USB_DEVICE(0x102c, 0x6151), DVNM("Qcam Sangha CIF")},
918#endif
919 {USB_DEVICE(0x102c, 0x6251), DVNM("Qcam xxxxxx VGA")},
920 {}
921};
922
923MODULE_DEVICE_TABLE(usb, device_table);
924
925/* -- device connect -- */
926static int sd_probe(struct usb_interface *intf,
927 const struct usb_device_id *id)
928{
929 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
930 THIS_MODULE);
931}
932
933static struct usb_driver sd_driver = {
934 .name = MODULE_NAME,
935 .id_table = device_table,
936 .probe = sd_probe,
937 .disconnect = gspca_disconnect,
938};
939
940/* -- module insert / remove -- */
941static int __init sd_mod_init(void)
942{
943 if (usb_register(&sd_driver) < 0)
944 return -1;
945 PDEBUG(D_PROBE, "v%s registered", version);
946 return 0;
947}
948
949static void __exit sd_mod_exit(void)
950{
951 usb_deregister(&sd_driver);
952 PDEBUG(D_PROBE, "deregistered");
953}
954
955module_init(sd_mod_init);
956module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
new file mode 100644
index 000000000000..16e367cec760
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.c
@@ -0,0 +1,1905 @@
1/*
2 * Main USB camera driver
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#define MODULE_NAME "gspca"
22
23#include <linux/init.h>
24#include <linux/fs.h>
25#include <linux/vmalloc.h>
26#include <linux/sched.h>
27#include <linux/slab.h>
28#include <linux/mm.h>
29#include <linux/string.h>
30#include <linux/pagemap.h>
31#include <linux/io.h>
32#include <asm/page.h>
33#include <linux/uaccess.h>
34#include <linux/jiffies.h>
35
36#include "gspca.h"
37
38/* global values */
39#define DEF_NURBS 2 /* default number of URBs */
40
41MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
42MODULE_DESCRIPTION("GSPCA USB Camera Driver");
43MODULE_LICENSE("GPL");
44
45#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
46static const char version[] = "2.1.7";
47
48static int video_nr = -1;
49
50#ifdef CONFIG_VIDEO_ADV_DEBUG
51int gspca_debug = D_ERR | D_PROBE;
52EXPORT_SYMBOL(gspca_debug);
53
54static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
55{
56 if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
57 PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
58 txt,
59 pixfmt & 0xff,
60 (pixfmt >> 8) & 0xff,
61 (pixfmt >> 16) & 0xff,
62 pixfmt >> 24,
63 w, h);
64 } else {
65 PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
66 txt,
67 pixfmt,
68 w, h);
69 }
70}
71#else
72#define PDEBUG_MODE(txt, pixfmt, w, h)
73#endif
74
75/* specific memory types - !! should different from V4L2_MEMORY_xxx */
76#define GSPCA_MEMORY_NO 0 /* V4L2_MEMORY_xxx starts from 1 */
77#define GSPCA_MEMORY_READ 7
78
79#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
80
81/*
82 * VMA operations.
83 */
84static void gspca_vm_open(struct vm_area_struct *vma)
85{
86 struct gspca_frame *frame = vma->vm_private_data;
87
88 frame->vma_use_count++;
89 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
90}
91
92static void gspca_vm_close(struct vm_area_struct *vma)
93{
94 struct gspca_frame *frame = vma->vm_private_data;
95
96 if (--frame->vma_use_count <= 0)
97 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
98}
99
100static struct vm_operations_struct gspca_vm_ops = {
101 .open = gspca_vm_open,
102 .close = gspca_vm_close,
103};
104
105/*
106 * fill a video frame from an URB and resubmit
107 */
108static void fill_frame(struct gspca_dev *gspca_dev,
109 struct urb *urb)
110{
111 struct gspca_frame *frame;
112 __u8 *data; /* address of data in the iso message */
113 int i, j, len, st;
114 cam_pkt_op pkt_scan;
115
116 if (urb->status != 0) {
117 PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
118 return; /* disconnection ? */
119 }
120 pkt_scan = gspca_dev->sd_desc->pkt_scan;
121 for (i = 0; i < urb->number_of_packets; i++) {
122
123 /* check the availability of the frame buffer */
124 j = gspca_dev->fr_i;
125 j = gspca_dev->fr_queue[j];
126 frame = &gspca_dev->frame[j];
127 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
128 != V4L2_BUF_FLAG_QUEUED) {
129 gspca_dev->last_packet_type = DISCARD_PACKET;
130 break;
131 }
132
133 /* check the packet status and length */
134 len = urb->iso_frame_desc[i].actual_length;
135 if (len == 0)
136 continue;
137 st = urb->iso_frame_desc[i].status;
138 if (st) {
139 PDEBUG(D_ERR,
140 "ISOC data error: [%d] len=%d, status=%d",
141 i, len, st);
142 gspca_dev->last_packet_type = DISCARD_PACKET;
143 continue;
144 }
145
146 /* let the packet be analyzed by the subdriver */
147 PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
148 i, urb->iso_frame_desc[i].offset, len);
149 data = (__u8 *) urb->transfer_buffer
150 + urb->iso_frame_desc[i].offset;
151 pkt_scan(gspca_dev, frame, data, len);
152 }
153
154 /* resubmit the URB */
155 urb->status = 0;
156 st = usb_submit_urb(urb, GFP_ATOMIC);
157 if (st < 0)
158 PDEBUG(D_ERR|D_PACK, "usb_submit_urb() ret %d", st);
159}
160
161/*
162 * ISOC message interrupt from the USB device
163 *
164 * Analyse each packet and call the subdriver for copy to the frame buffer.
165 */
166static void isoc_irq(struct urb *urb
167)
168{
169 struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
170
171 PDEBUG(D_PACK, "isoc irq");
172 if (!gspca_dev->streaming)
173 return;
174 fill_frame(gspca_dev, urb);
175}
176
177/*
178 * add data to the current frame
179 *
180 * This function is called by the subdrivers at interrupt level.
181 *
182 * To build a frame, these ones must add
183 * - one FIRST_PACKET
184 * - 0 or many INTER_PACKETs
185 * - one LAST_PACKET
186 * DISCARD_PACKET invalidates the whole frame.
187 * On LAST_PACKET, a new frame is returned.
188 */
189struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
190 int packet_type,
191 struct gspca_frame *frame,
192 const __u8 *data,
193 int len)
194{
195 int i, j;
196
197 PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
198
199 /* when start of a new frame, if the current frame buffer
200 * is not queued, discard the whole frame */
201 if (packet_type == FIRST_PACKET) {
202 if ((frame->v4l2_buf.flags & BUF_ALL_FLAGS)
203 != V4L2_BUF_FLAG_QUEUED) {
204 gspca_dev->last_packet_type = DISCARD_PACKET;
205 return frame;
206 }
207 frame->data_end = frame->data;
208 jiffies_to_timeval(get_jiffies_64(),
209 &frame->v4l2_buf.timestamp);
210 frame->v4l2_buf.sequence = ++gspca_dev->sequence;
211 } else if (gspca_dev->last_packet_type == DISCARD_PACKET) {
212 return frame;
213 }
214
215 /* append the packet to the frame buffer */
216 if (len > 0) {
217 if (frame->data_end - frame->data + len
218 > frame->v4l2_buf.length) {
219 PDEBUG(D_ERR|D_PACK, "frame overflow %zd > %d",
220 frame->data_end - frame->data + len,
221 frame->v4l2_buf.length);
222 packet_type = DISCARD_PACKET;
223 } else {
224 memcpy(frame->data_end, data, len);
225 frame->data_end += len;
226 }
227 }
228 gspca_dev->last_packet_type = packet_type;
229
230 /* if last packet, wake the application and advance in the queue */
231 if (packet_type == LAST_PACKET) {
232 frame->v4l2_buf.bytesused = frame->data_end - frame->data;
233 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_QUEUED;
234 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_DONE;
235 atomic_inc(&gspca_dev->nevent);
236 wake_up_interruptible(&gspca_dev->wq); /* event = new frame */
237 i = (gspca_dev->fr_i + 1) % gspca_dev->nframes;
238 gspca_dev->fr_i = i;
239 PDEBUG(D_FRAM, "frame complete len:%d q:%d i:%d o:%d",
240 frame->v4l2_buf.bytesused,
241 gspca_dev->fr_q,
242 i,
243 gspca_dev->fr_o);
244 j = gspca_dev->fr_queue[i];
245 frame = &gspca_dev->frame[j];
246 }
247 return frame;
248}
249EXPORT_SYMBOL(gspca_frame_add);
250
251static int gspca_is_compressed(__u32 format)
252{
253 switch (format) {
254 case V4L2_PIX_FMT_MJPEG:
255 case V4L2_PIX_FMT_JPEG:
256 case V4L2_PIX_FMT_SPCA561:
257 case V4L2_PIX_FMT_PAC207:
258 return 1;
259 }
260 return 0;
261}
262
263static void *rvmalloc(unsigned long size)
264{
265 void *mem;
266 unsigned long adr;
267
268/* size = PAGE_ALIGN(size); (already done) */
269 mem = vmalloc_32(size);
270 if (mem != NULL) {
271 adr = (unsigned long) mem;
272 while ((long) size > 0) {
273 SetPageReserved(vmalloc_to_page((void *) adr));
274 adr += PAGE_SIZE;
275 size -= PAGE_SIZE;
276 }
277 }
278 return mem;
279}
280
281static void rvfree(void *mem, long size)
282{
283 unsigned long adr;
284
285 adr = (unsigned long) mem;
286 while (size > 0) {
287 ClearPageReserved(vmalloc_to_page((void *) adr));
288 adr += PAGE_SIZE;
289 size -= PAGE_SIZE;
290 }
291 vfree(mem);
292}
293
294static int frame_alloc(struct gspca_dev *gspca_dev,
295 unsigned int count)
296{
297 struct gspca_frame *frame;
298 unsigned int frsz;
299 int i;
300
301 i = gspca_dev->curr_mode;
302 frsz = gspca_dev->cam.cam_mode[i].sizeimage;
303 PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
304 frsz = PAGE_ALIGN(frsz);
305 gspca_dev->frsz = frsz;
306 if (count > GSPCA_MAX_FRAMES)
307 count = GSPCA_MAX_FRAMES;
308 gspca_dev->frbuf = rvmalloc(frsz * count);
309 if (!gspca_dev->frbuf) {
310 err("frame alloc failed");
311 return -ENOMEM;
312 }
313 gspca_dev->nframes = count;
314 for (i = 0; i < count; i++) {
315 frame = &gspca_dev->frame[i];
316 frame->v4l2_buf.index = i;
317 frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
318 frame->v4l2_buf.flags = 0;
319 frame->v4l2_buf.field = V4L2_FIELD_NONE;
320 frame->v4l2_buf.length = frsz;
321 frame->v4l2_buf.memory = gspca_dev->memory;
322 frame->v4l2_buf.sequence = 0;
323 frame->data = frame->data_end =
324 gspca_dev->frbuf + i * frsz;
325 frame->v4l2_buf.m.offset = i * frsz;
326 }
327 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
328 gspca_dev->last_packet_type = DISCARD_PACKET;
329 gspca_dev->sequence = 0;
330 atomic_set(&gspca_dev->nevent, 0);
331 return 0;
332}
333
334static void frame_free(struct gspca_dev *gspca_dev)
335{
336 int i;
337
338 PDEBUG(D_STREAM, "frame free");
339 if (gspca_dev->frbuf != NULL) {
340 rvfree(gspca_dev->frbuf,
341 gspca_dev->nframes * gspca_dev->frsz);
342 gspca_dev->frbuf = NULL;
343 for (i = 0; i < gspca_dev->nframes; i++)
344 gspca_dev->frame[i].data = NULL;
345 }
346 gspca_dev->nframes = 0;
347}
348
349static void destroy_urbs(struct gspca_dev *gspca_dev)
350{
351 struct urb *urb;
352 unsigned int i;
353
354 PDEBUG(D_STREAM, "kill transfer");
355 for (i = 0; i < MAX_NURBS; ++i) {
356 urb = gspca_dev->urb[i];
357 if (urb == NULL)
358 break;
359
360 gspca_dev->urb[i] = NULL;
361 usb_kill_urb(urb);
362 if (urb->transfer_buffer != NULL)
363 usb_buffer_free(gspca_dev->dev,
364 urb->transfer_buffer_length,
365 urb->transfer_buffer,
366 urb->transfer_dma);
367 usb_free_urb(urb);
368 }
369}
370
371/*
372 * search an input isochronous endpoint in an alternate setting
373 */
374static struct usb_host_endpoint *alt_isoc(struct usb_host_interface *alt,
375 __u8 epaddr)
376{
377 struct usb_host_endpoint *ep;
378 int i, attr;
379
380 epaddr |= USB_DIR_IN;
381 for (i = 0; i < alt->desc.bNumEndpoints; i++) {
382 ep = &alt->endpoint[i];
383 if (ep->desc.bEndpointAddress == epaddr) {
384 attr = ep->desc.bmAttributes
385 & USB_ENDPOINT_XFERTYPE_MASK;
386 if (attr == USB_ENDPOINT_XFER_ISOC)
387 return ep;
388 break;
389 }
390 }
391 return NULL;
392}
393
394/*
395 * search an input isochronous endpoint
396 *
397 * The endpoint is defined by the subdriver.
398 * Use only the first isoc (some Zoran - 0x0572:0x0001 - have two such ep).
399 * This routine may be called many times when the bandwidth is too small
400 * (the bandwidth is checked on urb submit).
401 */
402struct usb_host_endpoint *get_isoc_ep(struct gspca_dev *gspca_dev)
403{
404 struct usb_interface *intf;
405 struct usb_host_endpoint *ep;
406 int i, ret;
407
408 intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
409 ep = NULL;
410 i = gspca_dev->alt; /* previous alt setting */
411 while (--i > 0) { /* alt 0 is unusable */
412 ep = alt_isoc(&intf->altsetting[i], gspca_dev->cam.epaddr);
413 if (ep)
414 break;
415 }
416 if (ep == NULL) {
417 err("no ISOC endpoint found");
418 return NULL;
419 }
420 PDEBUG(D_STREAM, "use ISOC alt %d ep 0x%02x",
421 i, ep->desc.bEndpointAddress);
422 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
423 if (ret < 0) {
424 err("set interface err %d", ret);
425 return NULL;
426 }
427 gspca_dev->alt = i; /* memorize the current alt setting */
428 return ep;
429}
430
431/*
432 * create the isochronous URBs
433 */
434static int create_urbs(struct gspca_dev *gspca_dev,
435 struct usb_host_endpoint *ep)
436{
437 struct urb *urb;
438 int n, nurbs, i, psize, npkt, bsize;
439
440 /* calculate the packet size and the number of packets */
441 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
442
443 /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
444 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
445 npkt = ISO_MAX_SIZE / psize;
446 if (npkt > ISO_MAX_PKT)
447 npkt = ISO_MAX_PKT;
448 bsize = psize * npkt;
449 PDEBUG(D_STREAM,
450 "isoc %d pkts size %d (bsize:%d)", npkt, psize, bsize);
451 nurbs = DEF_NURBS;
452 gspca_dev->nurbs = nurbs;
453 for (n = 0; n < nurbs; n++) {
454 urb = usb_alloc_urb(npkt, GFP_KERNEL);
455 if (!urb) {
456 err("usb_alloc_urb failed");
457 return -ENOMEM;
458 }
459 urb->transfer_buffer = usb_buffer_alloc(gspca_dev->dev,
460 bsize,
461 GFP_KERNEL,
462 &urb->transfer_dma);
463
464 if (urb->transfer_buffer == NULL) {
465 usb_free_urb(urb);
466 destroy_urbs(gspca_dev);
467 err("usb_buffer_urb failed");
468 return -ENOMEM;
469 }
470 gspca_dev->urb[n] = urb;
471 urb->dev = gspca_dev->dev;
472 urb->context = gspca_dev;
473 urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
474 ep->desc.bEndpointAddress);
475 urb->transfer_flags = URB_ISO_ASAP
476 | URB_NO_TRANSFER_DMA_MAP;
477 urb->interval = ep->desc.bInterval;
478 urb->complete = isoc_irq;
479 urb->number_of_packets = npkt;
480 urb->transfer_buffer_length = bsize;
481 for (i = 0; i < npkt; i++) {
482 urb->iso_frame_desc[i].length = psize;
483 urb->iso_frame_desc[i].offset = psize * i;
484 }
485 }
486 return 0;
487}
488
489/*
490 * start the USB transfer
491 */
492static int gspca_init_transfer(struct gspca_dev *gspca_dev)
493{
494 struct usb_host_endpoint *ep;
495 int n, ret;
496
497 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
498 return -ERESTARTSYS;
499
500 /* set the higher alternate setting and
501 * loop until urb submit succeeds */
502 gspca_dev->alt = gspca_dev->nbalt;
503 for (;;) {
504 PDEBUG(D_STREAM, "init transfer alt %d", gspca_dev->alt);
505 ep = get_isoc_ep(gspca_dev);
506 if (ep == NULL) {
507 ret = -EIO;
508 goto out;
509 }
510 ret = create_urbs(gspca_dev, ep);
511 if (ret < 0)
512 goto out;
513
514 /* start the cam */
515 gspca_dev->sd_desc->start(gspca_dev);
516 gspca_dev->streaming = 1;
517 atomic_set(&gspca_dev->nevent, 0);
518
519 /* submit the URBs */
520 for (n = 0; n < gspca_dev->nurbs; n++) {
521 ret = usb_submit_urb(gspca_dev->urb[n], GFP_KERNEL);
522 if (ret < 0) {
523 PDEBUG(D_ERR|D_STREAM,
524 "usb_submit_urb [%d] err %d", n, ret);
525 gspca_dev->streaming = 0;
526 destroy_urbs(gspca_dev);
527 if (ret == -ENOSPC)
528 break; /* try the previous alt */
529 goto out;
530 }
531 }
532 if (ret >= 0)
533 break;
534 }
535out:
536 mutex_unlock(&gspca_dev->usb_lock);
537 return ret;
538}
539
540static int gspca_set_alt0(struct gspca_dev *gspca_dev)
541{
542 int ret;
543
544 ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
545 if (ret < 0)
546 PDEBUG(D_ERR|D_STREAM, "set interface 0 err %d", ret);
547 return ret;
548}
549
550/* Note both the queue and the usb lock should be hold when calling this */
551static void gspca_stream_off(struct gspca_dev *gspca_dev)
552{
553 gspca_dev->streaming = 0;
554 atomic_set(&gspca_dev->nevent, 0);
555 if (gspca_dev->present) {
556 gspca_dev->sd_desc->stopN(gspca_dev);
557 destroy_urbs(gspca_dev);
558 gspca_set_alt0(gspca_dev);
559 gspca_dev->sd_desc->stop0(gspca_dev);
560 PDEBUG(D_STREAM, "stream off OK");
561 }
562}
563
564static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
565{
566 int i;
567
568 i = gspca_dev->cam.nmodes - 1; /* take the highest mode */
569 gspca_dev->curr_mode = i;
570 gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
571 gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
572 gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
573}
574
575static int wxh_to_mode(struct gspca_dev *gspca_dev,
576 int width, int height)
577{
578 int i;
579
580 for (i = gspca_dev->cam.nmodes; --i > 0; ) {
581 if (width >= gspca_dev->cam.cam_mode[i].width
582 && height >= gspca_dev->cam.cam_mode[i].height)
583 break;
584 }
585 return i;
586}
587
588/*
589 * search a mode with the right pixel format
590 */
591static int gspca_get_mode(struct gspca_dev *gspca_dev,
592 int mode,
593 int pixfmt)
594{
595 int modeU, modeD;
596
597 modeU = modeD = mode;
598 while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
599 if (--modeD >= 0) {
600 if (gspca_dev->cam.cam_mode[modeD].pixelformat
601 == pixfmt)
602 return modeD;
603 }
604 if (++modeU < gspca_dev->cam.nmodes) {
605 if (gspca_dev->cam.cam_mode[modeU].pixelformat
606 == pixfmt)
607 return modeU;
608 }
609 }
610 return -EINVAL;
611}
612
613static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
614 struct v4l2_fmtdesc *fmtdesc)
615{
616 struct gspca_dev *gspca_dev = priv;
617 int i, j, index;
618 __u32 fmt_tb[8];
619
620 /* give an index to each format */
621 index = 0;
622 j = 0;
623 for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
624 fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
625 j = 0;
626 for (;;) {
627 if (fmt_tb[j] == fmt_tb[index])
628 break;
629 j++;
630 }
631 if (j == index) {
632 if (fmtdesc->index == index)
633 break; /* new format */
634 index++;
635 if (index >= sizeof fmt_tb / sizeof fmt_tb[0])
636 return -EINVAL;
637 }
638 }
639 if (i < 0)
640 return -EINVAL; /* no more format */
641
642 fmtdesc->pixelformat = fmt_tb[index];
643 if (gspca_is_compressed(fmt_tb[index]))
644 fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
645 fmtdesc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
646 fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
647 fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
648 fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
649 fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
650 fmtdesc->description[4] = '\0';
651 return 0;
652}
653
654static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
655 struct v4l2_format *fmt)
656{
657 struct gspca_dev *gspca_dev = priv;
658 int mode;
659
660 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
661 return -EINVAL;
662 mode = gspca_dev->curr_mode;
663 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
664 sizeof fmt->fmt.pix);
665 return 0;
666}
667
668static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
669 struct v4l2_format *fmt)
670{
671 int w, h, mode, mode2;
672
673 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
674 return -EINVAL;
675 w = fmt->fmt.pix.width;
676 h = fmt->fmt.pix.height;
677
678#ifdef CONFIG_VIDEO_ADV_DEBUG
679 if (gspca_debug & D_CONF)
680 PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
681#endif
682 /* search the closest mode for width and height */
683 mode = wxh_to_mode(gspca_dev, w, h);
684
685 /* OK if right palette */
686 if (gspca_dev->cam.cam_mode[mode].pixelformat
687 != fmt->fmt.pix.pixelformat) {
688
689 /* else, search the closest mode with the same pixel format */
690 mode2 = gspca_get_mode(gspca_dev, mode,
691 fmt->fmt.pix.pixelformat);
692 if (mode2 >= 0)
693 mode = mode2;
694/* else
695 ; * no chance, return this mode */
696 }
697 memcpy(&fmt->fmt.pix, &gspca_dev->cam.cam_mode[mode],
698 sizeof fmt->fmt.pix);
699 return mode; /* used when s_fmt */
700}
701
702static int vidioc_try_fmt_vid_cap(struct file *file,
703 void *priv,
704 struct v4l2_format *fmt)
705{
706 struct gspca_dev *gspca_dev = priv;
707 int ret;
708
709 ret = try_fmt_vid_cap(gspca_dev, fmt);
710 if (ret < 0)
711 return ret;
712 return 0;
713}
714
715static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
716 struct v4l2_format *fmt)
717{
718 struct gspca_dev *gspca_dev = priv;
719 int ret;
720
721 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
722 return -ERESTARTSYS;
723
724 ret = try_fmt_vid_cap(gspca_dev, fmt);
725 if (ret < 0)
726 goto out;
727
728 if (gspca_dev->nframes != 0
729 && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
730 ret = -EINVAL;
731 goto out;
732 }
733
734 if (ret == gspca_dev->curr_mode) {
735 ret = 0;
736 goto out; /* same mode */
737 }
738
739 if (gspca_dev->streaming) {
740 ret = -EBUSY;
741 goto out;
742 }
743 gspca_dev->width = fmt->fmt.pix.width;
744 gspca_dev->height = fmt->fmt.pix.height;
745 gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
746 gspca_dev->curr_mode = ret;
747
748 ret = 0;
749out:
750 mutex_unlock(&gspca_dev->queue_lock);
751 return ret;
752}
753
754static int dev_open(struct inode *inode, struct file *file)
755{
756 struct gspca_dev *gspca_dev;
757 int ret;
758
759 PDEBUG(D_STREAM, "%s open", current->comm);
760 gspca_dev = (struct gspca_dev *) video_devdata(file);
761 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
762 return -ERESTARTSYS;
763 if (!gspca_dev->present) {
764 ret = -ENODEV;
765 goto out;
766 }
767
768 /* if not done yet, initialize the sensor */
769 if (gspca_dev->users == 0) {
770 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
771 ret = -ERESTARTSYS;
772 goto out;
773 }
774 ret = gspca_dev->sd_desc->open(gspca_dev);
775 mutex_unlock(&gspca_dev->usb_lock);
776 if (ret != 0) {
777 PDEBUG(D_ERR|D_CONF, "init device failed %d", ret);
778 goto out;
779 }
780 } else if (gspca_dev->users > 4) { /* (arbitrary value) */
781 ret = -EBUSY;
782 goto out;
783 }
784 gspca_dev->users++;
785 file->private_data = gspca_dev;
786#ifdef CONFIG_VIDEO_ADV_DEBUG
787 /* activate the v4l2 debug */
788 if (gspca_debug & D_V4L2)
789 gspca_dev->vdev.debug |= 3;
790 else
791 gspca_dev->vdev.debug &= ~3;
792#endif
793out:
794 mutex_unlock(&gspca_dev->queue_lock);
795 if (ret != 0)
796 PDEBUG(D_ERR|D_STREAM, "open failed err %d", ret);
797 else
798 PDEBUG(D_STREAM, "open done");
799 return ret;
800}
801
802static int dev_close(struct inode *inode, struct file *file)
803{
804 struct gspca_dev *gspca_dev = file->private_data;
805
806 PDEBUG(D_STREAM, "%s close", current->comm);
807 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
808 return -ERESTARTSYS;
809 gspca_dev->users--;
810
811 /* if the file did the capture, free the streaming resources */
812 if (gspca_dev->capt_file == file) {
813 mutex_lock(&gspca_dev->usb_lock);
814 if (gspca_dev->streaming)
815 gspca_stream_off(gspca_dev);
816 gspca_dev->sd_desc->close(gspca_dev);
817 mutex_unlock(&gspca_dev->usb_lock);
818 frame_free(gspca_dev);
819 gspca_dev->capt_file = NULL;
820 gspca_dev->memory = GSPCA_MEMORY_NO;
821 }
822 file->private_data = NULL;
823 mutex_unlock(&gspca_dev->queue_lock);
824 PDEBUG(D_STREAM, "close done");
825 return 0;
826}
827
828static int vidioc_querycap(struct file *file, void *priv,
829 struct v4l2_capability *cap)
830{
831 struct gspca_dev *gspca_dev = priv;
832
833 memset(cap, 0, sizeof *cap);
834 strncpy(cap->driver, gspca_dev->sd_desc->name, sizeof cap->driver);
835 strncpy(cap->card, gspca_dev->cam.dev_name, sizeof cap->card);
836 strncpy(cap->bus_info, gspca_dev->dev->bus->bus_name,
837 sizeof cap->bus_info);
838 cap->version = DRIVER_VERSION_NUMBER;
839 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
840 | V4L2_CAP_STREAMING
841 | V4L2_CAP_READWRITE;
842 return 0;
843}
844
845/* the use of V4L2_CTRL_FLAG_NEXT_CTRL asks for the controls to be sorted */
846static int vidioc_queryctrl(struct file *file, void *priv,
847 struct v4l2_queryctrl *q_ctrl)
848{
849 struct gspca_dev *gspca_dev = priv;
850 int i;
851 u32 id;
852
853 id = q_ctrl->id;
854 if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
855 id &= V4L2_CTRL_ID_MASK;
856 id++;
857 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
858 if (id >= gspca_dev->sd_desc->ctrls[i].qctrl.id) {
859 memcpy(q_ctrl,
860 &gspca_dev->sd_desc->ctrls[i].qctrl,
861 sizeof *q_ctrl);
862 return 0;
863 }
864 }
865 return -EINVAL;
866 }
867 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
868 if (id == gspca_dev->sd_desc->ctrls[i].qctrl.id) {
869 memcpy(q_ctrl,
870 &gspca_dev->sd_desc->ctrls[i].qctrl,
871 sizeof *q_ctrl);
872 return 0;
873 }
874 }
875 if (id >= V4L2_CID_BASE
876 && id <= V4L2_CID_LASTP1) {
877 q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
878 return 0;
879 }
880 return -EINVAL;
881}
882
883static int vidioc_s_ctrl(struct file *file, void *priv,
884 struct v4l2_control *ctrl)
885{
886 struct gspca_dev *gspca_dev = priv;
887 const struct ctrl *ctrls;
888 int i, ret;
889
890 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
891 i < gspca_dev->sd_desc->nctrls;
892 i++, ctrls++) {
893 if (ctrl->id != ctrls->qctrl.id)
894 continue;
895 if (ctrl->value < ctrls->qctrl.minimum
896 && ctrl->value > ctrls->qctrl.maximum)
897 return -ERANGE;
898 PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
899 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
900 return -ERESTARTSYS;
901 ret = ctrls->set(gspca_dev, ctrl->value);
902 mutex_unlock(&gspca_dev->usb_lock);
903 return ret;
904 }
905 return -EINVAL;
906}
907
908static int vidioc_g_ctrl(struct file *file, void *priv,
909 struct v4l2_control *ctrl)
910{
911 struct gspca_dev *gspca_dev = priv;
912
913 const struct ctrl *ctrls;
914 int i, ret;
915
916 for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
917 i < gspca_dev->sd_desc->nctrls;
918 i++, ctrls++) {
919 if (ctrl->id != ctrls->qctrl.id)
920 continue;
921 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
922 return -ERESTARTSYS;
923 ret = ctrls->get(gspca_dev, &ctrl->value);
924 mutex_unlock(&gspca_dev->usb_lock);
925 return ret;
926 }
927 return -EINVAL;
928}
929
930static int vidioc_querymenu(struct file *file, void *priv,
931 struct v4l2_querymenu *qmenu)
932{
933 struct gspca_dev *gspca_dev = priv;
934
935 if (!gspca_dev->sd_desc->querymenu)
936 return -EINVAL;
937 return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
938}
939
940static int vidioc_enum_input(struct file *file, void *priv,
941 struct v4l2_input *input)
942{
943 struct gspca_dev *gspca_dev = priv;
944
945 if (input->index != 0)
946 return -EINVAL;
947 memset(input, 0, sizeof *input);
948 input->type = V4L2_INPUT_TYPE_CAMERA;
949 strncpy(input->name, gspca_dev->sd_desc->name,
950 sizeof input->name);
951 return 0;
952}
953
954static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
955{
956 *i = 0;
957 return 0;
958}
959
960static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
961{
962 if (i > 0)
963 return -EINVAL;
964 return (0);
965}
966
967static int vidioc_reqbufs(struct file *file, void *priv,
968 struct v4l2_requestbuffers *rb)
969{
970 struct gspca_dev *gspca_dev = priv;
971 int i, ret = 0;
972
973 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
974 return -EINVAL;
975 switch (rb->memory) {
976 case GSPCA_MEMORY_READ: /* (internal call) */
977 case V4L2_MEMORY_MMAP:
978 case V4L2_MEMORY_USERPTR:
979 break;
980 default:
981 return -EINVAL;
982 }
983 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
984 return -ERESTARTSYS;
985
986 if (gspca_dev->memory != GSPCA_MEMORY_NO
987 && gspca_dev->memory != rb->memory) {
988 ret = -EBUSY;
989 goto out;
990 }
991
992 /* only one file may do the capture */
993 if (gspca_dev->capt_file != NULL
994 && gspca_dev->capt_file != file) {
995 ret = -EBUSY;
996 goto out;
997 }
998
999 /* if allocated, the buffers must not be mapped */
1000 for (i = 0; i < gspca_dev->nframes; i++) {
1001 if (gspca_dev->frame[i].vma_use_count) {
1002 ret = -EBUSY;
1003 goto out;
1004 }
1005 }
1006
1007 /* stop streaming */
1008 if (gspca_dev->streaming) {
1009 mutex_lock(&gspca_dev->usb_lock);
1010 gspca_stream_off(gspca_dev);
1011 mutex_unlock(&gspca_dev->usb_lock);
1012 }
1013
1014 /* free the previous allocated buffers, if any */
1015 if (gspca_dev->nframes != 0) {
1016 frame_free(gspca_dev);
1017 gspca_dev->capt_file = NULL;
1018 }
1019 if (rb->count == 0) /* unrequest */
1020 goto out;
1021 gspca_dev->memory = rb->memory;
1022 ret = frame_alloc(gspca_dev, rb->count);
1023 if (ret == 0) {
1024 rb->count = gspca_dev->nframes;
1025 gspca_dev->capt_file = file;
1026 }
1027out:
1028 mutex_unlock(&gspca_dev->queue_lock);
1029 PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
1030 return ret;
1031}
1032
1033static int vidioc_querybuf(struct file *file, void *priv,
1034 struct v4l2_buffer *v4l2_buf)
1035{
1036 struct gspca_dev *gspca_dev = priv;
1037 struct gspca_frame *frame;
1038
1039 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
1040 || v4l2_buf->index < 0
1041 || v4l2_buf->index >= gspca_dev->nframes)
1042 return -EINVAL;
1043
1044 frame = &gspca_dev->frame[v4l2_buf->index];
1045 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1046 return 0;
1047}
1048
1049static int vidioc_streamon(struct file *file, void *priv,
1050 enum v4l2_buf_type buf_type)
1051{
1052 struct gspca_dev *gspca_dev = priv;
1053 int ret;
1054
1055 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1056 return -EINVAL;
1057 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1058 return -ERESTARTSYS;
1059 if (!gspca_dev->present) {
1060 ret = -ENODEV;
1061 goto out;
1062 }
1063 if (gspca_dev->nframes == 0) {
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067 if (!gspca_dev->streaming) {
1068 ret = gspca_init_transfer(gspca_dev);
1069 if (ret < 0)
1070 goto out;
1071 }
1072#ifdef CONFIG_VIDEO_ADV_DEBUG
1073 if (gspca_debug & D_STREAM) {
1074 PDEBUG_MODE("stream on OK",
1075 gspca_dev->pixfmt,
1076 gspca_dev->width,
1077 gspca_dev->height);
1078 }
1079#endif
1080 ret = 0;
1081out:
1082 mutex_unlock(&gspca_dev->queue_lock);
1083 return ret;
1084}
1085
1086static int vidioc_streamoff(struct file *file, void *priv,
1087 enum v4l2_buf_type buf_type)
1088{
1089 struct gspca_dev *gspca_dev = priv;
1090 int i, ret;
1091
1092 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1093 return -EINVAL;
1094 if (!gspca_dev->streaming)
1095 return 0;
1096 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1097 return -ERESTARTSYS;
1098
1099 /* stop streaming */
1100 if (mutex_lock_interruptible(&gspca_dev->usb_lock)) {
1101 ret = -ERESTARTSYS;
1102 goto out;
1103 }
1104 gspca_stream_off(gspca_dev);
1105 mutex_unlock(&gspca_dev->usb_lock);
1106
1107 /* empty the application queues */
1108 for (i = 0; i < gspca_dev->nframes; i++)
1109 gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
1110 gspca_dev->fr_i = gspca_dev->fr_o = gspca_dev->fr_q = 0;
1111 gspca_dev->last_packet_type = DISCARD_PACKET;
1112 gspca_dev->sequence = 0;
1113 atomic_set(&gspca_dev->nevent, 0);
1114 ret = 0;
1115out:
1116 mutex_unlock(&gspca_dev->queue_lock);
1117 return ret;
1118}
1119
1120static int vidioc_g_jpegcomp(struct file *file, void *priv,
1121 struct v4l2_jpegcompression *jpegcomp)
1122{
1123 struct gspca_dev *gspca_dev = priv;
1124 int ret;
1125
1126 if (!gspca_dev->sd_desc->get_jcomp)
1127 return -EINVAL;
1128 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1129 return -ERESTARTSYS;
1130 ret = gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
1131 mutex_unlock(&gspca_dev->usb_lock);
1132 return ret;
1133}
1134
1135static int vidioc_s_jpegcomp(struct file *file, void *priv,
1136 struct v4l2_jpegcompression *jpegcomp)
1137{
1138 struct gspca_dev *gspca_dev = priv;
1139 int ret;
1140
1141 if (mutex_lock_interruptible(&gspca_dev->usb_lock))
1142 return -ERESTARTSYS;
1143 if (!gspca_dev->sd_desc->set_jcomp)
1144 return -EINVAL;
1145 ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
1146 mutex_unlock(&gspca_dev->usb_lock);
1147 return ret;
1148}
1149
1150static int vidioc_g_parm(struct file *filp, void *priv,
1151 struct v4l2_streamparm *parm)
1152{
1153 struct gspca_dev *gspca_dev = priv;
1154
1155 memset(parm, 0, sizeof *parm);
1156 parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1157 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1158 return 0;
1159}
1160
1161static int vidioc_s_parm(struct file *filp, void *priv,
1162 struct v4l2_streamparm *parm)
1163{
1164 struct gspca_dev *gspca_dev = priv;
1165 int n;
1166
1167 n = parm->parm.capture.readbuffers;
1168 if (n == 0 || n > GSPCA_MAX_FRAMES)
1169 parm->parm.capture.readbuffers = gspca_dev->nbufread;
1170 else
1171 gspca_dev->nbufread = n;
1172 return 0;
1173}
1174
1175static int vidioc_s_std(struct file *filp, void *priv,
1176 v4l2_std_id *parm)
1177{
1178 return 0;
1179}
1180
1181#ifdef CONFIG_VIDEO_V4L1_COMPAT
1182static int vidiocgmbuf(struct file *file, void *priv,
1183 struct video_mbuf *mbuf)
1184{
1185 struct gspca_dev *gspca_dev = file->private_data;
1186 int i;
1187
1188 PDEBUG(D_STREAM, "cgmbuf");
1189 if (gspca_dev->nframes == 0) {
1190 int ret;
1191
1192 {
1193 struct v4l2_format fmt;
1194
1195 memset(&fmt, 0, sizeof fmt);
1196 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1197 i = gspca_dev->cam.nmodes - 1; /* highest mode */
1198 fmt.fmt.pix.width = gspca_dev->cam.cam_mode[i].width;
1199 fmt.fmt.pix.height = gspca_dev->cam.cam_mode[i].height;
1200 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
1201 ret = vidioc_s_fmt_vid_cap(file, priv, &fmt);
1202 if (ret != 0)
1203 return ret;
1204 }
1205 {
1206 struct v4l2_requestbuffers rb;
1207
1208 memset(&rb, 0, sizeof rb);
1209 rb.count = 4;
1210 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1211 rb.memory = V4L2_MEMORY_MMAP;
1212 ret = vidioc_reqbufs(file, priv, &rb);
1213 if (ret != 0)
1214 return ret;
1215 }
1216 }
1217 mbuf->frames = gspca_dev->nframes;
1218 mbuf->size = gspca_dev->frsz * gspca_dev->nframes;
1219 for (i = 0; i < mbuf->frames; i++)
1220 mbuf->offsets[i] = gspca_dev->frame[i].v4l2_buf.m.offset;
1221 return 0;
1222}
1223#endif
1224
1225static int dev_mmap(struct file *file, struct vm_area_struct *vma)
1226{
1227 struct gspca_dev *gspca_dev = file->private_data;
1228 struct gspca_frame *frame;
1229 struct page *page;
1230 unsigned long addr, start, size;
1231 int i, ret;
1232
1233 start = vma->vm_start;
1234 size = vma->vm_end - vma->vm_start;
1235 PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
1236
1237 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1238 return -ERESTARTSYS;
1239 if (!gspca_dev->present) {
1240 ret = -ENODEV;
1241 goto out;
1242 }
1243 if (gspca_dev->capt_file != file) {
1244 ret = -EINVAL;
1245 goto out;
1246 }
1247
1248 frame = NULL;
1249 for (i = 0; i < gspca_dev->nframes; ++i) {
1250 if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
1251 PDEBUG(D_STREAM, "mmap bad memory type");
1252 break;
1253 }
1254 if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
1255 == vma->vm_pgoff) {
1256 frame = &gspca_dev->frame[i];
1257 break;
1258 }
1259 }
1260 if (frame == NULL) {
1261 PDEBUG(D_STREAM, "mmap no frame buffer found");
1262 ret = -EINVAL;
1263 goto out;
1264 }
1265#ifdef CONFIG_VIDEO_V4L1_COMPAT
1266 /* v4l1 maps all the buffers */
1267 if (i != 0
1268 || size != frame->v4l2_buf.length * gspca_dev->nframes)
1269#endif
1270 if (size != frame->v4l2_buf.length) {
1271 PDEBUG(D_STREAM, "mmap bad size");
1272 ret = -EINVAL;
1273 goto out;
1274 }
1275
1276 /*
1277 * - VM_IO marks the area as being a mmaped region for I/O to a
1278 * device. It also prevents the region from being core dumped.
1279 */
1280 vma->vm_flags |= VM_IO;
1281
1282 addr = (unsigned long) frame->data;
1283 while (size > 0) {
1284 page = vmalloc_to_page((void *) addr);
1285 ret = vm_insert_page(vma, start, page);
1286 if (ret < 0)
1287 goto out;
1288 start += PAGE_SIZE;
1289 addr += PAGE_SIZE;
1290 size -= PAGE_SIZE;
1291 }
1292
1293 vma->vm_ops = &gspca_vm_ops;
1294 vma->vm_private_data = frame;
1295 gspca_vm_open(vma);
1296 ret = 0;
1297out:
1298 mutex_unlock(&gspca_dev->queue_lock);
1299 return ret;
1300}
1301
1302/*
1303 * wait for a video frame
1304 *
1305 * If a frame is ready, its index is returned.
1306 */
1307static int frame_wait(struct gspca_dev *gspca_dev,
1308 int nonblock_ing)
1309{
1310 struct gspca_frame *frame;
1311 int i, j, ret;
1312
1313 /* check if a frame is ready */
1314 i = gspca_dev->fr_o;
1315 j = gspca_dev->fr_queue[i];
1316 frame = &gspca_dev->frame[j];
1317 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE) {
1318 atomic_dec(&gspca_dev->nevent);
1319 goto ok;
1320 }
1321 if (nonblock_ing) /* no frame yet */
1322 return -EAGAIN;
1323
1324 /* wait till a frame is ready */
1325 for (;;) {
1326 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1327 atomic_read(&gspca_dev->nevent) > 0,
1328 msecs_to_jiffies(3000));
1329 if (ret <= 0) {
1330 if (ret < 0)
1331 return ret; /* interrupt */
1332 return -EIO; /* timeout */
1333 }
1334 atomic_dec(&gspca_dev->nevent);
1335 if (!gspca_dev->streaming || !gspca_dev->present)
1336 return -EIO;
1337 i = gspca_dev->fr_o;
1338 j = gspca_dev->fr_queue[i];
1339 frame = &gspca_dev->frame[j];
1340 if (frame->v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1341 break;
1342 }
1343ok:
1344 gspca_dev->fr_o = (i + 1) % gspca_dev->nframes;
1345 PDEBUG(D_FRAM, "frame wait q:%d i:%d o:%d",
1346 gspca_dev->fr_q,
1347 gspca_dev->fr_i,
1348 gspca_dev->fr_o);
1349
1350 if (gspca_dev->sd_desc->dq_callback) {
1351 mutex_lock(&gspca_dev->usb_lock);
1352 gspca_dev->sd_desc->dq_callback(gspca_dev);
1353 mutex_unlock(&gspca_dev->usb_lock);
1354 }
1355 return j;
1356}
1357
1358/*
1359 * dequeue a video buffer
1360 *
1361 * If nonblock_ing is false, block until a buffer is available.
1362 */
1363static int vidioc_dqbuf(struct file *file, void *priv,
1364 struct v4l2_buffer *v4l2_buf)
1365{
1366 struct gspca_dev *gspca_dev = priv;
1367 struct gspca_frame *frame;
1368 int i, ret;
1369
1370 PDEBUG(D_FRAM, "dqbuf");
1371 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1372 return -EINVAL;
1373 if (v4l2_buf->memory != gspca_dev->memory)
1374 return -EINVAL;
1375
1376 /* if not streaming, be sure the application will not loop forever */
1377 if (!(file->f_flags & O_NONBLOCK)
1378 && !gspca_dev->streaming && gspca_dev->users == 1)
1379 return -EINVAL;
1380
1381 /* only the capturing file may dequeue */
1382 if (gspca_dev->capt_file != file)
1383 return -EINVAL;
1384
1385 /* only one dequeue / read at a time */
1386 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1387 return -ERESTARTSYS;
1388
1389 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
1390 if (ret < 0)
1391 goto out;
1392 i = ret; /* frame index */
1393 frame = &gspca_dev->frame[i];
1394 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
1395 if (copy_to_user((__u8 *) frame->v4l2_buf.m.userptr,
1396 frame->data,
1397 frame->v4l2_buf.bytesused)) {
1398 PDEBUG(D_ERR|D_STREAM,
1399 "dqbuf cp to user failed");
1400 ret = -EFAULT;
1401 goto out;
1402 }
1403 }
1404 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1405 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1406 PDEBUG(D_FRAM, "dqbuf %d", i);
1407 ret = 0;
1408out:
1409 mutex_unlock(&gspca_dev->read_lock);
1410 return ret;
1411}
1412
1413/*
1414 * queue a video buffer
1415 *
1416 * Attempting to queue a buffer that has already been
1417 * queued will return -EINVAL.
1418 */
1419static int vidioc_qbuf(struct file *file, void *priv,
1420 struct v4l2_buffer *v4l2_buf)
1421{
1422 struct gspca_dev *gspca_dev = priv;
1423 struct gspca_frame *frame;
1424 int i, index, ret;
1425
1426 PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
1427 if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1428 return -EINVAL;
1429
1430 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1431 return -ERESTARTSYS;
1432
1433 index = v4l2_buf->index;
1434 if ((unsigned) index >= gspca_dev->nframes) {
1435 PDEBUG(D_FRAM,
1436 "qbuf idx %d >= %d", index, gspca_dev->nframes);
1437 ret = -EINVAL;
1438 goto out;
1439 }
1440 if (v4l2_buf->memory != gspca_dev->memory) {
1441 PDEBUG(D_FRAM, "qbuf bad memory type");
1442 ret = -EINVAL;
1443 goto out;
1444 }
1445
1446 frame = &gspca_dev->frame[index];
1447 if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
1448 PDEBUG(D_FRAM, "qbuf bad state");
1449 ret = -EINVAL;
1450 goto out;
1451 }
1452
1453 frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
1454/* frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; */
1455
1456 if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
1457 frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
1458 frame->v4l2_buf.length = v4l2_buf->length;
1459 }
1460
1461 /* put the buffer in the 'queued' queue */
1462 i = gspca_dev->fr_q;
1463 gspca_dev->fr_queue[i] = index;
1464 gspca_dev->fr_q = (i + 1) % gspca_dev->nframes;
1465 PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d",
1466 gspca_dev->fr_q,
1467 gspca_dev->fr_i,
1468 gspca_dev->fr_o);
1469
1470 v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
1471 v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
1472 ret = 0;
1473out:
1474 mutex_unlock(&gspca_dev->queue_lock);
1475 return ret;
1476}
1477
1478/*
1479 * allocate the resources for read()
1480 */
1481static int read_alloc(struct gspca_dev *gspca_dev,
1482 struct file *file)
1483{
1484 struct v4l2_buffer v4l2_buf;
1485 int i, ret;
1486
1487 PDEBUG(D_STREAM, "read alloc");
1488 if (gspca_dev->nframes == 0) {
1489 struct v4l2_requestbuffers rb;
1490
1491 memset(&rb, 0, sizeof rb);
1492 rb.count = gspca_dev->nbufread;
1493 rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1494 rb.memory = GSPCA_MEMORY_READ;
1495 ret = vidioc_reqbufs(file, gspca_dev, &rb);
1496 if (ret != 0) {
1497 PDEBUG(D_STREAM, "read reqbuf err %d", ret);
1498 return ret;
1499 }
1500 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1501 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1502 v4l2_buf.memory = GSPCA_MEMORY_READ;
1503 for (i = 0; i < gspca_dev->nbufread; i++) {
1504 v4l2_buf.index = i;
1505 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1506 if (ret != 0) {
1507 PDEBUG(D_STREAM, "read qbuf err: %d", ret);
1508 return ret;
1509 }
1510 }
1511 gspca_dev->memory = GSPCA_MEMORY_READ;
1512 }
1513
1514 /* start streaming */
1515 ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
1516 if (ret != 0)
1517 PDEBUG(D_STREAM, "read streamon err %d", ret);
1518 return ret;
1519}
1520
1521static unsigned int dev_poll(struct file *file, poll_table *wait)
1522{
1523 struct gspca_dev *gspca_dev = file->private_data;
1524 int i, ret;
1525
1526 PDEBUG(D_FRAM, "poll");
1527
1528 poll_wait(file, &gspca_dev->wq, wait);
1529 if (!gspca_dev->present)
1530 return POLLERR;
1531
1532 /* if reqbufs is not done, the user would use read() */
1533 if (gspca_dev->nframes == 0) {
1534 if (gspca_dev->memory != GSPCA_MEMORY_NO)
1535 return POLLERR; /* not the 1st time */
1536 ret = read_alloc(gspca_dev, file);
1537 if (ret != 0)
1538 return POLLERR;
1539 }
1540
1541 if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0)
1542 return POLLERR;
1543 if (!gspca_dev->present) {
1544 ret = POLLERR;
1545 goto out;
1546 }
1547
1548 /* check the next incoming buffer */
1549 i = gspca_dev->fr_o;
1550 i = gspca_dev->fr_queue[i];
1551 if (gspca_dev->frame[i].v4l2_buf.flags & V4L2_BUF_FLAG_DONE)
1552 ret = POLLIN | POLLRDNORM; /* something to read */
1553 else
1554 ret = 0;
1555out:
1556 mutex_unlock(&gspca_dev->queue_lock);
1557 return ret;
1558}
1559
1560static ssize_t dev_read(struct file *file, char __user *data,
1561 size_t count, loff_t *ppos)
1562{
1563 struct gspca_dev *gspca_dev = file->private_data;
1564 struct gspca_frame *frame;
1565 struct v4l2_buffer v4l2_buf;
1566 struct timeval timestamp;
1567 int n, ret, ret2;
1568
1569 PDEBUG(D_FRAM, "read (%zd)", count);
1570 if (!gspca_dev->present)
1571 return -ENODEV;
1572 switch (gspca_dev->memory) {
1573 case GSPCA_MEMORY_NO: /* first time */
1574 ret = read_alloc(gspca_dev, file);
1575 if (ret != 0)
1576 return ret;
1577 break;
1578 case GSPCA_MEMORY_READ:
1579 if (gspca_dev->capt_file == file)
1580 break;
1581 /* fall thru */
1582 default:
1583 return -EINVAL;
1584 }
1585
1586 /* get a frame */
1587 jiffies_to_timeval(get_jiffies_64(), &timestamp);
1588 timestamp.tv_sec--;
1589 n = 2;
1590 for (;;) {
1591 memset(&v4l2_buf, 0, sizeof v4l2_buf);
1592 v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1593 v4l2_buf.memory = GSPCA_MEMORY_READ;
1594 ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
1595 if (ret != 0) {
1596 PDEBUG(D_STREAM, "read dqbuf err %d", ret);
1597 return ret;
1598 }
1599
1600 /* if the process slept for more than 1 second,
1601 * get anewer frame */
1602 frame = &gspca_dev->frame[v4l2_buf.index];
1603 if (--n < 0)
1604 break; /* avoid infinite loop */
1605 if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
1606 break;
1607 ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1608 if (ret != 0) {
1609 PDEBUG(D_STREAM, "read qbuf err %d", ret);
1610 return ret;
1611 }
1612 }
1613
1614 /* copy the frame */
1615 if (count > frame->v4l2_buf.bytesused)
1616 count = frame->v4l2_buf.bytesused;
1617 ret = copy_to_user(data, frame->data, count);
1618 if (ret != 0) {
1619 PDEBUG(D_ERR|D_STREAM,
1620 "read cp to user lack %d / %zd", ret, count);
1621 ret = -EFAULT;
1622 goto out;
1623 }
1624 ret = count;
1625out:
1626 /* in each case, requeue the buffer */
1627 ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
1628 if (ret2 != 0)
1629 return ret2;
1630 return ret;
1631}
1632
1633static void dev_release(struct video_device *vfd)
1634{
1635 /* nothing */
1636}
1637
1638static struct file_operations dev_fops = {
1639 .owner = THIS_MODULE,
1640 .open = dev_open,
1641 .release = dev_close,
1642 .read = dev_read,
1643 .mmap = dev_mmap,
1644 .ioctl = video_ioctl2,
1645#ifdef CONFIG_COMPAT
1646 .compat_ioctl = v4l_compat_ioctl32,
1647#endif
1648 .llseek = no_llseek,
1649 .poll = dev_poll,
1650};
1651
1652static struct video_device gspca_template = {
1653 .name = "gspca main driver",
1654 .type = VID_TYPE_CAPTURE,
1655 .fops = &dev_fops,
1656 .release = dev_release, /* mandatory */
1657 .minor = -1,
1658 .vidioc_querycap = vidioc_querycap,
1659 .vidioc_dqbuf = vidioc_dqbuf,
1660 .vidioc_qbuf = vidioc_qbuf,
1661 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1662 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
1663 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
1664 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
1665 .vidioc_streamon = vidioc_streamon,
1666 .vidioc_queryctrl = vidioc_queryctrl,
1667 .vidioc_g_ctrl = vidioc_g_ctrl,
1668 .vidioc_s_ctrl = vidioc_s_ctrl,
1669 .vidioc_querymenu = vidioc_querymenu,
1670 .vidioc_enum_input = vidioc_enum_input,
1671 .vidioc_g_input = vidioc_g_input,
1672 .vidioc_s_input = vidioc_s_input,
1673 .vidioc_reqbufs = vidioc_reqbufs,
1674 .vidioc_querybuf = vidioc_querybuf,
1675 .vidioc_streamoff = vidioc_streamoff,
1676 .vidioc_g_jpegcomp = vidioc_g_jpegcomp,
1677 .vidioc_s_jpegcomp = vidioc_s_jpegcomp,
1678 .vidioc_g_parm = vidioc_g_parm,
1679 .vidioc_s_parm = vidioc_s_parm,
1680 .vidioc_s_std = vidioc_s_std,
1681#ifdef CONFIG_VIDEO_V4L1_COMPAT
1682 .vidiocgmbuf = vidiocgmbuf,
1683#endif
1684};
1685
1686/*
1687 * probe and create a new gspca device
1688 *
1689 * This function must be called by the sub-driver when it is
1690 * called for probing a new device.
1691 */
1692int gspca_dev_probe(struct usb_interface *intf,
1693 const struct usb_device_id *id,
1694 const struct sd_desc *sd_desc,
1695 int dev_size,
1696 struct module *module)
1697{
1698 struct usb_interface_descriptor *interface;
1699 struct gspca_dev *gspca_dev;
1700 struct usb_device *dev = interface_to_usbdev(intf);
1701 int ret;
1702
1703 PDEBUG(D_PROBE, "probing %04x:%04x", id->idVendor, id->idProduct);
1704
1705 /* we don't handle multi-config cameras */
1706 if (dev->descriptor.bNumConfigurations != 1)
1707 return -ENODEV;
1708 interface = &intf->cur_altsetting->desc;
1709 if (interface->bInterfaceNumber > 0)
1710 return -ENODEV;
1711
1712 /* create the device */
1713 if (dev_size < sizeof *gspca_dev)
1714 dev_size = sizeof *gspca_dev;
1715 gspca_dev = kzalloc(dev_size, GFP_KERNEL);
1716 if (gspca_dev == NULL) {
1717 err("couldn't kzalloc gspca struct");
1718 return -EIO;
1719 }
1720 gspca_dev->dev = dev;
1721 gspca_dev->iface = interface->bInterfaceNumber;
1722 gspca_dev->nbalt = intf->num_altsetting;
1723 gspca_dev->sd_desc = sd_desc;
1724/* gspca_dev->users = 0; (done by kzalloc) */
1725 gspca_dev->nbufread = 2;
1726
1727 /* configure the subdriver */
1728 ret = gspca_dev->sd_desc->config(gspca_dev, id);
1729 if (ret < 0)
1730 goto out;
1731 ret = gspca_set_alt0(gspca_dev);
1732 if (ret < 0)
1733 goto out;
1734 gspca_set_default_mode(gspca_dev);
1735
1736 mutex_init(&gspca_dev->usb_lock);
1737 mutex_init(&gspca_dev->read_lock);
1738 mutex_init(&gspca_dev->queue_lock);
1739 init_waitqueue_head(&gspca_dev->wq);
1740
1741 /* init video stuff */
1742 memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
1743 gspca_dev->vdev.dev = &dev->dev;
1744 memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops);
1745 gspca_dev->vdev.fops = &gspca_dev->fops;
1746 gspca_dev->fops.owner = module; /* module protection */
1747 ret = video_register_device(&gspca_dev->vdev,
1748 VFL_TYPE_GRABBER,
1749 video_nr);
1750 if (ret < 0) {
1751 err("video_register_device err %d", ret);
1752 goto out;
1753 }
1754
1755 gspca_dev->present = 1;
1756 usb_set_intfdata(intf, gspca_dev);
1757 PDEBUG(D_PROBE, "probe ok");
1758 return 0;
1759out:
1760 kfree(gspca_dev);
1761 return ret;
1762}
1763EXPORT_SYMBOL(gspca_dev_probe);
1764
1765/*
1766 * USB disconnection
1767 *
1768 * This function must be called by the sub-driver
1769 * when the device disconnects, after the specific resources are freed.
1770 */
1771void gspca_disconnect(struct usb_interface *intf)
1772{
1773 struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
1774
1775 if (!gspca_dev)
1776 return;
1777 gspca_dev->present = 0;
1778 mutex_lock(&gspca_dev->queue_lock);
1779 mutex_lock(&gspca_dev->usb_lock);
1780 gspca_dev->streaming = 0;
1781 destroy_urbs(gspca_dev);
1782 mutex_unlock(&gspca_dev->usb_lock);
1783 mutex_unlock(&gspca_dev->queue_lock);
1784 while (gspca_dev->users != 0) { /* wait until fully closed */
1785 atomic_inc(&gspca_dev->nevent);
1786 wake_up_interruptible(&gspca_dev->wq); /* wake processes */
1787 schedule();
1788 }
1789/* We don't want people trying to open up the device */
1790 video_unregister_device(&gspca_dev->vdev);
1791/* Free the memory */
1792 kfree(gspca_dev);
1793 PDEBUG(D_PROBE, "disconnect complete");
1794}
1795EXPORT_SYMBOL(gspca_disconnect);
1796
1797/* -- cam driver utility functions -- */
1798
1799/* auto gain and exposure algorithm based on the knee algorithm described here:
1800 http://ytse.tricolour.net/docs/LowLightOptimization.html
1801
1802 Returns 0 if no changes were made, 1 if the gain and or exposure settings
1803 where changed. */
1804int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
1805 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
1806{
1807 int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
1808 const struct ctrl *gain_ctrl = NULL;
1809 const struct ctrl *exposure_ctrl = NULL;
1810 const struct ctrl *autogain_ctrl = NULL;
1811 int retval = 0;
1812
1813 for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
1814 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
1815 gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1816 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
1817 exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
1818 if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
1819 autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
1820 }
1821 if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
1822 PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
1823 "on cam without (auto)gain/exposure");
1824 return 0;
1825 }
1826
1827 if (gain_ctrl->get(gspca_dev, &gain) ||
1828 exposure_ctrl->get(gspca_dev, &exposure) ||
1829 autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
1830 return 0;
1831
1832 orig_gain = gain;
1833 orig_exposure = exposure;
1834
1835 /* If we are of a multiple of deadzone, do multiple steps to reach the
1836 desired lumination fast (with the risc of a slight overshoot) */
1837 steps = abs(desired_avg_lum - avg_lum) / deadzone;
1838
1839 PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
1840 avg_lum, desired_avg_lum, steps);
1841
1842 for (i = 0; i < steps; i++) {
1843 if (avg_lum > desired_avg_lum) {
1844 if (gain > gain_knee)
1845 gain--;
1846 else if (exposure > exposure_knee)
1847 exposure--;
1848 else if (gain > gain_ctrl->qctrl.default_value)
1849 gain--;
1850 else if (exposure > exposure_ctrl->qctrl.minimum)
1851 exposure--;
1852 else if (gain > gain_ctrl->qctrl.minimum)
1853 gain--;
1854 else
1855 break;
1856 } else {
1857 if (gain < gain_ctrl->qctrl.default_value)
1858 gain++;
1859 else if (exposure < exposure_knee)
1860 exposure++;
1861 else if (gain < gain_knee)
1862 gain++;
1863 else if (exposure < exposure_ctrl->qctrl.maximum)
1864 exposure++;
1865 else if (gain < gain_ctrl->qctrl.maximum)
1866 gain++;
1867 else
1868 break;
1869 }
1870 }
1871
1872 if (gain != orig_gain) {
1873 gain_ctrl->set(gspca_dev, gain);
1874 retval = 1;
1875 }
1876 if (exposure != orig_exposure) {
1877 exposure_ctrl->set(gspca_dev, exposure);
1878 retval = 1;
1879 }
1880
1881 return retval;
1882}
1883EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
1884
1885/* -- module insert / remove -- */
1886static int __init gspca_init(void)
1887{
1888 info("main v%s registered", version);
1889 return 0;
1890}
1891static void __exit gspca_exit(void)
1892{
1893 info("main deregistered");
1894}
1895
1896module_init(gspca_init);
1897module_exit(gspca_exit);
1898
1899#ifdef CONFIG_VIDEO_ADV_DEBUG
1900module_param_named(debug, gspca_debug, int, 0644);
1901MODULE_PARM_DESC(debug,
1902 "Debug (bit) 0x01:error 0x02:probe 0x04:config"
1903 " 0x08:stream 0x10:frame 0x20:packet 0x40:USBin 0x80:USBout"
1904 " 0x0100: v4l2");
1905#endif
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
new file mode 100644
index 000000000000..3fd2c4eee204
--- /dev/null
+++ b/drivers/media/video/gspca/gspca.h
@@ -0,0 +1,176 @@
1#ifndef GSPCAV2_H
2#define GSPCAV2_H
3
4#include <linux/module.h>
5#include <linux/version.h>
6#include <linux/kernel.h>
7#include <linux/usb.h>
8#include <linux/videodev2.h>
9#include <media/v4l2-common.h>
10#include <linux/mutex.h>
11
12#ifdef CONFIG_VIDEO_ADV_DEBUG
13/* GSPCA our debug messages */
14extern int gspca_debug;
15#define PDEBUG(level, fmt, args...) \
16 do {\
17 if (gspca_debug & (level)) \
18 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
19 } while (0)
20#define D_ERR 0x01
21#define D_PROBE 0x02
22#define D_CONF 0x04
23#define D_STREAM 0x08
24#define D_FRAM 0x10
25#define D_PACK 0x20
26#define D_USBI 0x40
27#define D_USBO 0x80
28#define D_V4L2 0x0100
29#else
30#define PDEBUG(level, fmt, args...)
31#endif
32#undef err
33#define err(fmt, args...) \
34 do {\
35 printk(KERN_ERR MODULE_NAME ": " fmt "\n", ## args); \
36 } while (0)
37#undef info
38#define info(fmt, args...) \
39 do {\
40 printk(KERN_INFO MODULE_NAME ": " fmt "\n", ## args); \
41 } while (0)
42#undef warn
43#define warn(fmt, args...) \
44 do {\
45 printk(KERN_WARNING MODULE_NAME ": " fmt "\n", ## args); \
46 } while (0)
47
48#define GSPCA_MAX_FRAMES 16 /* maximum number of video frame buffers */
49/* ISOC transfers */
50#define MAX_NURBS 16 /* max number of URBs */
51#define ISO_MAX_PKT 32 /* max number of packets in an ISOC transfer */
52#define ISO_MAX_SIZE 0x8000 /* max size of one URB buffer (32 Kb) */
53
54/* device information - set at probe time */
55struct cam {
56 char *dev_name;
57 struct v4l2_pix_format *cam_mode; /* size nmodes */
58 char nmodes;
59 __u8 epaddr;
60};
61
62struct gspca_dev;
63struct gspca_frame;
64
65/* subdriver operations */
66typedef int (*cam_op) (struct gspca_dev *);
67typedef void (*cam_v_op) (struct gspca_dev *);
68typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
69typedef int (*cam_jpg_op) (struct gspca_dev *,
70 struct v4l2_jpegcompression *);
71typedef int (*cam_qmnu_op) (struct gspca_dev *,
72 struct v4l2_querymenu *);
73typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
74 struct gspca_frame *frame,
75 __u8 *data,
76 int len);
77
78struct ctrl {
79 struct v4l2_queryctrl qctrl;
80 int (*set)(struct gspca_dev *, __s32);
81 int (*get)(struct gspca_dev *, __s32 *);
82};
83
84/* subdriver description */
85struct sd_desc {
86/* information */
87 const char *name; /* sub-driver name */
88/* controls */
89 const struct ctrl *ctrls;
90 int nctrls;
91/* operations */
92 cam_cf_op config; /* called on probe */
93 cam_op open; /* called on open */
94 cam_v_op start; /* called on stream on */
95 cam_v_op stopN; /* called on stream off - main alt */
96 cam_v_op stop0; /* called on stream off - alt 0 */
97 cam_v_op close; /* called on close */
98 cam_pkt_op pkt_scan;
99/* optional operations */
100 cam_v_op dq_callback; /* called when a frame has been dequeued */
101 cam_jpg_op get_jcomp;
102 cam_jpg_op set_jcomp;
103 cam_qmnu_op querymenu;
104};
105
106/* packet types when moving from iso buf to frame buf */
107#define DISCARD_PACKET 0
108#define FIRST_PACKET 1
109#define INTER_PACKET 2
110#define LAST_PACKET 3
111
112struct gspca_frame {
113 __u8 *data; /* frame buffer */
114 __u8 *data_end; /* end of frame while filling */
115 int vma_use_count;
116 struct v4l2_buffer v4l2_buf;
117};
118
119struct gspca_dev {
120 struct video_device vdev; /* !! must be the first item */
121 struct file_operations fops;
122 struct usb_device *dev;
123 struct file *capt_file; /* file doing video capture */
124
125 struct cam cam; /* device information */
126 const struct sd_desc *sd_desc; /* subdriver description */
127
128 __u8 usb_buf[8]; /* buffer for USB exchanges */
129 struct urb *urb[MAX_NURBS];
130
131 __u8 *frbuf; /* buffer for nframes */
132 struct gspca_frame frame[GSPCA_MAX_FRAMES];
133 __u32 frsz; /* frame size */
134 char nframes; /* number of frames */
135 char fr_i; /* frame being filled */
136 char fr_q; /* next frame to queue */
137 char fr_o; /* next frame to dequeue */
138 signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
139 char last_packet_type;
140
141 __u8 iface; /* USB interface number */
142 __u8 alt; /* USB alternate setting */
143 __u8 curr_mode; /* current camera mode */
144 __u32 pixfmt; /* current mode parameters */
145 __u16 width;
146 __u16 height;
147
148 atomic_t nevent; /* number of frames done */
149 wait_queue_head_t wq; /* wait queue */
150 struct mutex usb_lock; /* usb exchange protection */
151 struct mutex read_lock; /* read protection */
152 struct mutex queue_lock; /* ISOC queue protection */
153 __u32 sequence; /* frame sequence number */
154 char streaming;
155 char users; /* number of opens */
156 char present; /* device connected */
157 char nbufread; /* number of buffers for read() */
158 char nurbs; /* number of allocated URBs */
159 char memory; /* memory type (V4L2_MEMORY_xxx) */
160 __u8 nbalt; /* number of USB alternate settings */
161};
162
163int gspca_dev_probe(struct usb_interface *intf,
164 const struct usb_device_id *id,
165 const struct sd_desc *sd_desc,
166 int dev_size,
167 struct module *module);
168void gspca_disconnect(struct usb_interface *intf);
169struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
170 int packet_type,
171 struct gspca_frame *frame,
172 const __u8 *data,
173 int len);
174int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
175 int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
176#endif /* GSPCAV2_H */
diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h
new file mode 100644
index 000000000000..d823b47bd4e6
--- /dev/null
+++ b/drivers/media/video/gspca/jpeg.h
@@ -0,0 +1,301 @@
1#ifndef JPEG_H
2#define JPEG_H 1
3/*
4 * Insert a JPEG header at start of frame
5 *
6 * This module is used by the gspca subdrivers.
7 * A special case is done for Conexant webcams.
8 *
9 * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27/* start of jpeg frame + quantization table */
28static const unsigned char quant[][0x88] = {
29/* index 0 - Q40*/
30 {
31 0xff, 0xd8, /* jpeg */
32 0xff, 0xdb, 0x00, 0x84, /* DQT */
330, /* quantization table part 1 */
34 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50,
35 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64,
36 70, 69, 80, 90, 115, 98, 80, 85, 109, 86, 69, 70, 100, 136, 101,
37 109,
38 119, 123, 129, 130, 129, 78, 96, 141, 151, 140, 125, 150, 115,
39 126, 129, 124,
401, /* quantization table part 2 */
41 21, 23, 23, 30, 26, 30, 59, 33, 33, 59, 124, 83, 70, 83, 124, 124,
42 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
43 124, 124, 124,
44 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
45 124, 124, 124,
46 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
47 124, 124, 124},
48/* index 1 - Q50 */
49 {
50 0xff, 0xd8,
51 0xff, 0xdb, 0x00, 0x84, /* DQT */
520,
53 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
54 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
55 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87,
56 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101,
57 103, 99,
581,
59 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
60 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
61 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
62 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99},
63/* index 2 Q60 */
64 {
65 0xff, 0xd8,
66 0xff, 0xdb, 0x00, 0x84, /* DQT */
670,
68 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32,
69 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41,
70 45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70,
71 76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79,
721,
73 14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79,
74 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
75 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
76 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
77/* index 3 - Q70 */
78 {
79 0xff, 0xd8,
80 0xff, 0xdb, 0x00, 0x84, /* DQT */
810,
82 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24,
83 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31,
84 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52,
85 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59,
861,
87 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59,
88 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
89 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
90 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
91/* index 4 - Q80 */
92 {
93 0xff, 0xd8,
94 0xff, 0xdb, 0x00, 0x84, /* DQT */
950,
96 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16,
97 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20,
98 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35,
99 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40,
1001,
101 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40,
102 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
103 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
104 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
105/* index 5 - Q85 */
106 {
107 0xff, 0xd8,
108 0xff, 0xdb, 0x00, 0x84, /* DQT */
1090,
110 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12,
111 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15,
112 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26,
113 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30,
1141,
115 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30,
116 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
117 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
118 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
119/* index 6 - 86 */
120{
121 0xff, 0xd8,
122 0xff, 0xdb, 0x00, 0x84, /* DQT */
1230,
124 0x04, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x04,
125 0x04, 0x04, 0x05, 0x05, 0x04, 0x05, 0x07, 0x0B,
126 0x07, 0x07, 0x06, 0x06, 0x07, 0x0E, 0x0A, 0x0A,
127 0x08, 0x0B, 0x10, 0x0E, 0x11, 0x11, 0x10, 0x0E,
128 0x10, 0x0F, 0x12, 0x14, 0x1A, 0x16, 0x12, 0x13,
129 0x18, 0x13, 0x0F, 0x10, 0x16, 0x1F, 0x17, 0x18,
130 0x1B, 0x1B, 0x1D, 0x1D, 0x1D, 0x11, 0x16, 0x20,
131 0x22, 0x1F, 0x1C, 0x22, 0x1A, 0x1C, 0x1D, 0x1C,
1321,
133 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0D, 0x07,
134 0x07, 0x0D, 0x1C, 0x12, 0x10, 0x12, 0x1C, 0x1C,
135 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
136 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
137 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
138 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
139 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
140 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C,
141 },
142/* index 7 - 88 */
143{
144 0xff, 0xd8,
145 0xff, 0xdb, 0x00, 0x84, /* DQT */
1460,
147 0x04, 0x03, 0x03, 0x03, 0x03, 0x02, 0x04, 0x03,
148 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x06, 0x0A,
149 0x06, 0x06, 0x05, 0x05, 0x06, 0x0C, 0x08, 0x09,
150 0x07, 0x0A, 0x0E, 0x0C, 0x0F, 0x0E, 0x0E, 0x0C,
151 0x0D, 0x0D, 0x0F, 0x11, 0x16, 0x13, 0x0F, 0x10,
152 0x15, 0x11, 0x0D, 0x0D, 0x13, 0x1A, 0x13, 0x15,
153 0x17, 0x18, 0x19, 0x19, 0x19, 0x0F, 0x12, 0x1B,
154 0x1D, 0x1B, 0x18, 0x1D, 0x16, 0x18, 0x19, 0x18,
1551,
156 0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0B, 0x06,
157 0x06, 0x0B, 0x18, 0x10, 0x0D, 0x10, 0x18, 0x18,
158 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
159 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
160 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
161 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
162 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
163 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
164},
165/* index 8 - ?? */
166{
167 0xff, 0xd8,
168 0xff, 0xdb, 0x00, 0x84, /* DQT */
1690,
170 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
171 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x05,
172 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x04, 0x05,
173 0x04, 0x05, 0x07, 0x06, 0x08, 0x08, 0x07, 0x06,
174 0x07, 0x07, 0x08, 0x09, 0x0C, 0x0A, 0x08, 0x09,
175 0x0B, 0x09, 0x07, 0x07, 0x0A, 0x0E, 0x0A, 0x0B,
176 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x08, 0x0A, 0x0E,
177 0x0F, 0x0E, 0x0D, 0x0F, 0x0C, 0x0D, 0x0D, 0x0C,
1781,
179 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x06, 0x03,
180 0x03, 0x06, 0x0C, 0x08, 0x07, 0x08, 0x0C, 0x0C,
181 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
182 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
183 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
184 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
185 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
186 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C
187}
188};
189
190/* huffman table + start of SOF0 */
191static unsigned char huffman[] = {
192 0xff, 0xc4, 0x01, 0xa2,
193 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
194 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
196 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03,
197 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
198 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
199 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
200 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
201 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
202 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
203 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
204 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
205 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
206 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
207 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
208 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
209 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
210 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
211 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
212 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
213 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
214 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
215 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
216 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
217 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
218 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
219 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
220 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
221 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
222 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
223 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
224 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
225 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
226 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
227 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
228 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
229 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
230 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28,
231 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
232 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
233 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
234 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
235 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
236 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
237 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
238 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
239 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
240 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
241 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
242 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
243 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2,
244 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
245#ifdef CONEX_CAM
246/* the Conexant frames start with SOF0 */
247#else
248 0xff, 0xc0, 0x00, 0x11, /* SOF0 (start of frame 0 */
249 0x08, /* data precision */
250#endif
251};
252
253#ifndef CONEX_CAM
254/* variable part:
255 * 0x01, 0xe0, height
256 * 0x02, 0x80, width
257 * 0x03, component number
258 * 0x01,
259 * 0x21, samples Y
260 */
261
262/* end of header */
263static unsigned char eoh[] = {
264 0x00, /* quant Y */
265 0x02, 0x11, 0x01, /* samples CbCr - quant CbCr */
266 0x03, 0x11, 0x01,
267
268 0xff, 0xda, 0x00, 0x0c, /* SOS (start of scan) */
269 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
270};
271#endif
272
273/* -- output the JPEG header -- */
274static void jpeg_put_header(struct gspca_dev *gspca_dev,
275 struct gspca_frame *frame,
276 int qindex,
277 int samplesY)
278{
279#ifndef CONEX_CAM
280 unsigned char tmpbuf[8];
281#endif
282
283 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
284 (unsigned char *) quant[qindex], sizeof quant[0]);
285 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
286 (unsigned char *) huffman, sizeof huffman);
287#ifndef CONEX_CAM
288 tmpbuf[0] = gspca_dev->height >> 8;
289 tmpbuf[1] = gspca_dev->height & 0xff;
290 tmpbuf[2] = gspca_dev->width >> 8;
291 tmpbuf[3] = gspca_dev->width & 0xff;
292 tmpbuf[4] = 0x03; /* component number */
293 tmpbuf[5] = 0x01; /* first component */
294 tmpbuf[6] = samplesY;
295 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
296 tmpbuf, 7);
297 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
298 eoh, sizeof eoh);
299#endif
300}
301#endif
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
new file mode 100644
index 000000000000..88c2b02f380a
--- /dev/null
+++ b/drivers/media/video/gspca/mars.c
@@ -0,0 +1,464 @@
1/*
2 * Mars-Semi MR97311A library
3 * Copyright (C) 2005 <bradlch@hotmail.com>
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 "mars"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/Mars 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
38 char qindex;
39};
40
41/* V4L2 controls supported by the driver */
42static struct ctrl sd_ctrls[] = {
43};
44
45static struct v4l2_pix_format vga_mode[] = {
46 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
47 .bytesperline = 320,
48 .sizeimage = 320 * 240 * 3 / 8 + 589,
49 .colorspace = V4L2_COLORSPACE_JPEG,
50 .priv = 2},
51 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
52 .bytesperline = 640,
53 .sizeimage = 640 * 480 * 3 / 8 + 590,
54 .colorspace = V4L2_COLORSPACE_JPEG,
55 .priv = 1},
56};
57
58/* MI Register table //elvis */
59enum {
60 REG_HW_MI_0,
61 REG_HW_MI_1,
62 REG_HW_MI_2,
63 REG_HW_MI_3,
64 REG_HW_MI_4,
65 REG_HW_MI_5,
66 REG_HW_MI_6,
67 REG_HW_MI_7,
68 REG_HW_MI_9 = 0x09,
69 REG_HW_MI_B = 0x0B,
70 REG_HW_MI_C,
71 REG_HW_MI_D,
72 REG_HW_MI_1E = 0x1E,
73 REG_HW_MI_20 = 0x20,
74 REG_HW_MI_2B = 0x2B,
75 REG_HW_MI_2C,
76 REG_HW_MI_2D,
77 REG_HW_MI_2E,
78 REG_HW_MI_35 = 0x35,
79 REG_HW_MI_5F = 0x5f,
80 REG_HW_MI_60,
81 REG_HW_MI_61,
82 REG_HW_MI_62,
83 REG_HW_MI_63,
84 REG_HW_MI_64,
85 REG_HW_MI_F1 = 0xf1,
86 ATTR_TOTAL_MI_REG = 0xf2
87};
88
89/* the bytes to write are in gspca_dev->usb_buf */
90static int reg_w(struct gspca_dev *gspca_dev,
91 __u16 index, int len)
92{
93 int rc;
94
95 rc = usb_control_msg(gspca_dev->dev,
96 usb_sndbulkpipe(gspca_dev->dev, 4),
97 0x12,
98 0xc8, /* ?? */
99 0, /* value */
100 index, gspca_dev->usb_buf, len, 500);
101 if (rc < 0)
102 PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
103 return rc;
104}
105
106static int reg_w_buf(struct gspca_dev *gspca_dev,
107 __u16 index, __u8 *buf, int len)
108{
109 int rc;
110
111 rc = usb_control_msg(gspca_dev->dev,
112 usb_sndbulkpipe(gspca_dev->dev, 4),
113 0x12,
114 0xc8, /* ?? */
115 0, /* value */
116 index, buf, len, 500);
117 if (rc < 0)
118 PDEBUG(D_ERR, "reg write [%02x] error %d", index, rc);
119 return rc;
120}
121
122static void bulk_w(struct gspca_dev *gspca_dev,
123 __u16 *pch,
124 __u16 Address)
125{
126 gspca_dev->usb_buf[0] = 0x1f;
127 gspca_dev->usb_buf[1] = 0; /* control byte */
128 gspca_dev->usb_buf[2] = Address;
129 gspca_dev->usb_buf[3] = *pch >> 8; /* high byte */
130 gspca_dev->usb_buf[4] = *pch; /* low byte */
131
132 reg_w(gspca_dev, Address, 5);
133}
134
135/* this function is called at probe time */
136static int sd_config(struct gspca_dev *gspca_dev,
137 const struct usb_device_id *id)
138{
139 struct sd *sd = (struct sd *) gspca_dev;
140 struct cam *cam;
141
142 cam = &gspca_dev->cam;
143 cam->dev_name = (char *) id->driver_info;
144 cam->epaddr = 0x01;
145 cam->cam_mode = vga_mode;
146 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
147 sd->qindex = 1; /* set the quantization table */
148 return 0;
149}
150
151/* this function is called at open time */
152static int sd_open(struct gspca_dev *gspca_dev)
153{
154 return 0;
155}
156
157static void sd_start(struct gspca_dev *gspca_dev)
158{
159 int err_code;
160 __u8 *data;
161 __u16 *MI_buf;
162 int h_size, v_size;
163 int intpipe;
164
165 PDEBUG(D_STREAM, "camera start, iface %d, alt 8", gspca_dev->iface);
166 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 8) < 0) {
167 PDEBUG(D_ERR|D_STREAM, "Set packet size: set interface error");
168 return;
169 }
170
171 data = gspca_dev->usb_buf;
172 data[0] = 0x01; /* address */
173 data[1] = 0x01;
174
175 err_code = reg_w(gspca_dev, data[0], 2);
176 if (err_code < 0)
177 return;
178
179 /*
180 Initialize the MR97113 chip register
181 */
182 data = kmalloc(16, GFP_KERNEL);
183 data[0] = 0x00; /* address */
184 data[1] = 0x0c | 0x01; /* reg 0 */
185 data[2] = 0x01; /* reg 1 */
186 h_size = gspca_dev->width;
187 v_size = gspca_dev->height;
188 data[3] = h_size / 8; /* h_size , reg 2 */
189 data[4] = v_size / 8; /* v_size , reg 3 */
190 data[5] = 0x30; /* reg 4, MI, PAS5101 :
191 * 0x30 for 24mhz , 0x28 for 12mhz */
192 data[6] = 4; /* reg 5, H start */
193 data[7] = 0xc0; /* reg 6, gamma 1.5 */
194 data[8] = 3; /* reg 7, V start */
195/* if (h_size == 320 ) */
196/* data[9]= 0x56; * reg 8, 24MHz, 2:1 scale down */
197/* else */
198 data[9] = 0x52; /* reg 8, 24MHz, no scale down */
199 data[10] = 0x5d; /* reg 9, I2C device address
200 * [for PAS5101 (0x40)] [for MI (0x5d)] */
201
202 err_code = reg_w_buf(gspca_dev, data[0], data, 11);
203 kfree(data);
204 if (err_code < 0)
205 return;
206
207 data = gspca_dev->usb_buf;
208 data[0] = 0x23; /* address */
209 data[1] = 0x09; /* reg 35, append frame header */
210
211 err_code = reg_w(gspca_dev, data[0], 2);
212 if (err_code < 0)
213 return;
214
215 data[0] = 0x3c; /* address */
216/* if (gspca_dev->width == 1280) */
217/* data[1] = 200; * reg 60, pc-cam frame size
218 * (unit: 4KB) 800KB */
219/* else */
220 data[1] = 50; /* 50 reg 60, pc-cam frame size
221 * (unit: 4KB) 200KB */
222 err_code = reg_w(gspca_dev, data[0], 2);
223 if (err_code < 0)
224 return;
225
226 if (0) { /* fixed dark-gain */
227 data[1] = 0; /* reg 94, Y Gain (1.75) */
228 data[2] = 0; /* reg 95, UV Gain (1.75) */
229 data[3] = 0x3f; /* reg 96, Y Gain/UV Gain/disable
230 * auto dark-gain */
231 data[4] = 0; /* reg 97, set fixed dark level */
232 data[5] = 0; /* reg 98, don't care */
233 } else { /* auto dark-gain */
234 data[1] = 0; /* reg 94, Y Gain (auto) */
235 data[2] = 0; /* reg 95, UV Gain (1.75) */
236 data[3] = 0x78; /* reg 96, Y Gain/UV Gain/disable
237 * auto dark-gain */
238 switch (gspca_dev->width) {
239/* case 1280: */
240/* data[4] = 154;
241 * reg 97, %3 shadow point (unit: 256 pixel) */
242/* data[5] = 51;
243 * reg 98, %1 highlight point
244 * (uint: 256 pixel) */
245/* break; */
246 default:
247/* case 640: */
248 data[4] = 36; /* reg 97, %3 shadow point
249 * (unit: 256 pixel) */
250 data[5] = 12; /* reg 98, %1 highlight point
251 * (uint: 256 pixel) */
252 break;
253 case 320:
254 data[4] = 9; /* reg 97, %3 shadow point
255 * (unit: 256 pixel) */
256 data[5] = 3; /* reg 98, %1 highlight point
257 * (uint: 256 pixel) */
258 break;
259 }
260 }
261 /* auto dark-gain */
262 data[0] = 0x5e; /* address */
263
264 err_code = reg_w(gspca_dev, data[0], 6);
265 if (err_code < 0)
266 return;
267
268 data[0] = 0x67;
269 data[1] = 0x13; /* reg 103, first pixel B, disable sharpness */
270 err_code = reg_w(gspca_dev, data[0], 2);
271 if (err_code < 0)
272 return;
273
274 /*
275 * initialize the value of MI sensor...
276 */
277 MI_buf = kzalloc(ATTR_TOTAL_MI_REG * sizeof *MI_buf, GFP_KERNEL);
278 MI_buf[REG_HW_MI_1] = 0x000a;
279 MI_buf[REG_HW_MI_2] = 0x000c;
280 MI_buf[REG_HW_MI_3] = 0x0405;
281 MI_buf[REG_HW_MI_4] = 0x0507;
282 /* mi_Attr_Reg_[REG_HW_MI_5] = 0x01ff;//13 */
283 MI_buf[REG_HW_MI_5] = 0x0013; /* 13 */
284 MI_buf[REG_HW_MI_6] = 0x001f; /* vertical blanking */
285 /* mi_Attr_Reg_[REG_HW_MI_6] = 0x0400; // vertical blanking */
286 MI_buf[REG_HW_MI_7] = 0x0002;
287 /* mi_Attr_Reg_[REG_HW_MI_9] = 0x015f; */
288 /* mi_Attr_Reg_[REG_HW_MI_9] = 0x030f; */
289 MI_buf[REG_HW_MI_9] = 0x0374;
290 MI_buf[REG_HW_MI_B] = 0x0000;
291 MI_buf[REG_HW_MI_C] = 0x0000;
292 MI_buf[REG_HW_MI_D] = 0x0000;
293 MI_buf[REG_HW_MI_1E] = 0x8000;
294/* mi_Attr_Reg_[REG_HW_MI_20] = 0x1104; */
295 MI_buf[REG_HW_MI_20] = 0x1104; /* 0x111c; */
296 MI_buf[REG_HW_MI_2B] = 0x0008;
297/* mi_Attr_Reg_[REG_HW_MI_2C] = 0x000f; */
298 MI_buf[REG_HW_MI_2C] = 0x001f; /* lita suggest */
299 MI_buf[REG_HW_MI_2D] = 0x0008;
300 MI_buf[REG_HW_MI_2E] = 0x0008;
301 MI_buf[REG_HW_MI_35] = 0x0051;
302 MI_buf[REG_HW_MI_5F] = 0x0904; /* fail to write */
303 MI_buf[REG_HW_MI_60] = 0x0000;
304 MI_buf[REG_HW_MI_61] = 0x0000;
305 MI_buf[REG_HW_MI_62] = 0x0498;
306 MI_buf[REG_HW_MI_63] = 0x0000;
307 MI_buf[REG_HW_MI_64] = 0x0000;
308 MI_buf[REG_HW_MI_F1] = 0x0001;
309 /* changing while setting up the different value of dx/dy */
310
311 if (gspca_dev->width != 1280) {
312 MI_buf[0x01] = 0x010a;
313 MI_buf[0x02] = 0x014c;
314 MI_buf[0x03] = 0x01e5;
315 MI_buf[0x04] = 0x0287;
316 }
317 MI_buf[0x20] = 0x1104;
318
319 bulk_w(gspca_dev, MI_buf + 1, 1);
320 bulk_w(gspca_dev, MI_buf + 2, 2);
321 bulk_w(gspca_dev, MI_buf + 3, 3);
322 bulk_w(gspca_dev, MI_buf + 4, 4);
323 bulk_w(gspca_dev, MI_buf + 5, 5);
324 bulk_w(gspca_dev, MI_buf + 6, 6);
325 bulk_w(gspca_dev, MI_buf + 7, 7);
326 bulk_w(gspca_dev, MI_buf + 9, 9);
327 bulk_w(gspca_dev, MI_buf + 0x0b, 0x0b);
328 bulk_w(gspca_dev, MI_buf + 0x0c, 0x0c);
329 bulk_w(gspca_dev, MI_buf + 0x0d, 0x0d);
330 bulk_w(gspca_dev, MI_buf + 0x1e, 0x1e);
331 bulk_w(gspca_dev, MI_buf + 0x20, 0x20);
332 bulk_w(gspca_dev, MI_buf + 0x2b, 0x2b);
333 bulk_w(gspca_dev, MI_buf + 0x2c, 0x2c);
334 bulk_w(gspca_dev, MI_buf + 0x2d, 0x2d);
335 bulk_w(gspca_dev, MI_buf + 0x2e, 0x2e);
336 bulk_w(gspca_dev, MI_buf + 0x35, 0x35);
337 bulk_w(gspca_dev, MI_buf + 0x5f, 0x5f);
338 bulk_w(gspca_dev, MI_buf + 0x60, 0x60);
339 bulk_w(gspca_dev, MI_buf + 0x61, 0x61);
340 bulk_w(gspca_dev, MI_buf + 0x62, 0x62);
341 bulk_w(gspca_dev, MI_buf + 0x63, 0x63);
342 bulk_w(gspca_dev, MI_buf + 0x64, 0x64);
343 bulk_w(gspca_dev, MI_buf + 0xf1, 0xf1);
344 kfree(MI_buf);
345
346 intpipe = usb_sndintpipe(gspca_dev->dev, 0);
347 err_code = usb_clear_halt(gspca_dev->dev, intpipe);
348
349 data[0] = 0x00;
350 data[1] = 0x4d; /* ISOC transfering enable... */
351 reg_w(gspca_dev, data[0], 2);
352}
353
354static void sd_stopN(struct gspca_dev *gspca_dev)
355{
356 int result;
357
358 gspca_dev->usb_buf[0] = 1;
359 gspca_dev->usb_buf[1] = 0;
360 result = reg_w(gspca_dev, gspca_dev->usb_buf[0], 2);
361 if (result < 0)
362 PDEBUG(D_ERR, "Camera Stop failed");
363}
364
365static void sd_stop0(struct gspca_dev *gspca_dev)
366{
367}
368
369static void sd_close(struct gspca_dev *gspca_dev)
370{
371}
372
373static void sd_pkt_scan(struct gspca_dev *gspca_dev,
374 struct gspca_frame *frame, /* target */
375 __u8 *data, /* isoc packet */
376 int len) /* iso packet length */
377{
378 struct sd *sd = (struct sd *) gspca_dev;
379 int p;
380
381 if (len < 6) {
382/* gspca_dev->last_packet_type = DISCARD_PACKET; */
383 return;
384 }
385 for (p = 0; p < len - 6; p++) {
386 if (data[0 + p] == 0xff
387 && data[1 + p] == 0xff
388 && data[2 + p] == 0x00
389 && data[3 + p] == 0xff
390 && data[4 + p] == 0x96) {
391 if (data[5 + p] == 0x64
392 || data[5 + p] == 0x65
393 || data[5 + p] == 0x66
394 || data[5 + p] == 0x67) {
395 PDEBUG(D_PACK, "sof offset: %d leng: %d",
396 p, len);
397 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
398 frame, data, 0);
399
400 /* put the JPEG header */
401 jpeg_put_header(gspca_dev, frame,
402 sd->qindex, 0x21);
403 data += 16;
404 len -= 16;
405 break;
406 }
407 }
408 }
409 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
410}
411
412/* sub-driver description */
413static const struct sd_desc sd_desc = {
414 .name = MODULE_NAME,
415 .ctrls = sd_ctrls,
416 .nctrls = ARRAY_SIZE(sd_ctrls),
417 .config = sd_config,
418 .open = sd_open,
419 .start = sd_start,
420 .stopN = sd_stopN,
421 .stop0 = sd_stop0,
422 .close = sd_close,
423 .pkt_scan = sd_pkt_scan,
424};
425
426/* -- module initialisation -- */
427#define DVNM(name) .driver_info = (kernel_ulong_t) name
428static const __devinitdata struct usb_device_id device_table[] = {
429 {USB_DEVICE(0x093a, 0x050f), DVNM("Mars-Semi Pc-Camera")},
430 {}
431};
432MODULE_DEVICE_TABLE(usb, device_table);
433
434/* -- device connect -- */
435static int sd_probe(struct usb_interface *intf,
436 const struct usb_device_id *id)
437{
438 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
439 THIS_MODULE);
440}
441
442static struct usb_driver sd_driver = {
443 .name = MODULE_NAME,
444 .id_table = device_table,
445 .probe = sd_probe,
446 .disconnect = gspca_disconnect,
447};
448
449/* -- module insert / remove -- */
450static int __init sd_mod_init(void)
451{
452 if (usb_register(&sd_driver) < 0)
453 return -1;
454 PDEBUG(D_PROBE, "v%s registered", version);
455 return 0;
456}
457static void __exit sd_mod_exit(void)
458{
459 usb_deregister(&sd_driver);
460 PDEBUG(D_PROBE, "deregistered");
461}
462
463module_init(sd_mod_init);
464module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
new file mode 100644
index 000000000000..08d99c3b78e2
--- /dev/null
+++ b/drivers/media/video/gspca/ov519.c
@@ -0,0 +1,2186 @@
1/**
2 * OV519 driver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * (This module is adapted from the ov51x-jpeg package)
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 "ov519"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
31MODULE_DESCRIPTION("OV519 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* global parameters */
35static int frame_rate;
36
37/* Number of times to retry a failed I2C transaction. Increase this if you
38 * are getting "Failed to read sensor ID..." */
39static int i2c_detect_tries = 10;
40
41/* ov519 device descriptor */
42struct sd {
43 struct gspca_dev gspca_dev; /* !! must be the first item */
44
45 /* Determined by sensor type */
46 short maxwidth;
47 short maxheight;
48
49 unsigned char primary_i2c_slave; /* I2C write id of sensor */
50
51 unsigned char brightness;
52 unsigned char contrast;
53 unsigned char colors;
54
55 char compress; /* Should the next frame be compressed? */
56 char compress_inited; /* Are compression params uploaded? */
57 char stopped; /* Streaming is temporarily paused */
58
59 char frame_rate; /* current Framerate (OV519 only) */
60 char clockdiv; /* clockdiv override for OV519 only */
61
62 char sensor; /* Type of image sensor chip (SEN_*) */
63#define SEN_UNKNOWN 0
64#define SEN_OV6620 1
65#define SEN_OV6630 2
66#define SEN_OV7610 3
67#define SEN_OV7620 4
68#define SEN_OV7630 5
69#define SEN_OV7640 6
70#define SEN_OV7670 7
71#define SEN_OV76BE 8
72#define SEN_OV8610 9
73
74};
75
76/* V4L2 controls supported by the driver */
77static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
83
84static struct ctrl sd_ctrls[] = {
85#define SD_BRIGHTNESS 0
86 {
87 {
88 .id = V4L2_CID_BRIGHTNESS,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Brightness",
91 .minimum = 0,
92 .maximum = 255,
93 .step = 1,
94 .default_value = 127,
95 },
96 .set = sd_setbrightness,
97 .get = sd_getbrightness,
98 },
99#define SD_CONTRAST 1
100 {
101 {
102 .id = V4L2_CID_CONTRAST,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Contrast",
105 .minimum = 0,
106 .maximum = 255,
107 .step = 1,
108 .default_value = 127,
109 },
110 .set = sd_setcontrast,
111 .get = sd_getcontrast,
112 },
113#define SD_COLOR 2
114 {
115 {
116 .id = V4L2_CID_SATURATION,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "Saturation",
119 .minimum = 0,
120 .maximum = 255,
121 .step = 1,
122 .default_value = 127,
123 },
124 .set = sd_setcolors,
125 .get = sd_getcolors,
126 },
127};
128
129static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 589,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 1},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 0},
140};
141static struct v4l2_pix_format sif_mode[] = {
142 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
143 .bytesperline = 176,
144 .sizeimage = 176 * 144 * 3 / 8 + 589,
145 .colorspace = V4L2_COLORSPACE_JPEG,
146 .priv = 1},
147 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
148 .bytesperline = 352,
149 .sizeimage = 352 * 288 * 3 / 8 + 589,
150 .colorspace = V4L2_COLORSPACE_JPEG,
151 .priv = 0},
152};
153
154/* OV519 Camera interface register numbers */
155#define OV519_CAM_H_SIZE 0x10
156#define OV519_CAM_V_SIZE 0x11
157#define OV519_CAM_X_OFFSETL 0x12
158#define OV519_CAM_X_OFFSETH 0x13
159#define OV519_CAM_Y_OFFSETL 0x14
160#define OV519_CAM_Y_OFFSETH 0x15
161#define OV519_CAM_DIVIDER 0x16
162#define OV519_CAM_DFR 0x20
163#define OV519_CAM_FORMAT 0x25
164
165/* OV519 System Controller register numbers */
166#define OV519_SYS_RESET1 0x51
167#define OV519_SYS_EN_CLK1 0x54
168
169#define OV519_GPIO_DATA_OUT0 0x71
170#define OV519_GPIO_IO_CTRL0 0x72
171
172#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
173
174/* I2C registers */
175#define R51x_I2C_W_SID 0x41
176#define R51x_I2C_SADDR_3 0x42
177#define R51x_I2C_SADDR_2 0x43
178#define R51x_I2C_R_SID 0x44
179#define R51x_I2C_DATA 0x45
180#define R518_I2C_CTL 0x47 /* OV518(+) only */
181
182/* I2C ADDRESSES */
183#define OV7xx0_SID 0x42
184#define OV8xx0_SID 0xa0
185#define OV6xx0_SID 0xc0
186
187/* OV7610 registers */
188#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */
189#define OV7610_REG_SAT 0x03 /* saturation */
190#define OV8610_REG_HUE 0x04 /* 04 reserved */
191#define OV7610_REG_CNT 0x05 /* Y contrast */
192#define OV7610_REG_BRT 0x06 /* Y brightness */
193#define OV7610_REG_COM_C 0x14 /* misc common regs */
194#define OV7610_REG_ID_HIGH 0x1c /* manufacturer ID MSB */
195#define OV7610_REG_ID_LOW 0x1d /* manufacturer ID LSB */
196#define OV7610_REG_COM_I 0x29 /* misc settings */
197
198/* OV7670 registers */
199#define OV7670_REG_GAIN 0x00 /* Gain lower 8 bits (rest in vref) */
200#define OV7670_REG_BLUE 0x01 /* blue gain */
201#define OV7670_REG_RED 0x02 /* red gain */
202#define OV7670_REG_VREF 0x03 /* Pieces of GAIN, VSTART, VSTOP */
203#define OV7670_REG_COM1 0x04 /* Control 1 */
204#define OV7670_REG_AECHH 0x07 /* AEC MS 5 bits */
205#define OV7670_REG_COM3 0x0c /* Control 3 */
206#define OV7670_REG_COM4 0x0d /* Control 4 */
207#define OV7670_REG_COM5 0x0e /* All "reserved" */
208#define OV7670_REG_COM6 0x0f /* Control 6 */
209#define OV7670_REG_AECH 0x10 /* More bits of AEC value */
210#define OV7670_REG_CLKRC 0x11 /* Clock control */
211#define OV7670_REG_COM7 0x12 /* Control 7 */
212#define OV7670_COM7_FMT_VGA 0x00
213#define OV7670_COM7_YUV 0x00 /* YUV */
214#define OV7670_COM7_FMT_QVGA 0x10 /* QVGA format */
215#define OV7670_COM7_FMT_MASK 0x38
216#define OV7670_COM7_RESET 0x80 /* Register reset */
217#define OV7670_REG_COM8 0x13 /* Control 8 */
218#define OV7670_COM8_AEC 0x01 /* Auto exposure enable */
219#define OV7670_COM8_AWB 0x02 /* White balance enable */
220#define OV7670_COM8_AGC 0x04 /* Auto gain enable */
221#define OV7670_COM8_BFILT 0x20 /* Band filter enable */
222#define OV7670_COM8_AECSTEP 0x40 /* Unlimited AEC step size */
223#define OV7670_COM8_FASTAEC 0x80 /* Enable fast AGC/AEC */
224#define OV7670_REG_COM9 0x14 /* Control 9 - gain ceiling */
225#define OV7670_REG_COM10 0x15 /* Control 10 */
226#define OV7670_REG_HSTART 0x17 /* Horiz start high bits */
227#define OV7670_REG_HSTOP 0x18 /* Horiz stop high bits */
228#define OV7670_REG_VSTART 0x19 /* Vert start high bits */
229#define OV7670_REG_VSTOP 0x1a /* Vert stop high bits */
230#define OV7670_REG_MVFP 0x1e /* Mirror / vflip */
231#define OV7670_MVFP_MIRROR 0x20 /* Mirror image */
232#define OV7670_REG_AEW 0x24 /* AGC upper limit */
233#define OV7670_REG_AEB 0x25 /* AGC lower limit */
234#define OV7670_REG_VPT 0x26 /* AGC/AEC fast mode op region */
235#define OV7670_REG_HREF 0x32 /* HREF pieces */
236#define OV7670_REG_TSLB 0x3a /* lots of stuff */
237#define OV7670_REG_COM11 0x3b /* Control 11 */
238#define OV7670_COM11_EXP 0x02
239#define OV7670_COM11_HZAUTO 0x10 /* Auto detect 50/60 Hz */
240#define OV7670_REG_COM12 0x3c /* Control 12 */
241#define OV7670_REG_COM13 0x3d /* Control 13 */
242#define OV7670_COM13_GAMMA 0x80 /* Gamma enable */
243#define OV7670_COM13_UVSAT 0x40 /* UV saturation auto adjustment */
244#define OV7670_REG_COM14 0x3e /* Control 14 */
245#define OV7670_REG_EDGE 0x3f /* Edge enhancement factor */
246#define OV7670_REG_COM15 0x40 /* Control 15 */
247#define OV7670_COM15_R00FF 0xc0 /* 00 to FF */
248#define OV7670_REG_COM16 0x41 /* Control 16 */
249#define OV7670_COM16_AWBGAIN 0x08 /* AWB gain enable */
250#define OV7670_REG_BRIGHT 0x55 /* Brightness */
251#define OV7670_REG_CONTRAS 0x56 /* Contrast control */
252#define OV7670_REG_GFIX 0x69 /* Fix gain control */
253#define OV7670_REG_RGB444 0x8c /* RGB 444 control */
254#define OV7670_REG_HAECC1 0x9f /* Hist AEC/AGC control 1 */
255#define OV7670_REG_HAECC2 0xa0 /* Hist AEC/AGC control 2 */
256#define OV7670_REG_BD50MAX 0xa5 /* 50hz banding step limit */
257#define OV7670_REG_HAECC3 0xa6 /* Hist AEC/AGC control 3 */
258#define OV7670_REG_HAECC4 0xa7 /* Hist AEC/AGC control 4 */
259#define OV7670_REG_HAECC5 0xa8 /* Hist AEC/AGC control 5 */
260#define OV7670_REG_HAECC6 0xa9 /* Hist AEC/AGC control 6 */
261#define OV7670_REG_HAECC7 0xaa /* Hist AEC/AGC control 7 */
262#define OV7670_REG_BD60MAX 0xab /* 60hz banding step limit */
263
264struct ovsensor_window {
265 short x;
266 short y;
267 short width;
268 short height;
269/* int format; */
270 short quarter; /* Scale width and height down 2x */
271 short clockdiv; /* Clock divisor setting */
272};
273
274static unsigned char ov7670_abs_to_sm(unsigned char v)
275{
276 if (v > 127)
277 return v & 0x7f;
278 return (128 - v) | 0x80;
279}
280
281/* Write a OV519 register */
282static int reg_w(struct sd *sd, __u16 index, __u8 value)
283{
284 int ret;
285
286 sd->gspca_dev.usb_buf[0] = value;
287 ret = usb_control_msg(sd->gspca_dev.dev,
288 usb_sndctrlpipe(sd->gspca_dev.dev, 0),
289 1, /* REQ_IO (ov518/519) */
290 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
291 0, index,
292 sd->gspca_dev.usb_buf, 1, 500);
293 if (ret < 0)
294 PDEBUG(D_ERR, "Write reg [%02x] %02x failed", index, value);
295 return ret;
296}
297
298/* Read from a OV519 register */
299/* returns: negative is error, pos or zero is data */
300static int reg_r(struct sd *sd, __u16 index)
301{
302 int ret;
303
304 ret = usb_control_msg(sd->gspca_dev.dev,
305 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
306 1, /* REQ_IO */
307 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
308 0, index, sd->gspca_dev.usb_buf, 1, 500);
309
310 if (ret >= 0)
311 ret = sd->gspca_dev.usb_buf[0];
312 else
313 PDEBUG(D_ERR, "Read reg [0x%02x] failed", index);
314 return ret;
315}
316
317/* Read 8 values from a OV519 register */
318static int reg_r8(struct sd *sd,
319 __u16 index)
320{
321 int ret;
322
323 ret = usb_control_msg(sd->gspca_dev.dev,
324 usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
325 1, /* REQ_IO */
326 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
327 0, index, sd->gspca_dev.usb_buf, 8, 500);
328
329 if (ret >= 0)
330 ret = sd->gspca_dev.usb_buf[0];
331 else
332 PDEBUG(D_ERR, "Read reg 8 [0x%02x] failed", index);
333 return ret;
334}
335
336/*
337 * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
338 * the same position as 1's in "mask" are cleared and set to "value". Bits
339 * that are in the same position as 0's in "mask" are preserved, regardless
340 * of their respective state in "value".
341 */
342static int reg_w_mask(struct sd *sd,
343 __u16 index,
344 __u8 value,
345 __u8 mask)
346{
347 int ret;
348 __u8 oldval;
349
350 if (mask != 0xff) {
351 value &= mask; /* Enforce mask on value */
352 ret = reg_r(sd, index);
353 if (ret < 0)
354 return ret;
355
356 oldval = ret & ~mask; /* Clear the masked bits */
357 value |= oldval; /* Set the desired bits */
358 }
359 return reg_w(sd, index, value);
360}
361
362/*
363 * The OV518 I2C I/O procedure is different, hence, this function.
364 * This is normally only called from i2c_w(). Note that this function
365 * always succeeds regardless of whether the sensor is present and working.
366 */
367static int i2c_w(struct sd *sd,
368 __u8 reg,
369 __u8 value)
370{
371 int rc;
372
373 PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
374
375 /* Select camera register */
376 rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
377 if (rc < 0)
378 return rc;
379
380 /* Write "value" to I2C data port of OV511 */
381 rc = reg_w(sd, R51x_I2C_DATA, value);
382 if (rc < 0)
383 return rc;
384
385 /* Initiate 3-byte write cycle */
386 rc = reg_w(sd, R518_I2C_CTL, 0x01);
387
388 /* wait for write complete */
389 msleep(4);
390 if (rc < 0)
391 return rc;
392 return reg_r8(sd, R518_I2C_CTL);
393}
394
395/*
396 * returns: negative is error, pos or zero is data
397 *
398 * The OV518 I2C I/O procedure is different, hence, this function.
399 * This is normally only called from i2c_r(). Note that this function
400 * always succeeds regardless of whether the sensor is present and working.
401 */
402static int i2c_r(struct sd *sd, __u8 reg)
403{
404 int rc, value;
405
406 /* Select camera register */
407 rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
408 if (rc < 0)
409 return rc;
410
411 /* Initiate 2-byte write cycle */
412 rc = reg_w(sd, R518_I2C_CTL, 0x03);
413 if (rc < 0)
414 return rc;
415
416 /* Initiate 2-byte read cycle */
417 rc = reg_w(sd, R518_I2C_CTL, 0x05);
418 if (rc < 0)
419 return rc;
420 value = reg_r(sd, R51x_I2C_DATA);
421 PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
422 return value;
423}
424
425/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
426 * the same position as 1's in "mask" are cleared and set to "value". Bits
427 * that are in the same position as 0's in "mask" are preserved, regardless
428 * of their respective state in "value".
429 */
430static int i2c_w_mask(struct sd *sd,
431 __u8 reg,
432 __u8 value,
433 __u8 mask)
434{
435 int rc;
436 __u8 oldval;
437
438 value &= mask; /* Enforce mask on value */
439 rc = i2c_r(sd, reg);
440 if (rc < 0)
441 return rc;
442 oldval = rc & ~mask; /* Clear the masked bits */
443 value |= oldval; /* Set the desired bits */
444 return i2c_w(sd, reg, value);
445}
446
447/* Temporarily stops OV511 from functioning. Must do this before changing
448 * registers while the camera is streaming */
449static inline int ov51x_stop(struct sd *sd)
450{
451 PDEBUG(D_STREAM, "stopping");
452 sd->stopped = 1;
453 return reg_w(sd, OV519_SYS_RESET1, 0x0f);
454}
455
456/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
457 * actually stopped (for performance). */
458static inline int ov51x_restart(struct sd *sd)
459{
460 PDEBUG(D_STREAM, "restarting");
461 if (!sd->stopped)
462 return 0;
463 sd->stopped = 0;
464
465 /* Reinitialize the stream */
466 return reg_w(sd, OV519_SYS_RESET1, 0x00);
467}
468
469/* This does an initial reset of an OmniVision sensor and ensures that I2C
470 * is synchronized. Returns <0 on failure.
471 */
472static int init_ov_sensor(struct sd *sd)
473{
474 int i, success;
475
476 /* Reset the sensor */
477 if (i2c_w(sd, 0x12, 0x80) < 0)
478 return -EIO;
479
480 /* Wait for it to initialize */
481 msleep(150);
482
483 for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
484 if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
485 i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
486 success = 1;
487 continue;
488 }
489
490 /* Reset the sensor */
491 if (i2c_w(sd, 0x12, 0x80) < 0)
492 return -EIO;
493 /* Wait for it to initialize */
494 msleep(150);
495 /* Dummy read to sync I2C */
496 if (i2c_r(sd, 0x00) < 0)
497 return -EIO;
498 }
499 if (!success)
500 return -EIO;
501 PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
502 return 0;
503}
504
505/* Switch on standard JPEG compression. Returns 0 for success. */
506static int ov519_init_compression(struct sd *sd)
507{
508 if (!sd->compress_inited) {
509 if (reg_w_mask(sd, OV519_SYS_EN_CLK1, 1 << 2, 1 << 2) < 0) {
510 PDEBUG(D_ERR, "Error switching to compressed mode");
511 return -EIO;
512 }
513 sd->compress_inited = 1;
514 }
515 return 0;
516}
517
518/* Set the read and write slave IDs. The "slave" argument is the write slave,
519 * and the read slave will be set to (slave + 1).
520 * This should not be called from outside the i2c I/O functions.
521 * Sets I2C read and write slave IDs. Returns <0 for error
522 */
523static int ov51x_set_slave_ids(struct sd *sd,
524 __u8 slave)
525{
526 int rc;
527
528 rc = reg_w(sd, R51x_I2C_W_SID, slave);
529 if (rc < 0)
530 return rc;
531 return reg_w(sd, R51x_I2C_R_SID, slave + 1);
532}
533
534struct ov_regvals {
535 __u8 reg;
536 __u8 val;
537};
538struct ov_i2c_regvals {
539 __u8 reg;
540 __u8 val;
541};
542
543static int write_regvals(struct sd *sd,
544 const struct ov_regvals *regvals,
545 int n)
546{
547 int rc;
548
549 while (--n >= 0) {
550 rc = reg_w(sd, regvals->reg, regvals->val);
551 if (rc < 0)
552 return rc;
553 regvals++;
554 }
555 return 0;
556}
557
558static int write_i2c_regvals(struct sd *sd,
559 const struct ov_i2c_regvals *regvals,
560 int n)
561{
562 int rc;
563
564 while (--n >= 0) {
565 rc = i2c_w(sd, regvals->reg, regvals->val);
566 if (rc < 0)
567 return rc;
568 regvals++;
569 }
570 return 0;
571}
572
573/****************************************************************************
574 *
575 * OV511 and sensor configuration
576 *
577 ***************************************************************************/
578
579/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
580 * the same register settings as the OV8610, since they are very similar.
581 */
582static int ov8xx0_configure(struct sd *sd)
583{
584 int rc;
585 static const struct ov_i2c_regvals norm_8610[] = {
586 { 0x12, 0x80 },
587 { 0x00, 0x00 },
588 { 0x01, 0x80 },
589 { 0x02, 0x80 },
590 { 0x03, 0xc0 },
591 { 0x04, 0x30 },
592 { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
593 { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
594 { 0x0a, 0x86 },
595 { 0x0b, 0xb0 },
596 { 0x0c, 0x20 },
597 { 0x0d, 0x20 },
598 { 0x11, 0x01 },
599 { 0x12, 0x25 },
600 { 0x13, 0x01 },
601 { 0x14, 0x04 },
602 { 0x15, 0x01 }, /* Lin and Win think different about UV order */
603 { 0x16, 0x03 },
604 { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
605 { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
606 { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
607 { 0x1a, 0xf5 },
608 { 0x1b, 0x00 },
609 { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
610 { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
611 { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
612 { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
613 { 0x26, 0xa2 },
614 { 0x27, 0xea },
615 { 0x28, 0x00 },
616 { 0x29, 0x00 },
617 { 0x2a, 0x80 },
618 { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
619 { 0x2c, 0xac },
620 { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
621 { 0x2e, 0x80 },
622 { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
623 { 0x4c, 0x00 },
624 { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
625 { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
626 { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
627 { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
628 { 0x63, 0xff },
629 { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
630 * maybe thats wrong */
631 { 0x65, 0x00 },
632 { 0x66, 0x55 },
633 { 0x67, 0xb0 },
634 { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
635 { 0x69, 0x02 },
636 { 0x6a, 0x22 },
637 { 0x6b, 0x00 },
638 { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
639 deleting bit7 colors the first images red */
640 { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
641 { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
642 { 0x6f, 0x01 },
643 { 0x70, 0x8b },
644 { 0x71, 0x00 },
645 { 0x72, 0x14 },
646 { 0x73, 0x54 },
647 { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
648 { 0x75, 0x0e },
649 { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
650 { 0x77, 0xff },
651 { 0x78, 0x80 },
652 { 0x79, 0x80 },
653 { 0x7a, 0x80 },
654 { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
655 { 0x7c, 0x00 },
656 { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
657 { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
658 { 0x7f, 0xfb },
659 { 0x80, 0x28 },
660 { 0x81, 0x00 },
661 { 0x82, 0x23 },
662 { 0x83, 0x0b },
663 { 0x84, 0x00 },
664 { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
665 { 0x86, 0xc9 },
666 { 0x87, 0x00 },
667 { 0x88, 0x00 },
668 { 0x89, 0x01 },
669 { 0x12, 0x20 },
670 { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
671 };
672
673 PDEBUG(D_PROBE, "starting ov8xx0 configuration");
674
675 if (init_ov_sensor(sd) < 0)
676 PDEBUG(D_ERR|D_PROBE, "Failed to read sensor ID");
677 else
678 PDEBUG(D_PROBE, "OV86x0 initialized");
679
680 /* Detect sensor (sub)type */
681 rc = i2c_r(sd, OV7610_REG_COM_I);
682 if (rc < 0) {
683 PDEBUG(D_ERR, "Error detecting sensor type");
684 return -1;
685 }
686 if ((rc & 3) == 1) {
687 PDEBUG(D_PROBE, "Sensor is an OV8610");
688 sd->sensor = SEN_OV8610;
689 } else {
690 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
691 return -1;
692 }
693 PDEBUG(D_PROBE, "Writing 8610 registers");
694 if (write_i2c_regvals(sd,
695 norm_8610,
696 sizeof norm_8610 / sizeof norm_8610[0]))
697 return -1;
698
699 /* Set sensor-specific vars */
700 sd->maxwidth = 640;
701 sd->maxheight = 480;
702 return 0;
703}
704
705/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
706 * the same register settings as the OV7610, since they are very similar.
707 */
708static int ov7xx0_configure(struct sd *sd)
709{
710 int rc, high, low;
711
712 /* Lawrence Glaister <lg@jfm.bc.ca> reports:
713 *
714 * Register 0x0f in the 7610 has the following effects:
715 *
716 * 0x85 (AEC method 1): Best overall, good contrast range
717 * 0x45 (AEC method 2): Very overexposed
718 * 0xa5 (spec sheet default): Ok, but the black level is
719 * shifted resulting in loss of contrast
720 * 0x05 (old driver setting): very overexposed, too much
721 * contrast
722 */
723 static const struct ov_i2c_regvals norm_7610[] = {
724 { 0x10, 0xff },
725 { 0x16, 0x06 },
726 { 0x28, 0x24 },
727 { 0x2b, 0xac },
728 { 0x12, 0x00 },
729 { 0x38, 0x81 },
730 { 0x28, 0x24 }, /* 0c */
731 { 0x0f, 0x85 }, /* lg's setting */
732 { 0x15, 0x01 },
733 { 0x20, 0x1c },
734 { 0x23, 0x2a },
735 { 0x24, 0x10 },
736 { 0x25, 0x8a },
737 { 0x26, 0xa2 },
738 { 0x27, 0xc2 },
739 { 0x2a, 0x04 },
740 { 0x2c, 0xfe },
741 { 0x2d, 0x93 },
742 { 0x30, 0x71 },
743 { 0x31, 0x60 },
744 { 0x32, 0x26 },
745 { 0x33, 0x20 },
746 { 0x34, 0x48 },
747 { 0x12, 0x24 },
748 { 0x11, 0x01 },
749 { 0x0c, 0x24 },
750 { 0x0d, 0x24 },
751 };
752
753 static const struct ov_i2c_regvals norm_7620[] = {
754 { 0x00, 0x00 }, /* gain */
755 { 0x01, 0x80 }, /* blue gain */
756 { 0x02, 0x80 }, /* red gain */
757 { 0x03, 0xc0 }, /* OV7670_REG_VREF */
758 { 0x06, 0x60 },
759 { 0x07, 0x00 },
760 { 0x0c, 0x24 },
761 { 0x0c, 0x24 },
762 { 0x0d, 0x24 },
763 { 0x11, 0x01 },
764 { 0x12, 0x24 },
765 { 0x13, 0x01 },
766 { 0x14, 0x84 },
767 { 0x15, 0x01 },
768 { 0x16, 0x03 },
769 { 0x17, 0x2f },
770 { 0x18, 0xcf },
771 { 0x19, 0x06 },
772 { 0x1a, 0xf5 },
773 { 0x1b, 0x00 },
774 { 0x20, 0x18 },
775 { 0x21, 0x80 },
776 { 0x22, 0x80 },
777 { 0x23, 0x00 },
778 { 0x26, 0xa2 },
779 { 0x27, 0xea },
780 { 0x28, 0x20 },
781 { 0x29, 0x00 },
782 { 0x2a, 0x10 },
783 { 0x2b, 0x00 },
784 { 0x2c, 0x88 },
785 { 0x2d, 0x91 },
786 { 0x2e, 0x80 },
787 { 0x2f, 0x44 },
788 { 0x60, 0x27 },
789 { 0x61, 0x02 },
790 { 0x62, 0x5f },
791 { 0x63, 0xd5 },
792 { 0x64, 0x57 },
793 { 0x65, 0x83 },
794 { 0x66, 0x55 },
795 { 0x67, 0x92 },
796 { 0x68, 0xcf },
797 { 0x69, 0x76 },
798 { 0x6a, 0x22 },
799 { 0x6b, 0x00 },
800 { 0x6c, 0x02 },
801 { 0x6d, 0x44 },
802 { 0x6e, 0x80 },
803 { 0x6f, 0x1d },
804 { 0x70, 0x8b },
805 { 0x71, 0x00 },
806 { 0x72, 0x14 },
807 { 0x73, 0x54 },
808 { 0x74, 0x00 },
809 { 0x75, 0x8e },
810 { 0x76, 0x00 },
811 { 0x77, 0xff },
812 { 0x78, 0x80 },
813 { 0x79, 0x80 },
814 { 0x7a, 0x80 },
815 { 0x7b, 0xe2 },
816 { 0x7c, 0x00 },
817 };
818
819 /* 7640 and 7648. The defaults should be OK for most registers. */
820 static const struct ov_i2c_regvals norm_7640[] = {
821 { 0x12, 0x80 },
822 { 0x12, 0x14 },
823 };
824
825 /* 7670. Defaults taken from OmniVision provided data,
826 * as provided by Jonathan Corbet of OLPC */
827 static const struct ov_i2c_regvals norm_7670[] = {
828 { OV7670_REG_COM7, OV7670_COM7_RESET },
829 { OV7670_REG_TSLB, 0x04 }, /* OV */
830 { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
831 { OV7670_REG_CLKRC, 0x1 },
832 /*
833 * Set the hardware window. These values from OV don't entirely
834 * make sense - hstop is less than hstart. But they work...
835 */
836 { OV7670_REG_HSTART, 0x13 }, { OV7670_REG_HSTOP, 0x01 },
837 { OV7670_REG_HREF, 0xb6 }, { OV7670_REG_VSTART, 0x02 },
838 { OV7670_REG_VSTOP, 0x7a }, { OV7670_REG_VREF, 0x0a },
839
840 { OV7670_REG_COM3, 0 }, { OV7670_REG_COM14, 0 },
841 /* Mystery scaling numbers */
842 { 0x70, 0x3a }, { 0x71, 0x35 },
843 { 0x72, 0x11 }, { 0x73, 0xf0 },
844 { 0xa2, 0x02 },
845/* jfm */
846/* { OV7670_REG_COM10, 0x0 }, */
847
848 /* Gamma curve values */
849 { 0x7a, 0x20 },
850/* jfm:win 7b=1c */
851 { 0x7b, 0x10 },
852/* jfm:win 7c=28 */
853 { 0x7c, 0x1e },
854/* jfm:win 7d=3c */
855 { 0x7d, 0x35 },
856 { 0x7e, 0x5a }, { 0x7f, 0x69 },
857 { 0x80, 0x76 }, { 0x81, 0x80 },
858 { 0x82, 0x88 }, { 0x83, 0x8f },
859 { 0x84, 0x96 }, { 0x85, 0xa3 },
860 { 0x86, 0xaf }, { 0x87, 0xc4 },
861 { 0x88, 0xd7 }, { 0x89, 0xe8 },
862
863 /* AGC and AEC parameters. Note we start by disabling those features,
864 then turn them only after tweaking the values. */
865 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
866 | OV7670_COM8_AECSTEP
867 | OV7670_COM8_BFILT },
868 { OV7670_REG_GAIN, 0 }, { OV7670_REG_AECH, 0 },
869 { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
870/* jfm:win 14=38 */
871 { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
872 { OV7670_REG_BD50MAX, 0x05 }, { OV7670_REG_BD60MAX, 0x07 },
873 { OV7670_REG_AEW, 0x95 }, { OV7670_REG_AEB, 0x33 },
874 { OV7670_REG_VPT, 0xe3 }, { OV7670_REG_HAECC1, 0x78 },
875 { OV7670_REG_HAECC2, 0x68 },
876/* jfm:win a1=0b */
877 { 0xa1, 0x03 }, /* magic */
878 { OV7670_REG_HAECC3, 0xd8 }, { OV7670_REG_HAECC4, 0xd8 },
879 { OV7670_REG_HAECC5, 0xf0 }, { OV7670_REG_HAECC6, 0x90 },
880 { OV7670_REG_HAECC7, 0x94 },
881 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
882 | OV7670_COM8_AECSTEP
883 | OV7670_COM8_BFILT
884 | OV7670_COM8_AGC
885 | OV7670_COM8_AEC },
886
887 /* Almost all of these are magic "reserved" values. */
888 { OV7670_REG_COM5, 0x61 }, { OV7670_REG_COM6, 0x4b },
889 { 0x16, 0x02 },
890/* jfm */
891/* { OV7670_REG_MVFP, 0x07|OV7670_MVFP_MIRROR }, */
892 { OV7670_REG_MVFP, 0x07 },
893 { 0x21, 0x02 }, { 0x22, 0x91 },
894 { 0x29, 0x07 }, { 0x33, 0x0b },
895 { 0x35, 0x0b }, { 0x37, 0x1d },
896 { 0x38, 0x71 }, { 0x39, 0x2a },
897 { OV7670_REG_COM12, 0x78 }, { 0x4d, 0x40 },
898 { 0x4e, 0x20 }, { OV7670_REG_GFIX, 0 },
899 { 0x6b, 0x4a }, { 0x74, 0x10 },
900 { 0x8d, 0x4f }, { 0x8e, 0 },
901 { 0x8f, 0 }, { 0x90, 0 },
902 { 0x91, 0 }, { 0x96, 0 },
903 { 0x9a, 0 }, { 0xb0, 0x84 },
904 { 0xb1, 0x0c }, { 0xb2, 0x0e },
905 { 0xb3, 0x82 }, { 0xb8, 0x0a },
906
907 /* More reserved magic, some of which tweaks white balance */
908 { 0x43, 0x0a }, { 0x44, 0xf0 },
909 { 0x45, 0x34 }, { 0x46, 0x58 },
910 { 0x47, 0x28 }, { 0x48, 0x3a },
911 { 0x59, 0x88 }, { 0x5a, 0x88 },
912 { 0x5b, 0x44 }, { 0x5c, 0x67 },
913 { 0x5d, 0x49 }, { 0x5e, 0x0e },
914 { 0x6c, 0x0a }, { 0x6d, 0x55 },
915 { 0x6e, 0x11 }, { 0x6f, 0x9f },
916 /* "9e for advance AWB" */
917 { 0x6a, 0x40 }, { OV7670_REG_BLUE, 0x40 },
918 { OV7670_REG_RED, 0x60 },
919 { OV7670_REG_COM8, OV7670_COM8_FASTAEC
920 | OV7670_COM8_AECSTEP
921 | OV7670_COM8_BFILT
922 | OV7670_COM8_AGC
923 | OV7670_COM8_AEC
924 | OV7670_COM8_AWB },
925
926 /* Matrix coefficients */
927 { 0x4f, 0x80 }, { 0x50, 0x80 },
928 { 0x51, 0 }, { 0x52, 0x22 },
929 { 0x53, 0x5e }, { 0x54, 0x80 },
930 { 0x58, 0x9e },
931
932 { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
933 { OV7670_REG_EDGE, 0 },
934 { 0x75, 0x05 }, { 0x76, 0xe1 },
935 { 0x4c, 0 }, { 0x77, 0x01 },
936 { OV7670_REG_COM13, 0xc3 }, { 0x4b, 0x09 },
937 { 0xc9, 0x60 }, { OV7670_REG_COM16, 0x38 },
938 { 0x56, 0x40 },
939
940 { 0x34, 0x11 },
941 { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
942 { 0xa4, 0x88 }, { 0x96, 0 },
943 { 0x97, 0x30 }, { 0x98, 0x20 },
944 { 0x99, 0x30 }, { 0x9a, 0x84 },
945 { 0x9b, 0x29 }, { 0x9c, 0x03 },
946 { 0x9d, 0x4c }, { 0x9e, 0x3f },
947 { 0x78, 0x04 },
948
949 /* Extra-weird stuff. Some sort of multiplexor register */
950 { 0x79, 0x01 }, { 0xc8, 0xf0 },
951 { 0x79, 0x0f }, { 0xc8, 0x00 },
952 { 0x79, 0x10 }, { 0xc8, 0x7e },
953 { 0x79, 0x0a }, { 0xc8, 0x80 },
954 { 0x79, 0x0b }, { 0xc8, 0x01 },
955 { 0x79, 0x0c }, { 0xc8, 0x0f },
956 { 0x79, 0x0d }, { 0xc8, 0x20 },
957 { 0x79, 0x09 }, { 0xc8, 0x80 },
958 { 0x79, 0x02 }, { 0xc8, 0xc0 },
959 { 0x79, 0x03 }, { 0xc8, 0x40 },
960 { 0x79, 0x05 }, { 0xc8, 0x30 },
961 { 0x79, 0x26 },
962
963 /* Format YUV422 */
964 { OV7670_REG_COM7, OV7670_COM7_YUV }, /* Selects YUV mode */
965 { OV7670_REG_RGB444, 0 }, /* No RGB444 please */
966 { OV7670_REG_COM1, 0 },
967 { OV7670_REG_COM15, OV7670_COM15_R00FF },
968 { OV7670_REG_COM9, 0x18 },
969 /* 4x gain ceiling; 0x8 is reserved bit */
970 { 0x4f, 0x80 }, /* "matrix coefficient 1" */
971 { 0x50, 0x80 }, /* "matrix coefficient 2" */
972 { 0x52, 0x22 }, /* "matrix coefficient 4" */
973 { 0x53, 0x5e }, /* "matrix coefficient 5" */
974 { 0x54, 0x80 }, /* "matrix coefficient 6" */
975 { OV7670_REG_COM13, OV7670_COM13_GAMMA|OV7670_COM13_UVSAT },
976};
977
978 PDEBUG(D_PROBE, "starting OV7xx0 configuration");
979
980/* jfm:already done? */
981 if (init_ov_sensor(sd) < 0)
982 PDEBUG(D_ERR, "Failed to read sensor ID");
983 else
984 PDEBUG(D_PROBE, "OV7xx0 initialized");
985
986 /* Detect sensor (sub)type */
987 rc = i2c_r(sd, OV7610_REG_COM_I);
988
989 /* add OV7670 here
990 * it appears to be wrongly detected as a 7610 by default */
991 if (rc < 0) {
992 PDEBUG(D_ERR, "Error detecting sensor type");
993 return -1;
994 }
995 if ((rc & 3) == 3) {
996 /* quick hack to make OV7670s work */
997 high = i2c_r(sd, 0x0a);
998 low = i2c_r(sd, 0x0b);
999 /* info("%x, %x", high, low); */
1000 if (high == 0x76 && low == 0x73) {
1001 PDEBUG(D_PROBE, "Sensor is an OV7670");
1002 sd->sensor = SEN_OV7670;
1003 } else {
1004 PDEBUG(D_PROBE, "Sensor is an OV7610");
1005 sd->sensor = SEN_OV7610;
1006 }
1007 } else if ((rc & 3) == 1) {
1008 /* I don't know what's different about the 76BE yet. */
1009 if (i2c_r(sd, 0x15) & 1)
1010 PDEBUG(D_PROBE, "Sensor is an OV7620AE");
1011 else
1012 PDEBUG(D_PROBE, "Sensor is an OV76BE");
1013
1014 /* OV511+ will return all zero isoc data unless we
1015 * configure the sensor as a 7620. Someone needs to
1016 * find the exact reg. setting that causes this. */
1017 sd->sensor = SEN_OV76BE;
1018 } else if ((rc & 3) == 0) {
1019 /* try to read product id registers */
1020 high = i2c_r(sd, 0x0a);
1021 if (high < 0) {
1022 PDEBUG(D_ERR, "Error detecting camera chip PID");
1023 return high;
1024 }
1025 low = i2c_r(sd, 0x0b);
1026 if (low < 0) {
1027 PDEBUG(D_ERR, "Error detecting camera chip VER");
1028 return low;
1029 }
1030 if (high == 0x76) {
1031 if (low == 0x30) {
1032 PDEBUG(D_PROBE, "Sensor is an OV7630/OV7635");
1033 sd->sensor = SEN_OV7630;
1034 } else if (low == 0x40) {
1035 PDEBUG(D_PROBE, "Sensor is an OV7645");
1036 sd->sensor = SEN_OV7640; /* FIXME */
1037 } else if (low == 0x45) {
1038 PDEBUG(D_PROBE, "Sensor is an OV7645B");
1039 sd->sensor = SEN_OV7640; /* FIXME */
1040 } else if (low == 0x48) {
1041 PDEBUG(D_PROBE, "Sensor is an OV7648");
1042 sd->sensor = SEN_OV7640; /* FIXME */
1043 } else {
1044 PDEBUG(D_PROBE, "Unknown sensor: 0x76%X", low);
1045 return -1;
1046 }
1047 } else {
1048 PDEBUG(D_PROBE, "Sensor is an OV7620");
1049 sd->sensor = SEN_OV7620;
1050 }
1051 } else {
1052 PDEBUG(D_ERR, "Unknown image sensor version: %d", rc & 3);
1053 return -1;
1054 }
1055
1056 if (sd->sensor == SEN_OV7620) {
1057 PDEBUG(D_PROBE, "Writing 7620 registers");
1058 if (write_i2c_regvals(sd, norm_7620,
1059 sizeof norm_7620 / sizeof norm_7620[0]))
1060 return -1;
1061 } else if (sd->sensor == SEN_OV7630) {
1062 PDEBUG(D_ERR, "7630 is not supported by this driver version");
1063 return -1;
1064 } else if (sd->sensor == SEN_OV7640) {
1065 PDEBUG(D_PROBE, "Writing 7640 registers");
1066 if (write_i2c_regvals(sd, norm_7640,
1067 sizeof norm_7640 / sizeof norm_7640[0]))
1068 return -1;
1069 } else if (sd->sensor == SEN_OV7670) {
1070 PDEBUG(D_PROBE, "Writing 7670 registers");
1071 if (write_i2c_regvals(sd, norm_7670,
1072 sizeof norm_7670 / sizeof norm_7670[0]))
1073 return -1;
1074 } else {
1075 PDEBUG(D_PROBE, "Writing 7610 registers");
1076 if (write_i2c_regvals(sd, norm_7610,
1077 sizeof norm_7610 / sizeof norm_7610[0]))
1078 return -1;
1079 }
1080
1081 /* Set sensor-specific vars */
1082 sd->maxwidth = 640;
1083 sd->maxheight = 480;
1084 return 0;
1085}
1086
1087/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
1088static int ov6xx0_configure(struct sd *sd)
1089{
1090 int rc;
1091 static const struct ov_i2c_regvals norm_6x20[] = {
1092 { 0x12, 0x80 }, /* reset */
1093 { 0x11, 0x01 },
1094 { 0x03, 0x60 },
1095 { 0x05, 0x7f }, /* For when autoadjust is off */
1096 { 0x07, 0xa8 },
1097 /* The ratio of 0x0c and 0x0d controls the white point */
1098 { 0x0c, 0x24 },
1099 { 0x0d, 0x24 },
1100 { 0x0f, 0x15 }, /* COMS */
1101 { 0x10, 0x75 }, /* AEC Exposure time */
1102 { 0x12, 0x24 }, /* Enable AGC */
1103 { 0x14, 0x04 },
1104 /* 0x16: 0x06 helps frame stability with moving objects */
1105 { 0x16, 0x06 },
1106/* { 0x20, 0x30 }, * Aperture correction enable */
1107 { 0x26, 0xb2 }, /* BLC enable */
1108 /* 0x28: 0x05 Selects RGB format if RGB on */
1109 { 0x28, 0x05 },
1110 { 0x2a, 0x04 }, /* Disable framerate adjust */
1111/* { 0x2b, 0xac }, * Framerate; Set 2a[7] first */
1112 { 0x2d, 0x99 },
1113 { 0x33, 0xa0 }, /* Color Processing Parameter */
1114 { 0x34, 0xd2 }, /* Max A/D range */
1115 { 0x38, 0x8b },
1116 { 0x39, 0x40 },
1117
1118 { 0x3c, 0x39 }, /* Enable AEC mode changing */
1119 { 0x3c, 0x3c }, /* Change AEC mode */
1120 { 0x3c, 0x24 }, /* Disable AEC mode changing */
1121
1122 { 0x3d, 0x80 },
1123 /* These next two registers (0x4a, 0x4b) are undocumented.
1124 * They control the color balance */
1125 { 0x4a, 0x80 },
1126 { 0x4b, 0x80 },
1127 { 0x4d, 0xd2 }, /* This reduces noise a bit */
1128 { 0x4e, 0xc1 },
1129 { 0x4f, 0x04 },
1130/* Do 50-53 have any effect? */
1131/* Toggle 0x12[2] off and on here? */
1132 };
1133
1134 static const struct ov_i2c_regvals norm_6x30[] = {
1135 { 0x12, 0x80 }, /* Reset */
1136 { 0x00, 0x1f }, /* Gain */
1137 { 0x01, 0x99 }, /* Blue gain */
1138 { 0x02, 0x7c }, /* Red gain */
1139 { 0x03, 0xc0 }, /* Saturation */
1140 { 0x05, 0x0a }, /* Contrast */
1141 { 0x06, 0x95 }, /* Brightness */
1142 { 0x07, 0x2d }, /* Sharpness */
1143 { 0x0c, 0x20 },
1144 { 0x0d, 0x20 },
1145 { 0x0e, 0x20 },
1146 { 0x0f, 0x05 },
1147 { 0x10, 0x9a },
1148 { 0x11, 0x00 }, /* Pixel clock = fastest */
1149 { 0x12, 0x24 }, /* Enable AGC and AWB */
1150 { 0x13, 0x21 },
1151 { 0x14, 0x80 },
1152 { 0x15, 0x01 },
1153 { 0x16, 0x03 },
1154 { 0x17, 0x38 },
1155 { 0x18, 0xea },
1156 { 0x19, 0x04 },
1157 { 0x1a, 0x93 },
1158 { 0x1b, 0x00 },
1159 { 0x1e, 0xc4 },
1160 { 0x1f, 0x04 },
1161 { 0x20, 0x20 },
1162 { 0x21, 0x10 },
1163 { 0x22, 0x88 },
1164 { 0x23, 0xc0 }, /* Crystal circuit power level */
1165 { 0x25, 0x9a }, /* Increase AEC black ratio */
1166 { 0x26, 0xb2 }, /* BLC enable */
1167 { 0x27, 0xa2 },
1168 { 0x28, 0x00 },
1169 { 0x29, 0x00 },
1170 { 0x2a, 0x84 }, /* 60 Hz power */
1171 { 0x2b, 0xa8 }, /* 60 Hz power */
1172 { 0x2c, 0xa0 },
1173 { 0x2d, 0x95 }, /* Enable auto-brightness */
1174 { 0x2e, 0x88 },
1175 { 0x33, 0x26 },
1176 { 0x34, 0x03 },
1177 { 0x36, 0x8f },
1178 { 0x37, 0x80 },
1179 { 0x38, 0x83 },
1180 { 0x39, 0x80 },
1181 { 0x3a, 0x0f },
1182 { 0x3b, 0x3c },
1183 { 0x3c, 0x1a },
1184 { 0x3d, 0x80 },
1185 { 0x3e, 0x80 },
1186 { 0x3f, 0x0e },
1187 { 0x40, 0x00 }, /* White bal */
1188 { 0x41, 0x00 }, /* White bal */
1189 { 0x42, 0x80 },
1190 { 0x43, 0x3f }, /* White bal */
1191 { 0x44, 0x80 },
1192 { 0x45, 0x20 },
1193 { 0x46, 0x20 },
1194 { 0x47, 0x80 },
1195 { 0x48, 0x7f },
1196 { 0x49, 0x00 },
1197 { 0x4a, 0x00 },
1198 { 0x4b, 0x80 },
1199 { 0x4c, 0xd0 },
1200 { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
1201 { 0x4e, 0x40 },
1202 { 0x4f, 0x07 }, /* UV avg., col. killer: max */
1203 { 0x50, 0xff },
1204 { 0x54, 0x23 }, /* Max AGC gain: 18dB */
1205 { 0x55, 0xff },
1206 { 0x56, 0x12 },
1207 { 0x57, 0x81 },
1208 { 0x58, 0x75 },
1209 { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
1210 { 0x5a, 0x2c },
1211 { 0x5b, 0x0f }, /* AWB chrominance levels */
1212 { 0x5c, 0x10 },
1213 { 0x3d, 0x80 },
1214 { 0x27, 0xa6 },
1215 { 0x12, 0x20 }, /* Toggle AWB */
1216 { 0x12, 0x24 },
1217 };
1218
1219 PDEBUG(D_PROBE, "starting sensor configuration");
1220
1221 if (init_ov_sensor(sd) < 0) {
1222 PDEBUG(D_ERR, "Failed to read sensor ID.");
1223 return -1;
1224 }
1225 PDEBUG(D_PROBE, "OV6xx0 sensor detected");
1226
1227 /* Detect sensor (sub)type */
1228 rc = i2c_r(sd, OV7610_REG_COM_I);
1229 if (rc < 0) {
1230 PDEBUG(D_ERR, "Error detecting sensor type");
1231 return -1;
1232 }
1233
1234 /* Ugh. The first two bits are the version bits, but
1235 * the entire register value must be used. I guess OVT
1236 * underestimated how many variants they would make. */
1237 if (rc == 0x00) {
1238 sd->sensor = SEN_OV6630;
1239 PDEBUG(D_ERR,
1240 "WARNING: Sensor is an OV66308. Your camera may have");
1241 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1242 } else if (rc == 0x01) {
1243 sd->sensor = SEN_OV6620;
1244 PDEBUG(D_PROBE, "Sensor is an OV6620");
1245 } else if (rc == 0x02) {
1246 sd->sensor = SEN_OV6630;
1247 PDEBUG(D_PROBE, "Sensor is an OV66308AE");
1248 } else if (rc == 0x03) {
1249 sd->sensor = SEN_OV6630;
1250 PDEBUG(D_PROBE, "Sensor is an OV66308AF");
1251 } else if (rc == 0x90) {
1252 sd->sensor = SEN_OV6630;
1253 PDEBUG(D_ERR,
1254 "WARNING: Sensor is an OV66307. Your camera may have");
1255 PDEBUG(D_ERR, "been misdetected in previous driver versions.");
1256 } else {
1257 PDEBUG(D_ERR, "FATAL: Unknown sensor version: 0x%02x", rc);
1258 return -1;
1259 }
1260
1261 /* Set sensor-specific vars */
1262 sd->maxwidth = 352;
1263 sd->maxheight = 288;
1264
1265 if (sd->sensor == SEN_OV6620) {
1266 PDEBUG(D_PROBE, "Writing 6x20 registers");
1267 if (write_i2c_regvals(sd, norm_6x20,
1268 sizeof norm_6x20 / sizeof norm_6x20[0]))
1269 return -1;
1270 } else {
1271 PDEBUG(D_PROBE, "Writing 6x30 registers");
1272 if (write_i2c_regvals(sd, norm_6x30,
1273 sizeof norm_6x30 / sizeof norm_6x30[0]))
1274 return -1;
1275 }
1276 return 0;
1277}
1278
1279/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
1280static void ov51x_led_control(struct sd *sd, int on)
1281{
1282 PDEBUG(D_STREAM, "LED (%s)", on ? "on" : "off");
1283
1284/* if (sd->bridge == BRG_OV511PLUS) */
1285/* reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0); */
1286/* else if (sd->bridge == BRG_OV519) */
1287 reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1); /* 0 / 1 */
1288/* else if (sd->bclass == BCL_OV518) */
1289/* reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02); */
1290}
1291
1292/* this function is called at probe time */
1293static int sd_config(struct gspca_dev *gspca_dev,
1294 const struct usb_device_id *id)
1295{
1296 struct sd *sd = (struct sd *) gspca_dev;
1297 struct cam *cam;
1298
1299/* (from ov519_configure) */
1300 static const struct ov_regvals init_519[] = {
1301 { 0x5a, 0x6d }, /* EnableSystem */
1302/* jfm trace usbsnoop3-1.txt */
1303/* jfm 53 = fb */
1304 { 0x53, 0x9b },
1305 { 0x54, 0xff }, /* set bit2 to enable jpeg */
1306 { 0x5d, 0x03 },
1307 { 0x49, 0x01 },
1308 { 0x48, 0x00 },
1309 /* Set LED pin to output mode. Bit 4 must be cleared or sensor
1310 * detection will fail. This deserves further investigation. */
1311 { OV519_GPIO_IO_CTRL0, 0xee },
1312 { 0x51, 0x0f }, /* SetUsbInit */
1313 { 0x51, 0x00 },
1314 { 0x22, 0x00 },
1315 /* windows reads 0x55 at this point*/
1316 };
1317
1318 if (write_regvals(sd, init_519, ARRAY_SIZE(init_519)))
1319 goto error;
1320/* jfm: not seen in windows trace */
1321 if (ov519_init_compression(sd))
1322 goto error;
1323 ov51x_led_control(sd, 0); /* turn LED off */
1324
1325 /* Test for 76xx */
1326 sd->primary_i2c_slave = OV7xx0_SID;
1327 if (ov51x_set_slave_ids(sd, OV7xx0_SID) < 0)
1328 goto error;
1329
1330 /* The OV519 must be more aggressive about sensor detection since
1331 * I2C write will never fail if the sensor is not present. We have
1332 * to try to initialize the sensor to detect its presence */
1333 if (init_ov_sensor(sd) < 0) {
1334 /* Test for 6xx0 */
1335 sd->primary_i2c_slave = OV6xx0_SID;
1336 if (ov51x_set_slave_ids(sd, OV6xx0_SID) < 0)
1337 goto error;
1338
1339 if (init_ov_sensor(sd) < 0) {
1340 /* Test for 8xx0 */
1341 sd->primary_i2c_slave = OV8xx0_SID;
1342 if (ov51x_set_slave_ids(sd, OV8xx0_SID) < 0)
1343 goto error;
1344
1345 if (init_ov_sensor(sd) < 0) {
1346 PDEBUG(D_ERR,
1347 "Can't determine sensor slave IDs");
1348 goto error;
1349 } else {
1350 if (ov8xx0_configure(sd) < 0) {
1351 PDEBUG(D_ERR,
1352 "Failed to configure OV8xx0 sensor");
1353 goto error;
1354 }
1355 }
1356 } else {
1357 if (ov6xx0_configure(sd) < 0) {
1358 PDEBUG(D_ERR, "Failed to configure OV6xx0");
1359 goto error;
1360 }
1361 }
1362 } else {
1363 if (ov7xx0_configure(sd) < 0) {
1364 PDEBUG(D_ERR, "Failed to configure OV7xx0");
1365 goto error;
1366 }
1367 }
1368
1369 cam = &gspca_dev->cam;
1370 cam->epaddr = OV511_ENDPOINT_ADDRESS;
1371 if (sd->maxwidth == 640) {
1372 cam->cam_mode = vga_mode;
1373 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1374 } else {
1375 cam->cam_mode = sif_mode;
1376 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
1377 }
1378 cam->dev_name = (char *) id->driver_info;
1379 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1380 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1381 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1382 return 0;
1383error:
1384 PDEBUG(D_ERR, "OV519 Config failed");
1385 return -EBUSY;
1386}
1387
1388/* this function is called at open time */
1389static int sd_open(struct gspca_dev *gspca_dev)
1390{
1391 return 0;
1392}
1393
1394/* Sets up the OV519 with the given image parameters
1395 *
1396 * OV519 needs a completely different approach, until we can figure out what
1397 * the individual registers do.
1398 *
1399 * Do not put any sensor-specific code in here (including I2C I/O functions)
1400 */
1401static int ov519_mode_init_regs(struct sd *sd,
1402 int width, int height)
1403{
1404 static const struct ov_regvals mode_init_519_ov7670[] = {
1405 { 0x5d, 0x03 }, /* Turn off suspend mode */
1406 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
1407 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1408 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1409 { 0xa3, 0x18 },
1410 { 0xa4, 0x04 },
1411 { 0xa5, 0x28 },
1412 { 0x37, 0x00 }, /* SetUsbInit */
1413 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1414 /* Enable both fields, YUV Input, disable defect comp (why?) */
1415 { 0x20, 0x0c },
1416 { 0x21, 0x38 },
1417 { 0x22, 0x1d },
1418 { 0x17, 0x50 }, /* undocumented */
1419 { 0x37, 0x00 }, /* undocumented */
1420 { 0x40, 0xff }, /* I2C timeout counter */
1421 { 0x46, 0x00 }, /* I2C clock prescaler */
1422 { 0x59, 0x04 }, /* new from windrv 090403 */
1423 { 0xff, 0x00 }, /* undocumented */
1424 /* windows reads 0x55 at this point, why? */
1425 };
1426
1427 static const struct ov_regvals mode_init_519[] = {
1428 { 0x5d, 0x03 }, /* Turn off suspend mode */
1429 { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
1430 { 0x54, 0x0f }, /* bit2 (jpeg enable) */
1431 { 0xa2, 0x20 }, /* a2-a5 are undocumented */
1432 { 0xa3, 0x18 },
1433 { 0xa4, 0x04 },
1434 { 0xa5, 0x28 },
1435 { 0x37, 0x00 }, /* SetUsbInit */
1436 { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
1437 /* Enable both fields, YUV Input, disable defect comp (why?) */
1438 { 0x22, 0x1d },
1439 { 0x17, 0x50 }, /* undocumented */
1440 { 0x37, 0x00 }, /* undocumented */
1441 { 0x40, 0xff }, /* I2C timeout counter */
1442 { 0x46, 0x00 }, /* I2C clock prescaler */
1443 { 0x59, 0x04 }, /* new from windrv 090403 */
1444 { 0xff, 0x00 }, /* undocumented */
1445 /* windows reads 0x55 at this point, why? */
1446 };
1447
1448/* int hi_res; */
1449
1450 PDEBUG(D_CONF, "mode init %dx%d", width, height);
1451
1452/* if (width >= 800 && height >= 600)
1453 hi_res = 1;
1454 else
1455 hi_res = 0; */
1456
1457/* if (ov51x_stop(sd) < 0)
1458 return -EIO; */
1459
1460 /******** Set the mode ********/
1461 if (sd->sensor != SEN_OV7670) {
1462 if (write_regvals(sd, mode_init_519,
1463 ARRAY_SIZE(mode_init_519)))
1464 return -EIO;
1465 } else {
1466 if (write_regvals(sd, mode_init_519_ov7670,
1467 ARRAY_SIZE(mode_init_519_ov7670)))
1468 return -EIO;
1469 }
1470
1471 if (sd->sensor == SEN_OV7640) {
1472 /* Select 8-bit input mode */
1473 reg_w_mask(sd, OV519_CAM_DFR, 0x10, 0x10);
1474 }
1475
1476 reg_w(sd, OV519_CAM_H_SIZE, width >> 4);
1477 reg_w(sd, OV519_CAM_V_SIZE, height >> 3);
1478 reg_w(sd, OV519_CAM_X_OFFSETL, 0x00);
1479 reg_w(sd, OV519_CAM_X_OFFSETH, 0x00);
1480 reg_w(sd, OV519_CAM_Y_OFFSETL, 0x00);
1481 reg_w(sd, OV519_CAM_Y_OFFSETH, 0x00);
1482 reg_w(sd, OV519_CAM_DIVIDER, 0x00);
1483 reg_w(sd, OV519_CAM_FORMAT, 0x03); /* YUV422 */
1484 reg_w(sd, 0x26, 0x00); /* Undocumented */
1485
1486 /******** Set the framerate ********/
1487 if (frame_rate > 0)
1488 sd->frame_rate = frame_rate;
1489
1490/* FIXME: These are only valid at the max resolution. */
1491 sd->clockdiv = 0;
1492 if (sd->sensor == SEN_OV7640) {
1493 switch (sd->frame_rate) {
1494/*jfm: default was 30 fps */
1495 case 30:
1496 reg_w(sd, 0xa4, 0x0c);
1497 reg_w(sd, 0x23, 0xff);
1498 break;
1499 case 25:
1500 reg_w(sd, 0xa4, 0x0c);
1501 reg_w(sd, 0x23, 0x1f);
1502 break;
1503 case 20:
1504 reg_w(sd, 0xa4, 0x0c);
1505 reg_w(sd, 0x23, 0x1b);
1506 break;
1507 default:
1508/* case 15: */
1509 reg_w(sd, 0xa4, 0x04);
1510 reg_w(sd, 0x23, 0xff);
1511 sd->clockdiv = 1;
1512 break;
1513 case 10:
1514 reg_w(sd, 0xa4, 0x04);
1515 reg_w(sd, 0x23, 0x1f);
1516 sd->clockdiv = 1;
1517 break;
1518 case 5:
1519 reg_w(sd, 0xa4, 0x04);
1520 reg_w(sd, 0x23, 0x1b);
1521 sd->clockdiv = 1;
1522 break;
1523 }
1524 } else if (sd->sensor == SEN_OV8610) {
1525 switch (sd->frame_rate) {
1526 default: /* 15 fps */
1527/* case 15: */
1528 reg_w(sd, 0xa4, 0x06);
1529 reg_w(sd, 0x23, 0xff);
1530 break;
1531 case 10:
1532 reg_w(sd, 0xa4, 0x06);
1533 reg_w(sd, 0x23, 0x1f);
1534 break;
1535 case 5:
1536 reg_w(sd, 0xa4, 0x06);
1537 reg_w(sd, 0x23, 0x1b);
1538 break;
1539 }
1540 sd->clockdiv = 0;
1541 } else if (sd->sensor == SEN_OV7670) { /* guesses, based on 7640 */
1542 PDEBUG(D_STREAM, "Setting framerate to %d fps",
1543 (sd->frame_rate == 0) ? 15 : sd->frame_rate);
1544 switch (sd->frame_rate) {
1545 case 30:
1546 reg_w(sd, 0xa4, 0x10);
1547 reg_w(sd, 0x23, 0xff);
1548 break;
1549 case 20:
1550 reg_w(sd, 0xa4, 0x10);
1551 reg_w(sd, 0x23, 0x1b);
1552 break;
1553 default: /* 15 fps */
1554/* case 15: */
1555 reg_w(sd, 0xa4, 0x10);
1556 reg_w(sd, 0x23, 0xff);
1557 sd->clockdiv = 1;
1558 break;
1559 }
1560 }
1561
1562/* if (ov51x_restart(sd) < 0)
1563 return -EIO; */
1564
1565 /* Reset it just for good measure */
1566/* if (ov51x_reset(sd, OV511_RESET_NOREGS) < 0)
1567 return -EIO; */
1568 return 0;
1569}
1570
1571static int mode_init_ov_sensor_regs(struct sd *sd,
1572 struct ovsensor_window *win)
1573{
1574 int qvga = win->quarter;
1575
1576 /******** Mode (VGA/QVGA) and sensor specific regs ********/
1577 switch (sd->sensor) {
1578 case SEN_OV8610:
1579 /* For OV8610 qvga means qsvga */
1580 i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
1581 break;
1582 case SEN_OV7610:
1583 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1584 break;
1585 case SEN_OV7620:
1586/* i2c_w(sd, 0x2b, 0x00); */
1587 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1588 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
1589 i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
1590 i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
1591 i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
1592 i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
1593 i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
1594 break;
1595 case SEN_OV76BE:
1596/* i2c_w(sd, 0x2b, 0x00); */
1597 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1598 break;
1599 case SEN_OV7640:
1600/* i2c_w(sd, 0x2b, 0x00); */
1601 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1602 i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
1603/* i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
1604/* i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */
1605/* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */
1606/* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */
1607/* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */
1608 break;
1609 case SEN_OV7670:
1610 /* set COM7_FMT_VGA or COM7_FMT_QVGA
1611 * do we need to set anything else?
1612 * HSTART etc are set in set_ov_sensor_window itself */
1613 i2c_w_mask(sd, OV7670_REG_COM7,
1614 qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
1615 OV7670_COM7_FMT_MASK);
1616 break;
1617 case SEN_OV6620:
1618 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1619 break;
1620 case SEN_OV6630:
1621 i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
1622 break;
1623 default:
1624 return -EINVAL;
1625 }
1626
1627 /******** Palette-specific regs ********/
1628/* Need to do work here for the OV7670 */
1629
1630 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1631 /* not valid on the OV6620/OV7620/6630? */
1632 i2c_w_mask(sd, 0x0e, 0x00, 0x40);
1633 }
1634
1635 /* The OV518 needs special treatment. Although both the OV518
1636 * and the OV6630 support a 16-bit video bus, only the 8 bit Y
1637 * bus is actually used. The UV bus is tied to ground.
1638 * Therefore, the OV6630 needs to be in 8-bit multiplexed
1639 * output mode */
1640
1641 /* OV7640 is 8-bit only */
1642
1643 if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV7640)
1644 i2c_w_mask(sd, 0x13, 0x00, 0x20);
1645/* } */
1646
1647 /******** Clock programming ********/
1648 /* The OV6620 needs special handling. This prevents the
1649 * severe banding that normally occurs */
1650 if (sd->sensor == SEN_OV6620) {
1651
1652 /* Clock down */
1653 i2c_w(sd, 0x2a, 0x04);
1654 i2c_w(sd, 0x11, win->clockdiv);
1655 i2c_w(sd, 0x2a, 0x84);
1656 /* This next setting is critical. It seems to improve
1657 * the gain or the contrast. The "reserved" bits seem
1658 * to have some effect in this case. */
1659 i2c_w(sd, 0x2d, 0x85);
1660 } else if (win->clockdiv >= 0) {
1661 i2c_w(sd, 0x11, win->clockdiv);
1662 }
1663
1664 /******** Special Features ********/
1665/* no evidence this is possible with OV7670, either */
1666 /* Test Pattern */
1667 if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670)
1668 i2c_w_mask(sd, 0x12, 0x00, 0x02);
1669
1670 /* Enable auto white balance */
1671 if (sd->sensor == SEN_OV7670)
1672 i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,
1673 OV7670_COM8_AWB);
1674 else
1675 i2c_w_mask(sd, 0x12, 0x04, 0x04);
1676
1677 /* This will go away as soon as ov51x_mode_init_sensor_regs() */
1678 /* is fully tested. */
1679 /* 7620/6620/6630? don't have register 0x35, so play it safe */
1680 if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) {
1681 if (win->width == 640 /*&& win->height == 480*/)
1682 i2c_w(sd, 0x35, 0x9e);
1683 else
1684 i2c_w(sd, 0x35, 0x1e);
1685 }
1686 return 0;
1687}
1688
1689static int set_ov_sensor_window(struct sd *sd,
1690 struct ovsensor_window *win)
1691{
1692 int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
1693 int ret, hstart, hstop, vstop, vstart;
1694 __u8 v;
1695
1696 /* The different sensor ICs handle setting up of window differently.
1697 * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
1698 switch (sd->sensor) {
1699 case SEN_OV8610:
1700 hwsbase = 0x1e;
1701 hwebase = 0x1e;
1702 vwsbase = 0x02;
1703 vwebase = 0x02;
1704 break;
1705 case SEN_OV7610:
1706 case SEN_OV76BE:
1707 hwsbase = 0x38;
1708 hwebase = 0x3a;
1709 vwsbase = vwebase = 0x05;
1710 break;
1711 case SEN_OV6620:
1712 case SEN_OV6630:
1713 hwsbase = 0x38;
1714 hwebase = 0x3a;
1715 vwsbase = 0x05;
1716 vwebase = 0x06;
1717 break;
1718 case SEN_OV7620:
1719 hwsbase = 0x2f; /* From 7620.SET (spec is wrong) */
1720 hwebase = 0x2f;
1721 vwsbase = vwebase = 0x05;
1722 break;
1723 case SEN_OV7640:
1724 hwsbase = 0x1a;
1725 hwebase = 0x1a;
1726 vwsbase = vwebase = 0x03;
1727 break;
1728 case SEN_OV7670:
1729 /*handling of OV7670 hardware sensor start and stop values
1730 * is very odd, compared to the other OV sensors */
1731 vwsbase = vwebase = hwebase = hwsbase = 0x00;
1732 break;
1733 default:
1734 return -EINVAL;
1735 }
1736
1737 switch (sd->sensor) {
1738 case SEN_OV6620:
1739 case SEN_OV6630:
1740 if (win->quarter) { /* QCIF */
1741 hwscale = 0;
1742 vwscale = 0;
1743 } else { /* CIF */
1744 hwscale = 1;
1745 vwscale = 1; /* The datasheet says 0;
1746 * it's wrong */
1747 }
1748 break;
1749 case SEN_OV8610:
1750 if (win->quarter) { /* QSVGA */
1751 hwscale = 1;
1752 vwscale = 1;
1753 } else { /* SVGA */
1754 hwscale = 2;
1755 vwscale = 2;
1756 }
1757 break;
1758 default: /* SEN_OV7xx0 */
1759 if (win->quarter) { /* QVGA */
1760 hwscale = 1;
1761 vwscale = 0;
1762 } else { /* VGA */
1763 hwscale = 2;
1764 vwscale = 1;
1765 }
1766 }
1767
1768 ret = mode_init_ov_sensor_regs(sd, win);
1769 if (ret < 0)
1770 return ret;
1771
1772 if (sd->sensor == SEN_OV8610) {
1773 i2c_w_mask(sd, 0x2d, 0x05, 0x40);
1774 /* old 0x95, new 0x05 from windrv 090403 */
1775 /* bits 5-7: reserved */
1776 i2c_w_mask(sd, 0x28, 0x20, 0x20);
1777 /* bit 5: progressive mode on */
1778 }
1779
1780 /* The below is wrong for OV7670s because their window registers
1781 * only store the high bits in 0x17 to 0x1a */
1782
1783 /* SRH Use sd->max values instead of requested win values */
1784 /* SCS Since we're sticking with only the max hardware widths
1785 * for a given mode */
1786 /* I can hard code this for OV7670s */
1787 /* Yes, these numbers do look odd, but they're tested and work! */
1788 if (sd->sensor == SEN_OV7670) {
1789 if (win->quarter) { /* QVGA from ov7670.c by
1790 * Jonathan Corbet */
1791 hstart = 164;
1792 hstop = 20;
1793 vstart = 14;
1794 vstop = 494;
1795 } else { /* VGA */
1796 hstart = 158;
1797 hstop = 14;
1798 vstart = 10;
1799 vstop = 490;
1800 }
1801 /* OV7670 hardware window registers are split across
1802 * multiple locations */
1803 i2c_w(sd, OV7670_REG_HSTART, (hstart >> 3) & 0xff);
1804 i2c_w(sd, OV7670_REG_HSTOP, (hstop >> 3) & 0xff);
1805 v = i2c_r(sd, OV7670_REG_HREF);
1806 v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07);
1807 msleep(10); /* need to sleep between read and write to
1808 * same reg! */
1809 i2c_w(sd, OV7670_REG_HREF, v);
1810
1811 i2c_w(sd, OV7670_REG_VSTART, (vstart >> 2) & 0xff);
1812 i2c_w(sd, OV7670_REG_VSTOP, (vstop >> 2) & 0xff);
1813 v = i2c_r(sd, OV7670_REG_VREF);
1814 v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03);
1815 msleep(10); /* need to sleep between read and write to
1816 * same reg! */
1817 i2c_w(sd, OV7670_REG_VREF, v);
1818
1819 } else {
1820 i2c_w(sd, 0x17, hwsbase + (win->x >> hwscale));
1821 i2c_w(sd, 0x18, hwebase + ((win->x + win->width) >> hwscale));
1822 i2c_w(sd, 0x19, vwsbase + (win->y >> vwscale));
1823 i2c_w(sd, 0x1a, vwebase + ((win->y + win->height) >> vwscale));
1824 }
1825 return 0;
1826}
1827
1828static int ov_sensor_mode_setup(struct sd *sd,
1829 int width, int height)
1830{
1831 struct ovsensor_window win;
1832
1833/* win.format = mode; */
1834
1835 /* Unless subcapture is enabled,
1836 * center the image window and downsample
1837 * if possible to increase the field of view */
1838 /* NOTE: OV518(+) and OV519 does downsampling on its own */
1839 win.width = width;
1840 win.height = height;
1841 if (width == sd->maxwidth)
1842 win.quarter = 0;
1843 else
1844 win.quarter = 1;
1845
1846 /* Center it */
1847 win.x = (win.width - width) / 2;
1848 win.y = (win.height - height) / 2;
1849
1850 /* Clock is determined by OV519 frame rate code */
1851 win.clockdiv = sd->clockdiv;
1852
1853 PDEBUG(D_CONF, "Setting clock divider to %d", win.clockdiv);
1854 return set_ov_sensor_window(sd, &win);
1855}
1856
1857/* -- start the camera -- */
1858static void sd_start(struct gspca_dev *gspca_dev)
1859{
1860 struct sd *sd = (struct sd *) gspca_dev;
1861 int ret;
1862
1863
1864 ret = ov519_mode_init_regs(sd, gspca_dev->width, gspca_dev->height);
1865 if (ret < 0)
1866 goto out;
1867 ret = ov_sensor_mode_setup(sd, gspca_dev->width, gspca_dev->height);
1868 if (ret < 0)
1869 goto out;
1870
1871 ret = ov51x_restart((struct sd *) gspca_dev);
1872 if (ret < 0)
1873 goto out;
1874 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
1875 ov51x_led_control(sd, 1);
1876 return;
1877out:
1878 PDEBUG(D_ERR, "camera start error:%d", ret);
1879}
1880
1881static void sd_stopN(struct gspca_dev *gspca_dev)
1882{
1883 ov51x_stop((struct sd *) gspca_dev);
1884 ov51x_led_control((struct sd *) gspca_dev, 0);
1885}
1886
1887static void sd_stop0(struct gspca_dev *gspca_dev)
1888{
1889}
1890
1891static void sd_close(struct gspca_dev *gspca_dev)
1892{
1893}
1894
1895static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1896 struct gspca_frame *frame, /* target */
1897 __u8 *data, /* isoc packet */
1898 int len) /* iso packet length */
1899{
1900 /* Header of ov519 is 16 bytes:
1901 * Byte Value Description
1902 * 0 0xff magic
1903 * 1 0xff magic
1904 * 2 0xff magic
1905 * 3 0xXX 0x50 = SOF, 0x51 = EOF
1906 * 9 0xXX 0x01 initial frame without data,
1907 * 0x00 standard frame with image
1908 * 14 Lo in EOF: length of image data / 8
1909 * 15 Hi
1910 */
1911
1912 if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
1913 switch (data[3]) {
1914 case 0x50: /* start of frame */
1915#define HDRSZ 16
1916 data += HDRSZ;
1917 len -= HDRSZ;
1918#undef HDRSZ
1919 if (data[0] == 0xff || data[1] == 0xd8)
1920 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1921 data, len);
1922 else
1923 gspca_dev->last_packet_type = DISCARD_PACKET;
1924 return;
1925 case 0x51: /* end of frame */
1926 if (data[9] != 0)
1927 gspca_dev->last_packet_type = DISCARD_PACKET;
1928 gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1929 data, 0);
1930 return;
1931 }
1932 }
1933
1934 /* intermediate packet */
1935 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1936 data, len);
1937}
1938
1939/* -- management routines -- */
1940
1941static void setbrightness(struct gspca_dev *gspca_dev)
1942{
1943 struct sd *sd = (struct sd *) gspca_dev;
1944 int val;
1945/* int was_streaming; */
1946
1947 val = sd->brightness;
1948 PDEBUG(D_CONF, "brightness:%d", val);
1949/* was_streaming = gspca_dev->streaming;
1950 * if (was_streaming)
1951 * ov51x_stop(sd); */
1952 switch (sd->sensor) {
1953 case SEN_OV8610:
1954 case SEN_OV7610:
1955 case SEN_OV76BE:
1956 case SEN_OV6620:
1957 case SEN_OV6630:
1958 case SEN_OV7640:
1959 i2c_w(sd, OV7610_REG_BRT, val);
1960 break;
1961 case SEN_OV7620:
1962 /* 7620 doesn't like manual changes when in auto mode */
1963/*fixme
1964 * if (!sd->auto_brt) */
1965 i2c_w(sd, OV7610_REG_BRT, val);
1966 break;
1967 case SEN_OV7670:
1968/*jfm - from windblows
1969 * i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
1970 i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
1971 break;
1972 }
1973/* if (was_streaming)
1974 * ov51x_restart(sd); */
1975}
1976
1977static void setcontrast(struct gspca_dev *gspca_dev)
1978{
1979 struct sd *sd = (struct sd *) gspca_dev;
1980 int val;
1981/* int was_streaming; */
1982
1983 val = sd->contrast;
1984 PDEBUG(D_CONF, "contrast:%d", val);
1985/* was_streaming = gspca_dev->streaming;
1986 if (was_streaming)
1987 ov51x_stop(sd); */
1988 switch (sd->sensor) {
1989 case SEN_OV7610:
1990 case SEN_OV6620:
1991 i2c_w(sd, OV7610_REG_CNT, val);
1992 break;
1993 case SEN_OV6630:
1994 i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
1995 case SEN_OV8610: {
1996 static const __u8 ctab[] = {
1997 0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
1998 };
1999
2000 /* Use Y gamma control instead. Bit 0 enables it. */
2001 i2c_w(sd, 0x64, ctab[val >> 5]);
2002 break;
2003 }
2004 case SEN_OV7620: {
2005 static const __u8 ctab[] = {
2006 0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
2007 0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
2008 };
2009
2010 /* Use Y gamma control instead. Bit 0 enables it. */
2011 i2c_w(sd, 0x64, ctab[val >> 4]);
2012 break;
2013 }
2014 case SEN_OV7640:
2015 /* Use gain control instead. */
2016 i2c_w(sd, OV7610_REG_GAIN, val >> 2);
2017 break;
2018 case SEN_OV7670:
2019 /* check that this isn't just the same as ov7610 */
2020 i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
2021 break;
2022 }
2023/* if (was_streaming)
2024 ov51x_restart(sd); */
2025}
2026
2027static void setcolors(struct gspca_dev *gspca_dev)
2028{
2029 struct sd *sd = (struct sd *) gspca_dev;
2030 int val;
2031/* int was_streaming; */
2032
2033 val = sd->colors;
2034 PDEBUG(D_CONF, "saturation:%d", val);
2035/* was_streaming = gspca_dev->streaming;
2036 if (was_streaming)
2037 ov51x_stop(sd); */
2038 switch (sd->sensor) {
2039 case SEN_OV8610:
2040 case SEN_OV7610:
2041 case SEN_OV76BE:
2042 case SEN_OV6620:
2043 case SEN_OV6630:
2044 i2c_w(sd, OV7610_REG_SAT, val);
2045 break;
2046 case SEN_OV7620:
2047 /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
2048/* rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
2049 if (rc < 0)
2050 goto out; */
2051 i2c_w(sd, OV7610_REG_SAT, val);
2052 break;
2053 case SEN_OV7640:
2054 i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
2055 break;
2056 case SEN_OV7670:
2057 /* supported later once I work out how to do it
2058 * transparently fail now! */
2059 /* set REG_COM13 values for UV sat auto mode */
2060 break;
2061 }
2062/* if (was_streaming)
2063 ov51x_restart(sd); */
2064}
2065
2066static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2067{
2068 struct sd *sd = (struct sd *) gspca_dev;
2069
2070 sd->brightness = val;
2071 setbrightness(gspca_dev);
2072 return 0;
2073}
2074
2075static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2076{
2077 struct sd *sd = (struct sd *) gspca_dev;
2078
2079 *val = sd->brightness;
2080 return 0;
2081}
2082
2083static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2084{
2085 struct sd *sd = (struct sd *) gspca_dev;
2086
2087 sd->contrast = val;
2088 setcontrast(gspca_dev);
2089 return 0;
2090}
2091
2092static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2093{
2094 struct sd *sd = (struct sd *) gspca_dev;
2095
2096 *val = sd->contrast;
2097 return 0;
2098}
2099
2100static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
2101{
2102 struct sd *sd = (struct sd *) gspca_dev;
2103
2104 sd->colors = val;
2105 setcolors(gspca_dev);
2106 return 0;
2107}
2108
2109static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2110{
2111 struct sd *sd = (struct sd *) gspca_dev;
2112
2113 *val = sd->colors;
2114 return 0;
2115}
2116
2117/* sub-driver description */
2118static const struct sd_desc sd_desc = {
2119 .name = MODULE_NAME,
2120 .ctrls = sd_ctrls,
2121 .nctrls = ARRAY_SIZE(sd_ctrls),
2122 .config = sd_config,
2123 .open = sd_open,
2124 .start = sd_start,
2125 .stopN = sd_stopN,
2126 .stop0 = sd_stop0,
2127 .close = sd_close,
2128 .pkt_scan = sd_pkt_scan,
2129};
2130
2131/* -- module initialisation -- */
2132#define DVNM(name) .driver_info = (kernel_ulong_t) name
2133static const __devinitdata struct usb_device_id device_table[] = {
2134 {USB_DEVICE(0x041e, 0x4052), DVNM("Creative Live! VISTA IM")},
2135 {USB_DEVICE(0x041e, 0x405f), DVNM("Creative Live! VISTA VF0330")},
2136 {USB_DEVICE(0x041e, 0x4060), DVNM("Creative Live! VISTA VF0350")},
2137 {USB_DEVICE(0x041e, 0x4061), DVNM("Creative Live! VISTA VF0400")},
2138 {USB_DEVICE(0x041e, 0x4064), DVNM("Creative Live! VISTA VF0420")},
2139 {USB_DEVICE(0x041e, 0x4068), DVNM("Creative Live! VISTA VF0470")},
2140 {USB_DEVICE(0x045e, 0x028c), DVNM("Microsoft xbox cam")},
2141 {USB_DEVICE(0x054c, 0x0154), DVNM("Sonny toy4")},
2142 {USB_DEVICE(0x054c, 0x0155), DVNM("Sonny toy5")},
2143 {USB_DEVICE(0x05a9, 0x0519), DVNM("OmniVision")},
2144 {USB_DEVICE(0x05a9, 0x0530), DVNM("OmniVision")},
2145 {USB_DEVICE(0x05a9, 0x4519), DVNM("OmniVision")},
2146 {USB_DEVICE(0x05a9, 0x8519), DVNM("OmniVision")},
2147 {}
2148};
2149#undef DVNAME
2150MODULE_DEVICE_TABLE(usb, device_table);
2151
2152/* -- device connect -- */
2153static int sd_probe(struct usb_interface *intf,
2154 const struct usb_device_id *id)
2155{
2156 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2157 THIS_MODULE);
2158}
2159
2160static struct usb_driver sd_driver = {
2161 .name = MODULE_NAME,
2162 .id_table = device_table,
2163 .probe = sd_probe,
2164 .disconnect = gspca_disconnect,
2165};
2166
2167/* -- module insert / remove -- */
2168static int __init sd_mod_init(void)
2169{
2170 if (usb_register(&sd_driver) < 0)
2171 return -1;
2172 PDEBUG(D_PROBE, "v%s registered", version);
2173 return 0;
2174}
2175static void __exit sd_mod_exit(void)
2176{
2177 usb_deregister(&sd_driver);
2178 PDEBUG(D_PROBE, "deregistered");
2179}
2180
2181module_init(sd_mod_init);
2182module_exit(sd_mod_exit);
2183
2184module_param(frame_rate, int, 0644);
2185MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
2186
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
new file mode 100644
index 000000000000..fa7abc411090
--- /dev/null
+++ b/drivers/media/video/gspca/pac207.c
@@ -0,0 +1,622 @@
1/*
2 * Pixart PAC207BCA library
3 *
4 * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
5 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
6 * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
7 *
8 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#define MODULE_NAME "pac207"
27
28#include "gspca.h"
29
30#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
31static const char version[] = "2.1.7";
32
33MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
34MODULE_DESCRIPTION("Pixart PAC207");
35MODULE_LICENSE("GPL");
36
37#define PAC207_CTRL_TIMEOUT 100 /* ms */
38
39#define PAC207_BRIGHTNESS_MIN 0
40#define PAC207_BRIGHTNESS_MAX 255
41#define PAC207_BRIGHTNESS_DEFAULT 4 /* power on default: 4 */
42
43/* An exposure value of 4 also works (3 does not) but then we need to lower
44 the compression balance setting when in 352x288 mode, otherwise the usb
45 bandwidth is not enough and packets get dropped resulting in corrupt
46 frames. The problem with this is that when the compression balance gets
47 lowered below 0x80, the pac207 starts using a different compression
48 algorithm for some lines, these lines get prefixed with a 0x2dd2 prefix
49 and currently we do not know how to decompress these lines, so for now
50 we use a minimum exposure value of 5 */
51#define PAC207_EXPOSURE_MIN 5
52#define PAC207_EXPOSURE_MAX 26
53#define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 ?? */
54#define PAC207_EXPOSURE_KNEE 11 /* 4 = 30 fps, 11 = 8, 15 = 6 */
55
56#define PAC207_GAIN_MIN 0
57#define PAC207_GAIN_MAX 31
58#define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */
59#define PAC207_GAIN_KNEE 20
60
61#define PAC207_AUTOGAIN_DEADZONE 30
62/* We calculating the autogain at the end of the transfer of a frame, at this
63 moment a frame with the old settings is being transmitted, and a frame is
64 being captured with the old settings. So if we adjust the autogain we must
65 ignore atleast the 2 next frames for the new settings to come into effect
66 before doing any other adjustments */
67#define PAC207_AUTOGAIN_IGNORE_FRAMES 3
68
69/* specific webcam descriptor */
70struct sd {
71 struct gspca_dev gspca_dev; /* !! must be the first item */
72
73 u8 mode;
74
75 u8 brightness;
76 u8 exposure;
77 u8 autogain;
78 u8 gain;
79
80 u8 sof_read;
81 u8 header_read;
82 u8 autogain_ignore_frames;
83
84 atomic_t avg_lum;
85};
86
87/* V4L2 controls supported by the driver */
88static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
89static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
90static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
91static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
92static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
93static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
94static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
95static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
96
97static struct ctrl sd_ctrls[] = {
98#define SD_BRIGHTNESS 0
99 {
100 {
101 .id = V4L2_CID_BRIGHTNESS,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Brightness",
104 .minimum = PAC207_BRIGHTNESS_MIN,
105 .maximum = PAC207_BRIGHTNESS_MAX,
106 .step = 1,
107 .default_value = PAC207_BRIGHTNESS_DEFAULT,
108 .flags = 0,
109 },
110 .set = sd_setbrightness,
111 .get = sd_getbrightness,
112 },
113#define SD_EXPOSURE 1
114 {
115 {
116 .id = V4L2_CID_EXPOSURE,
117 .type = V4L2_CTRL_TYPE_INTEGER,
118 .name = "exposure",
119 .minimum = PAC207_EXPOSURE_MIN,
120 .maximum = PAC207_EXPOSURE_MAX,
121 .step = 1,
122 .default_value = PAC207_EXPOSURE_DEFAULT,
123 .flags = 0,
124 },
125 .set = sd_setexposure,
126 .get = sd_getexposure,
127 },
128#define SD_AUTOGAIN 2
129 {
130 {
131 .id = V4L2_CID_AUTOGAIN,
132 .type = V4L2_CTRL_TYPE_BOOLEAN,
133 .name = "Auto Gain",
134 .minimum = 0,
135 .maximum = 1,
136 .step = 1,
137 .default_value = 1,
138 .flags = 0,
139 },
140 .set = sd_setautogain,
141 .get = sd_getautogain,
142 },
143#define SD_GAIN 3
144 {
145 {
146 .id = V4L2_CID_GAIN,
147 .type = V4L2_CTRL_TYPE_INTEGER,
148 .name = "gain",
149 .minimum = PAC207_GAIN_MIN,
150 .maximum = PAC207_GAIN_MAX,
151 .step = 1,
152 .default_value = PAC207_GAIN_DEFAULT,
153 .flags = 0,
154 },
155 .set = sd_setgain,
156 .get = sd_getgain,
157 },
158};
159
160static struct v4l2_pix_format sif_mode[] = {
161 {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
162 .bytesperline = 176,
163 .sizeimage = (176 + 2) * 144,
164 /* uncompressed, add 2 bytes / line for line header */
165 .colorspace = V4L2_COLORSPACE_SRGB,
166 .priv = 1},
167 {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
168 .bytesperline = 352,
169 /* compressed, but only when needed (not compressed
170 when the framerate is low) */
171 .sizeimage = (352 + 2) * 288,
172 .colorspace = V4L2_COLORSPACE_SRGB,
173 .priv = 0},
174};
175
176static const __u8 pac207_sensor_init[][8] = {
177 {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0xf0},
178 {0x00, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
179 {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
180 {0x00, 0x00, 0x32, 0x00, 0x96, 0x00, 0xa2, 0x02},
181 {0x32, 0x00, 0x96, 0x00, 0xA2, 0x02, 0xaf, 0x00},
182};
183
184 /* 48 reg_72 Rate Control end BalSize_4a =0x36 */
185static const __u8 PacReg72[] = { 0x00, 0x00, 0x36, 0x00 };
186
187static const unsigned char pac207_sof_marker[5] =
188 { 0xff, 0xff, 0x00, 0xff, 0x96 };
189
190static int pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
191 const u8 *buffer, u16 length)
192{
193 struct usb_device *udev = gspca_dev->dev;
194 int err;
195
196 memcpy(gspca_dev->usb_buf, buffer, length);
197
198 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
199 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
200 0x00, index,
201 gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
202 if (err < 0)
203 PDEBUG(D_ERR,
204 "Failed to write registers to index 0x%04X, error %d)",
205 index, err);
206
207 return err;
208}
209
210
211int pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
212{
213 struct usb_device *udev = gspca_dev->dev;
214 int err;
215
216 err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
217 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
218 value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
219 if (err)
220 PDEBUG(D_ERR, "Failed to write a register (index 0x%04X,"
221 " value 0x%02X, error %d)", index, value, err);
222
223 return err;
224}
225
226
227int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
228{
229 struct usb_device *udev = gspca_dev->dev;
230 int res;
231
232 res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
233 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
234 0x00, index,
235 gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
236 if (res < 0) {
237 PDEBUG(D_ERR,
238 "Failed to read a register (index 0x%04X, error %d)",
239 index, res);
240 return res;
241 }
242
243 return gspca_dev->usb_buf[0];
244}
245
246/* this function is called at probe time */
247static int sd_config(struct gspca_dev *gspca_dev,
248 const struct usb_device_id *id)
249{
250 struct sd *sd = (struct sd *) gspca_dev;
251 struct cam *cam;
252 u8 idreg[2];
253
254 idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
255 idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
256 idreg[0] = ((idreg[0] & 0x0F) << 4) | ((idreg[1] & 0xf0) >> 4);
257 idreg[1] = idreg[1] & 0x0f;
258 PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
259 idreg[0], idreg[1]);
260
261 if (idreg[0] != 0x27) {
262 PDEBUG(D_PROBE, "Error invalid sensor ID!");
263 return -ENODEV;
264 }
265
266 pac207_write_reg(gspca_dev, 0x41, 0x00);
267 /* Bit_0=Image Format,
268 * Bit_1=LED,
269 * Bit_2=Compression test mode enable */
270 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
271 pac207_write_reg(gspca_dev, 0x11, 0x30); /* Analog Bias */
272
273 PDEBUG(D_PROBE,
274 "Pixart PAC207BCA Image Processor and Control Chip detected"
275 " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
276
277 cam = &gspca_dev->cam;
278 cam->dev_name = (char *) id->driver_info;
279 cam->epaddr = 0x05;
280 cam->cam_mode = sif_mode;
281 cam->nmodes = ARRAY_SIZE(sif_mode);
282 sd->brightness = PAC207_BRIGHTNESS_DEFAULT;
283 sd->exposure = PAC207_EXPOSURE_DEFAULT;
284 sd->gain = PAC207_GAIN_DEFAULT;
285
286 return 0;
287}
288
289/* this function is called at open time */
290static int sd_open(struct gspca_dev *gspca_dev)
291{
292 struct sd *sd = (struct sd *) gspca_dev;
293
294 sd->autogain = 1;
295 return 0;
296}
297
298/* -- start the camera -- */
299static void sd_start(struct gspca_dev *gspca_dev)
300{
301 struct sd *sd = (struct sd *) gspca_dev;
302 __u8 mode;
303
304 pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
305 pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
306 pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
307 pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
308 pac207_write_regs(gspca_dev, 0x0040, pac207_sensor_init[3], 8);
309 pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[4], 8);
310 pac207_write_regs(gspca_dev, 0x0048, PacReg72, 4);
311
312 /* Compression Balance */
313 if (gspca_dev->width == 176)
314 pac207_write_reg(gspca_dev, 0x4a, 0xff);
315 else
316 pac207_write_reg(gspca_dev, 0x4a, 0x88);
317 pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
318 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
319
320 /* PGA global gain (Bit 4-0) */
321 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
322 pac207_write_reg(gspca_dev, 0x02, sd->exposure); /* PXCK = 12MHz /n */
323
324 mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
325 if (gspca_dev->width == 176) { /* 176x144 */
326 mode |= 0x01;
327 PDEBUG(D_STREAM, "pac207_start mode 176x144");
328 } else { /* 352x288 */
329 PDEBUG(D_STREAM, "pac207_start mode 352x288");
330 }
331 pac207_write_reg(gspca_dev, 0x41, mode);
332
333 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
334 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
335 msleep(10);
336 pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
337
338 sd->sof_read = 0;
339 sd->autogain_ignore_frames = 0;
340 atomic_set(&sd->avg_lum, -1);
341}
342
343static void sd_stopN(struct gspca_dev *gspca_dev)
344{
345 pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
346 pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
347 pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
348}
349
350static void sd_stop0(struct gspca_dev *gspca_dev)
351{
352}
353
354/* this function is called at close time */
355static void sd_close(struct gspca_dev *gspca_dev)
356{
357}
358
359static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
360{
361 struct sd *sd = (struct sd *) gspca_dev;
362 int avg_lum = atomic_read(&sd->avg_lum);
363
364 if (avg_lum == -1)
365 return;
366
367 if (sd->autogain_ignore_frames > 0)
368 sd->autogain_ignore_frames--;
369 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
370 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
371 PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
372 sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
373}
374
375static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
376 unsigned char *m, int len)
377{
378 struct sd *sd = (struct sd *) gspca_dev;
379 int i;
380
381 /* Search for the SOF marker (fixed part) in the header */
382 for (i = 0; i < len; i++) {
383 if (m[i] == pac207_sof_marker[sd->sof_read]) {
384 sd->sof_read++;
385 if (sd->sof_read == sizeof(pac207_sof_marker)) {
386 PDEBUG(D_STREAM,
387 "SOF found, bytes to analyze: %u."
388 " Frame starts at byte #%u",
389 len, i + 1);
390 sd->sof_read = 0;
391 return m + i + 1;
392 }
393 } else {
394 sd->sof_read = 0;
395 }
396 }
397
398 return NULL;
399}
400
401static void sd_pkt_scan(struct gspca_dev *gspca_dev,
402 struct gspca_frame *frame,
403 __u8 *data,
404 int len)
405{
406 struct sd *sd = (struct sd *) gspca_dev;
407 unsigned char *sof;
408
409 sof = pac207_find_sof(gspca_dev, data, len);
410 if (sof) {
411 int n;
412
413 /* finish decoding current frame */
414 n = sof - data;
415 if (n > sizeof pac207_sof_marker)
416 n -= sizeof pac207_sof_marker;
417 else
418 n = 0;
419 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
420 data, n);
421 sd->header_read = 0;
422 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, NULL, 0);
423 len -= sof - data;
424 data = sof;
425 }
426 if (sd->header_read < 11) {
427 int needed;
428
429 /* get average lumination from frame header (byte 5) */
430 if (sd->header_read < 5) {
431 needed = 5 - sd->header_read;
432 if (len >= needed)
433 atomic_set(&sd->avg_lum, data[needed - 1]);
434 }
435 /* skip the rest of the header */
436 needed = 11 - sd->header_read;
437 if (len <= needed) {
438 sd->header_read += len;
439 return;
440 }
441 data += needed;
442 len -= needed;
443 sd->header_read = 11;
444 }
445
446 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
447}
448
449static void setbrightness(struct gspca_dev *gspca_dev)
450{
451 struct sd *sd = (struct sd *) gspca_dev;
452
453 pac207_write_reg(gspca_dev, 0x08, sd->brightness);
454 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
455 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
456}
457
458static void setexposure(struct gspca_dev *gspca_dev)
459{
460 struct sd *sd = (struct sd *) gspca_dev;
461
462 pac207_write_reg(gspca_dev, 0x02, sd->exposure);
463 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
464 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
465}
466
467static void setgain(struct gspca_dev *gspca_dev)
468{
469 struct sd *sd = (struct sd *) gspca_dev;
470
471 pac207_write_reg(gspca_dev, 0x0e, sd->gain);
472 pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
473 pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
474}
475
476static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
477{
478 struct sd *sd = (struct sd *) gspca_dev;
479
480 sd->brightness = val;
481 if (gspca_dev->streaming)
482 setbrightness(gspca_dev);
483 return 0;
484}
485
486static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
487{
488 struct sd *sd = (struct sd *) gspca_dev;
489
490 *val = sd->brightness;
491 return 0;
492}
493
494static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
495{
496 struct sd *sd = (struct sd *) gspca_dev;
497
498 sd->exposure = val;
499 if (gspca_dev->streaming)
500 setexposure(gspca_dev);
501 return 0;
502}
503
504static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
505{
506 struct sd *sd = (struct sd *) gspca_dev;
507
508 *val = sd->exposure;
509 return 0;
510}
511
512static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
513{
514 struct sd *sd = (struct sd *) gspca_dev;
515
516 sd->gain = val;
517 if (gspca_dev->streaming)
518 setgain(gspca_dev);
519 return 0;
520}
521
522static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
523{
524 struct sd *sd = (struct sd *) gspca_dev;
525
526 *val = sd->gain;
527 return 0;
528}
529
530static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
531{
532 struct sd *sd = (struct sd *) gspca_dev;
533
534 sd->autogain = val;
535 /* when switching to autogain set defaults to make sure
536 we are on a valid point of the autogain gain /
537 exposure knee graph, and give this change time to
538 take effect before doing autogain. */
539 if (sd->autogain) {
540 sd->exposure = PAC207_EXPOSURE_DEFAULT;
541 sd->gain = PAC207_GAIN_DEFAULT;
542 if (gspca_dev->streaming) {
543 sd->autogain_ignore_frames =
544 PAC207_AUTOGAIN_IGNORE_FRAMES;
545 setexposure(gspca_dev);
546 setgain(gspca_dev);
547 }
548 }
549
550 return 0;
551}
552
553static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
554{
555 struct sd *sd = (struct sd *) gspca_dev;
556
557 *val = sd->autogain;
558 return 0;
559}
560
561/* sub-driver description */
562static const struct sd_desc sd_desc = {
563 .name = MODULE_NAME,
564 .ctrls = sd_ctrls,
565 .nctrls = ARRAY_SIZE(sd_ctrls),
566 .config = sd_config,
567 .open = sd_open,
568 .start = sd_start,
569 .stopN = sd_stopN,
570 .stop0 = sd_stop0,
571 .close = sd_close,
572 .dq_callback = pac207_do_auto_gain,
573 .pkt_scan = sd_pkt_scan,
574};
575
576/* -- module initialisation -- */
577#define DVNM(name) .driver_info = (kernel_ulong_t) name
578static const __devinitdata struct usb_device_id device_table[] = {
579 {USB_DEVICE(0x041e, 0x4028), DVNM("Creative Webcam Vista Plus")},
580 {USB_DEVICE(0x093a, 0x2460), DVNM("Q-Tec Webcam 100")},
581 {USB_DEVICE(0x093a, 0x2463), DVNM("Philips spc200nc pac207")},
582 {USB_DEVICE(0x093a, 0x2464), DVNM("Labtec Webcam 1200")},
583 {USB_DEVICE(0x093a, 0x2468), DVNM("PAC207")},
584 {USB_DEVICE(0x093a, 0x2470), DVNM("Genius GF112")},
585 {USB_DEVICE(0x093a, 0x2471), DVNM("Genius VideoCam GE111")},
586 {USB_DEVICE(0x093a, 0x2472), DVNM("Genius VideoCam GE110")},
587 {USB_DEVICE(0x2001, 0xf115), DVNM("D-Link DSB-C120")},
588 {}
589};
590MODULE_DEVICE_TABLE(usb, device_table);
591
592/* -- device connect -- */
593static int sd_probe(struct usb_interface *intf,
594 const struct usb_device_id *id)
595{
596 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
597 THIS_MODULE);
598}
599
600static struct usb_driver sd_driver = {
601 .name = MODULE_NAME,
602 .id_table = device_table,
603 .probe = sd_probe,
604 .disconnect = gspca_disconnect,
605};
606
607/* -- module insert / remove -- */
608static int __init sd_mod_init(void)
609{
610 if (usb_register(&sd_driver) < 0)
611 return -1;
612 PDEBUG(D_PROBE, "v%s registered", version);
613 return 0;
614}
615static void __exit sd_mod_exit(void)
616{
617 usb_deregister(&sd_driver);
618 PDEBUG(D_PROBE, "deregistered");
619}
620
621module_init(sd_mod_init);
622module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
new file mode 100644
index 000000000000..5c052e31be4a
--- /dev/null
+++ b/drivers/media/video/gspca/pac7311.c
@@ -0,0 +1,760 @@
1/*
2 * Pixart PAC7311 library
3 * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
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 "pac7311"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
30MODULE_DESCRIPTION("Pixart PAC7311");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 int avg_lum;
38
39 unsigned char brightness;
40 unsigned char contrast;
41 unsigned char colors;
42 unsigned char autogain;
43
44 char ffseq;
45 signed char ag_cnt;
46#define AG_CNT_START 13
47};
48
49/* V4L2 controls supported by the driver */
50static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
58
59static struct ctrl sd_ctrls[] = {
60 {
61 {
62 .id = V4L2_CID_BRIGHTNESS,
63 .type = V4L2_CTRL_TYPE_INTEGER,
64 .name = "Brightness",
65 .minimum = 0,
66#define BRIGHTNESS_MAX 0x20
67 .maximum = BRIGHTNESS_MAX,
68 .step = 1,
69#define BRIGHTNESS_DEF 0x10
70 .default_value = BRIGHTNESS_DEF,
71 },
72 .set = sd_setbrightness,
73 .get = sd_getbrightness,
74 },
75 {
76 {
77 .id = V4L2_CID_CONTRAST,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Contrast",
80 .minimum = 0,
81 .maximum = 255,
82 .step = 1,
83#define CONTRAST_DEF 127
84 .default_value = CONTRAST_DEF,
85 },
86 .set = sd_setcontrast,
87 .get = sd_getcontrast,
88 },
89 {
90 {
91 .id = V4L2_CID_SATURATION,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Color",
94 .minimum = 0,
95 .maximum = 255,
96 .step = 1,
97#define COLOR_DEF 127
98 .default_value = COLOR_DEF,
99 },
100 .set = sd_setcolors,
101 .get = sd_getcolors,
102 },
103 {
104 {
105 .id = V4L2_CID_AUTOGAIN,
106 .type = V4L2_CTRL_TYPE_BOOLEAN,
107 .name = "Auto Gain",
108 .minimum = 0,
109 .maximum = 1,
110 .step = 1,
111#define AUTOGAIN_DEF 1
112 .default_value = AUTOGAIN_DEF,
113 },
114 .set = sd_setautogain,
115 .get = sd_getautogain,
116 },
117};
118
119static struct v4l2_pix_format vga_mode[] = {
120 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
121 .bytesperline = 160,
122 .sizeimage = 160 * 120 * 3 / 8 + 590,
123 .colorspace = V4L2_COLORSPACE_JPEG,
124 .priv = 2},
125 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
126 .bytesperline = 320,
127 .sizeimage = 320 * 240 * 3 / 8 + 590,
128 .colorspace = V4L2_COLORSPACE_JPEG,
129 .priv = 1},
130 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 640,
132 .sizeimage = 640 * 480 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 0},
135};
136
137#define PAC7311_JPEG_HEADER_SIZE (sizeof pac7311_jpeg_header) /* (594) */
138
139static const __u8 pac7311_jpeg_header[] = {
140 0xff, 0xd8,
141 0xff, 0xe0, 0x00, 0x03, 0x20,
142 0xff, 0xc0, 0x00, 0x11, 0x08,
143 0x01, 0xe0, /* 12: height */
144 0x02, 0x80, /* 14: width */
145 0x03, /* 16 */
146 0x01, 0x21, 0x00,
147 0x02, 0x11, 0x01,
148 0x03, 0x11, 0x01,
149 0xff, 0xdb, 0x00, 0x84,
150 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d,
151 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16,
152 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d,
153 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40,
154 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57, 0x5f,
155 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
156 0x78, 0x5c, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, 0x12, 0x18,
157 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
158 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
159 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
160 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
161 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
162 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
163 0xff, 0xc4, 0x01, 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01,
164 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
166 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02,
167 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
168 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31,
169 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
170 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
171 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
172 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
173 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
174 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57,
175 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
176 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
177 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
178 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
179 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
180 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
181 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
182 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
183 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
184 0xf9, 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
185 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
187 0x0b, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
188 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
189 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
190 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14,
191 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
192 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
193 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a,
194 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
195 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
196 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
197 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83,
198 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94,
199 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
200 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
201 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
202 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
203 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
204 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
205 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03,
206 0x11, 0x00, 0x3f, 0x00
207};
208
209static void reg_w_buf(struct gspca_dev *gspca_dev,
210 __u16 index,
211 const char *buffer, __u16 len)
212{
213 memcpy(gspca_dev->usb_buf, buffer, len);
214 usb_control_msg(gspca_dev->dev,
215 usb_sndctrlpipe(gspca_dev->dev, 0),
216 1, /* request */
217 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
218 0, /* value */
219 index, gspca_dev->usb_buf, len,
220 500);
221}
222
223static __u8 reg_r(struct gspca_dev *gspca_dev,
224 __u16 index)
225{
226 usb_control_msg(gspca_dev->dev,
227 usb_rcvctrlpipe(gspca_dev->dev, 0),
228 0, /* request */
229 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
230 0, /* value */
231 index, gspca_dev->usb_buf, 1,
232 500);
233 return gspca_dev->usb_buf[0];
234}
235
236static void reg_w(struct gspca_dev *gspca_dev,
237 __u16 index,
238 __u8 value)
239{
240 gspca_dev->usb_buf[0] = value;
241 usb_control_msg(gspca_dev->dev,
242 usb_sndctrlpipe(gspca_dev->dev, 0),
243 0, /* request */
244 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
245 value, index, gspca_dev->usb_buf, 1,
246 500);
247}
248
249/* this function is called at probe time */
250static int sd_config(struct gspca_dev *gspca_dev,
251 const struct usb_device_id *id)
252{
253 struct sd *sd = (struct sd *) gspca_dev;
254 struct cam *cam;
255
256 PDEBUG(D_CONF, "Find Sensor PAC7311");
257 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
258 reg_w(gspca_dev, 0x78, 0x40); /* Bit_0=start stream, Bit_7=LED */
259 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
260 reg_w(gspca_dev, 0xff, 0x04);
261 reg_w(gspca_dev, 0x27, 0x80);
262 reg_w(gspca_dev, 0x28, 0xca);
263 reg_w(gspca_dev, 0x29, 0x53);
264 reg_w(gspca_dev, 0x2a, 0x0e);
265 reg_w(gspca_dev, 0xff, 0x01);
266 reg_w(gspca_dev, 0x3e, 0x20);
267
268 cam = &gspca_dev->cam;
269 cam->dev_name = (char *) id->driver_info;
270 cam->epaddr = 0x05;
271 cam->cam_mode = vga_mode;
272 cam->nmodes = ARRAY_SIZE(vga_mode);
273
274 sd->brightness = BRIGHTNESS_DEF;
275 sd->contrast = CONTRAST_DEF;
276 sd->colors = COLOR_DEF;
277 sd->autogain = AUTOGAIN_DEF;
278 return 0;
279}
280
281static void setbrightness(struct gspca_dev *gspca_dev)
282{
283 struct sd *sd = (struct sd *) gspca_dev;
284 int brightness;
285
286/*jfm: inverted?*/
287 brightness = BRIGHTNESS_MAX - sd->brightness;
288 reg_w(gspca_dev, 0xff, 0x04);
289/* reg_w(gspca_dev, 0x0e, 0x00); */
290 reg_w(gspca_dev, 0x0f, brightness);
291 /* load registers to sensor (Bit 0, auto clear) */
292 reg_w(gspca_dev, 0x11, 0x01);
293 PDEBUG(D_CONF|D_STREAM, "brightness: %i", brightness);
294}
295
296static void setcontrast(struct gspca_dev *gspca_dev)
297{
298 struct sd *sd = (struct sd *) gspca_dev;
299
300 reg_w(gspca_dev, 0xff, 0x01);
301 reg_w(gspca_dev, 0x80, sd->contrast);
302 /* load registers to sensor (Bit 0, auto clear) */
303 reg_w(gspca_dev, 0x11, 0x01);
304 PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
305}
306
307static void setcolors(struct gspca_dev *gspca_dev)
308{
309 struct sd *sd = (struct sd *) gspca_dev;
310
311 reg_w(gspca_dev, 0xff, 0x01);
312 reg_w(gspca_dev, 0x10, sd->colors);
313 /* load registers to sensor (Bit 0, auto clear) */
314 reg_w(gspca_dev, 0x11, 0x01);
315 PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
316}
317
318/* this function is called at open time */
319static int sd_open(struct gspca_dev *gspca_dev)
320{
321 reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
322 return 0;
323}
324
325static void sd_start(struct gspca_dev *gspca_dev)
326{
327 struct sd *sd = (struct sd *) gspca_dev;
328
329 reg_w(gspca_dev, 0xff, 0x01);
330 reg_w_buf(gspca_dev, 0x0002, "\x48\x0a\x40\x08\x00\x00\x08\x00", 8);
331 reg_w_buf(gspca_dev, 0x000a, "\x06\xff\x11\xff\x5a\x30\x90\x4c", 8);
332 reg_w_buf(gspca_dev, 0x0012, "\x00\x07\x00\x0a\x10\x00\xa0\x10", 8);
333 reg_w_buf(gspca_dev, 0x001a, "\x02\x00\x00\x00\x00\x0b\x01\x00", 8);
334 reg_w_buf(gspca_dev, 0x0022, "\x00\x00\x00\x00\x00\x00\x00\x00", 8);
335 reg_w_buf(gspca_dev, 0x002a, "\x00\x00\x00", 3);
336 reg_w_buf(gspca_dev, 0x003e, "\x00\x00\x78\x52\x4a\x52\x78\x6e", 8);
337 reg_w_buf(gspca_dev, 0x0046, "\x48\x46\x48\x6e\x5f\x49\x42\x49", 8);
338 reg_w_buf(gspca_dev, 0x004e, "\x5f\x5f\x49\x42\x49\x5f\x6e\x48", 8);
339 reg_w_buf(gspca_dev, 0x0056, "\x46\x48\x6e\x78\x52\x4a\x52\x78", 8);
340 reg_w_buf(gspca_dev, 0x005e, "\x00\x00\x09\x1b\x34\x49\x5c\x9b", 8);
341 reg_w_buf(gspca_dev, 0x0066, "\xd0\xff", 2);
342 reg_w_buf(gspca_dev, 0x0078, "\x44\x00\xf2\x01\x01\x80", 6);
343 reg_w_buf(gspca_dev, 0x007f, "\x2a\x1c\x00\xc8\x02\x58\x03\x84", 8);
344 reg_w_buf(gspca_dev, 0x0087, "\x12\x00\x1a\x04\x08\x0c\x10\x14", 8);
345 reg_w_buf(gspca_dev, 0x008f, "\x18\x20", 2);
346 reg_w_buf(gspca_dev, 0x0096, "\x01\x08\x04", 3);
347 reg_w_buf(gspca_dev, 0x00a0, "\x44\x44\x44\x04", 4);
348 reg_w_buf(gspca_dev, 0x00f0, "\x01\x00\x00\x00\x22\x00\x20\x00", 8);
349 reg_w_buf(gspca_dev, 0x00f8, "\x3f\x00\x0a\x01\x00", 5);
350
351 reg_w(gspca_dev, 0xff, 0x04);
352 reg_w(gspca_dev, 0x02, 0x04);
353 reg_w(gspca_dev, 0x03, 0x54);
354 reg_w(gspca_dev, 0x04, 0x07);
355 reg_w(gspca_dev, 0x05, 0x2b);
356 reg_w(gspca_dev, 0x06, 0x09);
357 reg_w(gspca_dev, 0x07, 0x0f);
358 reg_w(gspca_dev, 0x08, 0x09);
359 reg_w(gspca_dev, 0x09, 0x00);
360 reg_w(gspca_dev, 0x0c, 0x07);
361 reg_w(gspca_dev, 0x0d, 0x00);
362 reg_w(gspca_dev, 0x0e, 0x00);
363 reg_w(gspca_dev, 0x0f, 0x62);
364 reg_w(gspca_dev, 0x10, 0x08);
365 reg_w(gspca_dev, 0x12, 0x07);
366 reg_w(gspca_dev, 0x13, 0x00);
367 reg_w(gspca_dev, 0x14, 0x00);
368 reg_w(gspca_dev, 0x15, 0x00);
369 reg_w(gspca_dev, 0x16, 0x00);
370 reg_w(gspca_dev, 0x17, 0x00);
371 reg_w(gspca_dev, 0x18, 0x00);
372 reg_w(gspca_dev, 0x19, 0x00);
373 reg_w(gspca_dev, 0x1a, 0x00);
374 reg_w(gspca_dev, 0x1b, 0x03);
375 reg_w(gspca_dev, 0x1c, 0xa0);
376 reg_w(gspca_dev, 0x1d, 0x01);
377 reg_w(gspca_dev, 0x1e, 0xf4);
378 reg_w(gspca_dev, 0x21, 0x00);
379 reg_w(gspca_dev, 0x22, 0x08);
380 reg_w(gspca_dev, 0x24, 0x03);
381 reg_w(gspca_dev, 0x26, 0x00);
382 reg_w(gspca_dev, 0x27, 0x01);
383 reg_w(gspca_dev, 0x28, 0xca);
384 reg_w(gspca_dev, 0x29, 0x10);
385 reg_w(gspca_dev, 0x2a, 0x06);
386 reg_w(gspca_dev, 0x2b, 0x78);
387 reg_w(gspca_dev, 0x2c, 0x00);
388 reg_w(gspca_dev, 0x2d, 0x00);
389 reg_w(gspca_dev, 0x2e, 0x00);
390 reg_w(gspca_dev, 0x2f, 0x00);
391 reg_w(gspca_dev, 0x30, 0x23);
392 reg_w(gspca_dev, 0x31, 0x28);
393 reg_w(gspca_dev, 0x32, 0x04);
394 reg_w(gspca_dev, 0x33, 0x11);
395 reg_w(gspca_dev, 0x34, 0x00);
396 reg_w(gspca_dev, 0x35, 0x00);
397 reg_w(gspca_dev, 0x11, 0x01);
398 setcontrast(gspca_dev);
399 setbrightness(gspca_dev);
400 setcolors(gspca_dev);
401
402 /* set correct resolution */
403 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
404 case 2: /* 160x120 */
405 reg_w(gspca_dev, 0xff, 0x04);
406 reg_w(gspca_dev, 0x02, 0x03);
407 reg_w(gspca_dev, 0xff, 0x01);
408 reg_w(gspca_dev, 0x08, 0x09);
409 reg_w(gspca_dev, 0x17, 0x20);
410 reg_w(gspca_dev, 0x1b, 0x00);
411/* reg_w(gspca_dev, 0x80, 0x69); */
412 reg_w(gspca_dev, 0x87, 0x10);
413 break;
414 case 1: /* 320x240 */
415 reg_w(gspca_dev, 0xff, 0x04);
416 reg_w(gspca_dev, 0x02, 0x03);
417 reg_w(gspca_dev, 0xff, 0x01);
418 reg_w(gspca_dev, 0x08, 0x09);
419 reg_w(gspca_dev, 0x17, 0x30);
420/* reg_w(gspca_dev, 0x80, 0x3f); */
421 reg_w(gspca_dev, 0x87, 0x11);
422 break;
423 case 0: /* 640x480 */
424 reg_w(gspca_dev, 0xff, 0x04);
425 reg_w(gspca_dev, 0x02, 0x03);
426 reg_w(gspca_dev, 0xff, 0x01);
427 reg_w(gspca_dev, 0x08, 0x08);
428 reg_w(gspca_dev, 0x17, 0x00);
429/* reg_w(gspca_dev, 0x80, 0x1c); */
430 reg_w(gspca_dev, 0x87, 0x12);
431 break;
432 }
433
434 /* start stream */
435 reg_w(gspca_dev, 0xff, 0x01);
436 reg_w(gspca_dev, 0x78, 0x04);
437 reg_w(gspca_dev, 0x78, 0x05);
438
439 if (sd->autogain) {
440 sd->ag_cnt = AG_CNT_START;
441 sd->avg_lum = 0;
442 } else {
443 sd->ag_cnt = -1;
444 }
445}
446
447static void sd_stopN(struct gspca_dev *gspca_dev)
448{
449 reg_w(gspca_dev, 0xff, 0x04);
450 reg_w(gspca_dev, 0x27, 0x80);
451 reg_w(gspca_dev, 0x28, 0xca);
452 reg_w(gspca_dev, 0x29, 0x53);
453 reg_w(gspca_dev, 0x2a, 0x0e);
454 reg_w(gspca_dev, 0xff, 0x01);
455 reg_w(gspca_dev, 0x3e, 0x20);
456 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
457 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
458 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
459}
460
461static void sd_stop0(struct gspca_dev *gspca_dev)
462{
463}
464
465/* this function is called at close time */
466static void sd_close(struct gspca_dev *gspca_dev)
467{
468 reg_w(gspca_dev, 0xff, 0x04);
469 reg_w(gspca_dev, 0x27, 0x80);
470 reg_w(gspca_dev, 0x28, 0xca);
471 reg_w(gspca_dev, 0x29, 0x53);
472 reg_w(gspca_dev, 0x2a, 0x0e);
473 reg_w(gspca_dev, 0xff, 0x01);
474 reg_w(gspca_dev, 0x3e, 0x20);
475 reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
476 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
477 reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
478}
479
480static void setautogain(struct gspca_dev *gspca_dev, int luma)
481{
482 int luma_mean = 128;
483 int luma_delta = 20;
484 __u8 spring = 5;
485 int Gbright;
486
487 Gbright = reg_r(gspca_dev, 0x02);
488 PDEBUG(D_FRAM, "luma mean %d", luma);
489 if (luma < luma_mean - luma_delta ||
490 luma > luma_mean + luma_delta) {
491 Gbright += (luma_mean - luma) >> spring;
492 if (Gbright > 0x1a)
493 Gbright = 0x1a;
494 else if (Gbright < 4)
495 Gbright = 4;
496 PDEBUG(D_FRAM, "gbright %d", Gbright);
497 reg_w(gspca_dev, 0xff, 0x04);
498 reg_w(gspca_dev, 0x0f, Gbright);
499 /* load registers to sensor (Bit 0, auto clear) */
500 reg_w(gspca_dev, 0x11, 0x01);
501 }
502}
503
504static void sd_pkt_scan(struct gspca_dev *gspca_dev,
505 struct gspca_frame *frame, /* target */
506 __u8 *data, /* isoc packet */
507 int len) /* iso packet length */
508{
509 struct sd *sd = (struct sd *) gspca_dev;
510 unsigned char tmpbuf[4];
511 int i, p, ffseq;
512
513/* if (len < 5) { */
514 if (len < 6) {
515/* gspca_dev->last_packet_type = DISCARD_PACKET; */
516 return;
517 }
518
519 ffseq = sd->ffseq;
520
521 for (p = 0; p < len - 6; p++) {
522 if ((data[0 + p] == 0xff)
523 && (data[1 + p] == 0xff)
524 && (data[2 + p] == 0x00)
525 && (data[3 + p] == 0xff)
526 && (data[4 + p] == 0x96)) {
527
528 /* start of frame */
529 if (sd->ag_cnt >= 0 && p > 28) {
530 sd->avg_lum += data[p - 23];
531 if (--sd->ag_cnt < 0) {
532 sd->ag_cnt = AG_CNT_START;
533 setautogain(gspca_dev,
534 sd->avg_lum / AG_CNT_START);
535 sd->avg_lum = 0;
536 }
537 }
538
539 /* copy the end of data to the current frame */
540 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
541 data, p);
542
543 /* put the JPEG header in the new frame */
544 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
545 (unsigned char *) pac7311_jpeg_header,
546 12);
547 tmpbuf[0] = gspca_dev->height >> 8;
548 tmpbuf[1] = gspca_dev->height & 0xff;
549 tmpbuf[2] = gspca_dev->width >> 8;
550 tmpbuf[3] = gspca_dev->width & 0xff;
551 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
552 tmpbuf, 4);
553 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
554 (unsigned char *) &pac7311_jpeg_header[16],
555 PAC7311_JPEG_HEADER_SIZE - 16);
556
557 data += p + 7;
558 len -= p + 7;
559 ffseq = 0;
560 break;
561 }
562 }
563
564 /* remove the 'ff ff ff xx' sequences */
565 switch (ffseq) {
566 case 3:
567 data += 1;
568 len -= 1;
569 break;
570 case 2:
571 if (data[0] == 0xff) {
572 data += 2;
573 len -= 2;
574 frame->data_end -= 2;
575 }
576 break;
577 case 1:
578 if (data[0] == 0xff
579 && data[1] == 0xff) {
580 data += 3;
581 len -= 3;
582 frame->data_end -= 1;
583 }
584 break;
585 }
586 for (i = 0; i < len - 4; i++) {
587 if (data[i] == 0xff
588 && data[i + 1] == 0xff
589 && data[i + 2] == 0xff) {
590 memmove(&data[i], &data[i + 4], len - i - 4);
591 len -= 4;
592 }
593 }
594 ffseq = 0;
595 if (data[len - 4] == 0xff) {
596 if (data[len - 3] == 0xff
597 && data[len - 2] == 0xff) {
598 len -= 4;
599 }
600 } else if (data[len - 3] == 0xff) {
601 if (data[len - 2] == 0xff
602 && data[len - 1] == 0xff)
603 ffseq = 3;
604 } else if (data[len - 2] == 0xff) {
605 if (data[len - 1] == 0xff)
606 ffseq = 2;
607 } else if (data[len - 1] == 0xff)
608 ffseq = 1;
609 sd->ffseq = ffseq;
610 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
611}
612
613static void getbrightness(struct gspca_dev *gspca_dev)
614{
615/* sd->brightness = reg_r(gspca_dev, 0x08);
616 return sd->brightness; */
617/* PDEBUG(D_CONF, "Called pac7311_getbrightness: Not implemented yet"); */
618}
619
620
621
622static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625
626 sd->brightness = val;
627 if (gspca_dev->streaming)
628 setbrightness(gspca_dev);
629 return 0;
630}
631
632static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
633{
634 struct sd *sd = (struct sd *) gspca_dev;
635
636 getbrightness(gspca_dev);
637 *val = sd->brightness;
638 return 0;
639}
640
641static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
642{
643 struct sd *sd = (struct sd *) gspca_dev;
644
645 sd->contrast = val;
646 if (gspca_dev->streaming)
647 setcontrast(gspca_dev);
648 return 0;
649}
650
651static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
652{
653 struct sd *sd = (struct sd *) gspca_dev;
654
655/* getcontrast(gspca_dev); */
656 *val = sd->contrast;
657 return 0;
658}
659
660static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
661{
662 struct sd *sd = (struct sd *) gspca_dev;
663
664 sd->colors = val;
665 if (gspca_dev->streaming)
666 setcolors(gspca_dev);
667 return 0;
668}
669
670static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673
674/* getcolors(gspca_dev); */
675 *val = sd->colors;
676 return 0;
677}
678
679static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
680{
681 struct sd *sd = (struct sd *) gspca_dev;
682
683 sd->autogain = val;
684 if (val) {
685 sd->ag_cnt = AG_CNT_START;
686 sd->avg_lum = 0;
687 } else {
688 sd->ag_cnt = -1;
689 }
690 return 0;
691}
692
693static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696
697 *val = sd->autogain;
698 return 0;
699}
700
701/* sub-driver description */
702static struct sd_desc sd_desc = {
703 .name = MODULE_NAME,
704 .ctrls = sd_ctrls,
705 .nctrls = ARRAY_SIZE(sd_ctrls),
706 .config = sd_config,
707 .open = sd_open,
708 .start = sd_start,
709 .stopN = sd_stopN,
710 .stop0 = sd_stop0,
711 .close = sd_close,
712 .pkt_scan = sd_pkt_scan,
713};
714
715/* -- module initialisation -- */
716#define DVNM(name) .driver_info = (kernel_ulong_t) name
717static __devinitdata struct usb_device_id device_table[] = {
718 {USB_DEVICE(0x093a, 0x2600), DVNM("Typhoon")},
719 {USB_DEVICE(0x093a, 0x2601), DVNM("Philips SPC610NC")},
720 {USB_DEVICE(0x093a, 0x2603), DVNM("PAC7312")},
721 {USB_DEVICE(0x093a, 0x2608), DVNM("Trust WB-3300p")},
722 {USB_DEVICE(0x093a, 0x260e), DVNM("Gigaware VGA PC Camera")},
723 /* and also ', Trust WB-3350p, SIGMA cam 2350' */
724 {USB_DEVICE(0x093a, 0x260f), DVNM("SnakeCam")},
725 {USB_DEVICE(0x093a, 0x2621), DVNM("PAC731x")},
726 {}
727};
728MODULE_DEVICE_TABLE(usb, device_table);
729
730/* -- device connect -- */
731static int sd_probe(struct usb_interface *intf,
732 const struct usb_device_id *id)
733{
734 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
735 THIS_MODULE);
736}
737
738static struct usb_driver sd_driver = {
739 .name = MODULE_NAME,
740 .id_table = device_table,
741 .probe = sd_probe,
742 .disconnect = gspca_disconnect,
743};
744
745/* -- module insert / remove -- */
746static int __init sd_mod_init(void)
747{
748 if (usb_register(&sd_driver) < 0)
749 return -1;
750 PDEBUG(D_PROBE, "v%s registered", version);
751 return 0;
752}
753static void __exit sd_mod_exit(void)
754{
755 usb_deregister(&sd_driver);
756 PDEBUG(D_PROBE, "deregistered");
757}
758
759module_init(sd_mod_init);
760module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
new file mode 100644
index 000000000000..dbeebe8625c5
--- /dev/null
+++ b/drivers/media/video/gspca/sonixb.c
@@ -0,0 +1,1477 @@
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
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
32MODULE_LICENSE("GPL");
33
34/* specific webcam descriptor */
35struct sd {
36 struct gspca_dev gspca_dev; /* !! must be the first item */
37
38 struct sd_desc sd_desc; /* our nctrls differ dependend upon the
39 sensor, so we use a per cam copy */
40 atomic_t avg_lum;
41
42 unsigned char gain;
43 unsigned char exposure;
44 unsigned char brightness;
45 unsigned char autogain;
46 unsigned char autogain_ignore_frames;
47 unsigned char freq; /* light freq filter setting */
48 unsigned char saturation;
49 unsigned char hue;
50 unsigned char contrast;
51
52 unsigned char fr_h_sz; /* size of frame header */
53 char sensor; /* Type of image sensor chip */
54#define SENSOR_HV7131R 0
55#define SENSOR_OV6650 1
56#define SENSOR_OV7630 2
57#define SENSOR_OV7630_3 3
58#define SENSOR_PAS106 4
59#define SENSOR_PAS202 5
60#define SENSOR_TAS5110 6
61#define SENSOR_TAS5130CXX 7
62 char sensor_has_gain;
63 __u8 sensor_addr;
64};
65
66#define COMP2 0x8f
67#define COMP 0xc7 /* 0x87 //0x07 */
68#define COMP1 0xc9 /* 0x89 //0x09 */
69
70#define MCK_INIT 0x63
71#define MCK_INIT1 0x20 /*fixme: Bayer - 0x50 for JPEG ??*/
72
73#define SYS_CLK 0x04
74
75/* We calculate the autogain at the end of the transfer of a frame, at this
76 moment a frame with the old settings is being transmitted, and a frame is
77 being captured with the old settings. So if we adjust the autogain we must
78 ignore atleast the 2 next frames for the new settings to come into effect
79 before doing any other adjustments */
80#define AUTOGAIN_IGNORE_FRAMES 3
81#define AUTOGAIN_DEADZONE 1000
82#define DESIRED_AVG_LUM 7000
83
84/* V4L2 controls supported by the driver */
85static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val);
89static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val);
90static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val);
91static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
92static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
93static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
94static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
95static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val);
96static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val);
97static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
98static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
99static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
100static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
101
102static struct ctrl sd_ctrls[] = {
103 {
104 {
105 .id = V4L2_CID_BRIGHTNESS,
106 .type = V4L2_CTRL_TYPE_INTEGER,
107 .name = "Brightness",
108 .minimum = 0,
109 .maximum = 255,
110 .step = 1,
111#define BRIGHTNESS_DEF 127
112 .default_value = BRIGHTNESS_DEF,
113 },
114 .set = sd_setbrightness,
115 .get = sd_getbrightness,
116 },
117 {
118 {
119 .id = V4L2_CID_GAIN,
120 .type = V4L2_CTRL_TYPE_INTEGER,
121 .name = "Gain",
122 .minimum = 0,
123 .maximum = 255,
124 .step = 1,
125#define GAIN_DEF 127
126#define GAIN_KNEE 200
127 .default_value = GAIN_DEF,
128 },
129 .set = sd_setgain,
130 .get = sd_getgain,
131 },
132 {
133 {
134 .id = V4L2_CID_EXPOSURE,
135 .type = V4L2_CTRL_TYPE_INTEGER,
136 .name = "Exposure",
137#define EXPOSURE_DEF 16 /* 32 ms / 30 fps */
138#define EXPOSURE_KNEE 50 /* 100 ms / 10 fps */
139 .minimum = 0,
140 .maximum = 255,
141 .step = 1,
142 .default_value = EXPOSURE_DEF,
143 .flags = 0,
144 },
145 .set = sd_setexposure,
146 .get = sd_getexposure,
147 },
148 {
149 {
150 .id = V4L2_CID_AUTOGAIN,
151 .type = V4L2_CTRL_TYPE_BOOLEAN,
152 .name = "Automatic Gain (and Exposure)",
153 .minimum = 0,
154 .maximum = 1,
155 .step = 1,
156#define AUTOGAIN_DEF 1
157 .default_value = AUTOGAIN_DEF,
158 .flags = 0,
159 },
160 .set = sd_setautogain,
161 .get = sd_getautogain,
162 },
163 {
164 {
165 .id = V4L2_CID_POWER_LINE_FREQUENCY,
166 .type = V4L2_CTRL_TYPE_MENU,
167 .name = "Light frequency filter",
168 .minimum = 0,
169 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
170 .step = 1,
171#define FREQ_DEF 1
172 .default_value = FREQ_DEF,
173 },
174 .set = sd_setfreq,
175 .get = sd_getfreq,
176 },
177 {
178 {
179 .id = V4L2_CID_SATURATION,
180 .type = V4L2_CTRL_TYPE_INTEGER,
181 .name = "Saturation",
182 .minimum = 0,
183 .maximum = 255,
184 .step = 1,
185#define SATURATION_DEF 127
186 .default_value = SATURATION_DEF,
187 },
188 .set = sd_setsaturation,
189 .get = sd_getsaturation,
190 },
191 {
192 {
193 .id = V4L2_CID_HUE,
194 .type = V4L2_CTRL_TYPE_INTEGER,
195 .name = "Hue",
196 .minimum = 0,
197 .maximum = 255,
198 .step = 1,
199#define HUE_DEF 127
200 .default_value = HUE_DEF,
201 },
202 .set = sd_sethue,
203 .get = sd_gethue,
204 },
205 {
206 {
207 .id = V4L2_CID_CONTRAST,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209 .name = "Contrast",
210 .minimum = 0,
211 .maximum = 255,
212 .step = 1,
213#define CONTRAST_DEF 127
214 .default_value = CONTRAST_DEF,
215 },
216 .set = sd_setcontrast,
217 .get = sd_getcontrast,
218 },
219};
220
221static struct v4l2_pix_format vga_mode[] = {
222 {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
223 .bytesperline = 160,
224 .sizeimage = 160 * 120,
225 .colorspace = V4L2_COLORSPACE_SRGB,
226 .priv = 2},
227 {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
228 .bytesperline = 320,
229 .sizeimage = 320 * 240,
230 .colorspace = V4L2_COLORSPACE_SRGB,
231 .priv = 1},
232 {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
233 .bytesperline = 640,
234 .sizeimage = 640 * 480,
235 .colorspace = V4L2_COLORSPACE_SRGB,
236 .priv = 0},
237};
238static struct v4l2_pix_format sif_mode[] = {
239 {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
240 .bytesperline = 176,
241 .sizeimage = 176 * 144,
242 .colorspace = V4L2_COLORSPACE_SRGB,
243 .priv = 1},
244 {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
245 .bytesperline = 352,
246 .sizeimage = 352 * 288,
247 .colorspace = V4L2_COLORSPACE_SRGB,
248 .priv = 0},
249};
250
251static const __u8 probe_ov7630[] = {0x08, 0x44};
252
253static const __u8 initHv7131[] = {
254 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
255 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* shift from 0x02 0x01 0x00 */
257 0x28, 0x1e, 0x60, 0x8a, 0x20,
258 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
259};
260static const __u8 hv7131_sensor_init[][8] = {
261 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
262 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
263 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
264 {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
265 {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
266};
267static const __u8 initOv6650[] = {
268 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
269 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x02, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x0b,
271 0x10, 0x1d, 0x10, 0x00, 0x06, 0x1f, 0x00
272};
273static const __u8 ov6650_sensor_init[][8] =
274{
275 /* Bright, contrast, etc are set througth SCBB interface.
276 * AVCAP on win2 do not send any data on this controls. */
277 /* Anyway, some registers appears to alter bright and constrat */
278
279 /* Reset sensor */
280 {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
281 /* Set clock register 0x11 low nibble is clock divider */
282 {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
283 /* Next some unknown stuff */
284 {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
285/* {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
286 * THIS SET GREEN SCREEN
287 * (pixels could be innverted in decode kind of "brg",
288 * but blue wont be there. Avoid this data ... */
289 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
290 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
291 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10},
292 /* Enable rgb brightness control */
293 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
294 /* HDG: Note windows uses the line below, which sets both register 0x60
295 and 0x61 I believe these registers of the ov6650 are identical as
296 those of the ov7630, because if this is true the windows settings
297 add a bit additional red gain and a lot additional blue gain, which
298 matches my findings that the windows settings make blue much too
299 blue and red a little too red.
300 {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
301 /* Some more unknown stuff */
302 {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
303 {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
304};
305
306static const __u8 initOv7630[] = {
307 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
308 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
309 0x00, 0x02, 0x01, 0x0a, /* r11 .. r14 */
310 0x28, 0x1e, /* H & V sizes r15 .. r16 */
311 0x68, COMP1, MCK_INIT1, /* r17 .. r19 */
312 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c /* r1a .. r1f */
313};
314static const __u8 initOv7630_3[] = {
315 0x44, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0x80, /* r01 .. r08 */
316 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /* r09 .. r10 */
317 0x00, 0x01, 0x01, 0x0a, /* r11 .. r14 */
318 0x28, 0x1e, /* H & V sizes r15 .. r16 */
319 0x68, 0x8f, MCK_INIT1, /* r17 .. r19 */
320 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c, 0x00, /* r1a .. r20 */
321 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, /* r21 .. r28 */
322 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff /* r29 .. r30 */
323};
324static const __u8 ov7630_sensor_init_com[][8] = {
325 {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
326 {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
327/* {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10}, jfm */
328 {0xd0, 0x21, 0x12, 0x1c, 0x00, 0x80, 0x34, 0x10}, /* jfm */
329 {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
330 {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
331 {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
332 {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
333 {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
334 {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
335 {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
336 {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
337/* {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10}, * jfm */
338 {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
339 {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
340 {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
341 {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
342 {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
343 {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
344};
345static const __u8 ov7630_sensor_init[][8] = {
346 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 200ms */
347 {0xa0, 0x21, 0x11, 0x01, 0xbd, 0x06, 0xf6, 0x10}, /* jfm */
348 {0xa0, 0x21, 0x10, 0x57, 0xbd, 0x06, 0xf6, 0x16},
349 {0xa0, 0x21, 0x76, 0x02, 0xbd, 0x06, 0xf6, 0x16},
350 {0xa0, 0x21, 0x00, 0x10, 0xbd, 0x06, 0xf6, 0x15}, /* gain */
351};
352static const __u8 ov7630_sensor_init_3[][8] = {
353 {0xa0, 0x21, 0x2a, 0xa0, 0x00, 0x00, 0x00, 0x10},
354 {0xa0, 0x21, 0x2a, 0x80, 0x00, 0x00, 0x00, 0x10},
355};
356
357static const __u8 initPas106[] = {
358 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
359 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x05, 0x01, 0x00,
361 0x16, 0x12, 0x28, COMP1, MCK_INIT1,
362 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
363};
364/* compression 0x86 mckinit1 0x2b */
365static const __u8 pas106_data[][2] = {
366 {0x02, 0x04}, /* Pixel Clock Divider 6 */
367 {0x03, 0x13}, /* Frame Time MSB */
368/* {0x03, 0x12}, * Frame Time MSB */
369 {0x04, 0x06}, /* Frame Time LSB */
370/* {0x04, 0x05}, * Frame Time LSB */
371 {0x05, 0x65}, /* Shutter Time Line Offset */
372/* {0x05, 0x6d}, * Shutter Time Line Offset */
373/* {0x06, 0xb1}, * Shutter Time Pixel Offset */
374 {0x06, 0xcd}, /* Shutter Time Pixel Offset */
375 {0x07, 0xc1}, /* Black Level Subtract Sign */
376/* {0x07, 0x00}, * Black Level Subtract Sign */
377 {0x08, 0x06}, /* Black Level Subtract Level */
378 {0x08, 0x06}, /* Black Level Subtract Level */
379/* {0x08, 0x01}, * Black Level Subtract Level */
380 {0x09, 0x05}, /* Color Gain B Pixel 5 a */
381 {0x0a, 0x04}, /* Color Gain G1 Pixel 1 5 */
382 {0x0b, 0x04}, /* Color Gain G2 Pixel 1 0 5 */
383 {0x0c, 0x05}, /* Color Gain R Pixel 3 1 */
384 {0x0d, 0x00}, /* Color GainH Pixel */
385 {0x0e, 0x0e}, /* Global Gain */
386 {0x0f, 0x00}, /* Contrast */
387 {0x10, 0x06}, /* H&V synchro polarity */
388 {0x11, 0x06}, /* ?default */
389 {0x12, 0x06}, /* DAC scale */
390 {0x14, 0x02}, /* ?default */
391 {0x13, 0x01}, /* Validate Settings */
392};
393static const __u8 initPas202[] = {
394 0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
395 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x07, 0x03, 0x0a, /* 6 */
397 0x28, 0x1e, 0x28, 0x89, 0x30,
398 0x00, 0x00, 0x02, 0x03, 0x0f, 0x0c
399};
400static const __u8 pas202_sensor_init[][8] = {
401 {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10},
402 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
403 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
404 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x00, 0x32, 0x10},
405 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
406 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
407 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
408 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
409 {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
410 {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
411 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x10},
412 {0xb0, 0x40, 0x0e, 0x00, 0x3d, 0x00, 0x63, 0x10},
413
414 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
415 {0xa0, 0x40, 0x10, 0x08, 0x3d, 0x00, 0x63, 0x15},
416 {0xa0, 0x40, 0x02, 0x04, 0x3d, 0x00, 0x63, 0x16},
417 {0xa0, 0x40, 0x11, 0x01, 0x3d, 0x00, 0x63, 0x16},
418 {0xb0, 0x40, 0x0e, 0x00, 0x31, 0x00, 0x63, 0x16},
419 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
420 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15},
421 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16},
422};
423
424static const __u8 initTas5110[] = {
425 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
426 0x00, 0x00,
427 0x00, 0x01, 0x00, 0x46, 0x09, 0x0a, /* shift from 0x45 0x09 0x0a */
428 0x16, 0x12, 0x60, 0x86, 0x2b,
429 0x14, 0x0a, 0x02, 0x02, 0x09, 0x07
430};
431static const __u8 tas5110_sensor_init[][8] = {
432 {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
433 {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
434 {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17},
435};
436
437static const __u8 initTas5130[] = {
438 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
439 0x00, 0x00,
440 0x00, 0x01, 0x00, 0x69, 0x0c, 0x0a,
441 0x28, 0x1e, 0x60, COMP, MCK_INIT,
442 0x18, 0x10, 0x04, 0x03, 0x11, 0x0c
443};
444static const __u8 tas5130_sensor_init[][8] = {
445/* {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
446 * shutter 0x47 short exposure? */
447 {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
448 /* shutter 0x01 long exposure */
449 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
450};
451
452/* get one byte in gspca_dev->usb_buf */
453static void reg_r(struct gspca_dev *gspca_dev,
454 __u16 value)
455{
456 usb_control_msg(gspca_dev->dev,
457 usb_rcvctrlpipe(gspca_dev->dev, 0),
458 0, /* request */
459 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
460 value,
461 0, /* index */
462 gspca_dev->usb_buf, 1,
463 500);
464}
465
466static void reg_w(struct gspca_dev *gspca_dev,
467 __u16 value,
468 const __u8 *buffer,
469 int len)
470{
471#ifdef CONFIG_VIDEO_ADV_DEBUG
472 if (len > sizeof gspca_dev->usb_buf) {
473 PDEBUG(D_ERR|D_PACK, "reg_w: buffer overflow");
474 return;
475 }
476#endif
477 memcpy(gspca_dev->usb_buf, buffer, len);
478 usb_control_msg(gspca_dev->dev,
479 usb_sndctrlpipe(gspca_dev->dev, 0),
480 0x08, /* request */
481 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
482 value,
483 0, /* index */
484 gspca_dev->usb_buf, len,
485 500);
486}
487
488static void reg_w_big(struct gspca_dev *gspca_dev,
489 __u16 value,
490 const __u8 *buffer,
491 int len)
492{
493 __u8 *tmpbuf;
494
495 tmpbuf = kmalloc(len, GFP_KERNEL);
496 memcpy(tmpbuf, buffer, len);
497 usb_control_msg(gspca_dev->dev,
498 usb_sndctrlpipe(gspca_dev->dev, 0),
499 0x08, /* request */
500 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
501 value,
502 0, /* index */
503 tmpbuf, len,
504 500);
505 kfree(tmpbuf);
506}
507
508static int i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
509{
510 int retry = 60;
511
512 /* is i2c ready */
513 reg_w(gspca_dev, 0x08, buffer, 8);
514 while (retry--) {
515 msleep(10);
516 reg_r(gspca_dev, 0x08);
517 if (gspca_dev->usb_buf[0] & 0x04) {
518 if (gspca_dev->usb_buf[0] & 0x08)
519 return -1;
520 return 0;
521 }
522 }
523 return -1;
524}
525
526static void i2c_w_vector(struct gspca_dev *gspca_dev,
527 const __u8 buffer[][8], int len)
528{
529 for (;;) {
530 reg_w(gspca_dev, 0x08, *buffer, 8);
531 len -= 8;
532 if (len <= 0)
533 break;
534 buffer++;
535 }
536}
537
538static void setbrightness(struct gspca_dev *gspca_dev)
539{
540 struct sd *sd = (struct sd *) gspca_dev;
541 __u8 value;
542
543 switch (sd->sensor) {
544 case SENSOR_OV6650:
545 case SENSOR_OV7630_3:
546 case SENSOR_OV7630: {
547 __u8 i2cOV[] =
548 {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
549
550 /* change reg 0x06 */
551 i2cOV[1] = sd->sensor_addr;
552 i2cOV[3] = sd->brightness;
553 if (i2c_w(gspca_dev, i2cOV) < 0)
554 goto err;
555 break;
556 }
557 case SENSOR_PAS106: {
558 __u8 i2c1[] =
559 {0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14};
560
561 i2c1[3] = sd->brightness >> 3;
562 i2c1[2] = 0x0e;
563 if (i2c_w(gspca_dev, i2c1) < 0)
564 goto err;
565 i2c1[3] = 0x01;
566 i2c1[2] = 0x13;
567 if (i2c_w(gspca_dev, i2c1) < 0)
568 goto err;
569 break;
570 }
571 case SENSOR_PAS202: {
572 /* __u8 i2cpexpo1[] =
573 {0xb0, 0x40, 0x04, 0x07, 0x2a, 0x00, 0x63, 0x16}; */
574 __u8 i2cpexpo[] =
575 {0xb0, 0x40, 0x0e, 0x01, 0xab, 0x00, 0x63, 0x16};
576 __u8 i2cp202[] =
577 {0xa0, 0x40, 0x10, 0x0e, 0x31, 0x00, 0x63, 0x15};
578 static __u8 i2cpdoit[] =
579 {0xa0, 0x40, 0x11, 0x01, 0x31, 0x00, 0x63, 0x16};
580
581 /* change reg 0x10 */
582 i2cpexpo[4] = 0xff - sd->brightness;
583/* if(i2c_w(gspca_dev,i2cpexpo1) < 0)
584 goto err; */
585/* if(i2c_w(gspca_dev,i2cpdoit) < 0)
586 goto err; */
587 if (i2c_w(gspca_dev, i2cpexpo) < 0)
588 goto err;
589 if (i2c_w(gspca_dev, i2cpdoit) < 0)
590 goto err;
591 i2cp202[3] = sd->brightness >> 3;
592 if (i2c_w(gspca_dev, i2cp202) < 0)
593 goto err;
594 if (i2c_w(gspca_dev, i2cpdoit) < 0)
595 goto err;
596 break;
597 }
598 case SENSOR_TAS5130CXX: {
599 __u8 i2c[] =
600 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
601
602 value = 0xff - sd->brightness;
603 i2c[4] = value;
604 PDEBUG(D_CONF, "brightness %d : %d", value, i2c[4]);
605 if (i2c_w(gspca_dev, i2c) < 0)
606 goto err;
607 break;
608 }
609 case SENSOR_TAS5110:
610 /* FIXME figure out howto control brightness on TAS5110 */
611 break;
612 }
613 return;
614err:
615 PDEBUG(D_ERR, "i2c error brightness");
616}
617
618static void setsensorgain(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 unsigned char gain = sd->gain;
622
623 switch (sd->sensor) {
624
625 case SENSOR_TAS5110: {
626 __u8 i2c[] =
627 {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
628
629 i2c[4] = 255 - gain;
630 if (i2c_w(gspca_dev, i2c) < 0)
631 goto err;
632 break;
633 }
634
635 case SENSOR_OV6650:
636 gain >>= 1;
637 /* fall thru */
638 case SENSOR_OV7630_3: {
639 __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
640
641 i2c[1] = sd->sensor_addr;
642 i2c[3] = gain >> 2;
643 if (i2c_w(gspca_dev, i2c) < 0)
644 goto err;
645 break;
646 }
647 }
648 return;
649err:
650 PDEBUG(D_ERR, "i2c error gain");
651}
652
653static void setgain(struct gspca_dev *gspca_dev)
654{
655 struct sd *sd = (struct sd *) gspca_dev;
656 __u8 gain;
657 __u8 rgb_value;
658
659 gain = sd->gain >> 4;
660
661 /* red and blue gain */
662 rgb_value = gain << 4 | gain;
663 reg_w(gspca_dev, 0x10, &rgb_value, 1);
664 /* green gain */
665 rgb_value = gain;
666 reg_w(gspca_dev, 0x11, &rgb_value, 1);
667
668 if (sd->sensor_has_gain)
669 setsensorgain(gspca_dev);
670}
671
672static void setexposure(struct gspca_dev *gspca_dev)
673{
674 struct sd *sd = (struct sd *) gspca_dev;
675
676 switch (sd->sensor) {
677 case SENSOR_TAS5110: {
678 __u8 reg;
679
680 /* register 19's high nibble contains the sn9c10x clock divider
681 The high nibble configures the no fps according to the
682 formula: 60 / high_nibble. With a maximum of 30 fps */
683 reg = 120 * sd->exposure / 1000;
684 if (reg < 2)
685 reg = 2;
686 else if (reg > 15)
687 reg = 15;
688 reg = (reg << 4) | 0x0b;
689 reg_w(gspca_dev, 0x19, &reg, 1);
690 break;
691 }
692 case SENSOR_OV6650:
693 case SENSOR_OV7630_3: {
694 /* The ov6650 / ov7630 have 2 registers which both influence
695 exposure, register 11, whose low nibble sets the nr off fps
696 according to: fps = 30 / (low_nibble + 1)
697
698 The fps configures the maximum exposure setting, but it is
699 possible to use less exposure then what the fps maximum
700 allows by setting register 10. register 10 configures the
701 actual exposure as quotient of the full exposure, with 0
702 being no exposure at all (not very usefull) and reg10_max
703 being max exposure possible at that framerate.
704
705 The code maps our 0 - 510 ms exposure ctrl to these 2
706 registers, trying to keep fps as high as possible.
707 */
708 __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0xc0, 0x00, 0x00, 0x10};
709 int reg10, reg11;
710 /* ov6645 datasheet says reg10_max is 9a, but that uses
711 tline * 2 * reg10 as formula for calculating texpo, the
712 ov6650 probably uses the same formula as the 7730 which uses
713 tline * 4 * reg10, which explains why the reg10max we've
714 found experimentally for the ov6650 is exactly half that of
715 the ov6645. The ov7630 datasheet says the max is 0x41. */
716 const int reg10_max = (sd->sensor == SENSOR_OV6650)
717 ? 0x4d : 0x41;
718
719 reg11 = (60 * sd->exposure + 999) / 1000;
720 if (reg11 < 1)
721 reg11 = 1;
722 else if (reg11 > 16)
723 reg11 = 16;
724
725 /* frame exposure time in ms = 1000 * reg11 / 30 ->
726 reg10 = sd->exposure * 2 * reg10_max / (1000 * reg11 / 30) */
727 reg10 = (sd->exposure * 60 * reg10_max) / (1000 * reg11);
728
729 /* Don't allow this to get below 10 when using autogain, the
730 steps become very large (relatively) when below 10 causing
731 the image to oscilate from much too dark, to much too bright
732 and back again. */
733 if (sd->autogain && reg10 < 10)
734 reg10 = 10;
735 else if (reg10 > reg10_max)
736 reg10 = reg10_max;
737
738 /* Write reg 10 and reg11 low nibble */
739 i2c[1] = sd->sensor_addr;
740 i2c[3] = reg10;
741 i2c[4] |= reg11 - 1;
742 if (sd->sensor == SENSOR_OV7630_3) {
743 __u8 reg76 = reg10 & 0x03;
744 __u8 i2c_reg76[] = {0xa0, 0x21, 0x76, 0x00,
745 0x00, 0x00, 0x00, 0x10};
746 reg10 >>= 2;
747 i2c_reg76[3] = reg76;
748 if (i2c_w(gspca_dev, i2c_reg76) < 0)
749 PDEBUG(D_ERR, "i2c error exposure");
750 }
751 if (i2c_w(gspca_dev, i2c) < 0)
752 PDEBUG(D_ERR, "i2c error exposure");
753 break;
754 }
755 }
756}
757
758static void setfreq(struct gspca_dev *gspca_dev)
759{
760 struct sd *sd = (struct sd *) gspca_dev;
761
762 switch (sd->sensor) {
763 case SENSOR_OV6650:
764 case SENSOR_OV7630_3: {
765 /* Framerate adjust register for artificial light 50 hz flicker
766 compensation, identical to ov6630 0x2b register, see ov6630
767 datasheet.
768 0x4f -> (30 fps -> 25 fps), 0x00 -> no adjustment */
769 __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
770 switch (sd->freq) {
771 default:
772/* case 0: * no filter*/
773/* case 2: * 60 hz */
774 i2c[3] = 0;
775 break;
776 case 1: /* 50 hz */
777 i2c[3] = (sd->sensor == SENSOR_OV6650)
778 ? 0x4f : 0x8a;
779 break;
780 }
781 i2c[1] = sd->sensor_addr;
782 if (i2c_w(gspca_dev, i2c) < 0)
783 PDEBUG(D_ERR, "i2c error setfreq");
784 break;
785 }
786 }
787}
788
789static void setsaturation(struct gspca_dev *gspca_dev)
790{
791 struct sd *sd = (struct sd *) gspca_dev;
792
793 switch (sd->sensor) {
794/* case SENSOR_OV6650: */
795 case SENSOR_OV7630_3:
796 case SENSOR_OV7630: {
797 __u8 i2c[] = {0xa0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10};
798 i2c[1] = sd->sensor_addr;
799 i2c[3] = sd->saturation & 0xf0;
800 if (i2c_w(gspca_dev, i2c) < 0)
801 PDEBUG(D_ERR, "i2c error setsaturation");
802 else
803 PDEBUG(D_CONF, "saturation set to: %d",
804 (int)sd->saturation);
805 break;
806 }
807 }
808}
809
810static void sethue(struct gspca_dev *gspca_dev)
811{
812 struct sd *sd = (struct sd *) gspca_dev;
813
814 switch (sd->sensor) {
815/* case SENSOR_OV6650: */
816 case SENSOR_OV7630_3:
817 case SENSOR_OV7630: {
818 __u8 i2c[] = {0xa0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10};
819 i2c[1] = sd->sensor_addr;
820 i2c[3] = 0x20 | (sd->hue >> 3);
821 if (i2c_w(gspca_dev, i2c) < 0)
822 PDEBUG(D_ERR, "i2c error setsaturation");
823 else
824 PDEBUG(D_CONF, "hue set to: %d", (int)sd->hue);
825 break;
826 }
827 }
828}
829
830static void setcontrast(struct gspca_dev *gspca_dev)
831{
832 struct sd *sd = (struct sd *) gspca_dev;
833
834 switch (sd->sensor) {
835/* case SENSOR_OV6650: */
836 case SENSOR_OV7630_3:
837 case SENSOR_OV7630: {
838 __u8 i2c[] = {0xa0, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10};
839 i2c[1] = sd->sensor_addr;
840 i2c[3] = 0x20 | (sd->contrast >> 3);
841 if (i2c_w(gspca_dev, i2c) < 0)
842 PDEBUG(D_ERR, "i2c error setcontrast");
843 else
844 PDEBUG(D_CONF, "contrast set to: %d",
845 (int)sd->contrast);
846 break;
847 }
848 }
849}
850
851
852static void do_autogain(struct gspca_dev *gspca_dev)
853{
854 struct sd *sd = (struct sd *) gspca_dev;
855 int avg_lum = atomic_read(&sd->avg_lum);
856
857 if (avg_lum == -1)
858 return;
859
860 if (sd->autogain_ignore_frames > 0)
861 sd->autogain_ignore_frames--;
862 else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
863 sd->brightness * DESIRED_AVG_LUM / 127,
864 AUTOGAIN_DEADZONE, GAIN_KNEE, EXPOSURE_KNEE)) {
865 PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d\n",
866 (int)sd->gain, (int)sd->exposure);
867 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
868 }
869}
870
871/* this function is called at probe time */
872static int sd_config(struct gspca_dev *gspca_dev,
873 const struct usb_device_id *id)
874{
875 struct sd *sd = (struct sd *) gspca_dev;
876 struct cam *cam;
877 __u16 product;
878 int sif = 0;
879
880 /* nctrls depends upon the sensor, so we use a per cam copy */
881 memcpy(&sd->sd_desc, gspca_dev->sd_desc, sizeof(struct sd_desc));
882 gspca_dev->sd_desc = &sd->sd_desc;
883
884 sd->fr_h_sz = 12; /* default size of the frame header */
885 sd->sd_desc.nctrls = 2; /* default nb of ctrls */
886 sd->autogain = AUTOGAIN_DEF; /* default is autogain active */
887
888 product = id->idProduct;
889/* switch (id->idVendor) { */
890/* case 0x0c45: * Sonix */
891 switch (product) {
892 case 0x6001: /* SN9C102 */
893 case 0x6005: /* SN9C101 */
894 case 0x6007: /* SN9C101 */
895 sd->sensor = SENSOR_TAS5110;
896 sd->sensor_has_gain = 1;
897 sd->sd_desc.nctrls = 4;
898 sd->sd_desc.dq_callback = do_autogain;
899 sif = 1;
900 break;
901 case 0x6009: /* SN9C101 */
902 case 0x600d: /* SN9C101 */
903 case 0x6029: /* SN9C101 */
904 sd->sensor = SENSOR_PAS106;
905 sif = 1;
906 break;
907 case 0x6011: /* SN9C101 - SN9C101G */
908 sd->sensor = SENSOR_OV6650;
909 sd->sensor_has_gain = 1;
910 sd->sensor_addr = 0x60;
911 sd->sd_desc.nctrls = 5;
912 sd->sd_desc.dq_callback = do_autogain;
913 sif = 1;
914 break;
915 case 0x6019: /* SN9C101 */
916 case 0x602c: /* SN9C102 */
917 case 0x602e: /* SN9C102 */
918 sd->sensor = SENSOR_OV7630;
919 sd->sensor_addr = 0x21;
920 break;
921 case 0x60b0: /* SN9C103 */
922 sd->sensor = SENSOR_OV7630_3;
923 sd->sensor_addr = 0x21;
924 sd->fr_h_sz = 18; /* size of frame header */
925 sd->sensor_has_gain = 1;
926 sd->sd_desc.nctrls = 8;
927 sd->sd_desc.dq_callback = do_autogain;
928 sd->autogain = 0;
929 break;
930 case 0x6024: /* SN9C102 */
931 case 0x6025: /* SN9C102 */
932 sd->sensor = SENSOR_TAS5130CXX;
933 break;
934 case 0x6028: /* SN9C102 */
935 sd->sensor = SENSOR_PAS202;
936 break;
937 case 0x602d: /* SN9C102 */
938 sd->sensor = SENSOR_HV7131R;
939 break;
940 case 0x60af: /* SN9C103 */
941 sd->sensor = SENSOR_PAS202;
942 sd->fr_h_sz = 18; /* size of frame header (?) */
943 break;
944 }
945/* break; */
946/* } */
947
948 cam = &gspca_dev->cam;
949 cam->dev_name = (char *) id->driver_info;
950 cam->epaddr = 0x01;
951 if (!sif) {
952 cam->cam_mode = vga_mode;
953 cam->nmodes = ARRAY_SIZE(vga_mode);
954 if (sd->sensor == SENSOR_OV7630_3) {
955 /* We only have 320x240 & 640x480 */
956 cam->cam_mode++;
957 cam->nmodes--;
958 }
959 } else {
960 cam->cam_mode = sif_mode;
961 cam->nmodes = ARRAY_SIZE(sif_mode);
962 }
963 sd->brightness = BRIGHTNESS_DEF;
964 sd->gain = GAIN_DEF;
965 sd->exposure = EXPOSURE_DEF;
966 sd->freq = FREQ_DEF;
967 sd->contrast = CONTRAST_DEF;
968 sd->saturation = SATURATION_DEF;
969 sd->hue = HUE_DEF;
970 if (sd->sensor == SENSOR_OV7630_3) /* jfm: from win trace */
971 reg_w(gspca_dev, 0x01, probe_ov7630, sizeof probe_ov7630);
972 return 0;
973}
974
975/* this function is called at open time */
976static int sd_open(struct gspca_dev *gspca_dev)
977{
978 reg_r(gspca_dev, 0x00);
979 if (gspca_dev->usb_buf[0] != 0x10)
980 return -ENODEV;
981 return 0;
982}
983
984static void pas106_i2cinit(struct gspca_dev *gspca_dev)
985{
986 int i;
987 const __u8 *data;
988 __u8 i2c1[] = { 0xa1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 };
989
990 i = ARRAY_SIZE(pas106_data);
991 data = pas106_data[0];
992 while (--i >= 0) {
993 memcpy(&i2c1[2], data, 2);
994 /* copy 2 bytes from the template */
995 if (i2c_w(gspca_dev, i2c1) < 0)
996 PDEBUG(D_ERR, "i2c error pas106");
997 data += 2;
998 }
999}
1000
1001/* -- start the camera -- */
1002static void sd_start(struct gspca_dev *gspca_dev)
1003{
1004 struct sd *sd = (struct sd *) gspca_dev;
1005 int mode, l;
1006 const __u8 *sn9c10x;
1007 __u8 reg01, reg17;
1008 __u8 reg17_19[3];
1009
1010 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1011 switch (sd->sensor) {
1012 case SENSOR_HV7131R:
1013 sn9c10x = initHv7131;
1014 reg17_19[0] = 0x60;
1015 reg17_19[1] = (mode << 4) | 0x8a;
1016 reg17_19[2] = 0x20;
1017 break;
1018 case SENSOR_OV6650:
1019 sn9c10x = initOv6650;
1020 reg17_19[0] = 0x68;
1021 reg17_19[1] = (mode << 4) | 0x8b;
1022 reg17_19[2] = 0x20;
1023 break;
1024 case SENSOR_OV7630:
1025 sn9c10x = initOv7630;
1026 reg17_19[0] = 0x68;
1027 reg17_19[1] = (mode << 4) | COMP2;
1028 reg17_19[2] = MCK_INIT1;
1029 break;
1030 case SENSOR_OV7630_3:
1031 sn9c10x = initOv7630_3;
1032 reg17_19[0] = 0x68;
1033 reg17_19[1] = (mode << 4) | COMP2;
1034 reg17_19[2] = MCK_INIT1;
1035 break;
1036 case SENSOR_PAS106:
1037 sn9c10x = initPas106;
1038 reg17_19[0] = 0x24; /* 0x28 */
1039 reg17_19[1] = (mode << 4) | COMP1;
1040 reg17_19[2] = MCK_INIT1;
1041 break;
1042 case SENSOR_PAS202:
1043 sn9c10x = initPas202;
1044 reg17_19[0] = mode ? 0x24 : 0x20;
1045 reg17_19[1] = (mode << 4) | 0x89;
1046 reg17_19[2] = 0x20;
1047 break;
1048 case SENSOR_TAS5110:
1049 sn9c10x = initTas5110;
1050 reg17_19[0] = 0x60;
1051 reg17_19[1] = (mode << 4) | 0x86;
1052 reg17_19[2] = 0x2b; /* 0xf3; */
1053 break;
1054 default:
1055/* case SENSOR_TAS5130CXX: */
1056 sn9c10x = initTas5130;
1057 reg17_19[0] = 0x60;
1058 reg17_19[1] = (mode << 4) | COMP;
1059 reg17_19[2] = mode ? 0x23 : 0x43;
1060 break;
1061 }
1062 switch (sd->sensor) {
1063 case SENSOR_OV7630:
1064 reg01 = 0x06;
1065 reg17 = 0x29;
1066 l = sizeof initOv7630;
1067 break;
1068 case SENSOR_OV7630_3:
1069 reg01 = 0x44;
1070 reg17 = 0x68;
1071 l = sizeof initOv7630_3;
1072 break;
1073 default:
1074 reg01 = sn9c10x[0];
1075 reg17 = sn9c10x[0x17 - 1];
1076 l = 0x1f;
1077 break;
1078 }
1079
1080 /* reg 0x01 bit 2 video transfert on */
1081 reg_w(gspca_dev, 0x01, &reg01, 1);
1082 /* reg 0x17 SensorClk enable inv Clk 0x60 */
1083 reg_w(gspca_dev, 0x17, &reg17, 1);
1084/*fixme: for ov7630 102
1085 reg_w(gspca_dev, 0x01, {0x06, sn9c10x[1]}, 2); */
1086 /* Set the registers from the template */
1087 reg_w_big(gspca_dev, 0x01, sn9c10x, l);
1088 switch (sd->sensor) {
1089 case SENSOR_HV7131R:
1090 i2c_w_vector(gspca_dev, hv7131_sensor_init,
1091 sizeof hv7131_sensor_init);
1092 break;
1093 case SENSOR_OV6650:
1094 i2c_w_vector(gspca_dev, ov6650_sensor_init,
1095 sizeof ov6650_sensor_init);
1096 break;
1097 case SENSOR_OV7630:
1098 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1099 sizeof ov7630_sensor_init_com);
1100 msleep(200);
1101 i2c_w_vector(gspca_dev, ov7630_sensor_init,
1102 sizeof ov7630_sensor_init);
1103 break;
1104 case SENSOR_OV7630_3:
1105 i2c_w_vector(gspca_dev, ov7630_sensor_init_com,
1106 sizeof ov7630_sensor_init_com);
1107 msleep(200);
1108 i2c_w(gspca_dev, ov7630_sensor_init_3[mode]);
1109 break;
1110 case SENSOR_PAS106:
1111 pas106_i2cinit(gspca_dev);
1112 break;
1113 case SENSOR_PAS202:
1114 i2c_w_vector(gspca_dev, pas202_sensor_init,
1115 sizeof pas202_sensor_init);
1116 break;
1117 case SENSOR_TAS5110:
1118 i2c_w_vector(gspca_dev, tas5110_sensor_init,
1119 sizeof tas5110_sensor_init);
1120 break;
1121 default:
1122/* case SENSOR_TAS5130CXX: */
1123 i2c_w_vector(gspca_dev, tas5130_sensor_init,
1124 sizeof tas5130_sensor_init);
1125 break;
1126 }
1127 /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
1128 reg_w(gspca_dev, 0x15, &sn9c10x[0x15 - 1], 2);
1129 /* compression register */
1130 reg_w(gspca_dev, 0x18, &reg17_19[1], 1);
1131 /* H_start */
1132 reg_w(gspca_dev, 0x12, &sn9c10x[0x12 - 1], 1);
1133 /* V_START */
1134 reg_w(gspca_dev, 0x13, &sn9c10x[0x13 - 1], 1);
1135 /* reset 0x17 SensorClk enable inv Clk 0x60 */
1136 /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
1137 reg_w(gspca_dev, 0x17, &reg17_19[0], 1);
1138 /*MCKSIZE ->3 */ /*fixme: not ov7630*/
1139 reg_w(gspca_dev, 0x19, &reg17_19[2], 1);
1140 /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
1141 reg_w(gspca_dev, 0x1c, &sn9c10x[0x1c - 1], 4);
1142 /* Enable video transfert */
1143 reg_w(gspca_dev, 0x01, &sn9c10x[0], 1);
1144 /* Compression */
1145 reg_w(gspca_dev, 0x18, &reg17_19[1], 2);
1146 msleep(20);
1147
1148 setgain(gspca_dev);
1149 setbrightness(gspca_dev);
1150 setexposure(gspca_dev);
1151 setfreq(gspca_dev);
1152 setsaturation(gspca_dev);
1153 sethue(gspca_dev);
1154 setcontrast(gspca_dev);
1155
1156 sd->autogain_ignore_frames = 0;
1157 atomic_set(&sd->avg_lum, -1);
1158}
1159
1160static void sd_stopN(struct gspca_dev *gspca_dev)
1161{
1162 __u8 ByteSend;
1163
1164 ByteSend = 0x09; /* 0X00 */
1165 reg_w(gspca_dev, 0x01, &ByteSend, 1);
1166}
1167
1168static void sd_stop0(struct gspca_dev *gspca_dev)
1169{
1170}
1171
1172static void sd_close(struct gspca_dev *gspca_dev)
1173{
1174}
1175
1176static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1177 struct gspca_frame *frame, /* target */
1178 unsigned char *data, /* isoc packet */
1179 int len) /* iso packet length */
1180{
1181 int i;
1182 struct sd *sd = (struct sd *) gspca_dev;
1183
1184 /* frames start with:
1185 * ff ff 00 c4 c4 96 synchro
1186 * 00 (unknown)
1187 * xx (frame sequence / size / compression)
1188 * (xx) (idem - extra byte for sn9c103)
1189 * ll mm brightness sum inside auto exposure
1190 * ll mm brightness sum outside auto exposure
1191 * (xx xx xx xx xx) audio values for snc103
1192 */
1193 if (len > 6 && len < 24) {
1194 for (i = 0; i < len - 6; i++) {
1195 if (data[0 + i] == 0xff
1196 && data[1 + i] == 0xff
1197 && data[2 + i] == 0x00
1198 && data[3 + i] == 0xc4
1199 && data[4 + i] == 0xc4
1200 && data[5 + i] == 0x96) { /* start of frame */
1201 frame = gspca_frame_add(gspca_dev, LAST_PACKET,
1202 frame, data, 0);
1203 if (len - i < sd->fr_h_sz) {
1204 atomic_set(&sd->avg_lum, -1);
1205 PDEBUG(D_STREAM, "packet too short to"
1206 " get avg brightness");
1207 } else if (sd->fr_h_sz == 12) {
1208 atomic_set(&sd->avg_lum,
1209 data[i + 8] +
1210 (data[i + 9] << 8));
1211 } else {
1212 atomic_set(&sd->avg_lum,
1213 data[i + 9] +
1214 (data[i + 10] << 8));
1215 }
1216 data += i + sd->fr_h_sz;
1217 len -= i + sd->fr_h_sz;
1218 gspca_frame_add(gspca_dev, FIRST_PACKET,
1219 frame, data, len);
1220 return;
1221 }
1222 }
1223 }
1224 gspca_frame_add(gspca_dev, INTER_PACKET,
1225 frame, data, len);
1226}
1227
1228static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1229{
1230 struct sd *sd = (struct sd *) gspca_dev;
1231
1232 sd->brightness = val;
1233 if (gspca_dev->streaming)
1234 setbrightness(gspca_dev);
1235 return 0;
1236}
1237
1238static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1239{
1240 struct sd *sd = (struct sd *) gspca_dev;
1241
1242 *val = sd->brightness;
1243 return 0;
1244}
1245
1246static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
1247{
1248 struct sd *sd = (struct sd *) gspca_dev;
1249
1250 sd->gain = val;
1251 if (gspca_dev->streaming)
1252 setgain(gspca_dev);
1253 return 0;
1254}
1255
1256static int sd_getgain(struct gspca_dev *gspca_dev, __s32 *val)
1257{
1258 struct sd *sd = (struct sd *) gspca_dev;
1259
1260 *val = sd->gain;
1261 return 0;
1262}
1263
1264static int sd_setexposure(struct gspca_dev *gspca_dev, __s32 val)
1265{
1266 struct sd *sd = (struct sd *) gspca_dev;
1267
1268 sd->exposure = val;
1269 if (gspca_dev->streaming)
1270 setexposure(gspca_dev);
1271 return 0;
1272}
1273
1274static int sd_getexposure(struct gspca_dev *gspca_dev, __s32 *val)
1275{
1276 struct sd *sd = (struct sd *) gspca_dev;
1277
1278 *val = sd->exposure;
1279 return 0;
1280}
1281
1282static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1283{
1284 struct sd *sd = (struct sd *) gspca_dev;
1285
1286 sd->autogain = val;
1287 /* when switching to autogain set defaults to make sure
1288 we are on a valid point of the autogain gain /
1289 exposure knee graph, and give this change time to
1290 take effect before doing autogain. */
1291 if (sd->autogain) {
1292 sd->exposure = EXPOSURE_DEF;
1293 sd->gain = GAIN_DEF;
1294 if (gspca_dev->streaming) {
1295 sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
1296 setexposure(gspca_dev);
1297 setgain(gspca_dev);
1298 }
1299 }
1300
1301 return 0;
1302}
1303
1304static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1305{
1306 struct sd *sd = (struct sd *) gspca_dev;
1307
1308 *val = sd->autogain;
1309 return 0;
1310}
1311
1312static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1313{
1314 struct sd *sd = (struct sd *) gspca_dev;
1315
1316 sd->freq = val;
1317 if (gspca_dev->streaming)
1318 setfreq(gspca_dev);
1319 return 0;
1320}
1321
1322static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1323{
1324 struct sd *sd = (struct sd *) gspca_dev;
1325
1326 *val = sd->freq;
1327 return 0;
1328}
1329
1330static int sd_setsaturation(struct gspca_dev *gspca_dev, __s32 val)
1331{
1332 struct sd *sd = (struct sd *) gspca_dev;
1333
1334 sd->saturation = val;
1335 if (gspca_dev->streaming)
1336 setsaturation(gspca_dev);
1337 return 0;
1338}
1339
1340static int sd_getsaturation(struct gspca_dev *gspca_dev, __s32 *val)
1341{
1342 struct sd *sd = (struct sd *) gspca_dev;
1343
1344 *val = sd->saturation;
1345 return 0;
1346}
1347
1348static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
1349{
1350 struct sd *sd = (struct sd *) gspca_dev;
1351
1352 sd->hue = val;
1353 if (gspca_dev->streaming)
1354 sethue(gspca_dev);
1355 return 0;
1356}
1357
1358static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
1359{
1360 struct sd *sd = (struct sd *) gspca_dev;
1361
1362 *val = sd->hue;
1363 return 0;
1364}
1365
1366static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1367{
1368 struct sd *sd = (struct sd *) gspca_dev;
1369
1370 sd->contrast = val;
1371 if (gspca_dev->streaming)
1372 setcontrast(gspca_dev);
1373 return 0;
1374}
1375
1376static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1377{
1378 struct sd *sd = (struct sd *) gspca_dev;
1379
1380 *val = sd->contrast;
1381 return 0;
1382}
1383
1384static int sd_querymenu(struct gspca_dev *gspca_dev,
1385 struct v4l2_querymenu *menu)
1386{
1387 switch (menu->id) {
1388 case V4L2_CID_POWER_LINE_FREQUENCY:
1389 switch (menu->index) {
1390 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1391 strcpy((char *) menu->name, "NoFliker");
1392 return 0;
1393 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1394 strcpy((char *) menu->name, "50 Hz");
1395 return 0;
1396 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1397 strcpy((char *) menu->name, "60 Hz");
1398 return 0;
1399 }
1400 break;
1401 }
1402 return -EINVAL;
1403}
1404
1405/* sub-driver description */
1406static const struct sd_desc sd_desc = {
1407 .name = MODULE_NAME,
1408 .ctrls = sd_ctrls,
1409 .nctrls = ARRAY_SIZE(sd_ctrls),
1410 .config = sd_config,
1411 .open = sd_open,
1412 .start = sd_start,
1413 .stopN = sd_stopN,
1414 .stop0 = sd_stop0,
1415 .close = sd_close,
1416 .pkt_scan = sd_pkt_scan,
1417 .querymenu = sd_querymenu,
1418};
1419
1420/* -- module initialisation -- */
1421#define DVNM(name) .driver_info = (kernel_ulong_t) name
1422static __devinitdata struct usb_device_id device_table[] = {
1423#ifndef CONFIG_USB_SN9C102
1424 {USB_DEVICE(0x0c45, 0x6001), DVNM("Genius VideoCAM NB")},
1425 {USB_DEVICE(0x0c45, 0x6005), DVNM("Sweex Tas5110")},
1426 {USB_DEVICE(0x0c45, 0x6007), DVNM("Sonix sn9c101 + Tas5110D")},
1427 {USB_DEVICE(0x0c45, 0x6009), DVNM("spcaCam@120")},
1428 {USB_DEVICE(0x0c45, 0x600d), DVNM("spcaCam@120")},
1429#endif
1430 {USB_DEVICE(0x0c45, 0x6011), DVNM("MAX Webcam Microdia")},
1431#ifndef CONFIG_USB_SN9C102
1432 {USB_DEVICE(0x0c45, 0x6019), DVNM("Generic Sonix OV7630")},
1433 {USB_DEVICE(0x0c45, 0x6024), DVNM("Generic Sonix Tas5130c")},
1434 {USB_DEVICE(0x0c45, 0x6025), DVNM("Xcam Shanga")},
1435 {USB_DEVICE(0x0c45, 0x6028), DVNM("Sonix Btc Pc380")},
1436 {USB_DEVICE(0x0c45, 0x6029), DVNM("spcaCam@150")},
1437 {USB_DEVICE(0x0c45, 0x602c), DVNM("Generic Sonix OV7630")},
1438 {USB_DEVICE(0x0c45, 0x602d), DVNM("LIC-200 LG")},
1439 {USB_DEVICE(0x0c45, 0x602e), DVNM("Genius VideoCam Messenger")},
1440 {USB_DEVICE(0x0c45, 0x60af), DVNM("Trust WB3100P")},
1441 {USB_DEVICE(0x0c45, 0x60b0), DVNM("Genius VideoCam Look")},
1442#endif
1443 {}
1444};
1445MODULE_DEVICE_TABLE(usb, device_table);
1446
1447/* -- device connect -- */
1448static int sd_probe(struct usb_interface *intf,
1449 const struct usb_device_id *id)
1450{
1451 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1452 THIS_MODULE);
1453}
1454
1455static struct usb_driver sd_driver = {
1456 .name = MODULE_NAME,
1457 .id_table = device_table,
1458 .probe = sd_probe,
1459 .disconnect = gspca_disconnect,
1460};
1461
1462/* -- module insert / remove -- */
1463static int __init sd_mod_init(void)
1464{
1465 if (usb_register(&sd_driver) < 0)
1466 return -1;
1467 PDEBUG(D_PROBE, "v%s registered", version);
1468 return 0;
1469}
1470static void __exit sd_mod_exit(void)
1471{
1472 usb_deregister(&sd_driver);
1473 PDEBUG(D_PROBE, "deregistered");
1474}
1475
1476module_init(sd_mod_init);
1477module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
new file mode 100644
index 000000000000..3e68b9926956
--- /dev/null
+++ b/drivers/media/video/gspca/sonixj.c
@@ -0,0 +1,1671 @@
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"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
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
38 int avg_lum;
39 unsigned int exposure;
40
41 unsigned short brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 signed char ag_cnt;
47#define AG_CNT_START 13
48
49 char qindex;
50 unsigned char bridge;
51#define BRIDGE_SN9C102P 0
52#define BRIDGE_SN9C105 1
53#define BRIDGE_SN9C110 2
54#define BRIDGE_SN9C120 3
55#define BRIDGE_SN9C325 4
56 char sensor; /* Type of image sensor chip */
57#define SENSOR_HV7131R 0
58#define SENSOR_MI0360 1
59#define SENSOR_MO4000 2
60#define SENSOR_OV7648 3
61#define SENSOR_OV7660 4
62 unsigned char i2c_base;
63};
64
65/* V4L2 controls supported by the driver */
66static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
67static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
68static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
69static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
70static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
71static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
72static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
73static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
74
75static struct ctrl sd_ctrls[] = {
76 {
77 {
78 .id = V4L2_CID_BRIGHTNESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Brightness",
81 .minimum = 0,
82 .maximum = 0xffff,
83 .step = 1,
84#define BRIGHTNESS_DEF 0x7fff
85 .default_value = BRIGHTNESS_DEF,
86 },
87 .set = sd_setbrightness,
88 .get = sd_getbrightness,
89 },
90 {
91 {
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
96 .maximum = 127,
97 .step = 1,
98#define CONTRAST_DEF 63
99 .default_value = CONTRAST_DEF,
100 },
101 .set = sd_setcontrast,
102 .get = sd_getcontrast,
103 },
104 {
105 {
106 .id = V4L2_CID_SATURATION,
107 .type = V4L2_CTRL_TYPE_INTEGER,
108 .name = "Color",
109 .minimum = 0,
110 .maximum = 255,
111 .step = 1,
112#define COLOR_DEF 127
113 .default_value = COLOR_DEF,
114 },
115 .set = sd_setcolors,
116 .get = sd_getcolors,
117 },
118 {
119 {
120 .id = V4L2_CID_AUTOGAIN,
121 .type = V4L2_CTRL_TYPE_BOOLEAN,
122 .name = "Auto Gain",
123 .minimum = 0,
124 .maximum = 1,
125 .step = 1,
126#define AUTOGAIN_DEF 1
127 .default_value = AUTOGAIN_DEF,
128 },
129 .set = sd_setautogain,
130 .get = sd_getautogain,
131 },
132};
133
134static struct v4l2_pix_format vga_mode[] = {
135 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 160,
137 .sizeimage = 160 * 120 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 2},
140 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
141 .bytesperline = 320,
142 .sizeimage = 320 * 240 * 3 / 8 + 590,
143 .colorspace = V4L2_COLORSPACE_JPEG,
144 .priv = 1},
145 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
146 .bytesperline = 640,
147 .sizeimage = 640 * 480 * 3 / 8 + 590,
148 .colorspace = V4L2_COLORSPACE_JPEG,
149 .priv = 0},
150};
151
152/*Data from sn9c102p+hv71331r */
153static const __u8 sn_hv7131[] = {
154/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
155 0x00, 0x03, 0x64, 0x00, 0x1A, 0x20, 0x20, 0x20, 0xA1, 0x11,
156/* rega regb regc regd rege regf reg10 reg11 */
157 0x02, 0x09, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, /* 00 */
158/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
159 0x00, 0x01, 0x03, 0x28, 0x1e, 0x41, 0x0a, 0x00, 0x00, 0x00,
160/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
162};
163
164static const __u8 sn_mi0360[] = {
165/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 */
166 0x00, 0x61, 0x44, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xb1, 0x5d,
167/* rega regb regc regd rege regf reg10 reg11 */
168 0x07, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
169/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a reg1b */
170 0x00, 0x02, 0x0a, 0x28, 0x1e, 0x61, 0x06, 0x00, 0x00, 0x00,
171/* reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23 */
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
173};
174
175static const __u8 sn_mo4000[] = {
176/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
177 0x12, 0x23, 0x60, 0x00, 0x1A, 0x00, 0x20, 0x18, 0x81,
178/* reg9 rega regb regc regd rege regf reg10 reg11*/
179 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
180/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
181 0x0b, 0x0f, 0x14, 0x28, 0x1e, 0x40, 0x08, 0x00, 0x00,
182/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x39, 0x4b,
184 0x5c, 0x6b, 0x79, 0x87, 0x95, 0xa2, 0xaf, 0xbb, 0xc7,
185 0xd3, 0xdf, 0xea, 0xf5
186};
187
188static const __u8 sn_ov7648[] = {
189 0x00, 0x21, 0x62, 0x00, 0x1a, 0x20, 0x20, 0x20, 0xA1, 0x6E, 0x18, 0x65,
190 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x06, 0x06, 0x28, 0x1E, 0x82,
191 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
192};
193
194static const __u8 sn_ov7660[] = {
195/* reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 */
196 0x00, 0x61, 0x40, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x81,
197/* reg9 rega regb regc regd rege regf reg10 reg11*/
198 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
199/* reg12 reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg1a*/
200 0x01, 0x01, 0x14, 0x28, 0x1e, 0x00, 0x07, 0x00, 0x00,
201/* reg1b reg1c reg1d reg1e reg1f reg20 reg21 reg22 reg23*/
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
203};
204
205/* sequence specific to the sensors - !! index = SENSOR_xxx */
206static const __u8 *sn_tb[] = {
207 sn_hv7131,
208 sn_mi0360,
209 sn_mo4000,
210 sn_ov7648,
211 sn_ov7660
212};
213
214static const __u8 regsn20[] = {
215 0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
216 0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
217};
218static const __u8 regsn20_sn9c120[] = {
219 0x00, 0x25, 0x3c, 0x50, 0x62, 0x72, 0x81, 0x90,
220 0x9e, 0xab, 0xb8, 0xc5, 0xd1, 0xdd, 0xe9, 0xf4, 0xff
221};
222static const __u8 regsn20_sn9c325[] = {
223 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
224 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
225};
226
227static const __u8 reg84[] = {
228 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
229 0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
230/* 0x00, 0x00, 0x00, 0x00, 0x00 */
231 0xf7, 0x0f, 0x0a, 0x00, 0x00
232};
233static const __u8 reg84_sn9c120_1[] = {
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x0c, 0x00, 0x00
237};
238static const __u8 reg84_sn9c120_2[] = {
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 0x00, 0x00, 0x0c, 0x02, 0x3b
242};
243static const __u8 reg84_sn9c120_3[] = {
244 0x14, 0x00, 0x27, 0x00, 0x08, 0x00, 0xeb, 0x0f,
245 0xd5, 0x0f, 0x42, 0x00, 0x41, 0x00, 0xca, 0x0f,
246 0xf5, 0x0f, 0x0c, 0x02, 0x3b
247};
248static const __u8 reg84_sn9c325[] = {
249 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
250 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
251 0xf8, 0x0f, 0x00, 0x00, 0x00
252};
253
254static const __u8 hv7131r_sensor_init[][8] = {
255 {0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
256 {0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
257 {0xD1, 0x11, 0x40, 0xFF, 0x7F, 0x7F, 0x7F, 0x10},
258 {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10},
259 {0xD1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
260 {0xD1, 0x11, 0x14, 0x01, 0xE2, 0x02, 0x82, 0x10},
261 {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
262
263 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
264 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
265 {0xC1, 0x11, 0x25, 0x00, 0x61, 0xA8, 0x00, 0x10},
266 {0xA1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
267 {0xC1, 0x11, 0x31, 0x20, 0x2E, 0x20, 0x00, 0x10},
268 {0xC1, 0x11, 0x25, 0x00, 0xC3, 0x50, 0x00, 0x10},
269 {0xA1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
270 {0xC1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
271
272 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
273 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
274 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
275 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
276 {0xA1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
277
278 {0xA1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
279 {0xA1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
280 {0xA1, 0x11, 0x21, 0xD0, 0x00, 0x00, 0x00, 0x10},
281 {0xA1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
282 {0xA1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
283 {}
284};
285static const __u8 mi0360_sensor_init[][8] = {
286 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
287 {0xB1, 0x5D, 0x0D, 0x00, 0x01, 0x00, 0x00, 0x10},
288 {0xB1, 0x5D, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x10},
289 {0xD1, 0x5D, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
290 {0xD1, 0x5D, 0x03, 0x01, 0xE2, 0x02, 0x82, 0x10},
291 {0xD1, 0x5D, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
292 {0xB1, 0x5D, 0x0D, 0x00, 0x02, 0x00, 0x00, 0x10},
293 {0xD1, 0x5D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x10},
294 {0xD1, 0x5D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10},
295 {0xD1, 0x5D, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x10},
296 {0xD1, 0x5D, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
297 {0xD1, 0x5D, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
298 {0xD1, 0x5D, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
299 {0xD1, 0x5D, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
300 {0xD1, 0x5D, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
301 {0xD1, 0x5D, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x10},
302 {0xD1, 0x5D, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x10},
303 {0xB1, 0x5D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
304 {0xD1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
305 {0xD1, 0x5D, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
306 {0xD1, 0x5D, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
307 {0xD1, 0x5D, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
308 {0xD1, 0x5D, 0x2F, 0xF7, 0xB0, 0x00, 0x04, 0x10},
309 {0xD1, 0x5D, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
310 {0xD1, 0x5D, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
311 {0xB1, 0x5D, 0x3D, 0x06, 0x8F, 0x00, 0x00, 0x10},
312 {0xD1, 0x5D, 0x40, 0x01, 0xE0, 0x00, 0xD1, 0x10},
313 {0xB1, 0x5D, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
314 {0xD1, 0x5D, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
315 {0xD1, 0x5D, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x10},
316 {0xD1, 0x5D, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x10},
317 {0xD1, 0x5D, 0x5E, 0x00, 0x00, 0xA3, 0x1D, 0x10},
318 {0xB1, 0x5D, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
319
320 {0xB1, 0x5D, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
321 {0xB1, 0x5D, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
322 {0xB1, 0x5D, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
323 {0xD1, 0x5D, 0x2B, 0x00, 0xA0, 0x00, 0xB0, 0x10},
324 {0xD1, 0x5D, 0x2D, 0x00, 0xA0, 0x00, 0xA0, 0x10},
325
326 {0xB1, 0x5D, 0x0A, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
327 {0xB1, 0x5D, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
328 {0xB1, 0x5D, 0x05, 0x00, 0x0A, 0x00, 0x00, 0x10},
329 {0xB1, 0x5D, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
330
331 {0xD1, 0x5D, 0x2B, 0x00, 0xB9, 0x00, 0xE3, 0x10},
332 {0xD1, 0x5D, 0x2D, 0x00, 0x5f, 0x00, 0xB9, 0x10}, /* 42 */
333/* {0xB1, 0x5D, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
334/* {0xB1, 0x5D, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
335 {0xB1, 0x5D, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
336 {0xB1, 0x5D, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
337 {}
338};
339static const __u8 mo4000_sensor_init[][8] = {
340 {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
341 {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
342 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
343 {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
344 {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
345 {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
346 {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
347 {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
348 {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
349 {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
350 {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
351 {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
352 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
353 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
354 {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
355 {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
356 {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
357 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
358 {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
359 {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
360 {}
361};
362static const __u8 ov7660_sensor_init[][8] = {
363 {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
364 {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
365 /* Outformat ?? rawRGB */
366 {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
367 {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
368/* {0xd1, 0x21, 0x00, 0x01, 0x74, 0x74, 0x00, 0x10}, */
369 /* GAIN BLUE RED VREF */
370 {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
371 /* COM 1 BAVE GEAVE AECHH */
372 {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
373 {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
374 {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xf8, 0x10},
375/* {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10}, */
376 /* AECH CLKRC COM7 COM8 */
377 {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
378 {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
379 /* HSTART HSTOP VSTRT VSTOP */
380 {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
381 {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
382 {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
383 /* BOS GBOS GROS ROS (BGGR offset) */
384 {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10},
385/* {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10}, */
386 /* AEW AEB VPT BBIAS */
387 {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
388 /* GbBIAS RSVD EXHCH EXHCL */
389 {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
390 /* RBIAS ADVFL ASDVFH YAVE */
391 {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
392 /* HSYST HSYEN HREF */
393 {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
394 {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
395 /* ADC ACOM OFON TSLB */
396 {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
397 /* COM11 COM12 COM13 COM14 */
398 {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
399 /* EDGE COM15 COM16 COM17 */
400 {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
401 {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
402 {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
403 {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
404 {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
405 {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
406 {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
407 {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
408 {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
409 {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
410 /* LCC1 LCC2 LCC3 LCC4 */
411 {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
412 {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10},
413 {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
414 /* band gap reference [0..3] DBLV */
415 {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
416 {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
417 {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
418 {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
419 {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
420 {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
421 {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
422 {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
423 {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
424 {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10},
425/****** (some exchanges in the win trace) ******/
426 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
427 /* bits[3..0]reserved */
428 {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
429 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
430 /* VREF vertical frame ctrl */
431 {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
432 {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* 0x20 */
433 {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
434 {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
435/* {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, */
436 {0xa1, 0x21, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10},
437 {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10},
438/****** (some exchanges in the win trace) ******/
439 {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
440 {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10},/* dummy line low */
441 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
442 {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
443 {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},
444/****** (some exchanges in the win trace) ******/
445/**********startsensor KO if changed !!****/
446 {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
447 {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
448 {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
449 {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
450/* here may start the isoc exchanges */
451 {}
452};
453/* reg0x04 reg0x07 reg 0x10 */
454/* expo = (COM1 & 0x02) | (AECHH & 0x2f <<10) [ (AECh << 2) */
455
456static const __u8 ov7648_sensor_init[][8] = {
457 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
458 {0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00},
459 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
460 {0xA1, 0x6E, 0x3F, 0x20, 0x00, 0x00, 0x00, 0x10},
461 {0xA1, 0x6E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x10},
462 {0xA1, 0x6E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x10},
463 {0xD1, 0x6E, 0x04, 0x02, 0xB1, 0x02, 0x39, 0x10},
464 {0xD1, 0x6E, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
465 {0xD1, 0x6E, 0x0C, 0x02, 0x7F, 0x01, 0xE0, 0x10},
466 {0xD1, 0x6E, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
467 {0xD1, 0x6E, 0x16, 0x85, 0x40, 0x4A, 0x40, 0x10},
468 {0xC1, 0x6E, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x10},
469 {0xD1, 0x6E, 0x1D, 0x08, 0x03, 0x00, 0x00, 0x10},
470 {0xD1, 0x6E, 0x23, 0x00, 0xB0, 0x00, 0x94, 0x10},
471 {0xD1, 0x6E, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
472 {0xD1, 0x6E, 0x2D, 0x14, 0x35, 0x61, 0x84, 0x10},
473 {0xD1, 0x6E, 0x31, 0xA2, 0xBD, 0xD8, 0xFF, 0x10},
474 {0xD1, 0x6E, 0x35, 0x06, 0x1E, 0x12, 0x02, 0x10},
475 {0xD1, 0x6E, 0x39, 0xAA, 0x53, 0x37, 0xD5, 0x10},
476 {0xA1, 0x6E, 0x3D, 0xF2, 0x00, 0x00, 0x00, 0x10},
477 {0xD1, 0x6E, 0x3E, 0x00, 0x00, 0x80, 0x03, 0x10},
478 {0xD1, 0x6E, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
479 {0xC1, 0x6E, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
480 {0xD1, 0x6E, 0x4B, 0x02, 0xEF, 0x08, 0xCD, 0x10},
481 {0xD1, 0x6E, 0x4F, 0x00, 0xD0, 0x00, 0xA0, 0x10},
482 {0xD1, 0x6E, 0x53, 0x01, 0xAA, 0x01, 0x40, 0x10},
483 {0xD1, 0x6E, 0x5A, 0x50, 0x04, 0x30, 0x03, 0x10},
484 {0xA1, 0x6E, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x10},
485 {0xD1, 0x6E, 0x5F, 0x10, 0x40, 0xFF, 0x00, 0x10},
486 /* {0xD1, 0x6E, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
487 {0xD1, 0x6E, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
488 * This is currently setting a
489 * blue tint, and some things more , i leave it here for future test if
490 * somene is having problems with color on this sensor
491 {0xD1, 0x6E, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x10},
492 {0xD1, 0x6E, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x10},
493 {0xC1, 0x6E, 0x73, 0x10, 0x80, 0xEB, 0x00, 0x10},
494 {0xA1, 0x6E, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x10},
495 {0xA1, 0x6E, 0x15, 0x01, 0x00, 0x00, 0x00, 0x10},
496 {0xC1, 0x6E, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10},
497 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
498 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
499 {0xA1, 0x6E, 0x07, 0xB5, 0x00, 0x00, 0x00, 0x10},
500 {0xA1, 0x6E, 0x18, 0x6B, 0x00, 0x00, 0x00, 0x10},
501 {0xA1, 0x6E, 0x1D, 0x08, 0x00, 0x00, 0x00, 0x10},
502 {0xA1, 0x6E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
503 {0xA1, 0x6E, 0x07, 0xB8, 0x00, 0x00, 0x00, 0x10}, */
504 {0xC1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00},
505 {0xA1, 0x6E, 0x06, 0x03, 0x00, 0x00, 0x00, 0x10}, /* Bright... */
506 {0xA1, 0x6E, 0x07, 0x66, 0x00, 0x00, 0x00, 0x10}, /* B.. */
507 {0xC1, 0x6E, 0x1A, 0x03, 0x65, 0x90, 0x00, 0x10}, /* Bright/Witen....*/
508/* {0xC1, 0x6E, 0x16, 0x45, 0x40, 0x60, 0x00, 0x10}, * Bright/Witene */
509 {}
510};
511
512static const __u8 qtable4[] = {
513 0x06, 0x04, 0x04, 0x06, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x08, 0x06,
514 0x06, 0x08, 0x0A, 0x11,
515 0x0A, 0x0A, 0x08, 0x08, 0x0A, 0x15, 0x0F, 0x0F, 0x0C, 0x11, 0x19, 0x15,
516 0x19, 0x19, 0x17, 0x15,
517 0x17, 0x17, 0x1B, 0x1D, 0x25, 0x21, 0x1B, 0x1D, 0x23, 0x1D, 0x17, 0x17,
518 0x21, 0x2E, 0x21, 0x23,
519 0x27, 0x29, 0x2C, 0x2C, 0x2C, 0x19, 0x1F, 0x30, 0x32, 0x2E, 0x29, 0x32,
520 0x25, 0x29, 0x2C, 0x29,
521 0x06, 0x08, 0x08, 0x0A, 0x08, 0x0A, 0x13, 0x0A, 0x0A, 0x13, 0x29, 0x1B,
522 0x17, 0x1B, 0x29, 0x29,
523 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
524 0x29, 0x29, 0x29, 0x29,
525 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
526 0x29, 0x29, 0x29, 0x29,
527 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
528 0x29, 0x29, 0x29, 0x29
529};
530
531/* read <len> bytes (len < sizeof gspca_dev->usb_buf) to gspca_dev->usb_buf */
532static void reg_r(struct gspca_dev *gspca_dev,
533 __u16 value, int len)
534{
535 usb_control_msg(gspca_dev->dev,
536 usb_rcvctrlpipe(gspca_dev->dev, 0),
537 0,
538 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
539 value, 0,
540 gspca_dev->usb_buf, len,
541 500);
542}
543
544static void reg_w(struct gspca_dev *gspca_dev,
545 __u16 value,
546 const __u8 *buffer,
547 int len)
548{
549 if (len <= sizeof gspca_dev->usb_buf) {
550 memcpy(gspca_dev->usb_buf, buffer, len);
551 usb_control_msg(gspca_dev->dev,
552 usb_sndctrlpipe(gspca_dev->dev, 0),
553 0x08,
554 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
555 value, 0,
556 gspca_dev->usb_buf, len,
557 500);
558 } else {
559 __u8 *tmpbuf;
560
561 tmpbuf = kmalloc(len, GFP_KERNEL);
562 memcpy(tmpbuf, buffer, len);
563 usb_control_msg(gspca_dev->dev,
564 usb_sndctrlpipe(gspca_dev->dev, 0),
565 0x08,
566 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
567 value, 0,
568 tmpbuf, len,
569 500);
570 kfree(tmpbuf);
571 }
572}
573
574/* I2C write 2 bytes */
575static void i2c_w2(struct gspca_dev *gspca_dev,
576 const __u8 *buffer)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
579 __u8 mode[8];
580
581 /* is i2c ready */
582 mode[0] = 0x81 | (2 << 4);
583 mode[1] = sd->i2c_base;
584 mode[2] = buffer[0];
585 mode[3] = buffer[1];
586 mode[4] = 0;
587 mode[5] = 0;
588 mode[6] = 0;
589 mode[7] = 0x10;
590 reg_w(gspca_dev, 0x08, mode, 8);
591}
592
593/* I2C write 8 bytes */
594static void i2c_w8(struct gspca_dev *gspca_dev,
595 const __u8 *buffer)
596{
597 reg_w(gspca_dev, 0x08, buffer, 8);
598 msleep(1);
599}
600
601/* read 5 bytes in gspca_dev->usb_buf */
602static void i2c_r5(struct gspca_dev *gspca_dev, __u8 reg)
603{
604 struct sd *sd = (struct sd *) gspca_dev;
605 __u8 mode[8];
606
607 mode[0] = 0x81 | 0x10;
608 mode[1] = sd->i2c_base;
609 mode[2] = reg;
610 mode[3] = 0;
611 mode[4] = 0;
612 mode[5] = 0;
613 mode[6] = 0;
614 mode[7] = 0x10;
615 i2c_w8(gspca_dev, mode);
616 mode[0] = 0x81 | (5 << 4) | 0x02;
617 mode[2] = 0;
618 i2c_w8(gspca_dev, mode);
619 reg_r(gspca_dev, 0x0a, 5);
620}
621
622static int probesensor(struct gspca_dev *gspca_dev)
623{
624 struct sd *sd = (struct sd *) gspca_dev;
625 __u8 reg02;
626 static const __u8 datasend[] = { 2, 0 };
627 /* reg val1 val2 val3 val4 */
628
629 i2c_w2(gspca_dev, datasend);
630/* should write 0xa1 0x11 0x02 0x00 0x00 0x00 0x00 the 0x10 is add by i2cw */
631 msleep(10);
632 reg02 = 0x66;
633 reg_w(gspca_dev, 0x02, &reg02, 1); /* Gpio on */
634 msleep(10);
635 i2c_r5(gspca_dev, 0); /* read sensor id */
636 if (gspca_dev->usb_buf[0] == 0x02
637 && gspca_dev->usb_buf[1] == 0x09
638 && gspca_dev->usb_buf[2] == 0x01
639 && gspca_dev->usb_buf[3] == 0x00
640 && gspca_dev->usb_buf[4] == 0x00) {
641 PDEBUG(D_PROBE, "Find Sensor sn9c102P HV7131R");
642 sd->sensor = SENSOR_HV7131R;
643 return SENSOR_HV7131R;
644 }
645 PDEBUG(D_PROBE, "Find Sensor %d %d %d",
646 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
647 gspca_dev->usb_buf[2]);
648 PDEBUG(D_PROBE, "Sensor sn9c102P Not found");
649 return -ENODEV;
650}
651
652static int configure_gpio(struct gspca_dev *gspca_dev,
653 const __u8 *sn9c1xx)
654{
655 struct sd *sd = (struct sd *) gspca_dev;
656 __u8 data;
657 __u8 regF1;
658 const __u8 *reg9a;
659 static const __u8 reg9a_def[] =
660 {0x08, 0x40, 0x20, 0x10, 0x00, 0x04};
661 static const __u8 reg9a_sn9c120[] = /* from win trace */
662 {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
663 static const __u8 reg9a_sn9c325[] =
664 {0x0a, 0x40, 0x38, 0x30, 0x00, 0x20};
665
666
667 regF1 = 0x00;
668 reg_w(gspca_dev, 0xf1, &regF1, 1);
669 reg_w(gspca_dev, 0x01, &sn9c1xx[0], 1); /*fixme:jfm was [1] en v1*/
670
671 /* configure gpio */
672 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
673 reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
674 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5); /* jfm was 3 */
675 switch (sd->bridge) {
676 case BRIDGE_SN9C325:
677 reg9a = reg9a_sn9c325;
678 break;
679 case BRIDGE_SN9C120:
680 reg9a = reg9a_sn9c120;
681 break;
682 default:
683 reg9a = reg9a_def;
684 break;
685 }
686 reg_w(gspca_dev, 0x9a, reg9a, 6);
687
688 data = 0x60; /*fixme:jfm 60 00 00 (3) */
689 reg_w(gspca_dev, 0xd4, &data, 1);
690
691 reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
692
693 switch (sd->bridge) {
694 case BRIDGE_SN9C120: /* from win trace */
695 data = 0x61;
696 reg_w(gspca_dev, 0x01, &data, 1);
697 data = 0x20;
698 reg_w(gspca_dev, 0x17, &data, 1);
699 data = 0x60;
700 reg_w(gspca_dev, 0x01, &data, 1);
701 break;
702 case BRIDGE_SN9C325:
703 data = 0x43;
704 reg_w(gspca_dev, 0x01, &data, 1);
705 data = 0xae;
706 reg_w(gspca_dev, 0x17, &data, 1);
707 data = 0x42;
708 reg_w(gspca_dev, 0x01, &data, 1);
709 break;
710 default:
711 data = 0x43;
712 reg_w(gspca_dev, 0x01, &data, 1);
713 data = 0x61;
714 reg_w(gspca_dev, 0x17, &data, 1);
715 data = 0x42;
716 reg_w(gspca_dev, 0x01, &data, 1);
717 }
718
719 if (sd->sensor == SENSOR_HV7131R) {
720 if (probesensor(gspca_dev) < 0)
721 return -ENODEV;
722 }
723 return 0;
724}
725
726static void hv7131R_InitSensor(struct gspca_dev *gspca_dev)
727{
728 int i = 0;
729 static const __u8 SetSensorClk[] = /* 0x08 Mclk */
730 { 0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10 };
731
732 while (hv7131r_sensor_init[i][0]) {
733 i2c_w8(gspca_dev, hv7131r_sensor_init[i]);
734 i++;
735 }
736 i2c_w8(gspca_dev, SetSensorClk);
737}
738
739static void mi0360_InitSensor(struct gspca_dev *gspca_dev)
740{
741 int i = 0;
742
743 while (mi0360_sensor_init[i][0]) {
744 i2c_w8(gspca_dev, mi0360_sensor_init[i]);
745 i++;
746 }
747}
748
749static void mo4000_InitSensor(struct gspca_dev *gspca_dev)
750{
751 int i = 0;
752
753 while (mo4000_sensor_init[i][0]) {
754 i2c_w8(gspca_dev, mo4000_sensor_init[i]);
755 i++;
756 }
757}
758
759static void ov7648_InitSensor(struct gspca_dev *gspca_dev)
760{
761 int i = 0;
762
763 while (ov7648_sensor_init[i][0]) {
764 i2c_w8(gspca_dev, ov7648_sensor_init[i]);
765 i++;
766 }
767}
768
769static void ov7660_InitSensor(struct gspca_dev *gspca_dev)
770{
771 int i = 0;
772
773 while (ov7660_sensor_init[i][0]) {
774 i2c_w8(gspca_dev, ov7660_sensor_init[i]);
775 i++;
776 }
777}
778
779/* this function is called at probe time */
780static int sd_config(struct gspca_dev *gspca_dev,
781 const struct usb_device_id *id)
782{
783 struct sd *sd = (struct sd *) gspca_dev;
784 struct cam *cam;
785 __u16 vendor;
786 __u16 product;
787
788 vendor = id->idVendor;
789 product = id->idProduct;
790 sd->sensor = -1;
791 switch (vendor) {
792 case 0x0458: /* Genius */
793/* switch (product) {
794 case 0x7025: */
795 sd->bridge = BRIDGE_SN9C120;
796 sd->sensor = SENSOR_MI0360;
797 sd->i2c_base = 0x5d;
798/* break;
799 } */
800 break;
801 case 0x045e:
802/* switch (product) {
803 case 0x00f5:
804 case 0x00f7: */
805 sd->bridge = BRIDGE_SN9C105;
806 sd->sensor = SENSOR_OV7660;
807 sd->i2c_base = 0x21;
808/* break;
809 } */
810 break;
811 case 0x0471: /* Philips */
812/* switch (product) {
813 case 0x0327:
814 case 0x0328:
815 case 0x0330: */
816 sd->bridge = BRIDGE_SN9C105;
817 sd->sensor = SENSOR_MI0360;
818 sd->i2c_base = 0x5d;
819/* break;
820 } */
821 break;
822 case 0x0c45: /* Sonix */
823 switch (product) {
824 case 0x6040:
825 sd->bridge = BRIDGE_SN9C102P;
826/* sd->sensor = SENSOR_MI0360; * from BW600.inf */
827/*fixme: MI0360 base=5d ? */
828 sd->sensor = SENSOR_HV7131R; /* gspcav1 value */
829 sd->i2c_base = 0x11;
830 break;
831/* case 0x607a: * from BW600.inf
832 sd->bridge = BRIDGE_SN9C102P;
833 sd->sensor = SENSOR_OV7648;
834 sd->i2c_base = 0x??;
835 break; */
836 case 0x607c:
837 sd->bridge = BRIDGE_SN9C102P;
838 sd->sensor = SENSOR_HV7131R;
839 sd->i2c_base = 0x11;
840 break;
841/* case 0x607e: * from BW600.inf
842 sd->bridge = BRIDGE_SN9C102P;
843 sd->sensor = SENSOR_OV7630;
844 sd->i2c_base = 0x??;
845 break; */
846 case 0x60c0:
847 sd->bridge = BRIDGE_SN9C105;
848 sd->sensor = SENSOR_MI0360;
849 sd->i2c_base = 0x5d;
850 break;
851/* case 0x60c8: * from BW600.inf
852 sd->bridge = BRIDGE_SN9C105;
853 sd->sensor = SENSOR_OM6801;
854 sd->i2c_base = 0x??;
855 break; */
856/* case 0x60cc: * from BW600.inf
857 sd->bridge = BRIDGE_SN9C105;
858 sd->sensor = SENSOR_HV7131GP;
859 sd->i2c_base = 0x??;
860 break; */
861 case 0x60ec:
862 sd->bridge = BRIDGE_SN9C105;
863 sd->sensor = SENSOR_MO4000;
864 sd->i2c_base = 0x21;
865 break;
866/* case 0x60ef: * from BW600.inf
867 sd->bridge = BRIDGE_SN9C105;
868 sd->sensor = SENSOR_ICM105C;
869 sd->i2c_base = 0x??;
870 break; */
871/* case 0x60fa: * from BW600.inf
872 sd->bridge = BRIDGE_SN9C105;
873 sd->sensor = SENSOR_OV7648;
874 sd->i2c_base = 0x??;
875 break; */
876 case 0x60fb:
877 sd->bridge = BRIDGE_SN9C105;
878 sd->sensor = SENSOR_OV7660;
879 sd->i2c_base = 0x21;
880 break;
881 case 0x60fc:
882 sd->bridge = BRIDGE_SN9C105;
883 sd->sensor = SENSOR_HV7131R;
884 sd->i2c_base = 0x11;
885 break;
886/* case 0x60fe: * from BW600.inf
887 sd->bridge = BRIDGE_SN9C105;
888 sd->sensor = SENSOR_OV7630;
889 sd->i2c_base = 0x??;
890 break; */
891/* case 0x6108: * from BW600.inf
892 sd->bridge = BRIDGE_SN9C120;
893 sd->sensor = SENSOR_OM6801;
894 sd->i2c_base = 0x??;
895 break; */
896/* case 0x6122: * from BW600.inf
897 sd->bridge = BRIDGE_SN9C110;
898 sd->sensor = SENSOR_ICM105C;
899 sd->i2c_base = 0x??;
900 break; */
901 case 0x612a:
902/* sd->bridge = BRIDGE_SN9C110; * in BW600.inf */
903 sd->bridge = BRIDGE_SN9C325;
904 sd->sensor = SENSOR_OV7648;
905 sd->i2c_base = 0x21;
906/*fixme: sensor_init has base = 00 et 6e!*/
907 break;
908/* case 0x6123: * from BW600.inf
909 sd->bridge = BRIDGE_SN9C110;
910 sd->sensor = SENSOR_SanyoCCD;
911 sd->i2c_base = 0x??;
912 break; */
913 case 0x612c:
914 sd->bridge = BRIDGE_SN9C110;
915 sd->sensor = SENSOR_MO4000;
916 sd->i2c_base = 0x21;
917 break;
918/* case 0x612e: * from BW600.inf
919 sd->bridge = BRIDGE_SN9C110;
920 sd->sensor = SENSOR_OV7630;
921 sd->i2c_base = 0x??;
922 break; */
923/* case 0x612f: * from BW600.inf
924 sd->bridge = BRIDGE_SN9C110;
925 sd->sensor = SENSOR_ICM105C;
926 sd->i2c_base = 0x??;
927 break; */
928 case 0x6130:
929 sd->bridge = BRIDGE_SN9C120;
930 sd->sensor = SENSOR_MI0360;
931 sd->i2c_base = 0x5d;
932 break;
933 case 0x6138:
934 sd->bridge = BRIDGE_SN9C120;
935 sd->sensor = SENSOR_MO4000;
936 sd->i2c_base = 0x21;
937 break;
938/* case 0x613a: * from BW600.inf
939 sd->bridge = BRIDGE_SN9C120;
940 sd->sensor = SENSOR_OV7648;
941 sd->i2c_base = 0x??;
942 break; */
943 case 0x613b:
944 sd->bridge = BRIDGE_SN9C120;
945 sd->sensor = SENSOR_OV7660;
946 sd->i2c_base = 0x21;
947 break;
948 case 0x613c:
949 sd->bridge = BRIDGE_SN9C120;
950 sd->sensor = SENSOR_HV7131R;
951 sd->i2c_base = 0x11;
952 break;
953/* case 0x613e: * from BW600.inf
954 sd->bridge = BRIDGE_SN9C120;
955 sd->sensor = SENSOR_OV7630;
956 sd->i2c_base = 0x??;
957 break; */
958 }
959 break;
960 }
961 if (sd->sensor < 0) {
962 PDEBUG(D_ERR, "Invalid vendor/product %04x:%04x",
963 vendor, product);
964 return -EINVAL;
965 }
966
967 cam = &gspca_dev->cam;
968 cam->dev_name = (char *) id->driver_info;
969 cam->epaddr = 0x01;
970 cam->cam_mode = vga_mode;
971 cam->nmodes = ARRAY_SIZE(vga_mode);
972
973 sd->qindex = 4; /* set the quantization table */
974 sd->brightness = BRIGHTNESS_DEF;
975 sd->contrast = CONTRAST_DEF;
976 sd->colors = COLOR_DEF;
977 sd->autogain = AUTOGAIN_DEF;
978 return 0;
979}
980
981/* this function is called at open time */
982static int sd_open(struct gspca_dev *gspca_dev)
983{
984 struct sd *sd = (struct sd *) gspca_dev;
985/* const __u8 *sn9c1xx; */
986 __u8 regF1;
987 __u8 regGpio[] = { 0x29, 0x74 };
988
989 /* setup a selector by bridge */
990 regF1 = 0x01;
991 reg_w(gspca_dev, 0xf1, &regF1, 1);
992 reg_r(gspca_dev, 0x00, 1); /* -> regF1 = 0x00 */
993 regF1 = gspca_dev->usb_buf[0];
994 reg_w(gspca_dev, 0xf1, &regF1, 1);
995 reg_r(gspca_dev, 0x00, 1);
996 regF1 = gspca_dev->usb_buf[0];
997 switch (sd->bridge) {
998 case BRIDGE_SN9C102P:
999 if (regF1 != 0x11)
1000 return -ENODEV;
1001 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1002 break;
1003 case BRIDGE_SN9C105:
1004 if (regF1 != 0x11)
1005 return -ENODEV;
1006 reg_w(gspca_dev, 0x02, regGpio, 2);
1007 break;
1008 case BRIDGE_SN9C110:
1009 if (regF1 != 0x12)
1010 return -ENODEV;
1011 regGpio[1] = 0x62;
1012 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1013 break;
1014 case BRIDGE_SN9C120:
1015 if (regF1 != 0x12)
1016 return -ENODEV;
1017 regGpio[1] = 0x70;
1018 reg_w(gspca_dev, 0x02, regGpio, 2);
1019 break;
1020 default:
1021/* case BRIDGE_SN9C325: */
1022 if (regF1 != 0x12)
1023 return -ENODEV;
1024 regGpio[1] = 0x62;
1025 reg_w(gspca_dev, 0x02, &regGpio[1], 1);
1026 break;
1027 }
1028
1029 regF1 = 0x01;
1030 reg_w(gspca_dev, 0xf1, &regF1, 1);
1031
1032 return 0;
1033}
1034
1035static unsigned int setexposure(struct gspca_dev *gspca_dev,
1036 unsigned int expo)
1037{
1038 struct sd *sd = (struct sd *) gspca_dev;
1039 static const __u8 doit[] = /* update sensor */
1040 { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
1041 static const __u8 sensorgo[] = /* sensor on */
1042 { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
1043 static const __u8 gainMo[] =
1044 { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
1045
1046 switch (sd->sensor) {
1047 case SENSOR_HV7131R: {
1048 __u8 Expodoit[] =
1049 { 0xc1, 0x11, 0x25, 0x07, 0x27, 0xc0, 0x00, 0x16 };
1050
1051 Expodoit[3] = expo >> 16;
1052 Expodoit[4] = expo >> 8;
1053 Expodoit[5] = expo;
1054 i2c_w8(gspca_dev, Expodoit);
1055 break;
1056 }
1057 case SENSOR_MI0360: {
1058 __u8 expoMi[] = /* exposure 0x0635 -> 4 fp/s 0x10 */
1059 { 0xb1, 0x5d, 0x09, 0x06, 0x35, 0x00, 0x00, 0x16 };
1060
1061 if (expo > 0x0635)
1062 expo = 0x0635;
1063 else if (expo < 0x0001)
1064 expo = 0x0001;
1065 expoMi[3] = expo >> 8;
1066 expoMi[4] = expo;
1067 i2c_w8(gspca_dev, expoMi);
1068 i2c_w8(gspca_dev, doit);
1069 i2c_w8(gspca_dev, sensorgo);
1070 break;
1071 }
1072 case SENSOR_MO4000: {
1073 __u8 expoMof[] =
1074 { 0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10 };
1075 __u8 expoMo10[] =
1076 { 0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10 };
1077
1078 if (expo > 0x1fff)
1079 expo = 0x1fff;
1080 else if (expo < 0x0001)
1081 expo = 0x0001;
1082 expoMof[3] = (expo & 0x03fc) >> 2;
1083 i2c_w8(gspca_dev, expoMof);
1084 expoMo10[3] = ((expo & 0x1c00) >> 10)
1085 | ((expo & 0x0003) << 4);
1086 i2c_w8(gspca_dev, expoMo10);
1087 i2c_w8(gspca_dev, gainMo);
1088 PDEBUG(D_CONF, "set exposure %d",
1089 ((expoMo10[3] & 0x07) << 10)
1090 | (expoMof[3] << 2)
1091 | ((expoMo10[3] & 0x30) >> 4));
1092 break;
1093 }
1094 }
1095 return expo;
1096}
1097
1098static void setbrightness(struct gspca_dev *gspca_dev)
1099{
1100 struct sd *sd = (struct sd *) gspca_dev;
1101 unsigned int expo;
1102 __u8 k2;
1103
1104 switch (sd->sensor) {
1105 case SENSOR_HV7131R:
1106 expo = sd->brightness << 4;
1107 if (expo > 0x002dc6c0)
1108 expo = 0x002dc6c0;
1109 else if (expo < 0x02a0)
1110 expo = 0x02a0;
1111 sd->exposure = setexposure(gspca_dev, expo);
1112 break;
1113 case SENSOR_MI0360:
1114 expo = sd->brightness >> 4;
1115 sd->exposure = setexposure(gspca_dev, expo);
1116 break;
1117 case SENSOR_MO4000:
1118 expo = sd->brightness >> 4;
1119 sd->exposure = setexposure(gspca_dev, expo);
1120 break;
1121 case SENSOR_OV7660:
1122 return; /*jfm??*/
1123 }
1124
1125 k2 = sd->brightness >> 10;
1126 reg_w(gspca_dev, 0x96, &k2, 1);
1127}
1128
1129static void setcontrast(struct gspca_dev *gspca_dev)
1130{
1131 struct sd *sd = (struct sd *) gspca_dev;
1132 __u8 k2;
1133 __u8 contrast[] = { 0x00, 0x00, 0x28, 0x00, 0x07, 0x00 };
1134
1135 if (sd->sensor == SENSOR_OV7660)
1136 return; /*jfm??*/
1137 k2 = sd->contrast;
1138 contrast[2] = k2;
1139 contrast[0] = (k2 + 1) >> 1;
1140 contrast[4] = (k2 + 1) / 5;
1141 reg_w(gspca_dev, 0x84, contrast, 6);
1142}
1143
1144static void setcolors(struct gspca_dev *gspca_dev)
1145{
1146 struct sd *sd = (struct sd *) gspca_dev;
1147 __u8 data;
1148 int colour;
1149
1150 colour = sd->colors - 128;
1151 if (colour > 0)
1152 data = (colour + 32) & 0x7f; /* blue */
1153 else
1154 data = (-colour + 32) & 0x7f; /* red */
1155 reg_w(gspca_dev, 0x05, &data, 1);
1156}
1157
1158/* -- start the camera -- */
1159static void sd_start(struct gspca_dev *gspca_dev)
1160{
1161 struct sd *sd = (struct sd *) gspca_dev;
1162 int i;
1163 __u8 data;
1164 __u8 reg1;
1165 __u8 reg17;
1166 const __u8 *sn9c1xx;
1167 int mode;
1168 static const __u8 DC29[] = { 0x6a, 0x50, 0x00, 0x00, 0x50, 0x3c };
1169 static const __u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
1170 static const __u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
1171 static const __u8 CA_sn9c120[] =
1172 { 0x14, 0xec, 0x0a, 0xf6 }; /* SN9C120 */
1173 static const __u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd }; /* MI0360 */
1174 static const __u8 CE_sn9c325[] =
1175 { 0x32, 0xdd, 0x32, 0xdd }; /* OV7648 - SN9C325 */
1176
1177 sn9c1xx = sn_tb[(int) sd->sensor];
1178 configure_gpio(gspca_dev, sn9c1xx);
1179
1180/*fixme:jfm this sequence should appear at end of sd_start */
1181/* with
1182 data = 0x44;
1183 reg_w(gspca_dev, 0x01, &data, 1); */
1184 reg_w(gspca_dev, 0x15, &sn9c1xx[0x15], 1);
1185 reg_w(gspca_dev, 0x16, &sn9c1xx[0x16], 1);
1186 reg_w(gspca_dev, 0x12, &sn9c1xx[0x12], 1);
1187 reg_w(gspca_dev, 0x13, &sn9c1xx[0x13], 1);
1188 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1189 reg_w(gspca_dev, 0xd2, &DC29[0], 1);
1190 reg_w(gspca_dev, 0xd3, &DC29[1], 1);
1191 reg_w(gspca_dev, 0xc6, &DC29[2], 1);
1192 reg_w(gspca_dev, 0xc7, &DC29[3], 1);
1193 reg_w(gspca_dev, 0xc8, &DC29[4], 1);
1194 reg_w(gspca_dev, 0xc9, &DC29[5], 1);
1195/*fixme:jfm end of ending sequence */
1196 reg_w(gspca_dev, 0x18, &sn9c1xx[0x18], 1);
1197 switch (sd->bridge) {
1198 case BRIDGE_SN9C325:
1199 data = 0xae;
1200 break;
1201 case BRIDGE_SN9C120:
1202 data = 0xa0;
1203 break;
1204 default:
1205 data = 0x60;
1206 break;
1207 }
1208 reg_w(gspca_dev, 0x17, &data, 1);
1209 reg_w(gspca_dev, 0x05, &sn9c1xx[5], 1);
1210 reg_w(gspca_dev, 0x07, &sn9c1xx[7], 1);
1211 reg_w(gspca_dev, 0x06, &sn9c1xx[6], 1);
1212 reg_w(gspca_dev, 0x14, &sn9c1xx[0x14], 1);
1213 switch (sd->bridge) {
1214 case BRIDGE_SN9C325:
1215 reg_w(gspca_dev, 0x20, regsn20_sn9c325,
1216 sizeof regsn20_sn9c325);
1217 for (i = 0; i < 8; i++)
1218 reg_w(gspca_dev, 0x84, reg84_sn9c325,
1219 sizeof reg84_sn9c325);
1220 data = 0x0a;
1221 reg_w(gspca_dev, 0x9a, &data, 1);
1222 data = 0x60;
1223 reg_w(gspca_dev, 0x99, &data, 1);
1224 break;
1225 case BRIDGE_SN9C120:
1226 reg_w(gspca_dev, 0x20, regsn20_sn9c120,
1227 sizeof regsn20_sn9c120);
1228 for (i = 0; i < 2; i++)
1229 reg_w(gspca_dev, 0x84, reg84_sn9c120_1,
1230 sizeof reg84_sn9c120_1);
1231 for (i = 0; i < 6; i++)
1232 reg_w(gspca_dev, 0x84, reg84_sn9c120_2,
1233 sizeof reg84_sn9c120_2);
1234 reg_w(gspca_dev, 0x84, reg84_sn9c120_3,
1235 sizeof reg84_sn9c120_3);
1236 data = 0x05;
1237 reg_w(gspca_dev, 0x9a, &data, 1);
1238 data = 0x5b;
1239 reg_w(gspca_dev, 0x99, &data, 1);
1240 break;
1241 default:
1242 reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
1243 for (i = 0; i < 8; i++)
1244 reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
1245 data = 0x08;
1246 reg_w(gspca_dev, 0x9a, &data, 1);
1247 data = 0x59;
1248 reg_w(gspca_dev, 0x99, &data, 1);
1249 break;
1250 }
1251
1252 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1253 reg1 = 0x02;
1254 reg17 = 0x61;
1255 switch (sd->sensor) {
1256 case SENSOR_HV7131R:
1257 hv7131R_InitSensor(gspca_dev);
1258 if (mode)
1259 reg1 = 0x46; /* 320 clk 48Mhz */
1260 else
1261 reg1 = 0x06; /* 640 clk 24Mz */
1262 break;
1263 case SENSOR_MI0360:
1264 mi0360_InitSensor(gspca_dev);
1265 if (mode)
1266 reg1 = 0x46; /* 320 clk 48Mhz */
1267 else
1268 reg1 = 0x06; /* 640 clk 24Mz */
1269 break;
1270 case SENSOR_MO4000:
1271 mo4000_InitSensor(gspca_dev);
1272 if (mode) {
1273/* reg1 = 0x46; * 320 clk 48Mhz 60fp/s */
1274 reg1 = 0x06; /* clk 24Mz */
1275 } else {
1276 reg17 = 0x22; /* 640 MCKSIZE */
1277 reg1 = 0x06; /* 640 clk 24Mz */
1278 }
1279 break;
1280 case SENSOR_OV7648:
1281 reg17 = 0xa2;
1282 reg1 = 0x44;
1283 ov7648_InitSensor(gspca_dev);
1284/* if (mode)
1285 ; * 320x2...
1286 else
1287 ; * 640x... */
1288 break;
1289 default:
1290/* case SENSOR_OV7660: */
1291 ov7660_InitSensor(gspca_dev);
1292 if (mode) {
1293/* reg17 = 0x21; * 320 */
1294/* reg1 = 0x44; */
1295 reg1 = 0x46;
1296 } else {
1297 reg17 = 0xa2; /* 640 */
1298 reg1 = 0x40;
1299 }
1300 break;
1301 }
1302 reg_w(gspca_dev, 0xc0, C0, 6);
1303 switch (sd->bridge) {
1304 case BRIDGE_SN9C120: /*jfm ?? */
1305 reg_w(gspca_dev, 0xca, CA_sn9c120, 4);
1306 break;
1307 default:
1308 reg_w(gspca_dev, 0xca, CA, 4);
1309 break;
1310 }
1311 switch (sd->bridge) {
1312 case BRIDGE_SN9C120: /*jfm ?? */
1313 case BRIDGE_SN9C325:
1314 reg_w(gspca_dev, 0xce, CE_sn9c325, 4);
1315 break;
1316 default:
1317 reg_w(gspca_dev, 0xce, CE, 4);
1318 /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
1319 break;
1320 }
1321
1322 /* here change size mode 0 -> VGA; 1 -> CIF */
1323 data = 0x40 | sn9c1xx[0x18] | (mode << 4);
1324 reg_w(gspca_dev, 0x18, &data, 1);
1325
1326 reg_w(gspca_dev, 0x100, qtable4, 0x40);
1327 reg_w(gspca_dev, 0x140, qtable4 + 0x40, 0x40);
1328
1329 data = sn9c1xx[0x18] | (mode << 4);
1330 reg_w(gspca_dev, 0x18, &data, 1);
1331
1332 reg_w(gspca_dev, 0x17, &reg17, 1);
1333 reg_w(gspca_dev, 0x01, &reg1, 1);
1334 setbrightness(gspca_dev);
1335 setcontrast(gspca_dev);
1336}
1337
1338static void sd_stopN(struct gspca_dev *gspca_dev)
1339{
1340 struct sd *sd = (struct sd *) gspca_dev;
1341 static const __u8 stophv7131[] =
1342 { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
1343 static const __u8 stopmi0360[] =
1344 { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
1345 __u8 regF1;
1346 __u8 data;
1347 const __u8 *sn9c1xx;
1348
1349 data = 0x0b;
1350 switch (sd->sensor) {
1351 case SENSOR_HV7131R:
1352 i2c_w8(gspca_dev, stophv7131);
1353 data = 0x2b;
1354 break;
1355 case SENSOR_MI0360:
1356 i2c_w8(gspca_dev, stopmi0360);
1357 data = 0x29;
1358 break;
1359 case SENSOR_MO4000:
1360 break;
1361 case SENSOR_OV7648:
1362 data = 0x29;
1363 break;
1364 default:
1365/* case SENSOR_OV7660: */
1366 break;
1367 }
1368 sn9c1xx = sn_tb[(int) sd->sensor];
1369 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1370 reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 1);
1371 reg_w(gspca_dev, 0x01, &sn9c1xx[1], 1);
1372 reg_w(gspca_dev, 0x01, &data, 1);
1373 regF1 = 0x01;
1374 reg_w(gspca_dev, 0xf1, &regF1, 1);
1375}
1376
1377static void sd_stop0(struct gspca_dev *gspca_dev)
1378{
1379}
1380
1381static void sd_close(struct gspca_dev *gspca_dev)
1382{
1383}
1384
1385static void setautogain(struct gspca_dev *gspca_dev)
1386{
1387 struct sd *sd = (struct sd *) gspca_dev;
1388 /* Thanks S., without your advice, autobright should not work :) */
1389 int delta;
1390 int expotimes = 0;
1391 __u8 luma_mean = 130;
1392 __u8 luma_delta = 20;
1393
1394 delta = sd->avg_lum;
1395 if (delta < luma_mean - luma_delta ||
1396 delta > luma_mean + luma_delta) {
1397 switch (sd->sensor) {
1398 case SENSOR_HV7131R:
1399 expotimes = sd->exposure >> 8;
1400 expotimes += (luma_mean - delta) >> 4;
1401 if (expotimes < 0)
1402 expotimes = 0;
1403 sd->exposure = setexposure(gspca_dev,
1404 (unsigned int) (expotimes << 8));
1405 break;
1406 case SENSOR_MO4000:
1407 case SENSOR_MI0360:
1408 expotimes = sd->exposure;
1409 expotimes += (luma_mean - delta) >> 6;
1410 if (expotimes < 0)
1411 expotimes = 0;
1412 sd->exposure = setexposure(gspca_dev,
1413 (unsigned int) expotimes);
1414 setcolors(gspca_dev);
1415 break;
1416 }
1417 }
1418}
1419
1420static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1421 struct gspca_frame *frame, /* target */
1422 __u8 *data, /* isoc packet */
1423 int len) /* iso packet length */
1424{
1425 struct sd *sd = (struct sd *) gspca_dev;
1426 int sof, avg_lum;
1427
1428 sof = len - 64;
1429 if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9) {
1430
1431 /* end of frame */
1432 gspca_frame_add(gspca_dev, LAST_PACKET,
1433 frame, data, sof + 2);
1434 if (sd->ag_cnt < 0)
1435 return;
1436 if (--sd->ag_cnt >= 0)
1437 return;
1438 sd->ag_cnt = AG_CNT_START;
1439/* w1 w2 w3 */
1440/* w4 w5 w6 */
1441/* w7 w8 */
1442/* w4 */
1443 avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
1444/* w6 */
1445 avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
1446/* w2 */
1447 avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
1448/* w8 */
1449 avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
1450/* w5 */
1451 avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
1452 avg_lum >>= 4;
1453 sd->avg_lum = avg_lum;
1454 PDEBUG(D_PACK, "mean lum %d", avg_lum);
1455 setautogain(gspca_dev);
1456 return;
1457 }
1458 if (gspca_dev->last_packet_type == LAST_PACKET) {
1459
1460 /* put the JPEG 422 header */
1461 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
1462 }
1463 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1464}
1465
1466static unsigned int getexposure(struct gspca_dev *gspca_dev)
1467{
1468 struct sd *sd = (struct sd *) gspca_dev;
1469 __u8 hexpo, mexpo, lexpo;
1470
1471 switch (sd->sensor) {
1472 case SENSOR_HV7131R:
1473 /* read sensor exposure */
1474 i2c_r5(gspca_dev, 0x25);
1475 return (gspca_dev->usb_buf[0] << 16)
1476 | (gspca_dev->usb_buf[1] << 8)
1477 | gspca_dev->usb_buf[2];
1478 case SENSOR_MI0360:
1479 /* read sensor exposure */
1480 i2c_r5(gspca_dev, 0x09);
1481 return (gspca_dev->usb_buf[0] << 8)
1482 | gspca_dev->usb_buf[1];
1483 case SENSOR_MO4000:
1484 i2c_r5(gspca_dev, 0x0e);
1485 hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
1486 mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
1487 lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
1488 PDEBUG(D_CONF, "exposure %d",
1489 (hexpo << 10) | (mexpo << 2) | lexpo);
1490 return (hexpo << 10) | (mexpo << 2) | lexpo;
1491 default:
1492/* case SENSOR_OV7660: */
1493 /* read sensor exposure */
1494 i2c_r5(gspca_dev, 0x04);
1495 hexpo = gspca_dev->usb_buf[3] & 0x2f;
1496 lexpo = gspca_dev->usb_buf[0] & 0x02;
1497 i2c_r5(gspca_dev, 0x08);
1498 mexpo = gspca_dev->usb_buf[2];
1499 return (hexpo << 10) | (mexpo << 2) | lexpo;
1500 }
1501}
1502
1503static void getbrightness(struct gspca_dev *gspca_dev)
1504{
1505 struct sd *sd = (struct sd *) gspca_dev;
1506
1507 /* hardcoded registers seem not readable */
1508 switch (sd->sensor) {
1509 case SENSOR_HV7131R:
1510/* sd->brightness = 0x7fff; */
1511 sd->brightness = getexposure(gspca_dev) >> 4;
1512 break;
1513 case SENSOR_MI0360:
1514 sd->brightness = getexposure(gspca_dev) << 4;
1515 break;
1516 case SENSOR_MO4000:
1517/* sd->brightness = 0x1fff; */
1518 sd->brightness = getexposure(gspca_dev) << 4;
1519 break;
1520 }
1521}
1522
1523static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1524{
1525 struct sd *sd = (struct sd *) gspca_dev;
1526
1527 sd->brightness = val;
1528 if (gspca_dev->streaming)
1529 setbrightness(gspca_dev);
1530 return 0;
1531}
1532
1533static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1534{
1535 struct sd *sd = (struct sd *) gspca_dev;
1536
1537 getbrightness(gspca_dev);
1538 *val = sd->brightness;
1539 return 0;
1540}
1541
1542static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1543{
1544 struct sd *sd = (struct sd *) gspca_dev;
1545
1546 sd->contrast = val;
1547 if (gspca_dev->streaming)
1548 setcontrast(gspca_dev);
1549 return 0;
1550}
1551
1552static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1553{
1554 struct sd *sd = (struct sd *) gspca_dev;
1555
1556 *val = sd->contrast;
1557 return 0;
1558}
1559
1560static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1561{
1562 struct sd *sd = (struct sd *) gspca_dev;
1563
1564 sd->colors = val;
1565 if (gspca_dev->streaming)
1566 setcolors(gspca_dev);
1567 return 0;
1568}
1569
1570static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1571{
1572 struct sd *sd = (struct sd *) gspca_dev;
1573
1574 *val = sd->colors;
1575 return 0;
1576}
1577
1578static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1579{
1580 struct sd *sd = (struct sd *) gspca_dev;
1581
1582 sd->autogain = val;
1583 if (val)
1584 sd->ag_cnt = AG_CNT_START;
1585 else
1586 sd->ag_cnt = -1;
1587 return 0;
1588}
1589
1590static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1591{
1592 struct sd *sd = (struct sd *) gspca_dev;
1593
1594 *val = sd->autogain;
1595 return 0;
1596}
1597
1598/* sub-driver description */
1599static const struct sd_desc sd_desc = {
1600 .name = MODULE_NAME,
1601 .ctrls = sd_ctrls,
1602 .nctrls = ARRAY_SIZE(sd_ctrls),
1603 .config = sd_config,
1604 .open = sd_open,
1605 .start = sd_start,
1606 .stopN = sd_stopN,
1607 .stop0 = sd_stop0,
1608 .close = sd_close,
1609 .pkt_scan = sd_pkt_scan,
1610};
1611
1612/* -- module initialisation -- */
1613#define DVNM(name) .driver_info = (kernel_ulong_t) name
1614static const __devinitdata struct usb_device_id device_table[] = {
1615#ifndef CONFIG_USB_SN9C102
1616 {USB_DEVICE(0x0458, 0x7025), DVNM("Genius Eye 311Q")},
1617 {USB_DEVICE(0x045e, 0x00f5), DVNM("MicroSoft VX3000")},
1618 {USB_DEVICE(0x045e, 0x00f7), DVNM("MicroSoft VX1000")},
1619 {USB_DEVICE(0x0471, 0x0327), DVNM("Philips SPC 600 NC")},
1620 {USB_DEVICE(0x0471, 0x0328), DVNM("Philips SPC 700 NC")},
1621#endif
1622 {USB_DEVICE(0x0471, 0x0330), DVNM("Philips SPC 710NC")},
1623 {USB_DEVICE(0x0c45, 0x6040), DVNM("Speed NVC 350K")},
1624 {USB_DEVICE(0x0c45, 0x607c), DVNM("Sonix sn9c102p Hv7131R")},
1625 {USB_DEVICE(0x0c45, 0x60c0), DVNM("Sangha Sn535")},
1626 {USB_DEVICE(0x0c45, 0x60ec), DVNM("SN9C105+MO4000")},
1627 {USB_DEVICE(0x0c45, 0x60fb), DVNM("Surfer NoName")},
1628 {USB_DEVICE(0x0c45, 0x60fc), DVNM("LG-LIC300")},
1629 {USB_DEVICE(0x0c45, 0x612a), DVNM("Avant Camera")},
1630 {USB_DEVICE(0x0c45, 0x612c), DVNM("Typhoon Rasy Cam 1.3MPix")},
1631#ifndef CONFIG_USB_SN9C102
1632 {USB_DEVICE(0x0c45, 0x6130), DVNM("Sonix Pccam")},
1633 {USB_DEVICE(0x0c45, 0x6138), DVNM("Sn9c120 Mo4000")},
1634 {USB_DEVICE(0x0c45, 0x613b), DVNM("Surfer SN-206")},
1635 {USB_DEVICE(0x0c45, 0x613c), DVNM("Sonix Pccam168")},
1636#endif
1637 {}
1638};
1639MODULE_DEVICE_TABLE(usb, device_table);
1640
1641/* -- device connect -- */
1642static int sd_probe(struct usb_interface *intf,
1643 const struct usb_device_id *id)
1644{
1645 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1646 THIS_MODULE);
1647}
1648
1649static struct usb_driver sd_driver = {
1650 .name = MODULE_NAME,
1651 .id_table = device_table,
1652 .probe = sd_probe,
1653 .disconnect = gspca_disconnect,
1654};
1655
1656/* -- module insert / remove -- */
1657static int __init sd_mod_init(void)
1658{
1659 if (usb_register(&sd_driver) < 0)
1660 return -1;
1661 info("v%s registered", version);
1662 return 0;
1663}
1664static void __exit sd_mod_exit(void)
1665{
1666 usb_deregister(&sd_driver);
1667 info("deregistered");
1668}
1669
1670module_init(sd_mod_init);
1671module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
new file mode 100644
index 000000000000..156206118795
--- /dev/null
+++ b/drivers/media/video/gspca/spca500.c
@@ -0,0 +1,1216 @@
1/*
2 * SPCA500 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca500"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA500 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
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44
45 char qindex;
46 char subtype;
47#define AgfaCl20 0
48#define AiptekPocketDV 1
49#define BenqDC1016 2
50#define CreativePCCam300 3
51#define DLinkDSC350 4
52#define Gsmartmini 5
53#define IntelPocketPCCamera 6
54#define KodakEZ200 7
55#define LogitechClickSmart310 8
56#define LogitechClickSmart510 9
57#define LogitechTraveler 10
58#define MustekGsmart300 11
59#define Optimedia 12
60#define PalmPixDC85 13
61#define ToptroIndus 14
62};
63
64/* V4L2 controls supported by the driver */
65static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
71
72static struct ctrl sd_ctrls[] = {
73 {
74 {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 255,
80 .step = 1,
81#define BRIGHTNESS_DEF 127
82 .default_value = BRIGHTNESS_DEF,
83 },
84 .set = sd_setbrightness,
85 .get = sd_getbrightness,
86 },
87 {
88 {
89 .id = V4L2_CID_CONTRAST,
90 .type = V4L2_CTRL_TYPE_INTEGER,
91 .name = "Contrast",
92 .minimum = 0,
93 .maximum = 63,
94 .step = 1,
95#define CONTRAST_DEF 31
96 .default_value = CONTRAST_DEF,
97 },
98 .set = sd_setcontrast,
99 .get = sd_getcontrast,
100 },
101 {
102 {
103 .id = V4L2_CID_SATURATION,
104 .type = V4L2_CTRL_TYPE_INTEGER,
105 .name = "Color",
106 .minimum = 0,
107 .maximum = 63,
108 .step = 1,
109#define COLOR_DEF 31
110 .default_value = COLOR_DEF,
111 },
112 .set = sd_setcolors,
113 .get = sd_getcolors,
114 },
115};
116
117static struct v4l2_pix_format vga_mode[] = {
118 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
119 .bytesperline = 320,
120 .sizeimage = 320 * 240 * 3 / 8 + 590,
121 .colorspace = V4L2_COLORSPACE_JPEG,
122 .priv = 1},
123 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
124 .bytesperline = 640,
125 .sizeimage = 640 * 480 * 3 / 8 + 590,
126 .colorspace = V4L2_COLORSPACE_JPEG,
127 .priv = 0},
128};
129
130static struct v4l2_pix_format sif_mode[] = {
131 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
132 .bytesperline = 176,
133 .sizeimage = 176 * 144 * 3 / 8 + 590,
134 .colorspace = V4L2_COLORSPACE_JPEG,
135 .priv = 1},
136 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
137 .bytesperline = 352,
138 .sizeimage = 352 * 288 * 3 / 8 + 590,
139 .colorspace = V4L2_COLORSPACE_JPEG,
140 .priv = 0},
141};
142
143/* Frame packet header offsets for the spca500 */
144#define SPCA500_OFFSET_PADDINGLB 2
145#define SPCA500_OFFSET_PADDINGHB 3
146#define SPCA500_OFFSET_MODE 4
147#define SPCA500_OFFSET_IMGWIDTH 5
148#define SPCA500_OFFSET_IMGHEIGHT 6
149#define SPCA500_OFFSET_IMGMODE 7
150#define SPCA500_OFFSET_QTBLINDEX 8
151#define SPCA500_OFFSET_FRAMSEQ 9
152#define SPCA500_OFFSET_CDSPINFO 10
153#define SPCA500_OFFSET_GPIO 11
154#define SPCA500_OFFSET_AUGPIO 12
155#define SPCA500_OFFSET_DATA 16
156
157
158static const __u16 spca500_visual_defaults[][3] = {
159 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
160 * hue (H byte) = 0,
161 * saturation/hue enable,
162 * brightness/contrast enable.
163 */
164 {0x00, 0x0000, 0x8167}, /* brightness = 0 */
165 {0x00, 0x0020, 0x8168}, /* contrast = 0 */
166 {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
167 * hue (H byte) = 0, saturation/hue enable,
168 * brightness/contrast enable.
169 * was 0x0003, now 0x0000.
170 */
171 {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
172 {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
173 {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
174 {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
175 {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
176 {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
177 {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
178 {0x0c, 0x0004, 0x0000},
179 /* set interface */
180 {}
181};
182static const __u16 Clicksmart510_defaults[][3] = {
183 {0x00, 0x00, 0x8211},
184 {0x00, 0x01, 0x82c0},
185 {0x00, 0x10, 0x82cb},
186 {0x00, 0x0f, 0x800d},
187 {0x00, 0x82, 0x8225},
188 {0x00, 0x21, 0x8228},
189 {0x00, 0x00, 0x8203},
190 {0x00, 0x00, 0x8204},
191 {0x00, 0x08, 0x8205},
192 {0x00, 0xf8, 0x8206},
193 {0x00, 0x28, 0x8207},
194 {0x00, 0xa0, 0x8208},
195 {0x00, 0x08, 0x824a},
196 {0x00, 0x08, 0x8214},
197 {0x00, 0x80, 0x82c1},
198 {0x00, 0x00, 0x82c2},
199 {0x00, 0x00, 0x82ca},
200 {0x00, 0x80, 0x82c1},
201 {0x00, 0x04, 0x82c2},
202 {0x00, 0x00, 0x82ca},
203 {0x00, 0xfc, 0x8100},
204 {0x00, 0xfc, 0x8105},
205 {0x00, 0x30, 0x8101},
206 {0x00, 0x00, 0x8102},
207 {0x00, 0x00, 0x8103},
208 {0x00, 0x66, 0x8107},
209 {0x00, 0x00, 0x816b},
210 {0x00, 0x00, 0x8155},
211 {0x00, 0x01, 0x8156},
212 {0x00, 0x60, 0x8157},
213 {0x00, 0x40, 0x8158},
214 {0x00, 0x0a, 0x8159},
215 {0x00, 0x06, 0x815a},
216 {0x00, 0x00, 0x813f},
217 {0x00, 0x00, 0x8200},
218 {0x00, 0x19, 0x8201},
219 {0x00, 0x00, 0x82c1},
220 {0x00, 0xa0, 0x82c2},
221 {0x00, 0x00, 0x82ca},
222 {0x00, 0x00, 0x8117},
223 {0x00, 0x00, 0x8118},
224 {0x00, 0x65, 0x8119},
225 {0x00, 0x00, 0x811a},
226 {0x00, 0x00, 0x811b},
227 {0x00, 0x55, 0x811c},
228 {0x00, 0x65, 0x811d},
229 {0x00, 0x55, 0x811e},
230 {0x00, 0x16, 0x811f},
231 {0x00, 0x19, 0x8120},
232 {0x00, 0x80, 0x8103},
233 {0x00, 0x83, 0x816b},
234 {0x00, 0x25, 0x8168},
235 {0x00, 0x01, 0x820f},
236 {0x00, 0xff, 0x8115},
237 {0x00, 0x48, 0x8116},
238 {0x00, 0x50, 0x8151},
239 {0x00, 0x40, 0x8152},
240 {0x00, 0x78, 0x8153},
241 {0x00, 0x40, 0x8154},
242 {0x00, 0x00, 0x8167},
243 {0x00, 0x20, 0x8168},
244 {0x00, 0x00, 0x816a},
245 {0x00, 0x03, 0x816b},
246 {0x00, 0x20, 0x8169},
247 {0x00, 0x60, 0x8157},
248 {0x00, 0x00, 0x8190},
249 {0x00, 0x00, 0x81a1},
250 {0x00, 0x00, 0x81b2},
251 {0x00, 0x27, 0x8191},
252 {0x00, 0x27, 0x81a2},
253 {0x00, 0x27, 0x81b3},
254 {0x00, 0x4b, 0x8192},
255 {0x00, 0x4b, 0x81a3},
256 {0x00, 0x4b, 0x81b4},
257 {0x00, 0x66, 0x8193},
258 {0x00, 0x66, 0x81a4},
259 {0x00, 0x66, 0x81b5},
260 {0x00, 0x79, 0x8194},
261 {0x00, 0x79, 0x81a5},
262 {0x00, 0x79, 0x81b6},
263 {0x00, 0x8a, 0x8195},
264 {0x00, 0x8a, 0x81a6},
265 {0x00, 0x8a, 0x81b7},
266 {0x00, 0x9b, 0x8196},
267 {0x00, 0x9b, 0x81a7},
268 {0x00, 0x9b, 0x81b8},
269 {0x00, 0xa6, 0x8197},
270 {0x00, 0xa6, 0x81a8},
271 {0x00, 0xa6, 0x81b9},
272 {0x00, 0xb2, 0x8198},
273 {0x00, 0xb2, 0x81a9},
274 {0x00, 0xb2, 0x81ba},
275 {0x00, 0xbe, 0x8199},
276 {0x00, 0xbe, 0x81aa},
277 {0x00, 0xbe, 0x81bb},
278 {0x00, 0xc8, 0x819a},
279 {0x00, 0xc8, 0x81ab},
280 {0x00, 0xc8, 0x81bc},
281 {0x00, 0xd2, 0x819b},
282 {0x00, 0xd2, 0x81ac},
283 {0x00, 0xd2, 0x81bd},
284 {0x00, 0xdb, 0x819c},
285 {0x00, 0xdb, 0x81ad},
286 {0x00, 0xdb, 0x81be},
287 {0x00, 0xe4, 0x819d},
288 {0x00, 0xe4, 0x81ae},
289 {0x00, 0xe4, 0x81bf},
290 {0x00, 0xed, 0x819e},
291 {0x00, 0xed, 0x81af},
292 {0x00, 0xed, 0x81c0},
293 {0x00, 0xf7, 0x819f},
294 {0x00, 0xf7, 0x81b0},
295 {0x00, 0xf7, 0x81c1},
296 {0x00, 0xff, 0x81a0},
297 {0x00, 0xff, 0x81b1},
298 {0x00, 0xff, 0x81c2},
299 {0x00, 0x03, 0x8156},
300 {0x00, 0x00, 0x8211},
301 {0x00, 0x20, 0x8168},
302 {0x00, 0x01, 0x8202},
303 {0x00, 0x30, 0x8101},
304 {0x00, 0x00, 0x8111},
305 {0x00, 0x00, 0x8112},
306 {0x00, 0x00, 0x8113},
307 {0x00, 0x00, 0x8114},
308 {}
309};
310
311static const __u8 qtable_creative_pccam[2][64] = {
312 { /* Q-table Y-components */
313 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
314 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
315 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
316 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
317 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
318 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
319 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
320 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
321 { /* Q-table C-components */
322 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
323 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
324 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
325 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
326 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
327 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
328 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
329 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
330};
331
332static const __u8 qtable_kodak_ez200[2][64] = {
333 { /* Q-table Y-components */
334 0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
335 0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
336 0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
337 0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
338 0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
339 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
340 0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
341 0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
342 { /* Q-table C-components */
343 0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
344 0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
345 0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
346 0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
347 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
348 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
349 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
350 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
351};
352
353static const __u8 qtable_pocketdv[2][64] = {
354 { /* Q-table Y-components start registers 0x8800 */
355 0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
356 0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
357 0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
358 0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
359 0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
360 0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
361 0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
362 0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
363 },
364 { /* Q-table C-components start registers 0x8840 */
365 0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
366 0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
367 0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
368 0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
369 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
370 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
371 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
372 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
373};
374
375/* read 'len' bytes to gspca_dev->usb_buf */
376static void reg_r(struct gspca_dev *gspca_dev,
377 __u16 index,
378 __u16 length)
379{
380 usb_control_msg(gspca_dev->dev,
381 usb_rcvctrlpipe(gspca_dev->dev, 0),
382 0,
383 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
384 0, /* value */
385 index, gspca_dev->usb_buf, length, 500);
386}
387
388static int reg_w(struct gspca_dev *gspca_dev,
389 __u16 req, __u16 index, __u16 value)
390{
391 int ret;
392
393 PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
394 ret = usb_control_msg(gspca_dev->dev,
395 usb_sndctrlpipe(gspca_dev->dev, 0),
396 req,
397 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
398 value, index, NULL, 0, 500);
399 if (ret < 0)
400 PDEBUG(D_ERR, "reg write: error %d", ret);
401 return ret;
402}
403
404/* returns: negative is error, pos or zero is data */
405static int reg_r_12(struct gspca_dev *gspca_dev,
406 __u16 req, /* bRequest */
407 __u16 index, /* wIndex */
408 __u16 length) /* wLength (1 or 2 only) */
409{
410 int ret;
411
412 gspca_dev->usb_buf[1] = 0;
413 ret = usb_control_msg(gspca_dev->dev,
414 usb_rcvctrlpipe(gspca_dev->dev, 0),
415 req,
416 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
417 0, /* value */
418 index,
419 gspca_dev->usb_buf, length,
420 500); /* timeout */
421 if (ret < 0) {
422 PDEBUG(D_ERR, "reg_r_12 err %d", ret);
423 return -1;
424 }
425 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
426}
427
428/*
429 * Simple function to wait for a given 8-bit value to be returned from
430 * a reg_read call.
431 * Returns: negative is error or timeout, zero is success.
432 */
433static int reg_r_wait(struct gspca_dev *gspca_dev,
434 __u16 reg, __u16 index, __u16 value)
435{
436 int ret, cnt = 20;
437
438 while (--cnt > 0) {
439 ret = reg_r_12(gspca_dev, reg, index, 1);
440 if (ret == value)
441 return 0;
442 msleep(50);
443 }
444 return -EIO;
445}
446
447static int write_vector(struct gspca_dev *gspca_dev,
448 const __u16 data[][3])
449{
450 int ret, i = 0;
451
452 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
453 ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
454 if (ret < 0)
455 return ret;
456 i++;
457 }
458 return 0;
459}
460
461static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
462 unsigned int request,
463 unsigned int ybase,
464 unsigned int cbase,
465 const __u8 qtable[2][64])
466{
467 int i, err;
468
469 /* loop over y components */
470 for (i = 0; i < 64; i++) {
471 err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
472 if (err < 0)
473 return err;
474 }
475
476 /* loop over c components */
477 for (i = 0; i < 64; i++) {
478 err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
479 if (err < 0)
480 return err;
481 }
482 return 0;
483}
484
485static void spca500_ping310(struct gspca_dev *gspca_dev)
486{
487 reg_r(gspca_dev, 0x0d04, 2);
488 PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
489 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
490}
491
492static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
493{
494 reg_r(gspca_dev, 0x0d05, 2);
495 PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
496 gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
497 reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
498 spca500_ping310(gspca_dev);
499
500 reg_w(gspca_dev, 0x00, 0x8168, 0x22);
501 reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
502 reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
503 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
504 reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
505 reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
506 reg_w(gspca_dev, 0x00, 0x813f, 0x03);
507 reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
508 reg_w(gspca_dev, 0x00, 0x8153, 0x78);
509 reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
510 /* 00 for adjust shutter */
511 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
512 reg_w(gspca_dev, 0x00, 0x8169, 0x25);
513 reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
514}
515
516static void spca500_setmode(struct gspca_dev *gspca_dev,
517 __u8 xmult, __u8 ymult)
518{
519 int mode;
520
521 /* set x multiplier */
522 reg_w(gspca_dev, 0, 0x8001, xmult);
523
524 /* set y multiplier */
525 reg_w(gspca_dev, 0, 0x8002, ymult);
526
527 /* use compressed mode, VGA, with mode specific subsample */
528 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
529 reg_w(gspca_dev, 0, 0x8003, mode << 4);
530}
531
532static int spca500_full_reset(struct gspca_dev *gspca_dev)
533{
534 int err;
535
536 /* send the reset command */
537 err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
538 if (err < 0)
539 return err;
540
541 /* wait for the reset to complete */
542 err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
543 if (err < 0)
544 return err;
545 err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
546 if (err < 0)
547 return err;
548 err = reg_r_wait(gspca_dev, 0x06, 0, 0);
549 if (err < 0) {
550 PDEBUG(D_ERR, "reg_r_wait() failed");
551 return err;
552 }
553 /* all ok */
554 return 0;
555}
556
557/* Synchro the Bridge with sensor */
558/* Maybe that will work on all spca500 chip */
559/* because i only own a clicksmart310 try for that chip */
560/* using spca50x_set_packet_size() cause an Ooops here */
561/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
562/* up-port the same feature as in 2.4.x kernel */
563static int spca500_synch310(struct gspca_dev *gspca_dev)
564{
565 if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
566 PDEBUG(D_ERR, "Set packet size: set interface error");
567 goto error;
568 }
569 spca500_ping310(gspca_dev);
570
571 reg_r(gspca_dev, 0x0d00, 1);
572
573 /* need alt setting here */
574 PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
575
576 /* Windoze use pipe with altsetting 6 why 7 here */
577 if (usb_set_interface(gspca_dev->dev,
578 gspca_dev->iface,
579 gspca_dev->alt) < 0) {
580 PDEBUG(D_ERR, "Set packet size: set interface error");
581 goto error;
582 }
583 return 0;
584error:
585 return -EBUSY;
586}
587
588static void spca500_reinit(struct gspca_dev *gspca_dev)
589{
590 int err;
591 __u8 Data;
592
593 /* some unknow command from Aiptek pocket dv and family300 */
594
595 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
596 reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
597 reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
598
599 /* enable drop packet */
600 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
601
602 err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
603 qtable_pocketdv);
604 if (err < 0)
605 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
606
607 /* set qtable index */
608 reg_w(gspca_dev, 0x00, 0x8880, 2);
609 /* family cam Quicksmart stuff */
610 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
611 /* Set agc transfer: synced inbetween frames */
612 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
613 /* Init SDRAM - needed for SDRAM access */
614 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
615 /*Start init sequence or stream */
616 reg_w(gspca_dev, 0, 0x8003, 0x00);
617 /* switch to video camera mode */
618 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
619 msleep(2000);
620 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
621 reg_r(gspca_dev, 0x816b, 1);
622 Data = gspca_dev->usb_buf[0];
623 reg_w(gspca_dev, 0x00, 0x816b, Data);
624 }
625}
626
627/* this function is called at probe time */
628static int sd_config(struct gspca_dev *gspca_dev,
629 const struct usb_device_id *id)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 struct cam *cam;
633 __u16 vendor;
634 __u16 product;
635
636 vendor = id->idVendor;
637 product = id->idProduct;
638 switch (vendor) {
639 case 0x040a: /* Kodak cameras */
640/* switch (product) { */
641/* case 0x0300: */
642 sd->subtype = KodakEZ200;
643/* break; */
644/* } */
645 break;
646 case 0x041e: /* Creative cameras */
647/* switch (product) { */
648/* case 0x400a: */
649 sd->subtype = CreativePCCam300;
650/* break; */
651/* } */
652 break;
653 case 0x046d: /* Logitech Labtec */
654 switch (product) {
655 case 0x0890:
656 sd->subtype = LogitechTraveler;
657 break;
658 case 0x0900:
659 sd->subtype = LogitechClickSmart310;
660 break;
661 case 0x0901:
662 sd->subtype = LogitechClickSmart510;
663 break;
664 }
665 break;
666 case 0x04a5: /* Benq */
667/* switch (product) { */
668/* case 0x300c: */
669 sd->subtype = BenqDC1016;
670/* break; */
671/* } */
672 break;
673 case 0x04fc: /* SunPlus */
674/* switch (product) { */
675/* case 0x7333: */
676 sd->subtype = PalmPixDC85;
677/* break; */
678/* } */
679 break;
680 case 0x055f: /* Mustek cameras */
681 switch (product) {
682 case 0xc200:
683 sd->subtype = MustekGsmart300;
684 break;
685 case 0xc220:
686 sd->subtype = Gsmartmini;
687 break;
688 }
689 break;
690 case 0x06bd: /* Agfa Cl20 */
691/* switch (product) { */
692/* case 0x0404: */
693 sd->subtype = AgfaCl20;
694/* break; */
695/* } */
696 break;
697 case 0x06be: /* Optimedia */
698/* switch (product) { */
699/* case 0x0800: */
700 sd->subtype = Optimedia;
701/* break; */
702/* } */
703 break;
704 case 0x084d: /* D-Link / Minton */
705/* switch (product) { */
706/* case 0x0003: * DSC-350 / S-Cam F5 */
707 sd->subtype = DLinkDSC350;
708/* break; */
709/* } */
710 break;
711 case 0x08ca: /* Aiptek */
712/* switch (product) { */
713/* case 0x0103: */
714 sd->subtype = AiptekPocketDV;
715/* break; */
716/* } */
717 break;
718 case 0x2899: /* ToptroIndustrial */
719/* switch (product) { */
720/* case 0x012c: */
721 sd->subtype = ToptroIndus;
722/* break; */
723/* } */
724 break;
725 case 0x8086: /* Intel */
726/* switch (product) { */
727/* case 0x0630: * Pocket PC Camera */
728 sd->subtype = IntelPocketPCCamera;
729/* break; */
730/* } */
731 break;
732 }
733 cam = &gspca_dev->cam;
734 cam->dev_name = (char *) id->driver_info;
735 cam->epaddr = 0x01;
736 if (sd->subtype != LogitechClickSmart310) {
737 cam->cam_mode = vga_mode;
738 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
739 } else {
740 cam->cam_mode = sif_mode;
741 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
742 }
743 sd->qindex = 5;
744 sd->brightness = BRIGHTNESS_DEF;
745 sd->contrast = CONTRAST_DEF;
746 sd->colors = COLOR_DEF;
747 return 0;
748}
749
750/* this function is called at open time */
751static int sd_open(struct gspca_dev *gspca_dev)
752{
753 struct sd *sd = (struct sd *) gspca_dev;
754
755 /* initialisation of spca500 based cameras is deferred */
756 PDEBUG(D_STREAM, "SPCA500 init");
757 if (sd->subtype == LogitechClickSmart310)
758 spca500_clksmart310_init(gspca_dev);
759/* else
760 spca500_initialise(gspca_dev); */
761 PDEBUG(D_STREAM, "SPCA500 init done");
762 return 0;
763}
764
765static void sd_start(struct gspca_dev *gspca_dev)
766{
767 struct sd *sd = (struct sd *) gspca_dev;
768 int err;
769 __u8 Data;
770 __u8 xmult, ymult;
771
772 if (sd->subtype == LogitechClickSmart310) {
773 xmult = 0x16;
774 ymult = 0x12;
775 } else {
776 xmult = 0x28;
777 ymult = 0x1e;
778 }
779
780 /* is there a sensor here ? */
781 reg_r(gspca_dev, 0x8a04, 1);
782 PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
783 gspca_dev->usb_buf[0]);
784 PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
785 gspca_dev->curr_mode, xmult, ymult);
786
787 /* setup qtable */
788 switch (sd->subtype) {
789 case LogitechClickSmart310:
790 spca500_setmode(gspca_dev, xmult, ymult);
791
792 /* enable drop packet */
793 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
794 reg_w(gspca_dev, 0x00, 0x8880, 3);
795 err = spca50x_setup_qtable(gspca_dev,
796 0x00, 0x8800, 0x8840,
797 qtable_creative_pccam);
798 if (err < 0)
799 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
800 /* Init SDRAM - needed for SDRAM access */
801 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
802
803 /* switch to video camera mode */
804 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
805 msleep(500);
806 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
807 PDEBUG(D_ERR, "reg_r_wait() failed");
808
809 reg_r(gspca_dev, 0x816b, 1);
810 Data = gspca_dev->usb_buf[0];
811 reg_w(gspca_dev, 0x00, 0x816b, Data);
812
813 spca500_synch310(gspca_dev);
814
815 write_vector(gspca_dev, spca500_visual_defaults);
816 spca500_setmode(gspca_dev, xmult, ymult);
817 /* enable drop packet */
818 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
819 PDEBUG(D_ERR, "failed to enable drop packet");
820 reg_w(gspca_dev, 0x00, 0x8880, 3);
821 err = spca50x_setup_qtable(gspca_dev,
822 0x00, 0x8800, 0x8840,
823 qtable_creative_pccam);
824 if (err < 0)
825 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
826
827 /* Init SDRAM - needed for SDRAM access */
828 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
829
830 /* switch to video camera mode */
831 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
832
833 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
834 PDEBUG(D_ERR, "reg_r_wait() failed");
835
836 reg_r(gspca_dev, 0x816b, 1);
837 Data = gspca_dev->usb_buf[0];
838 reg_w(gspca_dev, 0x00, 0x816b, Data);
839 break;
840 case CreativePCCam300: /* Creative PC-CAM 300 640x480 CCD */
841 case IntelPocketPCCamera: /* FIXME: Temporary fix for
842 * Intel Pocket PC Camera
843 * - NWG (Sat 29th March 2003) */
844
845 /* do a full reset */
846 err = spca500_full_reset(gspca_dev);
847 if (err < 0)
848 PDEBUG(D_ERR, "spca500_full_reset failed");
849
850 /* enable drop packet */
851 err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
852 if (err < 0)
853 PDEBUG(D_ERR, "failed to enable drop packet");
854 reg_w(gspca_dev, 0x00, 0x8880, 3);
855 err = spca50x_setup_qtable(gspca_dev,
856 0x00, 0x8800, 0x8840,
857 qtable_creative_pccam);
858 if (err < 0)
859 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
860
861 spca500_setmode(gspca_dev, xmult, ymult);
862 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
863
864 /* switch to video camera mode */
865 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
866
867 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
868 PDEBUG(D_ERR, "reg_r_wait() failed");
869
870 reg_r(gspca_dev, 0x816b, 1);
871 Data = gspca_dev->usb_buf[0];
872 reg_w(gspca_dev, 0x00, 0x816b, Data);
873
874/* write_vector(gspca_dev, spca500_visual_defaults); */
875 break;
876 case KodakEZ200: /* Kodak EZ200 */
877
878 /* do a full reset */
879 err = spca500_full_reset(gspca_dev);
880 if (err < 0)
881 PDEBUG(D_ERR, "spca500_full_reset failed");
882 /* enable drop packet */
883 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
884 reg_w(gspca_dev, 0x00, 0x8880, 0);
885 err = spca50x_setup_qtable(gspca_dev,
886 0x00, 0x8800, 0x8840,
887 qtable_kodak_ez200);
888 if (err < 0)
889 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
890 spca500_setmode(gspca_dev, xmult, ymult);
891
892 reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
893
894 /* switch to video camera mode */
895 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
896
897 if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
898 PDEBUG(D_ERR, "reg_r_wait() failed");
899
900 reg_r(gspca_dev, 0x816b, 1);
901 Data = gspca_dev->usb_buf[0];
902 reg_w(gspca_dev, 0x00, 0x816b, Data);
903
904/* write_vector(gspca_dev, spca500_visual_defaults); */
905 break;
906
907 case BenqDC1016:
908 case DLinkDSC350: /* FamilyCam 300 */
909 case AiptekPocketDV: /* Aiptek PocketDV */
910 case Gsmartmini: /*Mustek Gsmart Mini */
911 case MustekGsmart300: /* Mustek Gsmart 300 */
912 case PalmPixDC85:
913 case Optimedia:
914 case ToptroIndus:
915 case AgfaCl20:
916 spca500_reinit(gspca_dev);
917 reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
918 /* enable drop packet */
919 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
920
921 err = spca50x_setup_qtable(gspca_dev,
922 0x00, 0x8800, 0x8840, qtable_pocketdv);
923 if (err < 0)
924 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
925 reg_w(gspca_dev, 0x00, 0x8880, 2);
926
927 /* familycam Quicksmart pocketDV stuff */
928 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
929 /* Set agc transfer: synced inbetween frames */
930 reg_w(gspca_dev, 0x00, 0x820f, 0x01);
931 /* Init SDRAM - needed for SDRAM access */
932 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
933
934 spca500_setmode(gspca_dev, xmult, ymult);
935 /* switch to video camera mode */
936 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
937
938 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
939
940 reg_r(gspca_dev, 0x816b, 1);
941 Data = gspca_dev->usb_buf[0];
942 reg_w(gspca_dev, 0x00, 0x816b, Data);
943 break;
944 case LogitechTraveler:
945 case LogitechClickSmart510:
946 reg_w(gspca_dev, 0x02, 0x00, 0x00);
947 /* enable drop packet */
948 reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
949
950 err = spca50x_setup_qtable(gspca_dev,
951 0x00, 0x8800,
952 0x8840, qtable_creative_pccam);
953 if (err < 0)
954 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
955 reg_w(gspca_dev, 0x00, 0x8880, 3);
956 reg_w(gspca_dev, 0x00, 0x800a, 0x00);
957 /* Init SDRAM - needed for SDRAM access */
958 reg_w(gspca_dev, 0x00, 0x870a, 0x04);
959
960 spca500_setmode(gspca_dev, xmult, ymult);
961
962 /* switch to video camera mode */
963 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
964 reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
965
966 reg_r(gspca_dev, 0x816b, 1);
967 Data = gspca_dev->usb_buf[0];
968 reg_w(gspca_dev, 0x00, 0x816b, Data);
969 write_vector(gspca_dev, Clicksmart510_defaults);
970 break;
971 }
972}
973
974static void sd_stopN(struct gspca_dev *gspca_dev)
975{
976 reg_w(gspca_dev, 0, 0x8003, 0x00);
977
978 /* switch to video camera mode */
979 reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
980 reg_r(gspca_dev, 0x8000, 1);
981 PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
982 gspca_dev->usb_buf[0]);
983}
984
985static void sd_stop0(struct gspca_dev *gspca_dev)
986{
987}
988
989static void sd_close(struct gspca_dev *gspca_dev)
990{
991}
992
993static void sd_pkt_scan(struct gspca_dev *gspca_dev,
994 struct gspca_frame *frame, /* target */
995 __u8 *data, /* isoc packet */
996 int len) /* iso packet length */
997{
998 struct sd *sd = (struct sd *) gspca_dev;
999 int i;
1000 __u8 *s, *d;
1001 static __u8 ffd9[] = {0xff, 0xd9};
1002
1003/* frames are jpeg 4.1.1 without 0xff escape */
1004 if (data[0] == 0xff) {
1005 if (data[1] != 0x01) { /* drop packet */
1006/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1007 return;
1008 }
1009 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1010 ffd9, 2);
1011
1012 /* put the JPEG header in the new frame */
1013 jpeg_put_header(gspca_dev, frame, sd->qindex, 0x22);
1014
1015 data += SPCA500_OFFSET_DATA;
1016 len -= SPCA500_OFFSET_DATA;
1017 } else {
1018 data += 1;
1019 len -= 1;
1020 }
1021
1022 /* add 0x00 after 0xff */
1023 for (i = len; --i >= 0; )
1024 if (data[i] == 0xff)
1025 break;
1026 if (i < 0) { /* no 0xff */
1027 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1028 return;
1029 }
1030 s = data;
1031 d = sd->packet;
1032 for (i = 0; i < len; i++) {
1033 *d++ = *s++;
1034 if (s[-1] == 0xff)
1035 *d++ = 0x00;
1036 }
1037 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1038 sd->packet, d - sd->packet);
1039}
1040
1041static void setbrightness(struct gspca_dev *gspca_dev)
1042{
1043 struct sd *sd = (struct sd *) gspca_dev;
1044
1045 reg_w(gspca_dev, 0x00, 0x8167,
1046 (__u8) (sd->brightness - 128));
1047}
1048
1049static void getbrightness(struct gspca_dev *gspca_dev)
1050{
1051 struct sd *sd = (struct sd *) gspca_dev;
1052 int ret;
1053
1054 ret = reg_r_12(gspca_dev, 0x00, 0x8167, 1);
1055 if (ret >= 0)
1056 sd->brightness = ret + 128;
1057}
1058
1059static void setcontrast(struct gspca_dev *gspca_dev)
1060{
1061 struct sd *sd = (struct sd *) gspca_dev;
1062
1063 reg_w(gspca_dev, 0x00, 0x8168, sd->contrast);
1064}
1065
1066static void getcontrast(struct gspca_dev *gspca_dev)
1067{
1068 struct sd *sd = (struct sd *) gspca_dev;
1069 int ret;
1070
1071 ret = reg_r_12(gspca_dev, 0x0, 0x8168, 1);
1072 if (ret >= 0)
1073 sd->contrast = ret;
1074}
1075
1076static void setcolors(struct gspca_dev *gspca_dev)
1077{
1078 struct sd *sd = (struct sd *) gspca_dev;
1079
1080 reg_w(gspca_dev, 0x00, 0x8169, sd->colors);
1081}
1082
1083static void getcolors(struct gspca_dev *gspca_dev)
1084{
1085 struct sd *sd = (struct sd *) gspca_dev;
1086 int ret;
1087
1088 ret = reg_r_12(gspca_dev, 0x0, 0x8169, 1);
1089 if (ret >= 0)
1090 sd->colors = ret;
1091}
1092
1093static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1094{
1095 struct sd *sd = (struct sd *) gspca_dev;
1096
1097 sd->brightness = val;
1098 if (gspca_dev->streaming)
1099 setbrightness(gspca_dev);
1100 return 0;
1101}
1102
1103static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1104{
1105 struct sd *sd = (struct sd *) gspca_dev;
1106
1107 getbrightness(gspca_dev);
1108 *val = sd->brightness;
1109 return 0;
1110}
1111
1112static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1113{
1114 struct sd *sd = (struct sd *) gspca_dev;
1115
1116 sd->contrast = val;
1117 if (gspca_dev->streaming)
1118 setcontrast(gspca_dev);
1119 return 0;
1120}
1121
1122static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1123{
1124 struct sd *sd = (struct sd *) gspca_dev;
1125
1126 getcontrast(gspca_dev);
1127 *val = sd->contrast;
1128 return 0;
1129}
1130
1131static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1132{
1133 struct sd *sd = (struct sd *) gspca_dev;
1134
1135 sd->colors = val;
1136 if (gspca_dev->streaming)
1137 setcolors(gspca_dev);
1138 return 0;
1139}
1140
1141static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1142{
1143 struct sd *sd = (struct sd *) gspca_dev;
1144
1145 getcolors(gspca_dev);
1146 *val = sd->colors;
1147 return 0;
1148}
1149
1150/* sub-driver description */
1151static struct sd_desc sd_desc = {
1152 .name = MODULE_NAME,
1153 .ctrls = sd_ctrls,
1154 .nctrls = ARRAY_SIZE(sd_ctrls),
1155 .config = sd_config,
1156 .open = sd_open,
1157 .start = sd_start,
1158 .stopN = sd_stopN,
1159 .stop0 = sd_stop0,
1160 .close = sd_close,
1161 .pkt_scan = sd_pkt_scan,
1162};
1163
1164/* -- module initialisation -- */
1165#define DVNM(name) .driver_info = (kernel_ulong_t) name
1166static const __devinitdata struct usb_device_id device_table[] = {
1167 {USB_DEVICE(0x040a, 0x0300), DVNM("Kodak EZ200")},
1168 {USB_DEVICE(0x041e, 0x400a), DVNM("Creative PC-CAM 300")},
1169 {USB_DEVICE(0x046d, 0x0890), DVNM("Logitech QuickCam traveler")},
1170 {USB_DEVICE(0x046d, 0x0900), DVNM("Logitech Inc. ClickSmart 310")},
1171 {USB_DEVICE(0x046d, 0x0901), DVNM("Logitech Inc. ClickSmart 510")},
1172 {USB_DEVICE(0x04a5, 0x300c), DVNM("Benq DC1016")},
1173 {USB_DEVICE(0x04fc, 0x7333), DVNM("PalmPixDC85")},
1174 {USB_DEVICE(0x055f, 0xc200), DVNM("Mustek Gsmart 300")},
1175 {USB_DEVICE(0x055f, 0xc220), DVNM("Gsmart Mini")},
1176 {USB_DEVICE(0x06bd, 0x0404), DVNM("Agfa CL20")},
1177 {USB_DEVICE(0x06be, 0x0800), DVNM("Optimedia")},
1178 {USB_DEVICE(0x084d, 0x0003), DVNM("D-Link DSC-350")},
1179 {USB_DEVICE(0x08ca, 0x0103), DVNM("Aiptek PocketDV")},
1180 {USB_DEVICE(0x2899, 0x012c), DVNM("Toptro Industrial")},
1181 {USB_DEVICE(0x8086, 0x0630), DVNM("Intel Pocket PC Camera")},
1182 {}
1183};
1184MODULE_DEVICE_TABLE(usb, device_table);
1185
1186/* -- device connect -- */
1187static int sd_probe(struct usb_interface *intf,
1188 const struct usb_device_id *id)
1189{
1190 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1191 THIS_MODULE);
1192}
1193
1194static struct usb_driver sd_driver = {
1195 .name = MODULE_NAME,
1196 .id_table = device_table,
1197 .probe = sd_probe,
1198 .disconnect = gspca_disconnect,
1199};
1200
1201/* -- module insert / remove -- */
1202static int __init sd_mod_init(void)
1203{
1204 if (usb_register(&sd_driver) < 0)
1205 return -1;
1206 PDEBUG(D_PROBE, "v%s registered", version);
1207 return 0;
1208}
1209static void __exit sd_mod_exit(void)
1210{
1211 usb_deregister(&sd_driver);
1212 PDEBUG(D_PROBE, "deregistered");
1213}
1214
1215module_init(sd_mod_init);
1216module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
new file mode 100644
index 000000000000..50e929de0203
--- /dev/null
+++ b/drivers/media/video/gspca/spca501.c
@@ -0,0 +1,2229 @@
1/*
2 * SPCA501 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca501"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 unsigned short contrast;
38 __u8 brightness;
39 __u8 colors;
40
41 char subtype;
42#define Arowana300KCMOSCamera 0
43#define IntelCreateAndShare 1
44#define KodakDVC325 2
45#define MystFromOriUnknownCamera 3
46#define SmileIntlCamera 4
47#define ThreeComHomeConnectLite 5
48#define ViewQuestM318B 6
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
58
59static struct ctrl sd_ctrls[] = {
60#define MY_BRIGHTNESS 0
61 {
62 {
63 .id = V4L2_CID_BRIGHTNESS,
64 .type = V4L2_CTRL_TYPE_INTEGER,
65 .name = "Brightness",
66 .minimum = 0,
67 .maximum = 127,
68 .step = 1,
69 .default_value = 63,
70 },
71 .set = sd_setbrightness,
72 .get = sd_getbrightness,
73 },
74#define MY_CONTRAST 1
75 {
76 {
77 .id = V4L2_CID_CONTRAST,
78 .type = V4L2_CTRL_TYPE_INTEGER,
79 .name = "Contrast",
80 .minimum = 0,
81 .maximum = 0xffff,
82 .step = 1,
83 .default_value = 0xaa00,
84 },
85 .set = sd_setcontrast,
86 .get = sd_getcontrast,
87 },
88#define MY_COLOR 2
89 {
90 {
91 .id = V4L2_CID_SATURATION,
92 .type = V4L2_CTRL_TYPE_INTEGER,
93 .name = "Color",
94 .minimum = 0,
95 .maximum = 63,
96 .step = 1,
97 .default_value = 31,
98 },
99 .set = sd_setcolors,
100 .get = sd_getcolors,
101 },
102};
103
104static struct v4l2_pix_format vga_mode[] = {
105 {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
106 .bytesperline = 160,
107 .sizeimage = 160 * 120 * 3 / 2,
108 .colorspace = V4L2_COLORSPACE_SRGB,
109 .priv = 2},
110 {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
111 .bytesperline = 320,
112 .sizeimage = 320 * 240 * 3 / 2,
113 .colorspace = V4L2_COLORSPACE_SRGB,
114 .priv = 1},
115 {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
116 .bytesperline = 640,
117 .sizeimage = 640 * 480 * 3 / 2,
118 .colorspace = V4L2_COLORSPACE_SRGB,
119 .priv = 0},
120};
121
122#define SPCA50X_REG_USB 0x2 /* spca505 501 */
123/*
124 * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
125 * With SPCA501 chip description
126 */
127#define CCDSP_SET /* set CCDSP parameters */
128#define TG_SET /* set time generator set */
129#undef DSPWIN_SET /* set DSP windows parameters */
130#undef ALTER_GAMA /* Set alternate set to YUV transform coeffs. */
131#define SPCA501_SNAPBIT 0x80
132#define SPCA501_SNAPCTRL 0x10
133/* Frame packet header offsets for the spca501 */
134#define SPCA501_OFFSET_GPIO 1
135#define SPCA501_OFFSET_TYPE 2
136#define SPCA501_OFFSET_TURN3A 3
137#define SPCA501_OFFSET_FRAMSEQ 4
138#define SPCA501_OFFSET_COMPRESS 5
139#define SPCA501_OFFSET_QUANT 6
140#define SPCA501_OFFSET_QUANT2 7
141#define SPCA501_OFFSET_DATA 8
142
143#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
144#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
145#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
146#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
147#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
148
149/* SPCA501 CCDSP control */
150#define SPCA501_REG_CCDSP 0x01
151/* SPCA501 control/status registers */
152#define SPCA501_REG_CTLRL 0x02
153
154/* registers for color correction and YUV transformation */
155#define SPCA501_A11 0x08
156#define SPCA501_A12 0x09
157#define SPCA501_A13 0x0A
158#define SPCA501_A21 0x0B
159#define SPCA501_A22 0x0C
160#define SPCA501_A23 0x0D
161#define SPCA501_A31 0x0E
162#define SPCA501_A32 0x0F
163#define SPCA501_A33 0x10
164
165/* Data for video camera initialization before capturing */
166static const __u16 spca501_open_data[][3] = {
167 /* bmRequest,value,index */
168
169 {0x2, 0x50, 0x00}, /* C/S enable soft reset */
170 {0x2, 0x40, 0x00}, /* C/S disable soft reset */
171 {0x2, 0x02, 0x05}, /* C/S general purpose I/O data */
172 {0x2, 0x03, 0x05}, /* C/S general purpose I/O data */
173
174#ifdef CCDSP_SET
175 {0x1, 0x38, 0x01}, /* CCDSP options */
176 {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
177 {0x1, 0xC0, 0x03}, /* CCDSP Optical black settings */
178
179 {0x1, 0x67, 0x07},
180 {0x1, 0x63, 0x3f}, /* CCDSP CCD gamma enable */
181 {0x1, 0x03, 0x56}, /* Add gamma correction */
182
183 {0x1, 0xFF, 0x15}, /* CCDSP High luminance for white balance */
184 {0x1, 0x01, 0x16}, /* CCDSP Low luminance for white balance */
185
186/* Color correction and RGB-to-YUV transformation coefficients changing */
187#ifdef ALTER_GAMA
188 {0x0, 0x00, 0x08}, /* A11 */
189 {0x0, 0x00, 0x09}, /* A12 */
190 {0x0, 0x90, 0x0A}, /* A13 */
191 {0x0, 0x12, 0x0B}, /* A21 */
192 {0x0, 0x00, 0x0C}, /* A22 */
193 {0x0, 0x00, 0x0D}, /* A23 */
194 {0x0, 0x00, 0x0E}, /* A31 */
195 {0x0, 0x02, 0x0F}, /* A32 */
196 {0x0, 0x00, 0x10}, /* A33 */
197#else
198 {0x1, 0x2a, 0x08}, /* A11 0x31 */
199 {0x1, 0xf8, 0x09}, /* A12 f8 */
200 {0x1, 0xf8, 0x0A}, /* A13 f8 */
201 {0x1, 0xf8, 0x0B}, /* A21 f8 */
202 {0x1, 0x14, 0x0C}, /* A22 0x14 */
203 {0x1, 0xf8, 0x0D}, /* A23 f8 */
204 {0x1, 0xf8, 0x0E}, /* A31 f8 */
205 {0x1, 0xf8, 0x0F}, /* A32 f8 */
206 {0x1, 0x20, 0x10}, /* A33 0x20 */
207#endif
208 {0x1, 0x00, 0x11}, /* R offset */
209 {0x1, 0x00, 0x12}, /* G offset */
210 {0x1, 0x00, 0x13}, /* B offset */
211 {0x1, 0x00, 0x14}, /* GB offset */
212
213#endif
214
215#ifdef TG_SET
216 /* Time generator manipulations */
217 {0x0, 0xfc, 0x0}, /* Set up high bits of shutter speed */
218 {0x0, 0x01, 0x1}, /* Set up low bits of shutter speed */
219
220 {0x0, 0xe4, 0x04}, /* DCLK*2 clock phase adjustment */
221 {0x0, 0x08, 0x05}, /* ADCK phase adjustment, inv. ext. VB */
222 {0x0, 0x03, 0x06}, /* FR phase adjustment */
223 {0x0, 0x01, 0x07}, /* FCDS phase adjustment */
224 {0x0, 0x39, 0x08}, /* FS phase adjustment */
225 {0x0, 0x88, 0x0a}, /* FH1 phase and delay adjustment */
226 {0x0, 0x03, 0x0f}, /* pixel identification */
227 {0x0, 0x00, 0x11}, /* clock source selection (default) */
228
229 /*VERY strange manipulations with
230 * select DMCLP or OBPX to be ADCLP output (0x0C)
231 * OPB always toggle or not (0x0D) but they allow
232 * us to set up brightness
233 */
234 {0x0, 0x01, 0x0c},
235 {0x0, 0xe0, 0x0d},
236 /* Done */
237#endif
238
239#ifdef DSPWIN_SET
240 {0x1, 0xa0, 0x01}, /* Setting image processing parameters */
241 {0x1, 0x1c, 0x17}, /* Changing Windows positions X1 */
242 {0x1, 0xe2, 0x19}, /* X2 */
243 {0x1, 0x1c, 0x1b}, /* X3 */
244 {0x1, 0xe2, 0x1d}, /* X4 */
245 {0x1, 0x5f, 0x1f}, /* X5 */
246 {0x1, 0x32, 0x20}, /* Y5 */
247 {0x1, 0x01, 0x10}, /* Changing A33 */
248#endif
249
250 {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
251 {0x2, 0x94, 0x06}, /* Setting video no compression */
252 {}
253};
254
255/*
256 The SPCAxxx docs from Sunplus document these values
257 in tables, one table per register number. In the data
258 below, dmRequest is the register number, index is the Addr,
259 and value is a combination of Bit values.
260 Bit Value (hex)
261 0 01
262 1 02
263 2 04
264 3 08
265 4 10
266 5 20
267 6 40
268 7 80
269 */
270
271/* Data for chip initialization (set default values) */
272static const __u16 spca501_init_data[][3] = {
273 /* Set all the values to powerup defaults */
274 /* bmRequest,value,index */
275 {0x0, 0xAA, 0x00},
276 {0x0, 0x02, 0x01},
277 {0x0, 0x01, 0x02},
278 {0x0, 0x02, 0x03},
279 {0x0, 0xCE, 0x04},
280 {0x0, 0x00, 0x05},
281 {0x0, 0x00, 0x06},
282 {0x0, 0x00, 0x07},
283 {0x0, 0x00, 0x08},
284 {0x0, 0x00, 0x09},
285 {0x0, 0x90, 0x0A},
286 {0x0, 0x12, 0x0B},
287 {0x0, 0x00, 0x0C},
288 {0x0, 0x00, 0x0D},
289 {0x0, 0x00, 0x0E},
290 {0x0, 0x02, 0x0F},
291 {0x0, 0x00, 0x10},
292 {0x0, 0x00, 0x11},
293 {0x0, 0x00, 0x12},
294 {0x0, 0x00, 0x13},
295 {0x0, 0x00, 0x14},
296 {0x0, 0x00, 0x15},
297 {0x0, 0x00, 0x16},
298 {0x0, 0x00, 0x17},
299 {0x0, 0x00, 0x18},
300 {0x0, 0x00, 0x19},
301 {0x0, 0x00, 0x1A},
302 {0x0, 0x00, 0x1B},
303 {0x0, 0x00, 0x1C},
304 {0x0, 0x00, 0x1D},
305 {0x0, 0x00, 0x1E},
306 {0x0, 0x00, 0x1F},
307 {0x0, 0x00, 0x20},
308 {0x0, 0x00, 0x21},
309 {0x0, 0x00, 0x22},
310 {0x0, 0x00, 0x23},
311 {0x0, 0x00, 0x24},
312 {0x0, 0x00, 0x25},
313 {0x0, 0x00, 0x26},
314 {0x0, 0x00, 0x27},
315 {0x0, 0x00, 0x28},
316 {0x0, 0x00, 0x29},
317 {0x0, 0x00, 0x2A},
318 {0x0, 0x00, 0x2B},
319 {0x0, 0x00, 0x2C},
320 {0x0, 0x00, 0x2D},
321 {0x0, 0x00, 0x2E},
322 {0x0, 0x00, 0x2F},
323 {0x0, 0x00, 0x30},
324 {0x0, 0x00, 0x31},
325 {0x0, 0x00, 0x32},
326 {0x0, 0x00, 0x33},
327 {0x0, 0x00, 0x34},
328 {0x0, 0x00, 0x35},
329 {0x0, 0x00, 0x36},
330 {0x0, 0x00, 0x37},
331 {0x0, 0x00, 0x38},
332 {0x0, 0x00, 0x39},
333 {0x0, 0x00, 0x3A},
334 {0x0, 0x00, 0x3B},
335 {0x0, 0x00, 0x3C},
336 {0x0, 0x00, 0x3D},
337 {0x0, 0x00, 0x3E},
338 {0x0, 0x00, 0x3F},
339 {0x0, 0x00, 0x40},
340 {0x0, 0x00, 0x41},
341 {0x0, 0x00, 0x42},
342 {0x0, 0x00, 0x43},
343 {0x0, 0x00, 0x44},
344 {0x0, 0x00, 0x45},
345 {0x0, 0x00, 0x46},
346 {0x0, 0x00, 0x47},
347 {0x0, 0x00, 0x48},
348 {0x0, 0x00, 0x49},
349 {0x0, 0x00, 0x4A},
350 {0x0, 0x00, 0x4B},
351 {0x0, 0x00, 0x4C},
352 {0x0, 0x00, 0x4D},
353 {0x0, 0x00, 0x4E},
354 {0x0, 0x00, 0x4F},
355 {0x0, 0x00, 0x50},
356 {0x0, 0x00, 0x51},
357 {0x0, 0x00, 0x52},
358 {0x0, 0x00, 0x53},
359 {0x0, 0x00, 0x54},
360 {0x0, 0x00, 0x55},
361 {0x0, 0x00, 0x56},
362 {0x0, 0x00, 0x57},
363 {0x0, 0x00, 0x58},
364 {0x0, 0x00, 0x59},
365 {0x0, 0x00, 0x5A},
366 {0x0, 0x00, 0x5B},
367 {0x0, 0x00, 0x5C},
368 {0x0, 0x00, 0x5D},
369 {0x0, 0x00, 0x5E},
370 {0x0, 0x00, 0x5F},
371 {0x0, 0x00, 0x60},
372 {0x0, 0x00, 0x61},
373 {0x0, 0x00, 0x62},
374 {0x0, 0x00, 0x63},
375 {0x0, 0x00, 0x64},
376 {0x0, 0x00, 0x65},
377 {0x0, 0x00, 0x66},
378 {0x0, 0x00, 0x67},
379 {0x0, 0x00, 0x68},
380 {0x0, 0x00, 0x69},
381 {0x0, 0x00, 0x6A},
382 {0x0, 0x00, 0x6B},
383 {0x0, 0x00, 0x6C},
384 {0x0, 0x00, 0x6D},
385 {0x0, 0x00, 0x6E},
386 {0x0, 0x00, 0x6F},
387 {0x0, 0x00, 0x70},
388 {0x0, 0x00, 0x71},
389 {0x0, 0x00, 0x72},
390 {0x0, 0x00, 0x73},
391 {0x0, 0x00, 0x74},
392 {0x0, 0x00, 0x75},
393 {0x0, 0x00, 0x76},
394 {0x0, 0x00, 0x77},
395 {0x0, 0x00, 0x78},
396 {0x0, 0x00, 0x79},
397 {0x0, 0x00, 0x7A},
398 {0x0, 0x00, 0x7B},
399 {0x0, 0x00, 0x7C},
400 {0x0, 0x00, 0x7D},
401 {0x0, 0x00, 0x7E},
402 {0x0, 0x00, 0x7F},
403 {0x0, 0x00, 0x80},
404 {0x0, 0x00, 0x81},
405 {0x0, 0x00, 0x82},
406 {0x0, 0x00, 0x83},
407 {0x0, 0x00, 0x84},
408 {0x0, 0x00, 0x85},
409 {0x0, 0x00, 0x86},
410 {0x0, 0x00, 0x87},
411 {0x0, 0x00, 0x88},
412 {0x0, 0x00, 0x89},
413 {0x0, 0x00, 0x8A},
414 {0x0, 0x00, 0x8B},
415 {0x0, 0x00, 0x8C},
416 {0x0, 0x00, 0x8D},
417 {0x0, 0x00, 0x8E},
418 {0x0, 0x00, 0x8F},
419 {0x0, 0x00, 0x90},
420 {0x0, 0x00, 0x91},
421 {0x0, 0x00, 0x92},
422 {0x0, 0x00, 0x93},
423 {0x0, 0x00, 0x94},
424 {0x0, 0x00, 0x95},
425 {0x0, 0x00, 0x96},
426 {0x0, 0x00, 0x97},
427 {0x0, 0x00, 0x98},
428 {0x0, 0x00, 0x99},
429 {0x0, 0x00, 0x9A},
430 {0x0, 0x00, 0x9B},
431 {0x0, 0x00, 0x9C},
432 {0x0, 0x00, 0x9D},
433 {0x0, 0x00, 0x9E},
434 {0x0, 0x00, 0x9F},
435 {0x0, 0x00, 0xA0},
436 {0x0, 0x00, 0xA1},
437 {0x0, 0x00, 0xA2},
438 {0x0, 0x00, 0xA3},
439 {0x0, 0x00, 0xA4},
440 {0x0, 0x00, 0xA5},
441 {0x0, 0x00, 0xA6},
442 {0x0, 0x00, 0xA7},
443 {0x0, 0x00, 0xA8},
444 {0x0, 0x00, 0xA9},
445 {0x0, 0x00, 0xAA},
446 {0x0, 0x00, 0xAB},
447 {0x0, 0x00, 0xAC},
448 {0x0, 0x00, 0xAD},
449 {0x0, 0x00, 0xAE},
450 {0x0, 0x00, 0xAF},
451 {0x0, 0x00, 0xB0},
452 {0x0, 0x00, 0xB1},
453 {0x0, 0x00, 0xB2},
454 {0x0, 0x00, 0xB3},
455 {0x0, 0x00, 0xB4},
456 {0x0, 0x00, 0xB5},
457 {0x0, 0x00, 0xB6},
458 {0x0, 0x00, 0xB7},
459 {0x0, 0x00, 0xB8},
460 {0x0, 0x00, 0xB9},
461 {0x0, 0x00, 0xBA},
462 {0x0, 0x00, 0xBB},
463 {0x0, 0x00, 0xBC},
464 {0x0, 0x00, 0xBD},
465 {0x0, 0x00, 0xBE},
466 {0x0, 0x00, 0xBF},
467 {0x0, 0x00, 0xC0},
468 {0x0, 0x00, 0xC1},
469 {0x0, 0x00, 0xC2},
470 {0x0, 0x00, 0xC3},
471 {0x0, 0x00, 0xC4},
472 {0x0, 0x00, 0xC5},
473 {0x0, 0x00, 0xC6},
474 {0x0, 0x00, 0xC7},
475 {0x0, 0x00, 0xC8},
476 {0x0, 0x00, 0xC9},
477 {0x0, 0x00, 0xCA},
478 {0x0, 0x00, 0xCB},
479 {0x0, 0x00, 0xCC},
480 {0x1, 0xF4, 0x00},
481 {0x1, 0x38, 0x01},
482 {0x1, 0x40, 0x02},
483 {0x1, 0x0A, 0x03},
484 {0x1, 0x40, 0x04},
485 {0x1, 0x40, 0x05},
486 {0x1, 0x40, 0x06},
487 {0x1, 0x67, 0x07},
488 {0x1, 0x31, 0x08},
489 {0x1, 0x00, 0x09},
490 {0x1, 0x00, 0x0A},
491 {0x1, 0x00, 0x0B},
492 {0x1, 0x14, 0x0C},
493 {0x1, 0x00, 0x0D},
494 {0x1, 0x00, 0x0E},
495 {0x1, 0x00, 0x0F},
496 {0x1, 0x1E, 0x10},
497 {0x1, 0x00, 0x11},
498 {0x1, 0x00, 0x12},
499 {0x1, 0x00, 0x13},
500 {0x1, 0x00, 0x14},
501 {0x1, 0xFF, 0x15},
502 {0x1, 0x01, 0x16},
503 {0x1, 0x32, 0x17},
504 {0x1, 0x23, 0x18},
505 {0x1, 0xCE, 0x19},
506 {0x1, 0x23, 0x1A},
507 {0x1, 0x32, 0x1B},
508 {0x1, 0x8D, 0x1C},
509 {0x1, 0xCE, 0x1D},
510 {0x1, 0x8D, 0x1E},
511 {0x1, 0x00, 0x1F},
512 {0x1, 0x00, 0x20},
513 {0x1, 0xFF, 0x3E},
514 {0x1, 0x02, 0x3F},
515 {0x1, 0x00, 0x40},
516 {0x1, 0x00, 0x41},
517 {0x1, 0x00, 0x42},
518 {0x1, 0x00, 0x43},
519 {0x1, 0x00, 0x44},
520 {0x1, 0x00, 0x45},
521 {0x1, 0x00, 0x46},
522 {0x1, 0x00, 0x47},
523 {0x1, 0x00, 0x48},
524 {0x1, 0x00, 0x49},
525 {0x1, 0x00, 0x4A},
526 {0x1, 0x00, 0x4B},
527 {0x1, 0x00, 0x4C},
528 {0x1, 0x00, 0x4D},
529 {0x1, 0x00, 0x4E},
530 {0x1, 0x00, 0x4F},
531 {0x1, 0x00, 0x50},
532 {0x1, 0x00, 0x51},
533 {0x1, 0x00, 0x52},
534 {0x1, 0x00, 0x53},
535 {0x1, 0x00, 0x54},
536 {0x1, 0x00, 0x55},
537 {0x1, 0x00, 0x56},
538 {0x1, 0x00, 0x57},
539 {0x1, 0x00, 0x58},
540 {0x1, 0x00, 0x59},
541 {0x1, 0x00, 0x5A},
542 {0x2, 0x03, 0x00},
543 {0x2, 0x00, 0x01},
544 {0x2, 0x00, 0x05},
545 {0x2, 0x00, 0x06},
546 {0x2, 0x00, 0x07},
547 {0x2, 0x00, 0x10},
548 {0x2, 0x00, 0x11},
549 /* Strange - looks like the 501 driver doesn't do anything
550 * at insert time except read the EEPROM
551 */
552 {}
553};
554
555/* Data for video camera init before capture.
556 * Capture and decoding by Colin Peart.
557 * This is is for the 3com HomeConnect Lite which is spca501a based.
558 */
559static const __u16 spca501_3com_open_data[][3] = {
560 /* bmRequest,value,index */
561 {0x2, 0x0050, 0x0000}, /* C/S Enable TG soft reset, timing mode=010 */
562 {0x2, 0x0043, 0x0000}, /* C/S Disable TG soft reset, timing mode=010 */
563 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
564 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
565
566#ifdef CCDSP_SET
567 {0x1, 0x0020, 0x0001}, /* CCDSP Options */
568
569 {0x1, 0x0020, 0x0002}, /* CCDSP Black Level */
570 {0x1, 0x006e, 0x0007}, /* CCDSP Gamma options */
571 {0x1, 0x0090, 0x0015}, /* CCDSP Luminance Low */
572 {0x1, 0x00ff, 0x0016}, /* CCDSP Luminance High */
573 {0x1, 0x0003, 0x003F}, /* CCDSP Gamma correction toggle */
574
575#ifdef ALTER_GAMMA
576 {0x1, 0x0010, 0x0008}, /* CCDSP YUV A11 */
577 {0x1, 0x0000, 0x0009}, /* CCDSP YUV A12 */
578 {0x1, 0x0000, 0x000a}, /* CCDSP YUV A13 */
579 {0x1, 0x0000, 0x000b}, /* CCDSP YUV A21 */
580 {0x1, 0x0010, 0x000c}, /* CCDSP YUV A22 */
581 {0x1, 0x0000, 0x000d}, /* CCDSP YUV A23 */
582 {0x1, 0x0000, 0x000e}, /* CCDSP YUV A31 */
583 {0x1, 0x0000, 0x000f}, /* CCDSP YUV A32 */
584 {0x1, 0x0010, 0x0010}, /* CCDSP YUV A33 */
585 {0x1, 0x0000, 0x0011}, /* CCDSP R Offset */
586 {0x1, 0x0000, 0x0012}, /* CCDSP G Offset */
587 {0x1, 0x0001, 0x0013}, /* CCDSP B Offset */
588 {0x1, 0x0001, 0x0014}, /* CCDSP BG Offset */
589 {0x1, 0x003f, 0x00C1}, /* CCDSP Gamma Correction Enable */
590#endif
591#endif
592
593#ifdef TG_SET
594 {0x0, 0x00fc, 0x0000}, /* TG Shutter Speed High Bits */
595 {0x0, 0x0000, 0x0001}, /* TG Shutter Speed Low Bits */
596 {0x0, 0x00e4, 0x0004}, /* TG DCLK*2 Adjust */
597 {0x0, 0x0008, 0x0005}, /* TG ADCK Adjust */
598 {0x0, 0x0003, 0x0006}, /* TG FR Phase Adjust */
599 {0x0, 0x0001, 0x0007}, /* TG FCDS Phase Adjust */
600 {0x0, 0x0039, 0x0008}, /* TG FS Phase Adjust */
601 {0x0, 0x0088, 0x000a}, /* TG MH1 */
602 {0x0, 0x0003, 0x000f}, /* TG Pixel ID */
603
604 /* Like below, unexplained toglleing */
605 {0x0, 0x0080, 0x000c},
606 {0x0, 0x0000, 0x000d},
607 {0x0, 0x0080, 0x000c},
608 {0x0, 0x0004, 0x000d},
609 {0x0, 0x0000, 0x000c},
610 {0x0, 0x0000, 0x000d},
611 {0x0, 0x0040, 0x000c},
612 {0x0, 0x0017, 0x000d},
613 {0x0, 0x00c0, 0x000c},
614 {0x0, 0x0000, 0x000d},
615 {0x0, 0x0080, 0x000c},
616 {0x0, 0x0006, 0x000d},
617 {0x0, 0x0080, 0x000c},
618 {0x0, 0x0004, 0x000d},
619 {0x0, 0x0002, 0x0003},
620#endif
621
622#ifdef DSPWIN_SET
623 {0x1, 0x001c, 0x0017}, /* CCDSP W1 Start X */
624 {0x1, 0x00e2, 0x0019}, /* CCDSP W2 Start X */
625 {0x1, 0x001c, 0x001b}, /* CCDSP W3 Start X */
626 {0x1, 0x00e2, 0x001d}, /* CCDSP W4 Start X */
627 {0x1, 0x00aa, 0x001f}, /* CCDSP W5 Start X */
628 {0x1, 0x0070, 0x0020}, /* CCDSP W5 Start Y */
629#endif
630 {0x0, 0x0001, 0x0010}, /* TG Start Clock */
631
632/* {0x2, 0x006a, 0x0001}, * C/S Enable ISOSYNCH Packet Engine */
633 {0x2, 0x0068, 0x0001}, /* C/S Diable ISOSYNCH Packet Engine */
634 {0x2, 0x0000, 0x0005},
635 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
636 {0x2, 0x0043, 0x0000}, /* C/S Set Timing Mode, Disable TG soft reset */
637 {0x2, 0x0002, 0x0005}, /* C/S GPIO */
638 {0x2, 0x0003, 0x0005}, /* C/S GPIO */
639
640 {0x2, 0x006a, 0x0001}, /* C/S Enable ISOSYNCH Packet Engine */
641 {}
642};
643
644/*
645 * Data used to initialize a SPCA501C with HV7131B sensor.
646 * From a capture file taken with USBSnoop v 1.5
647 * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
648 * of the value meanings are obscure or simply "reserved".
649 * to do list:
650 * 1) Understand what every value means
651 * 2) Understand why some values seem to appear more than once
652 * 3) Write a small comment for each line of the following arrays.
653 */
654static const __u16 spca501c_arowana_open_data[][3] = {
655 /* bmRequest,value,index */
656 {0x02, 0x0007, 0x0005},
657 {0x02, 0xa048, 0x0000},
658 {0x05, 0x0022, 0x0004},
659 {0x01, 0x0006, 0x0011},
660 {0x01, 0x00ff, 0x0012},
661 {0x01, 0x0014, 0x0013},
662 {0x01, 0x0000, 0x0014},
663 {0x01, 0x0042, 0x0051},
664 {0x01, 0x0040, 0x0052},
665 {0x01, 0x0051, 0x0053},
666 {0x01, 0x0040, 0x0054},
667 {0x01, 0x0000, 0x0055},
668 {0x00, 0x0025, 0x0000},
669 {0x00, 0x0026, 0x0000},
670 {0x00, 0x0001, 0x0000},
671 {0x00, 0x0027, 0x0000},
672 {0x00, 0x008a, 0x0000},
673 {}
674};
675
676static const __u16 spca501c_arowana_init_data[][3] = {
677 /* bmRequest,value,index */
678 {0x02, 0x0007, 0x0005},
679 {0x02, 0xa048, 0x0000},
680 {0x05, 0x0022, 0x0004},
681 {0x01, 0x0006, 0x0011},
682 {0x01, 0x00ff, 0x0012},
683 {0x01, 0x0014, 0x0013},
684 {0x01, 0x0000, 0x0014},
685 {0x01, 0x0042, 0x0051},
686 {0x01, 0x0040, 0x0052},
687 {0x01, 0x0051, 0x0053},
688 {0x01, 0x0040, 0x0054},
689 {0x01, 0x0000, 0x0055},
690 {0x00, 0x0025, 0x0000},
691 {0x00, 0x0026, 0x0000},
692 {0x00, 0x0001, 0x0000},
693 {0x00, 0x0027, 0x0000},
694 {0x00, 0x008a, 0x0000},
695 {0x02, 0x0000, 0x0005},
696 {0x02, 0x0007, 0x0005},
697 {0x02, 0x2000, 0x0000},
698 {0x05, 0x0022, 0x0004},
699 {0x05, 0x0015, 0x0001},
700 {0x05, 0x00ea, 0x0000},
701 {0x05, 0x0021, 0x0001},
702 {0x05, 0x00d2, 0x0000},
703 {0x05, 0x0023, 0x0001},
704 {0x05, 0x0003, 0x0000},
705 {0x05, 0x0030, 0x0001},
706 {0x05, 0x002b, 0x0000},
707 {0x05, 0x0031, 0x0001},
708 {0x05, 0x0023, 0x0000},
709 {0x05, 0x0032, 0x0001},
710 {0x05, 0x0023, 0x0000},
711 {0x05, 0x0033, 0x0001},
712 {0x05, 0x0023, 0x0000},
713 {0x05, 0x0034, 0x0001},
714 {0x05, 0x0002, 0x0000},
715 {0x05, 0x0050, 0x0001},
716 {0x05, 0x0000, 0x0000},
717 {0x05, 0x0051, 0x0001},
718 {0x05, 0x0000, 0x0000},
719 {0x05, 0x0052, 0x0001},
720 {0x05, 0x0000, 0x0000},
721 {0x05, 0x0054, 0x0001},
722 {0x05, 0x0001, 0x0000},
723 {0x00, 0x0000, 0x0001},
724 {0x00, 0x0000, 0x0002},
725 {0x00, 0x000c, 0x0003},
726 {0x00, 0x0000, 0x0004},
727 {0x00, 0x0090, 0x0005},
728 {0x00, 0x0000, 0x0006},
729 {0x00, 0x0040, 0x0007},
730 {0x00, 0x00c0, 0x0008},
731 {0x00, 0x004a, 0x0009},
732 {0x00, 0x0000, 0x000a},
733 {0x00, 0x0000, 0x000b},
734 {0x00, 0x0001, 0x000c},
735 {0x00, 0x0001, 0x000d},
736 {0x00, 0x0000, 0x000e},
737 {0x00, 0x0002, 0x000f},
738 {0x00, 0x0001, 0x0010},
739 {0x00, 0x0000, 0x0011},
740 {0x00, 0x0000, 0x0012},
741 {0x00, 0x0002, 0x0020},
742 {0x00, 0x0080, 0x0021},
743 {0x00, 0x0001, 0x0022},
744 {0x00, 0x00e0, 0x0023},
745 {0x00, 0x0000, 0x0024},
746 {0x00, 0x00d5, 0x0025},
747 {0x00, 0x0000, 0x0026},
748 {0x00, 0x000b, 0x0027},
749 {0x00, 0x0000, 0x0046},
750 {0x00, 0x0000, 0x0047},
751 {0x00, 0x0000, 0x0048},
752 {0x00, 0x0000, 0x0049},
753 {0x00, 0x0008, 0x004a},
754 {0xff, 0x0000, 0x00d0},
755 {0xff, 0x00d8, 0x00d1},
756 {0xff, 0x0000, 0x00d4},
757 {0xff, 0x0000, 0x00d5},
758 {0x01, 0x00a6, 0x0000},
759 {0x01, 0x0028, 0x0001},
760 {0x01, 0x0000, 0x0002},
761 {0x01, 0x000a, 0x0003},
762 {0x01, 0x0040, 0x0004},
763 {0x01, 0x0066, 0x0007},
764 {0x01, 0x0011, 0x0008},
765 {0x01, 0x0032, 0x0009},
766 {0x01, 0x00fd, 0x000a},
767 {0x01, 0x0038, 0x000b},
768 {0x01, 0x00d1, 0x000c},
769 {0x01, 0x00f7, 0x000d},
770 {0x01, 0x00ed, 0x000e},
771 {0x01, 0x00d8, 0x000f},
772 {0x01, 0x0038, 0x0010},
773 {0x01, 0x00ff, 0x0015},
774 {0x01, 0x0001, 0x0016},
775 {0x01, 0x0032, 0x0017},
776 {0x01, 0x0023, 0x0018},
777 {0x01, 0x00ce, 0x0019},
778 {0x01, 0x0023, 0x001a},
779 {0x01, 0x0032, 0x001b},
780 {0x01, 0x008d, 0x001c},
781 {0x01, 0x00ce, 0x001d},
782 {0x01, 0x008d, 0x001e},
783 {0x01, 0x0000, 0x001f},
784 {0x01, 0x0000, 0x0020},
785 {0x01, 0x00ff, 0x003e},
786 {0x01, 0x0003, 0x003f},
787 {0x01, 0x0000, 0x0040},
788 {0x01, 0x0035, 0x0041},
789 {0x01, 0x0053, 0x0042},
790 {0x01, 0x0069, 0x0043},
791 {0x01, 0x007c, 0x0044},
792 {0x01, 0x008c, 0x0045},
793 {0x01, 0x009a, 0x0046},
794 {0x01, 0x00a8, 0x0047},
795 {0x01, 0x00b4, 0x0048},
796 {0x01, 0x00bf, 0x0049},
797 {0x01, 0x00ca, 0x004a},
798 {0x01, 0x00d4, 0x004b},
799 {0x01, 0x00dd, 0x004c},
800 {0x01, 0x00e7, 0x004d},
801 {0x01, 0x00ef, 0x004e},
802 {0x01, 0x00f8, 0x004f},
803 {0x01, 0x00ff, 0x0050},
804 {0x01, 0x0001, 0x0056},
805 {0x01, 0x0060, 0x0057},
806 {0x01, 0x0040, 0x0058},
807 {0x01, 0x0011, 0x0059},
808 {0x01, 0x0001, 0x005a},
809 {0x02, 0x0007, 0x0005},
810 {0x02, 0xa048, 0x0000},
811 {0x02, 0x0007, 0x0005},
812 {0x02, 0x0015, 0x0006},
813 {0x02, 0x100a, 0x0007},
814 {0x02, 0xa048, 0x0000},
815 {0x02, 0xc002, 0x0001},
816 {0x02, 0x000f, 0x0005},
817 {0x02, 0xa048, 0x0000},
818 {0x05, 0x0022, 0x0004},
819 {0x05, 0x0025, 0x0001},
820 {0x05, 0x0000, 0x0000},
821 {0x05, 0x0026, 0x0001},
822 {0x05, 0x0001, 0x0000},
823 {0x05, 0x0027, 0x0001},
824 {0x05, 0x0000, 0x0000},
825 {0x05, 0x0001, 0x0001},
826 {0x05, 0x0000, 0x0000},
827 {0x05, 0x0021, 0x0001},
828 {0x05, 0x00d2, 0x0000},
829 {0x05, 0x0020, 0x0001},
830 {0x05, 0x0000, 0x0000},
831 {0x00, 0x0090, 0x0005},
832 {0x01, 0x00a6, 0x0000},
833 {0x02, 0x0007, 0x0005},
834 {0x02, 0x2000, 0x0000},
835 {0x05, 0x0022, 0x0004},
836 {0x05, 0x0015, 0x0001},
837 {0x05, 0x00ea, 0x0000},
838 {0x05, 0x0021, 0x0001},
839 {0x05, 0x00d2, 0x0000},
840 {0x05, 0x0023, 0x0001},
841 {0x05, 0x0003, 0x0000},
842 {0x05, 0x0030, 0x0001},
843 {0x05, 0x002b, 0x0000},
844 {0x05, 0x0031, 0x0001},
845 {0x05, 0x0023, 0x0000},
846 {0x05, 0x0032, 0x0001},
847 {0x05, 0x0023, 0x0000},
848 {0x05, 0x0033, 0x0001},
849 {0x05, 0x0023, 0x0000},
850 {0x05, 0x0034, 0x0001},
851 {0x05, 0x0002, 0x0000},
852 {0x05, 0x0050, 0x0001},
853 {0x05, 0x0000, 0x0000},
854 {0x05, 0x0051, 0x0001},
855 {0x05, 0x0000, 0x0000},
856 {0x05, 0x0052, 0x0001},
857 {0x05, 0x0000, 0x0000},
858 {0x05, 0x0054, 0x0001},
859 {0x05, 0x0001, 0x0000},
860 {0x00, 0x0000, 0x0001},
861 {0x00, 0x0000, 0x0002},
862 {0x00, 0x000c, 0x0003},
863 {0x00, 0x0000, 0x0004},
864 {0x00, 0x0090, 0x0005},
865 {0x00, 0x0000, 0x0006},
866 {0x00, 0x0040, 0x0007},
867 {0x00, 0x00c0, 0x0008},
868 {0x00, 0x004a, 0x0009},
869 {0x00, 0x0000, 0x000a},
870 {0x00, 0x0000, 0x000b},
871 {0x00, 0x0001, 0x000c},
872 {0x00, 0x0001, 0x000d},
873 {0x00, 0x0000, 0x000e},
874 {0x00, 0x0002, 0x000f},
875 {0x00, 0x0001, 0x0010},
876 {0x00, 0x0000, 0x0011},
877 {0x00, 0x0000, 0x0012},
878 {0x00, 0x0002, 0x0020},
879 {0x00, 0x0080, 0x0021},
880 {0x00, 0x0001, 0x0022},
881 {0x00, 0x00e0, 0x0023},
882 {0x00, 0x0000, 0x0024},
883 {0x00, 0x00d5, 0x0025},
884 {0x00, 0x0000, 0x0026},
885 {0x00, 0x000b, 0x0027},
886 {0x00, 0x0000, 0x0046},
887 {0x00, 0x0000, 0x0047},
888 {0x00, 0x0000, 0x0048},
889 {0x00, 0x0000, 0x0049},
890 {0x00, 0x0008, 0x004a},
891 {0xff, 0x0000, 0x00d0},
892 {0xff, 0x00d8, 0x00d1},
893 {0xff, 0x0000, 0x00d4},
894 {0xff, 0x0000, 0x00d5},
895 {0x01, 0x00a6, 0x0000},
896 {0x01, 0x0028, 0x0001},
897 {0x01, 0x0000, 0x0002},
898 {0x01, 0x000a, 0x0003},
899 {0x01, 0x0040, 0x0004},
900 {0x01, 0x0066, 0x0007},
901 {0x01, 0x0011, 0x0008},
902 {0x01, 0x0032, 0x0009},
903 {0x01, 0x00fd, 0x000a},
904 {0x01, 0x0038, 0x000b},
905 {0x01, 0x00d1, 0x000c},
906 {0x01, 0x00f7, 0x000d},
907 {0x01, 0x00ed, 0x000e},
908 {0x01, 0x00d8, 0x000f},
909 {0x01, 0x0038, 0x0010},
910 {0x01, 0x00ff, 0x0015},
911 {0x01, 0x0001, 0x0016},
912 {0x01, 0x0032, 0x0017},
913 {0x01, 0x0023, 0x0018},
914 {0x01, 0x00ce, 0x0019},
915 {0x01, 0x0023, 0x001a},
916 {0x01, 0x0032, 0x001b},
917 {0x01, 0x008d, 0x001c},
918 {0x01, 0x00ce, 0x001d},
919 {0x01, 0x008d, 0x001e},
920 {0x01, 0x0000, 0x001f},
921 {0x01, 0x0000, 0x0020},
922 {0x01, 0x00ff, 0x003e},
923 {0x01, 0x0003, 0x003f},
924 {0x01, 0x0000, 0x0040},
925 {0x01, 0x0035, 0x0041},
926 {0x01, 0x0053, 0x0042},
927 {0x01, 0x0069, 0x0043},
928 {0x01, 0x007c, 0x0044},
929 {0x01, 0x008c, 0x0045},
930 {0x01, 0x009a, 0x0046},
931 {0x01, 0x00a8, 0x0047},
932 {0x01, 0x00b4, 0x0048},
933 {0x01, 0x00bf, 0x0049},
934 {0x01, 0x00ca, 0x004a},
935 {0x01, 0x00d4, 0x004b},
936 {0x01, 0x00dd, 0x004c},
937 {0x01, 0x00e7, 0x004d},
938 {0x01, 0x00ef, 0x004e},
939 {0x01, 0x00f8, 0x004f},
940 {0x01, 0x00ff, 0x0050},
941 {0x01, 0x0001, 0x0056},
942 {0x01, 0x0060, 0x0057},
943 {0x01, 0x0040, 0x0058},
944 {0x01, 0x0011, 0x0059},
945 {0x01, 0x0001, 0x005a},
946 {0x02, 0x0007, 0x0005},
947 {0x02, 0xa048, 0x0000},
948 {0x02, 0x0007, 0x0005},
949 {0x02, 0x0015, 0x0006},
950 {0x02, 0x100a, 0x0007},
951 {0x02, 0xa048, 0x0000},
952 {0x02, 0xc002, 0x0001},
953 {0x02, 0x000f, 0x0005},
954 {0x02, 0xa048, 0x0000},
955 {0x05, 0x0022, 0x0004},
956 {0x05, 0x0025, 0x0001},
957 {0x05, 0x0000, 0x0000},
958 {0x05, 0x0026, 0x0001},
959 {0x05, 0x0001, 0x0000},
960 {0x05, 0x0027, 0x0001},
961 {0x05, 0x0000, 0x0000},
962 {0x05, 0x0001, 0x0001},
963 {0x05, 0x0000, 0x0000},
964 {0x05, 0x0021, 0x0001},
965 {0x05, 0x00d2, 0x0000},
966 {0x05, 0x0020, 0x0001},
967 {0x05, 0x0000, 0x0000},
968 {0x00, 0x0090, 0x0005},
969 {0x01, 0x00a6, 0x0000},
970 {0x01, 0x0003, 0x003f},
971 {0x01, 0x0001, 0x0056},
972 {0x01, 0x0011, 0x0008},
973 {0x01, 0x0032, 0x0009},
974 {0x01, 0xfffd, 0x000a},
975 {0x01, 0x0023, 0x000b},
976 {0x01, 0xffea, 0x000c},
977 {0x01, 0xfff4, 0x000d},
978 {0x01, 0xfffc, 0x000e},
979 {0x01, 0xffe3, 0x000f},
980 {0x01, 0x001f, 0x0010},
981 {0x01, 0x00a8, 0x0001},
982 {0x01, 0x0067, 0x0007},
983 {0x01, 0x0032, 0x0017},
984 {0x01, 0x0023, 0x0018},
985 {0x01, 0x00ce, 0x0019},
986 {0x01, 0x0023, 0x001a},
987 {0x01, 0x0032, 0x001b},
988 {0x01, 0x008d, 0x001c},
989 {0x01, 0x00ce, 0x001d},
990 {0x01, 0x008d, 0x001e},
991 {0x01, 0x00c8, 0x0015},
992 {0x01, 0x0032, 0x0016},
993 {0x01, 0x0000, 0x0011},
994 {0x01, 0x0000, 0x0012},
995 {0x01, 0x0000, 0x0013},
996 {0x01, 0x000a, 0x0003},
997 {0x02, 0xc002, 0x0001},
998 {0x02, 0x0007, 0x0005},
999 {0x02, 0xc000, 0x0001},
1000 {0x02, 0x0000, 0x0005},
1001 {0x02, 0x0007, 0x0005},
1002 {0x02, 0x2000, 0x0000},
1003 {0x05, 0x0022, 0x0004},
1004 {0x05, 0x0015, 0x0001},
1005 {0x05, 0x00ea, 0x0000},
1006 {0x05, 0x0021, 0x0001},
1007 {0x05, 0x00d2, 0x0000},
1008 {0x05, 0x0023, 0x0001},
1009 {0x05, 0x0003, 0x0000},
1010 {0x05, 0x0030, 0x0001},
1011 {0x05, 0x002b, 0x0000},
1012 {0x05, 0x0031, 0x0001},
1013 {0x05, 0x0023, 0x0000},
1014 {0x05, 0x0032, 0x0001},
1015 {0x05, 0x0023, 0x0000},
1016 {0x05, 0x0033, 0x0001},
1017 {0x05, 0x0023, 0x0000},
1018 {0x05, 0x0034, 0x0001},
1019 {0x05, 0x0002, 0x0000},
1020 {0x05, 0x0050, 0x0001},
1021 {0x05, 0x0000, 0x0000},
1022 {0x05, 0x0051, 0x0001},
1023 {0x05, 0x0000, 0x0000},
1024 {0x05, 0x0052, 0x0001},
1025 {0x05, 0x0000, 0x0000},
1026 {0x05, 0x0054, 0x0001},
1027 {0x05, 0x0001, 0x0000},
1028 {0x00, 0x0000, 0x0001},
1029 {0x00, 0x0000, 0x0002},
1030 {0x00, 0x000c, 0x0003},
1031 {0x00, 0x0000, 0x0004},
1032 {0x00, 0x0090, 0x0005},
1033 {0x00, 0x0000, 0x0006},
1034 {0x00, 0x0040, 0x0007},
1035 {0x00, 0x00c0, 0x0008},
1036 {0x00, 0x004a, 0x0009},
1037 {0x00, 0x0000, 0x000a},
1038 {0x00, 0x0000, 0x000b},
1039 {0x00, 0x0001, 0x000c},
1040 {0x00, 0x0001, 0x000d},
1041 {0x00, 0x0000, 0x000e},
1042 {0x00, 0x0002, 0x000f},
1043 {0x00, 0x0001, 0x0010},
1044 {0x00, 0x0000, 0x0011},
1045 {0x00, 0x0000, 0x0012},
1046 {0x00, 0x0002, 0x0020},
1047 {0x00, 0x0080, 0x0021},
1048 {0x00, 0x0001, 0x0022},
1049 {0x00, 0x00e0, 0x0023},
1050 {0x00, 0x0000, 0x0024},
1051 {0x00, 0x00d5, 0x0025},
1052 {0x00, 0x0000, 0x0026},
1053 {0x00, 0x000b, 0x0027},
1054 {0x00, 0x0000, 0x0046},
1055 {0x00, 0x0000, 0x0047},
1056 {0x00, 0x0000, 0x0048},
1057 {0x00, 0x0000, 0x0049},
1058 {0x00, 0x0008, 0x004a},
1059 {0xff, 0x0000, 0x00d0},
1060 {0xff, 0x00d8, 0x00d1},
1061 {0xff, 0x0000, 0x00d4},
1062 {0xff, 0x0000, 0x00d5},
1063 {0x01, 0x00a6, 0x0000},
1064 {0x01, 0x0028, 0x0001},
1065 {0x01, 0x0000, 0x0002},
1066 {0x01, 0x000a, 0x0003},
1067 {0x01, 0x0040, 0x0004},
1068 {0x01, 0x0066, 0x0007},
1069 {0x01, 0x0011, 0x0008},
1070 {0x01, 0x0032, 0x0009},
1071 {0x01, 0x00fd, 0x000a},
1072 {0x01, 0x0038, 0x000b},
1073 {0x01, 0x00d1, 0x000c},
1074 {0x01, 0x00f7, 0x000d},
1075 {0x01, 0x00ed, 0x000e},
1076 {0x01, 0x00d8, 0x000f},
1077 {0x01, 0x0038, 0x0010},
1078 {0x01, 0x00ff, 0x0015},
1079 {0x01, 0x0001, 0x0016},
1080 {0x01, 0x0032, 0x0017},
1081 {0x01, 0x0023, 0x0018},
1082 {0x01, 0x00ce, 0x0019},
1083 {0x01, 0x0023, 0x001a},
1084 {0x01, 0x0032, 0x001b},
1085 {0x01, 0x008d, 0x001c},
1086 {0x01, 0x00ce, 0x001d},
1087 {0x01, 0x008d, 0x001e},
1088 {0x01, 0x0000, 0x001f},
1089 {0x01, 0x0000, 0x0020},
1090 {0x01, 0x00ff, 0x003e},
1091 {0x01, 0x0003, 0x003f},
1092 {0x01, 0x0000, 0x0040},
1093 {0x01, 0x0035, 0x0041},
1094 {0x01, 0x0053, 0x0042},
1095 {0x01, 0x0069, 0x0043},
1096 {0x01, 0x007c, 0x0044},
1097 {0x01, 0x008c, 0x0045},
1098 {0x01, 0x009a, 0x0046},
1099 {0x01, 0x00a8, 0x0047},
1100 {0x01, 0x00b4, 0x0048},
1101 {0x01, 0x00bf, 0x0049},
1102 {0x01, 0x00ca, 0x004a},
1103 {0x01, 0x00d4, 0x004b},
1104 {0x01, 0x00dd, 0x004c},
1105 {0x01, 0x00e7, 0x004d},
1106 {0x01, 0x00ef, 0x004e},
1107 {0x01, 0x00f8, 0x004f},
1108 {0x01, 0x00ff, 0x0050},
1109 {0x01, 0x0001, 0x0056},
1110 {0x01, 0x0060, 0x0057},
1111 {0x01, 0x0040, 0x0058},
1112 {0x01, 0x0011, 0x0059},
1113 {0x01, 0x0001, 0x005a},
1114 {0x02, 0x0007, 0x0005},
1115 {0x02, 0xa048, 0x0000},
1116 {0x02, 0x0007, 0x0005},
1117 {0x02, 0x0015, 0x0006},
1118 {0x02, 0x100a, 0x0007},
1119 {0x02, 0xa048, 0x0000},
1120 {0x02, 0xc002, 0x0001},
1121 {0x02, 0x000f, 0x0005},
1122 {0x02, 0xa048, 0x0000},
1123 {0x05, 0x0022, 0x0004},
1124 {0x05, 0x0025, 0x0001},
1125 {0x05, 0x0000, 0x0000},
1126 {0x05, 0x0026, 0x0001},
1127 {0x05, 0x0001, 0x0000},
1128 {0x05, 0x0027, 0x0001},
1129 {0x05, 0x0000, 0x0000},
1130 {0x05, 0x0001, 0x0001},
1131 {0x05, 0x0000, 0x0000},
1132 {0x05, 0x0021, 0x0001},
1133 {0x05, 0x00d2, 0x0000},
1134 {0x05, 0x0020, 0x0001},
1135 {0x05, 0x0000, 0x0000},
1136 {0x00, 0x0090, 0x0005},
1137 {0x01, 0x00a6, 0x0000},
1138 {0x02, 0x0007, 0x0005},
1139 {0x02, 0x2000, 0x0000},
1140 {0x05, 0x0022, 0x0004},
1141 {0x05, 0x0015, 0x0001},
1142 {0x05, 0x00ea, 0x0000},
1143 {0x05, 0x0021, 0x0001},
1144 {0x05, 0x00d2, 0x0000},
1145 {0x05, 0x0023, 0x0001},
1146 {0x05, 0x0003, 0x0000},
1147 {0x05, 0x0030, 0x0001},
1148 {0x05, 0x002b, 0x0000},
1149 {0x05, 0x0031, 0x0001},
1150 {0x05, 0x0023, 0x0000},
1151 {0x05, 0x0032, 0x0001},
1152 {0x05, 0x0023, 0x0000},
1153 {0x05, 0x0033, 0x0001},
1154 {0x05, 0x0023, 0x0000},
1155 {0x05, 0x0034, 0x0001},
1156 {0x05, 0x0002, 0x0000},
1157 {0x05, 0x0050, 0x0001},
1158 {0x05, 0x0000, 0x0000},
1159 {0x05, 0x0051, 0x0001},
1160 {0x05, 0x0000, 0x0000},
1161 {0x05, 0x0052, 0x0001},
1162 {0x05, 0x0000, 0x0000},
1163 {0x05, 0x0054, 0x0001},
1164 {0x05, 0x0001, 0x0000},
1165 {0x00, 0x0000, 0x0001},
1166 {0x00, 0x0000, 0x0002},
1167 {0x00, 0x000c, 0x0003},
1168 {0x00, 0x0000, 0x0004},
1169 {0x00, 0x0090, 0x0005},
1170 {0x00, 0x0000, 0x0006},
1171 {0x00, 0x0040, 0x0007},
1172 {0x00, 0x00c0, 0x0008},
1173 {0x00, 0x004a, 0x0009},
1174 {0x00, 0x0000, 0x000a},
1175 {0x00, 0x0000, 0x000b},
1176 {0x00, 0x0001, 0x000c},
1177 {0x00, 0x0001, 0x000d},
1178 {0x00, 0x0000, 0x000e},
1179 {0x00, 0x0002, 0x000f},
1180 {0x00, 0x0001, 0x0010},
1181 {0x00, 0x0000, 0x0011},
1182 {0x00, 0x0000, 0x0012},
1183 {0x00, 0x0002, 0x0020},
1184 {0x00, 0x0080, 0x0021},
1185 {0x00, 0x0001, 0x0022},
1186 {0x00, 0x00e0, 0x0023},
1187 {0x00, 0x0000, 0x0024},
1188 {0x00, 0x00d5, 0x0025},
1189 {0x00, 0x0000, 0x0026},
1190 {0x00, 0x000b, 0x0027},
1191 {0x00, 0x0000, 0x0046},
1192 {0x00, 0x0000, 0x0047},
1193 {0x00, 0x0000, 0x0048},
1194 {0x00, 0x0000, 0x0049},
1195 {0x00, 0x0008, 0x004a},
1196 {0xff, 0x0000, 0x00d0},
1197 {0xff, 0x00d8, 0x00d1},
1198 {0xff, 0x0000, 0x00d4},
1199 {0xff, 0x0000, 0x00d5},
1200 {0x01, 0x00a6, 0x0000},
1201 {0x01, 0x0028, 0x0001},
1202 {0x01, 0x0000, 0x0002},
1203 {0x01, 0x000a, 0x0003},
1204 {0x01, 0x0040, 0x0004},
1205 {0x01, 0x0066, 0x0007},
1206 {0x01, 0x0011, 0x0008},
1207 {0x01, 0x0032, 0x0009},
1208 {0x01, 0x00fd, 0x000a},
1209 {0x01, 0x0038, 0x000b},
1210 {0x01, 0x00d1, 0x000c},
1211 {0x01, 0x00f7, 0x000d},
1212 {0x01, 0x00ed, 0x000e},
1213 {0x01, 0x00d8, 0x000f},
1214 {0x01, 0x0038, 0x0010},
1215 {0x01, 0x00ff, 0x0015},
1216 {0x01, 0x0001, 0x0016},
1217 {0x01, 0x0032, 0x0017},
1218 {0x01, 0x0023, 0x0018},
1219 {0x01, 0x00ce, 0x0019},
1220 {0x01, 0x0023, 0x001a},
1221 {0x01, 0x0032, 0x001b},
1222 {0x01, 0x008d, 0x001c},
1223 {0x01, 0x00ce, 0x001d},
1224 {0x01, 0x008d, 0x001e},
1225 {0x01, 0x0000, 0x001f},
1226 {0x01, 0x0000, 0x0020},
1227 {0x01, 0x00ff, 0x003e},
1228 {0x01, 0x0003, 0x003f},
1229 {0x01, 0x0000, 0x0040},
1230 {0x01, 0x0035, 0x0041},
1231 {0x01, 0x0053, 0x0042},
1232 {0x01, 0x0069, 0x0043},
1233 {0x01, 0x007c, 0x0044},
1234 {0x01, 0x008c, 0x0045},
1235 {0x01, 0x009a, 0x0046},
1236 {0x01, 0x00a8, 0x0047},
1237 {0x01, 0x00b4, 0x0048},
1238 {0x01, 0x00bf, 0x0049},
1239 {0x01, 0x00ca, 0x004a},
1240 {0x01, 0x00d4, 0x004b},
1241 {0x01, 0x00dd, 0x004c},
1242 {0x01, 0x00e7, 0x004d},
1243 {0x01, 0x00ef, 0x004e},
1244 {0x01, 0x00f8, 0x004f},
1245 {0x01, 0x00ff, 0x0050},
1246 {0x01, 0x0001, 0x0056},
1247 {0x01, 0x0060, 0x0057},
1248 {0x01, 0x0040, 0x0058},
1249 {0x01, 0x0011, 0x0059},
1250 {0x01, 0x0001, 0x005a},
1251 {0x02, 0x0007, 0x0005},
1252 {0x02, 0xa048, 0x0000},
1253 {0x02, 0x0007, 0x0005},
1254 {0x02, 0x0015, 0x0006},
1255 {0x02, 0x100a, 0x0007},
1256 {0x02, 0xa048, 0x0000},
1257 {0x02, 0xc002, 0x0001},
1258 {0x02, 0x000f, 0x0005},
1259 {0x02, 0xa048, 0x0000},
1260 {0x05, 0x0022, 0x0004},
1261 {0x05, 0x0025, 0x0001},
1262 {0x05, 0x0000, 0x0000},
1263 {0x05, 0x0026, 0x0001},
1264 {0x05, 0x0001, 0x0000},
1265 {0x05, 0x0027, 0x0001},
1266 {0x05, 0x0000, 0x0000},
1267 {0x05, 0x0001, 0x0001},
1268 {0x05, 0x0000, 0x0000},
1269 {0x05, 0x0021, 0x0001},
1270 {0x05, 0x00d2, 0x0000},
1271 {0x05, 0x0020, 0x0001},
1272 {0x05, 0x0000, 0x0000},
1273 {0x00, 0x0090, 0x0005},
1274 {0x01, 0x00a6, 0x0000},
1275 {0x05, 0x0026, 0x0001},
1276 {0x05, 0x0001, 0x0000},
1277 {0x05, 0x0027, 0x0001},
1278 {0x05, 0x000f, 0x0000},
1279 {0x01, 0x0003, 0x003f},
1280 {0x01, 0x0001, 0x0056},
1281 {0x01, 0x0011, 0x0008},
1282 {0x01, 0x0032, 0x0009},
1283 {0x01, 0xfffd, 0x000a},
1284 {0x01, 0x0023, 0x000b},
1285 {0x01, 0xffea, 0x000c},
1286 {0x01, 0xfff4, 0x000d},
1287 {0x01, 0xfffc, 0x000e},
1288 {0x01, 0xffe3, 0x000f},
1289 {0x01, 0x001f, 0x0010},
1290 {0x01, 0x00a8, 0x0001},
1291 {0x01, 0x0067, 0x0007},
1292 {0x01, 0x0042, 0x0051},
1293 {0x01, 0x0051, 0x0053},
1294 {0x01, 0x000a, 0x0003},
1295 {0x02, 0xc002, 0x0001},
1296 {0x02, 0x0007, 0x0005},
1297 {0x02, 0xc000, 0x0001},
1298 {0x02, 0x0000, 0x0005},
1299 {0x02, 0x0007, 0x0005},
1300 {0x02, 0x2000, 0x0000},
1301 {0x05, 0x0022, 0x0004},
1302 {0x05, 0x0015, 0x0001},
1303 {0x05, 0x00ea, 0x0000},
1304 {0x05, 0x0021, 0x0001},
1305 {0x05, 0x00d2, 0x0000},
1306 {0x05, 0x0023, 0x0001},
1307 {0x05, 0x0003, 0x0000},
1308 {0x05, 0x0030, 0x0001},
1309 {0x05, 0x002b, 0x0000},
1310 {0x05, 0x0031, 0x0001},
1311 {0x05, 0x0023, 0x0000},
1312 {0x05, 0x0032, 0x0001},
1313 {0x05, 0x0023, 0x0000},
1314 {0x05, 0x0033, 0x0001},
1315 {0x05, 0x0023, 0x0000},
1316 {0x05, 0x0034, 0x0001},
1317 {0x05, 0x0002, 0x0000},
1318 {0x05, 0x0050, 0x0001},
1319 {0x05, 0x0000, 0x0000},
1320 {0x05, 0x0051, 0x0001},
1321 {0x05, 0x0000, 0x0000},
1322 {0x05, 0x0052, 0x0001},
1323 {0x05, 0x0000, 0x0000},
1324 {0x05, 0x0054, 0x0001},
1325 {0x05, 0x0001, 0x0000},
1326 {0x00, 0x0000, 0x0001},
1327 {0x00, 0x0000, 0x0002},
1328 {0x00, 0x000c, 0x0003},
1329 {0x00, 0x0000, 0x0004},
1330 {0x00, 0x0090, 0x0005},
1331 {0x00, 0x0000, 0x0006},
1332 {0x00, 0x0040, 0x0007},
1333 {0x00, 0x00c0, 0x0008},
1334 {0x00, 0x004a, 0x0009},
1335 {0x00, 0x0000, 0x000a},
1336 {0x00, 0x0000, 0x000b},
1337 {0x00, 0x0001, 0x000c},
1338 {0x00, 0x0001, 0x000d},
1339 {0x00, 0x0000, 0x000e},
1340 {0x00, 0x0002, 0x000f},
1341 {0x00, 0x0001, 0x0010},
1342 {0x00, 0x0000, 0x0011},
1343 {0x00, 0x0000, 0x0012},
1344 {0x00, 0x0002, 0x0020},
1345 {0x00, 0x0080, 0x0021},
1346 {0x00, 0x0001, 0x0022},
1347 {0x00, 0x00e0, 0x0023},
1348 {0x00, 0x0000, 0x0024},
1349 {0x00, 0x00d5, 0x0025},
1350 {0x00, 0x0000, 0x0026},
1351 {0x00, 0x000b, 0x0027},
1352 {0x00, 0x0000, 0x0046},
1353 {0x00, 0x0000, 0x0047},
1354 {0x00, 0x0000, 0x0048},
1355 {0x00, 0x0000, 0x0049},
1356 {0x00, 0x0008, 0x004a},
1357 {0xff, 0x0000, 0x00d0},
1358 {0xff, 0x00d8, 0x00d1},
1359 {0xff, 0x0000, 0x00d4},
1360 {0xff, 0x0000, 0x00d5},
1361 {0x01, 0x00a6, 0x0000},
1362 {0x01, 0x0028, 0x0001},
1363 {0x01, 0x0000, 0x0002},
1364 {0x01, 0x000a, 0x0003},
1365 {0x01, 0x0040, 0x0004},
1366 {0x01, 0x0066, 0x0007},
1367 {0x01, 0x0011, 0x0008},
1368 {0x01, 0x0032, 0x0009},
1369 {0x01, 0x00fd, 0x000a},
1370 {0x01, 0x0038, 0x000b},
1371 {0x01, 0x00d1, 0x000c},
1372 {0x01, 0x00f7, 0x000d},
1373 {0x01, 0x00ed, 0x000e},
1374 {0x01, 0x00d8, 0x000f},
1375 {0x01, 0x0038, 0x0010},
1376 {0x01, 0x00ff, 0x0015},
1377 {0x01, 0x0001, 0x0016},
1378 {0x01, 0x0032, 0x0017},
1379 {0x01, 0x0023, 0x0018},
1380 {0x01, 0x00ce, 0x0019},
1381 {0x01, 0x0023, 0x001a},
1382 {0x01, 0x0032, 0x001b},
1383 {0x01, 0x008d, 0x001c},
1384 {0x01, 0x00ce, 0x001d},
1385 {0x01, 0x008d, 0x001e},
1386 {0x01, 0x0000, 0x001f},
1387 {0x01, 0x0000, 0x0020},
1388 {0x01, 0x00ff, 0x003e},
1389 {0x01, 0x0003, 0x003f},
1390 {0x01, 0x0000, 0x0040},
1391 {0x01, 0x0035, 0x0041},
1392 {0x01, 0x0053, 0x0042},
1393 {0x01, 0x0069, 0x0043},
1394 {0x01, 0x007c, 0x0044},
1395 {0x01, 0x008c, 0x0045},
1396 {0x01, 0x009a, 0x0046},
1397 {0x01, 0x00a8, 0x0047},
1398 {0x01, 0x00b4, 0x0048},
1399 {0x01, 0x00bf, 0x0049},
1400 {0x01, 0x00ca, 0x004a},
1401 {0x01, 0x00d4, 0x004b},
1402 {0x01, 0x00dd, 0x004c},
1403 {0x01, 0x00e7, 0x004d},
1404 {0x01, 0x00ef, 0x004e},
1405 {0x01, 0x00f8, 0x004f},
1406 {0x01, 0x00ff, 0x0050},
1407 {0x01, 0x0001, 0x0056},
1408 {0x01, 0x0060, 0x0057},
1409 {0x01, 0x0040, 0x0058},
1410 {0x01, 0x0011, 0x0059},
1411 {0x01, 0x0001, 0x005a},
1412 {0x02, 0x0007, 0x0005},
1413 {0x02, 0xa048, 0x0000},
1414 {0x02, 0x0007, 0x0005},
1415 {0x02, 0x0015, 0x0006},
1416 {0x02, 0x100a, 0x0007},
1417 {0x02, 0xa048, 0x0000},
1418 {0x02, 0xc002, 0x0001},
1419 {0x02, 0x000f, 0x0005},
1420 {0x02, 0xa048, 0x0000},
1421 {0x05, 0x0022, 0x0004},
1422 {0x05, 0x0025, 0x0001},
1423 {0x05, 0x0000, 0x0000},
1424 {0x05, 0x0026, 0x0001},
1425 {0x05, 0x0001, 0x0000},
1426 {0x05, 0x0027, 0x0001},
1427 {0x05, 0x0000, 0x0000},
1428 {0x05, 0x0001, 0x0001},
1429 {0x05, 0x0000, 0x0000},
1430 {0x05, 0x0021, 0x0001},
1431 {0x05, 0x00d2, 0x0000},
1432 {0x05, 0x0020, 0x0001},
1433 {0x05, 0x0000, 0x0000},
1434 {0x00, 0x0090, 0x0005},
1435 {0x01, 0x00a6, 0x0000},
1436 {0x02, 0x0007, 0x0005},
1437 {0x02, 0x2000, 0x0000},
1438 {0x05, 0x0022, 0x0004},
1439 {0x05, 0x0015, 0x0001},
1440 {0x05, 0x00ea, 0x0000},
1441 {0x05, 0x0021, 0x0001},
1442 {0x05, 0x00d2, 0x0000},
1443 {0x05, 0x0023, 0x0001},
1444 {0x05, 0x0003, 0x0000},
1445 {0x05, 0x0030, 0x0001},
1446 {0x05, 0x002b, 0x0000},
1447 {0x05, 0x0031, 0x0001},
1448 {0x05, 0x0023, 0x0000},
1449 {0x05, 0x0032, 0x0001},
1450 {0x05, 0x0023, 0x0000},
1451 {0x05, 0x0033, 0x0001},
1452 {0x05, 0x0023, 0x0000},
1453 {0x05, 0x0034, 0x0001},
1454 {0x05, 0x0002, 0x0000},
1455 {0x05, 0x0050, 0x0001},
1456 {0x05, 0x0000, 0x0000},
1457 {0x05, 0x0051, 0x0001},
1458 {0x05, 0x0000, 0x0000},
1459 {0x05, 0x0052, 0x0001},
1460 {0x05, 0x0000, 0x0000},
1461 {0x05, 0x0054, 0x0001},
1462 {0x05, 0x0001, 0x0000},
1463 {0x00, 0x0000, 0x0001},
1464 {0x00, 0x0000, 0x0002},
1465 {0x00, 0x000c, 0x0003},
1466 {0x00, 0x0000, 0x0004},
1467 {0x00, 0x0090, 0x0005},
1468 {0x00, 0x0000, 0x0006},
1469 {0x00, 0x0040, 0x0007},
1470 {0x00, 0x00c0, 0x0008},
1471 {0x00, 0x004a, 0x0009},
1472 {0x00, 0x0000, 0x000a},
1473 {0x00, 0x0000, 0x000b},
1474 {0x00, 0x0001, 0x000c},
1475 {0x00, 0x0001, 0x000d},
1476 {0x00, 0x0000, 0x000e},
1477 {0x00, 0x0002, 0x000f},
1478 {0x00, 0x0001, 0x0010},
1479 {0x00, 0x0000, 0x0011},
1480 {0x00, 0x0000, 0x0012},
1481 {0x00, 0x0002, 0x0020},
1482 {0x00, 0x0080, 0x0021},
1483 {0x00, 0x0001, 0x0022},
1484 {0x00, 0x00e0, 0x0023},
1485 {0x00, 0x0000, 0x0024},
1486 {0x00, 0x00d5, 0x0025},
1487 {0x00, 0x0000, 0x0026},
1488 {0x00, 0x000b, 0x0027},
1489 {0x00, 0x0000, 0x0046},
1490 {0x00, 0x0000, 0x0047},
1491 {0x00, 0x0000, 0x0048},
1492 {0x00, 0x0000, 0x0049},
1493 {0x00, 0x0008, 0x004a},
1494 {0xff, 0x0000, 0x00d0},
1495 {0xff, 0x00d8, 0x00d1},
1496 {0xff, 0x0000, 0x00d4},
1497 {0xff, 0x0000, 0x00d5},
1498 {0x01, 0x00a6, 0x0000},
1499 {0x01, 0x0028, 0x0001},
1500 {0x01, 0x0000, 0x0002},
1501 {0x01, 0x000a, 0x0003},
1502 {0x01, 0x0040, 0x0004},
1503 {0x01, 0x0066, 0x0007},
1504 {0x01, 0x0011, 0x0008},
1505 {0x01, 0x0032, 0x0009},
1506 {0x01, 0x00fd, 0x000a},
1507 {0x01, 0x0038, 0x000b},
1508 {0x01, 0x00d1, 0x000c},
1509 {0x01, 0x00f7, 0x000d},
1510 {0x01, 0x00ed, 0x000e},
1511 {0x01, 0x00d8, 0x000f},
1512 {0x01, 0x0038, 0x0010},
1513 {0x01, 0x00ff, 0x0015},
1514 {0x01, 0x0001, 0x0016},
1515 {0x01, 0x0032, 0x0017},
1516 {0x01, 0x0023, 0x0018},
1517 {0x01, 0x00ce, 0x0019},
1518 {0x01, 0x0023, 0x001a},
1519 {0x01, 0x0032, 0x001b},
1520 {0x01, 0x008d, 0x001c},
1521 {0x01, 0x00ce, 0x001d},
1522 {0x01, 0x008d, 0x001e},
1523 {0x01, 0x0000, 0x001f},
1524 {0x01, 0x0000, 0x0020},
1525 {0x01, 0x00ff, 0x003e},
1526 {0x01, 0x0003, 0x003f},
1527 {0x01, 0x0000, 0x0040},
1528 {0x01, 0x0035, 0x0041},
1529 {0x01, 0x0053, 0x0042},
1530 {0x01, 0x0069, 0x0043},
1531 {0x01, 0x007c, 0x0044},
1532 {0x01, 0x008c, 0x0045},
1533 {0x01, 0x009a, 0x0046},
1534 {0x01, 0x00a8, 0x0047},
1535 {0x01, 0x00b4, 0x0048},
1536 {0x01, 0x00bf, 0x0049},
1537 {0x01, 0x00ca, 0x004a},
1538 {0x01, 0x00d4, 0x004b},
1539 {0x01, 0x00dd, 0x004c},
1540 {0x01, 0x00e7, 0x004d},
1541 {0x01, 0x00ef, 0x004e},
1542 {0x01, 0x00f8, 0x004f},
1543 {0x01, 0x00ff, 0x0050},
1544 {0x01, 0x0001, 0x0056},
1545 {0x01, 0x0060, 0x0057},
1546 {0x01, 0x0040, 0x0058},
1547 {0x01, 0x0011, 0x0059},
1548 {0x01, 0x0001, 0x005a},
1549 {0x02, 0x0007, 0x0005},
1550 {0x02, 0xa048, 0x0000},
1551 {0x02, 0x0007, 0x0005},
1552 {0x02, 0x0015, 0x0006},
1553 {0x02, 0x100a, 0x0007},
1554 {0x02, 0xa048, 0x0000},
1555 {0x02, 0xc002, 0x0001},
1556 {0x02, 0x000f, 0x0005},
1557 {0x02, 0xa048, 0x0000},
1558 {0x05, 0x0022, 0x0004},
1559 {0x05, 0x0025, 0x0001},
1560 {0x05, 0x0000, 0x0000},
1561 {0x05, 0x0026, 0x0001},
1562 {0x05, 0x0001, 0x0000},
1563 {0x05, 0x0027, 0x0001},
1564 {0x05, 0x0000, 0x0000},
1565 {0x05, 0x0001, 0x0001},
1566 {0x05, 0x0000, 0x0000},
1567 {0x05, 0x0021, 0x0001},
1568 {0x05, 0x00d2, 0x0000},
1569 {0x05, 0x0020, 0x0001},
1570 {0x05, 0x0000, 0x0000},
1571 {0x00, 0x0090, 0x0005},
1572 {0x01, 0x00a6, 0x0000},
1573 {0x05, 0x0026, 0x0001},
1574 {0x05, 0x0001, 0x0000},
1575 {0x05, 0x0027, 0x0001},
1576 {0x05, 0x001e, 0x0000},
1577 {0x01, 0x0003, 0x003f},
1578 {0x01, 0x0001, 0x0056},
1579 {0x01, 0x0011, 0x0008},
1580 {0x01, 0x0032, 0x0009},
1581 {0x01, 0xfffd, 0x000a},
1582 {0x01, 0x0023, 0x000b},
1583 {0x01, 0xffea, 0x000c},
1584 {0x01, 0xfff4, 0x000d},
1585 {0x01, 0xfffc, 0x000e},
1586 {0x01, 0xffe3, 0x000f},
1587 {0x01, 0x001f, 0x0010},
1588 {0x01, 0x00a8, 0x0001},
1589 {0x01, 0x0067, 0x0007},
1590 {0x01, 0x0042, 0x0051},
1591 {0x01, 0x0051, 0x0053},
1592 {0x01, 0x000a, 0x0003},
1593 {0x02, 0xc002, 0x0001},
1594 {0x02, 0x0007, 0x0005},
1595 {0x01, 0x0042, 0x0051},
1596 {0x01, 0x0051, 0x0053},
1597 {0x05, 0x0026, 0x0001},
1598 {0x05, 0x0001, 0x0000},
1599 {0x05, 0x0027, 0x0001},
1600 {0x05, 0x002d, 0x0000},
1601 {0x01, 0x0003, 0x003f},
1602 {0x01, 0x0001, 0x0056},
1603 {0x02, 0xc000, 0x0001},
1604 {0x02, 0x0000, 0x0005},
1605 {}
1606};
1607
1608/* Unknow camera from Ori Usbid 0x0000:0x0000 */
1609/* Based on snoops from Ori Cohen */
1610static const __u16 spca501c_mysterious_open_data[][3] = {
1611 {0x02, 0x000f, 0x0005},
1612 {0x02, 0xa048, 0x0000},
1613 {0x05, 0x0022, 0x0004},
1614/* DSP Registers */
1615 {0x01, 0x0016, 0x0011}, /* RGB offset */
1616 {0x01, 0x0000, 0x0012},
1617 {0x01, 0x0006, 0x0013},
1618 {0x01, 0x0078, 0x0051},
1619 {0x01, 0x0040, 0x0052},
1620 {0x01, 0x0046, 0x0053},
1621 {0x01, 0x0040, 0x0054},
1622 {0x00, 0x0025, 0x0000},
1623/* {0x00, 0x0000, 0x0000 }, */
1624/* Part 2 */
1625/* TG Registers */
1626 {0x00, 0x0026, 0x0000},
1627 {0x00, 0x0001, 0x0000},
1628 {0x00, 0x0027, 0x0000},
1629 {0x00, 0x008a, 0x0000},
1630 {0x02, 0x0007, 0x0005},
1631 {0x02, 0x2000, 0x0000},
1632 {0x05, 0x0022, 0x0004},
1633 {0x05, 0x0015, 0x0001},
1634 {0x05, 0x00ea, 0x0000},
1635 {0x05, 0x0021, 0x0001},
1636 {0x05, 0x00d2, 0x0000},
1637 {0x05, 0x0023, 0x0001},
1638 {0x05, 0x0003, 0x0000},
1639 {0x05, 0x0030, 0x0001},
1640 {0x05, 0x002b, 0x0000},
1641 {0x05, 0x0031, 0x0001},
1642 {0x05, 0x0023, 0x0000},
1643 {0x05, 0x0032, 0x0001},
1644 {0x05, 0x0023, 0x0000},
1645 {0x05, 0x0033, 0x0001},
1646 {0x05, 0x0023, 0x0000},
1647 {0x05, 0x0034, 0x0001},
1648 {0x05, 0x0002, 0x0000},
1649 {0x05, 0x0050, 0x0001},
1650 {0x05, 0x0000, 0x0000},
1651 {0x05, 0x0051, 0x0001},
1652 {0x05, 0x0000, 0x0000},
1653 {0x05, 0x0052, 0x0001},
1654 {0x05, 0x0000, 0x0000},
1655 {0x05, 0x0054, 0x0001},
1656 {0x05, 0x0001, 0x0000},
1657 {}
1658};
1659
1660/* Based on snoops from Ori Cohen */
1661static const __u16 spca501c_mysterious_init_data[][3] = {
1662/* Part 3 */
1663/* TG registers */
1664/* {0x00, 0x0000, 0x0000}, */
1665 {0x00, 0x0000, 0x0001},
1666 {0x00, 0x0000, 0x0002},
1667 {0x00, 0x0006, 0x0003},
1668 {0x00, 0x0000, 0x0004},
1669 {0x00, 0x0090, 0x0005},
1670 {0x00, 0x0000, 0x0006},
1671 {0x00, 0x0040, 0x0007},
1672 {0x00, 0x00c0, 0x0008},
1673 {0x00, 0x004a, 0x0009},
1674 {0x00, 0x0000, 0x000a},
1675 {0x00, 0x0000, 0x000b},
1676 {0x00, 0x0001, 0x000c},
1677 {0x00, 0x0001, 0x000d},
1678 {0x00, 0x0000, 0x000e},
1679 {0x00, 0x0002, 0x000f},
1680 {0x00, 0x0001, 0x0010},
1681 {0x00, 0x0000, 0x0011},
1682 {0x00, 0x0001, 0x0012},
1683 {0x00, 0x0002, 0x0020},
1684 {0x00, 0x0080, 0x0021}, /* 640 */
1685 {0x00, 0x0001, 0x0022},
1686 {0x00, 0x00e0, 0x0023}, /* 480 */
1687 {0x00, 0x0000, 0x0024}, /* Offset H hight */
1688 {0x00, 0x00d3, 0x0025}, /* low */
1689 {0x00, 0x0000, 0x0026}, /* Offset V */
1690 {0x00, 0x000d, 0x0027}, /* low */
1691 {0x00, 0x0000, 0x0046},
1692 {0x00, 0x0000, 0x0047},
1693 {0x00, 0x0000, 0x0048},
1694 {0x00, 0x0000, 0x0049},
1695 {0x00, 0x0008, 0x004a},
1696/* DSP Registers */
1697 {0x01, 0x00a6, 0x0000},
1698 {0x01, 0x0028, 0x0001},
1699 {0x01, 0x0000, 0x0002},
1700 {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
1701 {0x01, 0x0040, 0x0004},
1702 {0x01, 0x0066, 0x0007},
1703 {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
1704 {0x01, 0x002d, 0x0009}, /* A12 */
1705 {0x01, 0x0005, 0x000a}, /* A13 */
1706 {0x01, 0x0023, 0x000b}, /* A21 */
1707 {0x01, 0x00e0, 0x000c}, /* A22 */
1708 {0x01, 0x00fd, 0x000d}, /* A23 */
1709 {0x01, 0x00f4, 0x000e}, /* A31 */
1710 {0x01, 0x00e4, 0x000f}, /* A32 */
1711 {0x01, 0x0028, 0x0010}, /* A33 */
1712 {0x01, 0x00ff, 0x0015}, /* Reserved */
1713 {0x01, 0x0001, 0x0016}, /* Reserved */
1714 {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
1715 {0x01, 0x0023, 0x0018},
1716 {0x01, 0x00ce, 0x0019},
1717 {0x01, 0x0023, 0x001a},
1718 {0x01, 0x0032, 0x001b},
1719 {0x01, 0x008d, 0x001c},
1720 {0x01, 0x00ce, 0x001d},
1721 {0x01, 0x008d, 0x001e},
1722 {0x01, 0x0000, 0x001f},
1723 {0x01, 0x0000, 0x0020}, /* Win1 Start end */
1724 {0x01, 0x00ff, 0x003e}, /* Reserved begin */
1725 {0x01, 0x0002, 0x003f},
1726 {0x01, 0x0000, 0x0040},
1727 {0x01, 0x0035, 0x0041},
1728 {0x01, 0x0053, 0x0042},
1729 {0x01, 0x0069, 0x0043},
1730 {0x01, 0x007c, 0x0044},
1731 {0x01, 0x008c, 0x0045},
1732 {0x01, 0x009a, 0x0046},
1733 {0x01, 0x00a8, 0x0047},
1734 {0x01, 0x00b4, 0x0048},
1735 {0x01, 0x00bf, 0x0049},
1736 {0x01, 0x00ca, 0x004a},
1737 {0x01, 0x00d4, 0x004b},
1738 {0x01, 0x00dd, 0x004c},
1739 {0x01, 0x00e7, 0x004d},
1740 {0x01, 0x00ef, 0x004e},
1741 {0x01, 0x00f8, 0x004f},
1742 {0x01, 0x00ff, 0x0050},
1743 {0x01, 0x0003, 0x0056}, /* Reserved end */
1744 {0x01, 0x0060, 0x0057}, /* Edge Gain */
1745 {0x01, 0x0040, 0x0058},
1746 {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
1747 {0x01, 0x0001, 0x005a},
1748 {0x02, 0x0007, 0x0005},
1749 {0x02, 0xa048, 0x0000},
1750 {0x02, 0x0007, 0x0005},
1751 {0x02, 0x0015, 0x0006},
1752 {0x02, 0x200a, 0x0007},
1753 {0x02, 0xa048, 0x0000},
1754 {0x02, 0xc000, 0x0001},
1755 {0x02, 0x000f, 0x0005},
1756 {0x02, 0xa048, 0x0000},
1757 {0x05, 0x0022, 0x0004},
1758 {0x05, 0x0025, 0x0001},
1759 {0x05, 0x0000, 0x0000},
1760/* Part 4 */
1761 {0x05, 0x0026, 0x0001},
1762 {0x05, 0x0001, 0x0000},
1763 {0x05, 0x0027, 0x0001},
1764 {0x05, 0x0000, 0x0000},
1765 {0x05, 0x0001, 0x0001},
1766 {0x05, 0x0000, 0x0000},
1767 {0x05, 0x0021, 0x0001},
1768 {0x05, 0x00d2, 0x0000},
1769 {0x05, 0x0020, 0x0001},
1770 {0x05, 0x0000, 0x0000},
1771 {0x00, 0x0090, 0x0005},
1772 {0x01, 0x00a6, 0x0000},
1773 {0x02, 0x0000, 0x0005},
1774 {0x05, 0x0026, 0x0001},
1775 {0x05, 0x0001, 0x0000},
1776 {0x05, 0x0027, 0x0001},
1777 {0x05, 0x004e, 0x0000},
1778/* Part 5 */
1779 {0x01, 0x0003, 0x003f},
1780 {0x01, 0x0001, 0x0056},
1781 {0x01, 0x000f, 0x0008},
1782 {0x01, 0x002d, 0x0009},
1783 {0x01, 0x0005, 0x000a},
1784 {0x01, 0x0023, 0x000b},
1785 {0x01, 0xffe0, 0x000c},
1786 {0x01, 0xfffd, 0x000d},
1787 {0x01, 0xfff4, 0x000e},
1788 {0x01, 0xffe4, 0x000f},
1789 {0x01, 0x0028, 0x0010},
1790 {0x01, 0x00a8, 0x0001},
1791 {0x01, 0x0066, 0x0007},
1792 {0x01, 0x0032, 0x0017},
1793 {0x01, 0x0023, 0x0018},
1794 {0x01, 0x00ce, 0x0019},
1795 {0x01, 0x0023, 0x001a},
1796 {0x01, 0x0032, 0x001b},
1797 {0x01, 0x008d, 0x001c},
1798 {0x01, 0x00ce, 0x001d},
1799 {0x01, 0x008d, 0x001e},
1800 {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
1801 {0x01, 0x0032, 0x0016}, /* 32 */
1802 {0x01, 0x0016, 0x0011}, /* R 00 */
1803 {0x01, 0x0016, 0x0012}, /* G 00 */
1804 {0x01, 0x0016, 0x0013}, /* B 00 */
1805 {0x01, 0x000a, 0x0003},
1806 {0x02, 0xc002, 0x0001},
1807 {0x02, 0x0007, 0x0005},
1808 {}
1809};
1810
1811static int reg_write(struct usb_device *dev,
1812 __u16 req, __u16 index, __u16 value)
1813{
1814 int ret;
1815
1816 ret = usb_control_msg(dev,
1817 usb_sndctrlpipe(dev, 0),
1818 req,
1819 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1820 value, index, NULL, 0, 500);
1821 PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
1822 req, index, value);
1823 if (ret < 0)
1824 PDEBUG(D_ERR, "reg write: error %d", ret);
1825 return ret;
1826}
1827
1828/* returns: negative is error, pos or zero is data */
1829static int reg_read(struct gspca_dev *gspca_dev,
1830 __u16 req, /* bRequest */
1831 __u16 index, /* wIndex */
1832 __u16 length) /* wLength (1 or 2 only) */
1833{
1834 int ret;
1835
1836 gspca_dev->usb_buf[1] = 0;
1837 ret = usb_control_msg(gspca_dev->dev,
1838 usb_rcvctrlpipe(gspca_dev->dev, 0),
1839 req,
1840 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1841 0, /* value */
1842 index,
1843 gspca_dev->usb_buf, length,
1844 500); /* timeout */
1845 if (ret < 0) {
1846 PDEBUG(D_ERR, "reg_read err %d", ret);
1847 return -1;
1848 }
1849 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
1850}
1851
1852static int write_vector(struct gspca_dev *gspca_dev,
1853 const __u16 data[][3])
1854{
1855 struct usb_device *dev = gspca_dev->dev;
1856 int ret, i = 0;
1857
1858 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
1859 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
1860 if (ret < 0) {
1861 PDEBUG(D_ERR,
1862 "Reg write failed for 0x%02x,0x%02x,0x%02x",
1863 data[i][0], data[i][1], data[i][2]);
1864 return ret;
1865 }
1866 i++;
1867 }
1868 return 0;
1869}
1870
1871static void setbrightness(struct gspca_dev *gspca_dev)
1872{
1873 struct sd *sd = (struct sd *) gspca_dev;
1874
1875 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, sd->brightness);
1876 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, sd->brightness);
1877 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, sd->brightness);
1878}
1879
1880static void getbrightness(struct gspca_dev *gspca_dev)
1881{
1882 struct sd *sd = (struct sd *) gspca_dev;
1883 __u16 brightness;
1884
1885 brightness = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x11, 2);
1886 sd->brightness = brightness << 1;
1887}
1888
1889static void setcontrast(struct gspca_dev *gspca_dev)
1890{
1891 struct sd *sd = (struct sd *) gspca_dev;
1892
1893 reg_write(gspca_dev->dev, 0x00, 0x00,
1894 (sd->contrast >> 8) & 0xff);
1895 reg_write(gspca_dev->dev, 0x00, 0x01,
1896 sd->contrast & 0xff);
1897}
1898
1899static void getcontrast(struct gspca_dev *gspca_dev)
1900{
1901/* spca50x->contrast = 0xaa01; */
1902}
1903
1904static void setcolors(struct gspca_dev *gspca_dev)
1905{
1906 struct sd *sd = (struct sd *) gspca_dev;
1907
1908 reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, sd->colors);
1909}
1910
1911static void getcolors(struct gspca_dev *gspca_dev)
1912{
1913 struct sd *sd = (struct sd *) gspca_dev;
1914
1915 sd->colors = reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x0c, 2);
1916/* sd->hue = (reg_read(gspca_dev, SPCA501_REG_CCDSP, 0x13, */
1917/* 2) & 0xFF) << 8; */
1918}
1919
1920/* this function is called at probe time */
1921static int sd_config(struct gspca_dev *gspca_dev,
1922 const struct usb_device_id *id)
1923{
1924 struct sd *sd = (struct sd *) gspca_dev;
1925 struct cam *cam;
1926 __u16 vendor;
1927 __u16 product;
1928
1929 vendor = id->idVendor;
1930 product = id->idProduct;
1931 switch (vendor) {
1932 case 0x0000: /* Unknow Camera */
1933/* switch (product) { */
1934/* case 0x0000: */
1935 sd->subtype = MystFromOriUnknownCamera;
1936/* break; */
1937/* } */
1938 break;
1939 case 0x040a: /* Kodak cameras */
1940/* switch (product) { */
1941/* case 0x0002: */
1942 sd->subtype = KodakDVC325;
1943/* break; */
1944/* } */
1945 break;
1946 case 0x0497: /* Smile International */
1947/* switch (product) { */
1948/* case 0xc001: */
1949 sd->subtype = SmileIntlCamera;
1950/* break; */
1951/* } */
1952 break;
1953 case 0x0506: /* 3COM cameras */
1954/* switch (product) { */
1955/* case 0x00df: */
1956 sd->subtype = ThreeComHomeConnectLite;
1957/* break; */
1958/* } */
1959 break;
1960 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
1961 switch (product) {
1962 case 0x0401:
1963 sd->subtype = IntelCreateAndShare;
1964 break;
1965 case 0x0402:
1966 sd->subtype = ViewQuestM318B;
1967 break;
1968 }
1969 break;
1970 case 0x1776: /* Arowana */
1971/* switch (product) { */
1972/* case 0x501c: */
1973 sd->subtype = Arowana300KCMOSCamera;
1974/* break; */
1975/* } */
1976 break;
1977 }
1978 cam = &gspca_dev->cam;
1979 cam->dev_name = (char *) id->driver_info;
1980 cam->epaddr = 0x01;
1981 cam->cam_mode = vga_mode;
1982 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1983 sd->brightness = sd_ctrls[MY_BRIGHTNESS].qctrl.default_value;
1984 sd->contrast = sd_ctrls[MY_CONTRAST].qctrl.default_value;
1985 sd->colors = sd_ctrls[MY_COLOR].qctrl.default_value;
1986
1987 switch (sd->subtype) {
1988 case Arowana300KCMOSCamera:
1989 case SmileIntlCamera:
1990 /* Arowana 300k CMOS Camera data */
1991 if (write_vector(gspca_dev, spca501c_arowana_init_data))
1992 goto error;
1993 break;
1994 case MystFromOriUnknownCamera:
1995 /* UnKnow Ori CMOS Camera data */
1996 if (write_vector(gspca_dev, spca501c_mysterious_open_data))
1997 goto error;
1998 break;
1999 default:
2000 /* generic spca501 init data */
2001 if (write_vector(gspca_dev, spca501_init_data))
2002 goto error;
2003 break;
2004 }
2005 return 0;
2006error:
2007 return -EINVAL;
2008}
2009
2010/* this function is called at open time */
2011static int sd_open(struct gspca_dev *gspca_dev)
2012{
2013 struct sd *sd = (struct sd *) gspca_dev;
2014
2015 switch (sd->subtype) {
2016 case ThreeComHomeConnectLite:
2017 /* Special handling for 3com data */
2018 write_vector(gspca_dev, spca501_3com_open_data);
2019 break;
2020 case Arowana300KCMOSCamera:
2021 case SmileIntlCamera:
2022 /* Arowana 300k CMOS Camera data */
2023 write_vector(gspca_dev, spca501c_arowana_open_data);
2024 break;
2025 case MystFromOriUnknownCamera:
2026 /* UnKnow CMOS Camera data */
2027 write_vector(gspca_dev, spca501c_mysterious_init_data);
2028 break;
2029 default:
2030 /* Generic 501 open data */
2031 write_vector(gspca_dev, spca501_open_data);
2032 }
2033 PDEBUG(D_STREAM, "Initializing SPCA501 finished");
2034 return 0;
2035}
2036
2037static void sd_start(struct gspca_dev *gspca_dev)
2038{
2039 struct usb_device *dev = gspca_dev->dev;
2040 int mode;
2041
2042 /* memorize the wanted pixel format */
2043 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
2044
2045 /* Enable ISO packet machine CTRL reg=2,
2046 * index=1 bitmask=0x2 (bit ordinal 1) */
2047 reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
2048 switch (mode) {
2049 case 0: /* 640x480 */
2050 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
2051 break;
2052 case 1: /* 320x240 */
2053 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
2054 break;
2055 default:
2056/* case 2: * 160x120 */
2057 reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
2058 break;
2059 }
2060 reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
2061
2062 /* HDG atleast the Intel CreateAndShare needs to have one of its
2063 * brightness / contrast / color set otherwise it assumes what seems
2064 * max contrast. Note that strange enough setting any of these is
2065 * enough to fix the max contrast problem, to be sure we set all 3 */
2066 setbrightness(gspca_dev);
2067 setcontrast(gspca_dev);
2068 setcolors(gspca_dev);
2069}
2070
2071static void sd_stopN(struct gspca_dev *gspca_dev)
2072{
2073 /* Disable ISO packet
2074 * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
2075 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
2076}
2077
2078static void sd_stop0(struct gspca_dev *gspca_dev)
2079{
2080}
2081
2082/* this function is called at close time */
2083static void sd_close(struct gspca_dev *gspca_dev)
2084{
2085 reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
2086}
2087
2088static void sd_pkt_scan(struct gspca_dev *gspca_dev,
2089 struct gspca_frame *frame, /* target */
2090 __u8 *data, /* isoc packet */
2091 int len) /* iso packet length */
2092{
2093 switch (data[0]) {
2094 case 0: /* start of frame */
2095 frame = gspca_frame_add(gspca_dev,
2096 LAST_PACKET,
2097 frame,
2098 data, 0);
2099 data += SPCA501_OFFSET_DATA;
2100 len -= SPCA501_OFFSET_DATA;
2101 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
2102 data, len);
2103 return;
2104 case 0xff: /* drop */
2105/* gspca_dev->last_packet_type = DISCARD_PACKET; */
2106 return;
2107 }
2108 data++;
2109 len--;
2110 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
2111 data, len);
2112}
2113
2114static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
2115{
2116 struct sd *sd = (struct sd *) gspca_dev;
2117
2118 sd->brightness = val;
2119 if (gspca_dev->streaming)
2120 setbrightness(gspca_dev);
2121 return 0;
2122}
2123
2124static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
2125{
2126 struct sd *sd = (struct sd *) gspca_dev;
2127
2128 getbrightness(gspca_dev);
2129 *val = sd->brightness;
2130 return 0;
2131}
2132
2133static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
2134{
2135 struct sd *sd = (struct sd *) gspca_dev;
2136
2137 sd->contrast = val;
2138 if (gspca_dev->streaming)
2139 setcontrast(gspca_dev);
2140 return 0;
2141}
2142
2143static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
2144{
2145 struct sd *sd = (struct sd *) gspca_dev;
2146
2147 getcontrast(gspca_dev);
2148 *val = sd->contrast;
2149 return 0;
2150}
2151
2152static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
2153{
2154 struct sd *sd = (struct sd *) gspca_dev;
2155
2156 sd->colors = val;
2157 if (gspca_dev->streaming)
2158 setcolors(gspca_dev);
2159 return 0;
2160}
2161
2162static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
2163{
2164 struct sd *sd = (struct sd *) gspca_dev;
2165
2166 getcolors(gspca_dev);
2167 *val = sd->colors;
2168 return 0;
2169}
2170
2171/* sub-driver description */
2172static const struct sd_desc sd_desc = {
2173 .name = MODULE_NAME,
2174 .ctrls = sd_ctrls,
2175 .nctrls = ARRAY_SIZE(sd_ctrls),
2176 .config = sd_config,
2177 .open = sd_open,
2178 .start = sd_start,
2179 .stopN = sd_stopN,
2180 .stop0 = sd_stop0,
2181 .close = sd_close,
2182 .pkt_scan = sd_pkt_scan,
2183};
2184
2185/* -- module initialisation -- */
2186#define DVNM(name) .driver_info = (kernel_ulong_t) name
2187static const __devinitdata struct usb_device_id device_table[] = {
2188 {USB_DEVICE(0x040a, 0x0002), DVNM("Kodak DVC-325")},
2189 {USB_DEVICE(0x0497, 0xc001), DVNM("Smile International")},
2190 {USB_DEVICE(0x0506, 0x00df), DVNM("3Com HomeConnect Lite")},
2191 {USB_DEVICE(0x0733, 0x0401), DVNM("Intel Create and Share")},
2192 {USB_DEVICE(0x0733, 0x0402), DVNM("ViewQuest M318B")},
2193 {USB_DEVICE(0x1776, 0x501c), DVNM("Arowana 300K CMOS Camera")},
2194 {USB_DEVICE(0x0000, 0x0000), DVNM("MystFromOri Unknow Camera")},
2195 {}
2196};
2197MODULE_DEVICE_TABLE(usb, device_table);
2198
2199/* -- device connect -- */
2200static int sd_probe(struct usb_interface *intf,
2201 const struct usb_device_id *id)
2202{
2203 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
2204 THIS_MODULE);
2205}
2206
2207static struct usb_driver sd_driver = {
2208 .name = MODULE_NAME,
2209 .id_table = device_table,
2210 .probe = sd_probe,
2211 .disconnect = gspca_disconnect,
2212};
2213
2214/* -- module insert / remove -- */
2215static int __init sd_mod_init(void)
2216{
2217 if (usb_register(&sd_driver) < 0)
2218 return -1;
2219 PDEBUG(D_PROBE, "v%s registered", version);
2220 return 0;
2221}
2222static void __exit sd_mod_exit(void)
2223{
2224 usb_deregister(&sd_driver);
2225 PDEBUG(D_PROBE, "deregistered");
2226}
2227
2228module_init(sd_mod_init);
2229module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
new file mode 100644
index 000000000000..ddea6e140aa8
--- /dev/null
+++ b/drivers/media/video/gspca/spca505.c
@@ -0,0 +1,951 @@
1/*
2 * SPCA505 chip based cameras initialization data
3 *
4 * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#define MODULE_NAME "spca505"
23
24#include "gspca.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
30MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 int buflen;
38 unsigned char tmpbuf[640 * 480 * 3 / 2]; /* YYUV per line */
39 unsigned char tmpbuf2[640 * 480 * 2]; /* YUYV */
40
41 unsigned char brightness;
42
43 char subtype;
44#define IntelPCCameraPro 0
45#define Nxultra 1
46};
47
48/* V4L2 controls supported by the driver */
49static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
51
52static struct ctrl sd_ctrls[] = {
53#define SD_BRIGHTNESS 0
54 {
55 {
56 .id = V4L2_CID_BRIGHTNESS,
57 .type = V4L2_CTRL_TYPE_INTEGER,
58 .name = "Brightness",
59 .minimum = 0,
60 .maximum = 255,
61 .step = 1,
62 .default_value = 127,
63 },
64 .set = sd_setbrightness,
65 .get = sd_getbrightness,
66 },
67};
68
69static struct v4l2_pix_format vga_mode[] = {
70 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
71 .bytesperline = 160 * 2,
72 .sizeimage = 160 * 120 * 2,
73 .colorspace = V4L2_COLORSPACE_SRGB,
74 .priv = 5},
75 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
76 .bytesperline = 176 * 2,
77 .sizeimage = 176 * 144 * 2,
78 .colorspace = V4L2_COLORSPACE_SRGB,
79 .priv = 4},
80 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
81 .bytesperline = 320 * 2,
82 .sizeimage = 320 * 240 * 2,
83 .colorspace = V4L2_COLORSPACE_SRGB,
84 .priv = 2},
85 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
86 .bytesperline = 352 * 2,
87 .sizeimage = 352 * 288 * 2,
88 .colorspace = V4L2_COLORSPACE_SRGB,
89 .priv = 1},
90 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
91 .bytesperline = 640 * 2,
92 .sizeimage = 640 * 480 * 2,
93 .colorspace = V4L2_COLORSPACE_SRGB,
94 .priv = 0},
95};
96
97#define SPCA50X_OFFSET_DATA 10
98
99#define SPCA50X_REG_USB 0x02 /* spca505 501 */
100
101#define SPCA50X_USB_CTRL 0x00 /* spca505 */
102#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
103#define SPCA50X_REG_GLOBAL 0x03 /* spca505 */
104#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
105#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
106
107#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
108#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
109#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
110
111/*
112 * Data to initialize a SPCA505. Common to the CCD and external modes
113 */
114static const __u16 spca505_init_data[][3] = {
115 /* line bmRequest,value,index */
116 /* 1819 */
117 {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
118 /* Sensor reset */
119 /* 1822 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
120 /* 1825 */ {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
121 /* Block USB reset */
122 /* 1828 */ {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL,
123 SPCA50X_GLOBAL_MISC0},
124
125 /* 1831 */ {0x5, 0x01, 0x10},
126 /* Maybe power down some stuff */
127 /* 1834 */ {0x5, 0x0f, 0x11},
128
129 /* Setup internal CCD ? */
130 /* 1837 */ {0x6, 0x10, 0x08},
131 /* 1840 */ {0x6, 0x00, 0x09},
132 /* 1843 */ {0x6, 0x00, 0x0a},
133 /* 1846 */ {0x6, 0x00, 0x0b},
134 /* 1849 */ {0x6, 0x10, 0x0c},
135 /* 1852 */ {0x6, 0x00, 0x0d},
136 /* 1855 */ {0x6, 0x00, 0x0e},
137 /* 1858 */ {0x6, 0x00, 0x0f},
138 /* 1861 */ {0x6, 0x10, 0x10},
139 /* 1864 */ {0x6, 0x02, 0x11},
140 /* 1867 */ {0x6, 0x00, 0x12},
141 /* 1870 */ {0x6, 0x04, 0x13},
142 /* 1873 */ {0x6, 0x02, 0x14},
143 /* 1876 */ {0x6, 0x8a, 0x51},
144 /* 1879 */ {0x6, 0x40, 0x52},
145 /* 1882 */ {0x6, 0xb6, 0x53},
146 /* 1885 */ {0x6, 0x3d, 0x54},
147 {}
148};
149
150/*
151 * Data to initialize the camera using the internal CCD
152 */
153static const __u16 spca505_open_data_ccd[][3] = {
154 /* line bmRequest,value,index */
155 /* Internal CCD data set */
156 /* 1891 */ {0x3, 0x04, 0x01},
157 /* This could be a reset */
158 /* 1894 */ {0x3, 0x00, 0x01},
159
160 /* Setup compression and image registers. 0x6 and 0x7 seem to be
161 related to H&V hold, and are resolution mode specific */
162 /* 1897 */ {0x4, 0x10, 0x01},
163 /* DIFF(0x50), was (0x10) */
164 /* 1900 */ {0x4, 0x00, 0x04},
165 /* 1903 */ {0x4, 0x00, 0x05},
166 /* 1906 */ {0x4, 0x20, 0x06},
167 /* 1909 */ {0x4, 0x20, 0x07},
168
169 /* 1912 */ {0x8, 0x0a, 0x00},
170 /* DIFF (0x4a), was (0xa) */
171
172 /* 1915 */ {0x5, 0x00, 0x10},
173 /* 1918 */ {0x5, 0x00, 0x11},
174 /* 1921 */ {0x5, 0x00, 0x00},
175 /* DIFF not written */
176 /* 1924 */ {0x5, 0x00, 0x01},
177 /* DIFF not written */
178 /* 1927 */ {0x5, 0x00, 0x02},
179 /* DIFF not written */
180 /* 1930 */ {0x5, 0x00, 0x03},
181 /* DIFF not written */
182 /* 1933 */ {0x5, 0x00, 0x04},
183 /* DIFF not written */
184 /* 1936 */ {0x5, 0x80, 0x05},
185 /* DIFF not written */
186 /* 1939 */ {0x5, 0xe0, 0x06},
187 /* DIFF not written */
188 /* 1942 */ {0x5, 0x20, 0x07},
189 /* DIFF not written */
190 /* 1945 */ {0x5, 0xa0, 0x08},
191 /* DIFF not written */
192 /* 1948 */ {0x5, 0x0, 0x12},
193 /* DIFF not written */
194 /* 1951 */ {0x5, 0x02, 0x0f},
195 /* DIFF not written */
196 /* 1954 */ {0x5, 0x10, 0x46},
197 /* DIFF not written */
198 /* 1957 */ {0x5, 0x8, 0x4a},
199 /* DIFF not written */
200
201 /* 1960 */ {0x3, 0x08, 0x03},
202 /* DIFF (0x3,0x28,0x3) */
203 /* 1963 */ {0x3, 0x08, 0x01},
204 /* 1966 */ {0x3, 0x0c, 0x03},
205 /* DIFF not written */
206 /* 1969 */ {0x3, 0x21, 0x00},
207 /* DIFF (0x39) */
208
209/* Extra block copied from init to hopefully ensure CCD is in a sane state */
210 /* 1837 */ {0x6, 0x10, 0x08},
211 /* 1840 */ {0x6, 0x00, 0x09},
212 /* 1843 */ {0x6, 0x00, 0x0a},
213 /* 1846 */ {0x6, 0x00, 0x0b},
214 /* 1849 */ {0x6, 0x10, 0x0c},
215 /* 1852 */ {0x6, 0x00, 0x0d},
216 /* 1855 */ {0x6, 0x00, 0x0e},
217 /* 1858 */ {0x6, 0x00, 0x0f},
218 /* 1861 */ {0x6, 0x10, 0x10},
219 /* 1864 */ {0x6, 0x02, 0x11},
220 /* 1867 */ {0x6, 0x00, 0x12},
221 /* 1870 */ {0x6, 0x04, 0x13},
222 /* 1873 */ {0x6, 0x02, 0x14},
223 /* 1876 */ {0x6, 0x8a, 0x51},
224 /* 1879 */ {0x6, 0x40, 0x52},
225 /* 1882 */ {0x6, 0xb6, 0x53},
226 /* 1885 */ {0x6, 0x3d, 0x54},
227 /* End of extra block */
228
229 /* 1972 */ {0x6, 0x3f, 0x1},
230 /* Block skipped */
231 /* 1975 */ {0x6, 0x10, 0x02},
232 /* 1978 */ {0x6, 0x64, 0x07},
233 /* 1981 */ {0x6, 0x10, 0x08},
234 /* 1984 */ {0x6, 0x00, 0x09},
235 /* 1987 */ {0x6, 0x00, 0x0a},
236 /* 1990 */ {0x6, 0x00, 0x0b},
237 /* 1993 */ {0x6, 0x10, 0x0c},
238 /* 1996 */ {0x6, 0x00, 0x0d},
239 /* 1999 */ {0x6, 0x00, 0x0e},
240 /* 2002 */ {0x6, 0x00, 0x0f},
241 /* 2005 */ {0x6, 0x10, 0x10},
242 /* 2008 */ {0x6, 0x02, 0x11},
243 /* 2011 */ {0x6, 0x00, 0x12},
244 /* 2014 */ {0x6, 0x04, 0x13},
245 /* 2017 */ {0x6, 0x02, 0x14},
246 /* 2020 */ {0x6, 0x8a, 0x51},
247 /* 2023 */ {0x6, 0x40, 0x52},
248 /* 2026 */ {0x6, 0xb6, 0x53},
249 /* 2029 */ {0x6, 0x3d, 0x54},
250 /* 2032 */ {0x6, 0x60, 0x57},
251 /* 2035 */ {0x6, 0x20, 0x58},
252 /* 2038 */ {0x6, 0x15, 0x59},
253 /* 2041 */ {0x6, 0x05, 0x5a},
254
255 /* 2044 */ {0x5, 0x01, 0xc0},
256 /* 2047 */ {0x5, 0x10, 0xcb},
257 /* 2050 */ {0x5, 0x80, 0xc1},
258 /* */
259 /* 2053 */ {0x5, 0x0, 0xc2},
260 /* 4 was 0 */
261 /* 2056 */ {0x5, 0x00, 0xca},
262 /* 2059 */ {0x5, 0x80, 0xc1},
263 /* */
264 /* 2062 */ {0x5, 0x04, 0xc2},
265 /* 2065 */ {0x5, 0x00, 0xca},
266 /* 2068 */ {0x5, 0x0, 0xc1},
267 /* */
268 /* 2071 */ {0x5, 0x00, 0xc2},
269 /* 2074 */ {0x5, 0x00, 0xca},
270 /* 2077 */ {0x5, 0x40, 0xc1},
271 /* */
272 /* 2080 */ {0x5, 0x17, 0xc2},
273 /* 2083 */ {0x5, 0x00, 0xca},
274 /* 2086 */ {0x5, 0x80, 0xc1},
275 /* */
276 /* 2089 */ {0x5, 0x06, 0xc2},
277 /* 2092 */ {0x5, 0x00, 0xca},
278 /* 2095 */ {0x5, 0x80, 0xc1},
279 /* */
280 /* 2098 */ {0x5, 0x04, 0xc2},
281 /* 2101 */ {0x5, 0x00, 0xca},
282
283 /* 2104 */ {0x3, 0x4c, 0x3},
284 /* 2107 */ {0x3, 0x18, 0x1},
285
286 /* 2110 */ {0x6, 0x70, 0x51},
287 /* 2113 */ {0x6, 0xbe, 0x53},
288 /* 2116 */ {0x6, 0x71, 0x57},
289 /* 2119 */ {0x6, 0x20, 0x58},
290 /* 2122 */ {0x6, 0x05, 0x59},
291 /* 2125 */ {0x6, 0x15, 0x5a},
292
293 /* 2128 */ {0x4, 0x00, 0x08},
294 /* Compress = OFF (0x1 to turn on) */
295 /* 2131 */ {0x4, 0x12, 0x09},
296 /* 2134 */ {0x4, 0x21, 0x0a},
297 /* 2137 */ {0x4, 0x10, 0x0b},
298 /* 2140 */ {0x4, 0x21, 0x0c},
299 /* 2143 */ {0x4, 0x05, 0x00},
300 /* was 5 (Image Type ? ) */
301 /* 2146 */ {0x4, 0x00, 0x01},
302
303 /* 2149 */ {0x6, 0x3f, 0x01},
304
305 /* 2152 */ {0x4, 0x00, 0x04},
306 /* 2155 */ {0x4, 0x00, 0x05},
307 /* 2158 */ {0x4, 0x40, 0x06},
308 /* 2161 */ {0x4, 0x40, 0x07},
309
310 /* 2164 */ {0x6, 0x1c, 0x17},
311 /* 2167 */ {0x6, 0xe2, 0x19},
312 /* 2170 */ {0x6, 0x1c, 0x1b},
313 /* 2173 */ {0x6, 0xe2, 0x1d},
314 /* 2176 */ {0x6, 0xaa, 0x1f},
315 /* 2179 */ {0x6, 0x70, 0x20},
316
317 /* 2182 */ {0x5, 0x01, 0x10},
318 /* 2185 */ {0x5, 0x00, 0x11},
319 /* 2188 */ {0x5, 0x01, 0x00},
320 /* 2191 */ {0x5, 0x05, 0x01},
321 /* 2194 */ {0x5, 0x00, 0xc1},
322 /* */
323 /* 2197 */ {0x5, 0x00, 0xc2},
324 /* 2200 */ {0x5, 0x00, 0xca},
325
326 /* 2203 */ {0x6, 0x70, 0x51},
327 /* 2206 */ {0x6, 0xbe, 0x53},
328 {}
329};
330
331/*
332 Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
333 * SPCA505b chip based cameras initialization data
334 *
335 */
336/* jfm */
337#define initial_brightness 0x7f /* 0x0(white)-0xff(black) */
338/* #define initial_brightness 0x0 //0x0(white)-0xff(black) */
339/*
340 * Data to initialize a SPCA505. Common to the CCD and external modes
341 */
342static const __u16 spca505b_init_data[][3] = {
343/* start */
344 {0x02, 0x00, 0x00}, /* init */
345 {0x02, 0x00, 0x01},
346 {0x02, 0x00, 0x02},
347 {0x02, 0x00, 0x03},
348 {0x02, 0x00, 0x04},
349 {0x02, 0x00, 0x05},
350 {0x02, 0x00, 0x06},
351 {0x02, 0x00, 0x07},
352 {0x02, 0x00, 0x08},
353 {0x02, 0x00, 0x09},
354 {0x03, 0x00, 0x00},
355 {0x03, 0x00, 0x01},
356 {0x03, 0x00, 0x02},
357 {0x03, 0x00, 0x03},
358 {0x03, 0x00, 0x04},
359 {0x03, 0x00, 0x05},
360 {0x03, 0x00, 0x06},
361 {0x04, 0x00, 0x00},
362 {0x04, 0x00, 0x02},
363 {0x04, 0x00, 0x04},
364 {0x04, 0x00, 0x05},
365 {0x04, 0x00, 0x06},
366 {0x04, 0x00, 0x07},
367 {0x04, 0x00, 0x08},
368 {0x04, 0x00, 0x09},
369 {0x04, 0x00, 0x0a},
370 {0x04, 0x00, 0x0b},
371 {0x04, 0x00, 0x0c},
372 {0x07, 0x00, 0x00},
373 {0x07, 0x00, 0x03},
374 {0x08, 0x00, 0x00},
375 {0x08, 0x00, 0x01},
376 {0x08, 0x00, 0x02},
377 {0x00, 0x01, 0x00},
378 {0x00, 0x01, 0x01},
379 {0x00, 0x01, 0x34},
380 {0x00, 0x01, 0x35},
381 {0x06, 0x18, 0x08},
382 {0x06, 0xfc, 0x09},
383 {0x06, 0xfc, 0x0a},
384 {0x06, 0xfc, 0x0b},
385 {0x06, 0x18, 0x0c},
386 {0x06, 0xfc, 0x0d},
387 {0x06, 0xfc, 0x0e},
388 {0x06, 0xfc, 0x0f},
389 {0x06, 0x18, 0x10},
390 {0x06, 0xfe, 0x12},
391 {0x06, 0x00, 0x11},
392 {0x06, 0x00, 0x14},
393 {0x06, 0x00, 0x13},
394 {0x06, 0x28, 0x51},
395 {0x06, 0xff, 0x53},
396 {0x02, 0x00, 0x08},
397
398 {0x03, 0x00, 0x03},
399 {0x03, 0x10, 0x03},
400 {}
401};
402
403/*
404 * Data to initialize the camera using the internal CCD
405 */
406static const __u16 spca505b_open_data_ccd[][3] = {
407
408/* {0x02,0x00,0x00}, */
409 {0x03, 0x04, 0x01}, /* rst */
410 {0x03, 0x00, 0x01},
411 {0x03, 0x00, 0x00},
412 {0x03, 0x21, 0x00},
413 {0x03, 0x00, 0x04},
414 {0x03, 0x00, 0x03},
415 {0x03, 0x18, 0x03},
416 {0x03, 0x08, 0x01},
417 {0x03, 0x1c, 0x03},
418 {0x03, 0x5c, 0x03},
419 {0x03, 0x5c, 0x03},
420 {0x03, 0x18, 0x01},
421
422/* same as 505 */
423 {0x04, 0x10, 0x01},
424 {0x04, 0x00, 0x04},
425 {0x04, 0x00, 0x05},
426 {0x04, 0x20, 0x06},
427 {0x04, 0x20, 0x07},
428
429 {0x08, 0x0a, 0x00},
430
431 {0x05, 0x00, 0x10},
432 {0x05, 0x00, 0x11},
433 {0x05, 0x00, 0x12},
434 {0x05, 0x6f, 0x00},
435 {0x05, initial_brightness >> 6, 0x00},
436 {0x05, initial_brightness << 2, 0x01},
437 {0x05, 0x00, 0x02},
438 {0x05, 0x01, 0x03},
439 {0x05, 0x00, 0x04},
440 {0x05, 0x03, 0x05},
441 {0x05, 0xe0, 0x06},
442 {0x05, 0x20, 0x07},
443 {0x05, 0xa0, 0x08},
444 {0x05, 0x00, 0x12},
445 {0x05, 0x02, 0x0f},
446 {0x05, 128, 0x14}, /* max exposure off (0=on) */
447 {0x05, 0x01, 0xb0},
448 {0x05, 0x01, 0xbf},
449 {0x03, 0x02, 0x06},
450 {0x05, 0x10, 0x46},
451 {0x05, 0x08, 0x4a},
452
453 {0x06, 0x00, 0x01},
454 {0x06, 0x10, 0x02},
455 {0x06, 0x64, 0x07},
456 {0x06, 0x18, 0x08},
457 {0x06, 0xfc, 0x09},
458 {0x06, 0xfc, 0x0a},
459 {0x06, 0xfc, 0x0b},
460 {0x04, 0x00, 0x01},
461 {0x06, 0x18, 0x0c},
462 {0x06, 0xfc, 0x0d},
463 {0x06, 0xfc, 0x0e},
464 {0x06, 0xfc, 0x0f},
465 {0x06, 0x11, 0x10}, /* contrast */
466 {0x06, 0x00, 0x11},
467 {0x06, 0xfe, 0x12},
468 {0x06, 0x00, 0x13},
469 {0x06, 0x00, 0x14},
470 {0x06, 0x9d, 0x51},
471 {0x06, 0x40, 0x52},
472 {0x06, 0x7c, 0x53},
473 {0x06, 0x40, 0x54},
474 {0x06, 0x02, 0x57},
475 {0x06, 0x03, 0x58},
476 {0x06, 0x15, 0x59},
477 {0x06, 0x05, 0x5a},
478 {0x06, 0x03, 0x56},
479 {0x06, 0x02, 0x3f},
480 {0x06, 0x00, 0x40},
481 {0x06, 0x39, 0x41},
482 {0x06, 0x69, 0x42},
483 {0x06, 0x87, 0x43},
484 {0x06, 0x9e, 0x44},
485 {0x06, 0xb1, 0x45},
486 {0x06, 0xbf, 0x46},
487 {0x06, 0xcc, 0x47},
488 {0x06, 0xd5, 0x48},
489 {0x06, 0xdd, 0x49},
490 {0x06, 0xe3, 0x4a},
491 {0x06, 0xe8, 0x4b},
492 {0x06, 0xed, 0x4c},
493 {0x06, 0xf2, 0x4d},
494 {0x06, 0xf7, 0x4e},
495 {0x06, 0xfc, 0x4f},
496 {0x06, 0xff, 0x50},
497
498 {0x05, 0x01, 0xc0},
499 {0x05, 0x10, 0xcb},
500 {0x05, 0x40, 0xc1},
501 {0x05, 0x04, 0xc2},
502 {0x05, 0x00, 0xca},
503 {0x05, 0x40, 0xc1},
504 {0x05, 0x09, 0xc2},
505 {0x05, 0x00, 0xca},
506 {0x05, 0xc0, 0xc1},
507 {0x05, 0x09, 0xc2},
508 {0x05, 0x00, 0xca},
509 {0x05, 0x40, 0xc1},
510 {0x05, 0x59, 0xc2},
511 {0x05, 0x00, 0xca},
512 {0x04, 0x00, 0x01},
513 {0x05, 0x80, 0xc1},
514 {0x05, 0xec, 0xc2},
515 {0x05, 0x0, 0xca},
516
517 {0x06, 0x02, 0x57},
518 {0x06, 0x01, 0x58},
519 {0x06, 0x15, 0x59},
520 {0x06, 0x0a, 0x5a},
521 {0x06, 0x01, 0x57},
522 {0x06, 0x8a, 0x03},
523 {0x06, 0x0a, 0x6c},
524 {0x06, 0x30, 0x01},
525 {0x06, 0x20, 0x02},
526 {0x06, 0x00, 0x03},
527
528 {0x05, 0x8c, 0x25},
529
530 {0x06, 0x4d, 0x51}, /* maybe saturation (4d) */
531 {0x06, 0x84, 0x53}, /* making green (84) */
532 {0x06, 0x00, 0x57}, /* sharpness (1) */
533 {0x06, 0x18, 0x08},
534 {0x06, 0xfc, 0x09},
535 {0x06, 0xfc, 0x0a},
536 {0x06, 0xfc, 0x0b},
537 {0x06, 0x18, 0x0c}, /* maybe hue (18) */
538 {0x06, 0xfc, 0x0d},
539 {0x06, 0xfc, 0x0e},
540 {0x06, 0xfc, 0x0f},
541 {0x06, 0x18, 0x10}, /* maybe contrast (18) */
542
543 {0x05, 0x01, 0x02},
544
545 {0x04, 0x00, 0x08}, /* compression */
546 {0x04, 0x12, 0x09},
547 {0x04, 0x21, 0x0a},
548 {0x04, 0x10, 0x0b},
549 {0x04, 0x21, 0x0c},
550 {0x04, 0x1d, 0x00}, /* imagetype (1d) */
551 {0x04, 0x41, 0x01}, /* hardware snapcontrol */
552
553 {0x04, 0x00, 0x04},
554 {0x04, 0x00, 0x05},
555 {0x04, 0x10, 0x06},
556 {0x04, 0x10, 0x07},
557 {0x04, 0x40, 0x06},
558 {0x04, 0x40, 0x07},
559 {0x04, 0x00, 0x04},
560 {0x04, 0x00, 0x05},
561
562 {0x06, 0x1c, 0x17},
563 {0x06, 0xe2, 0x19},
564 {0x06, 0x1c, 0x1b},
565 {0x06, 0xe2, 0x1d},
566 {0x06, 0x5f, 0x1f},
567 {0x06, 0x32, 0x20},
568
569 {0x05, initial_brightness >> 6, 0x00},
570 {0x05, initial_brightness << 2, 0x01},
571 {0x05, 0x06, 0xc1},
572 {0x05, 0x58, 0xc2},
573 {0x05, 0x0, 0xca},
574 {0x05, 0x0, 0x11},
575 {}
576};
577
578static int reg_write(struct usb_device *dev,
579 __u16 reg, __u16 index, __u16 value)
580{
581 int ret;
582
583 ret = usb_control_msg(dev,
584 usb_sndctrlpipe(dev, 0),
585 reg,
586 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
587 value, index, NULL, 0, 500);
588 PDEBUG(D_PACK, "reg write: 0x%02x,0x%02x:0x%02x, 0x%x",
589 reg, index, value, ret);
590 if (ret < 0)
591 PDEBUG(D_ERR, "reg write: error %d", ret);
592 return ret;
593}
594
595/* returns: negative is error, pos or zero is data */
596static int reg_read(struct gspca_dev *gspca_dev,
597 __u16 reg, /* bRequest */
598 __u16 index, /* wIndex */
599 __u16 length) /* wLength (1 or 2 only) */
600{
601 int ret;
602
603 gspca_dev->usb_buf[1] = 0;
604 ret = usb_control_msg(gspca_dev->dev,
605 usb_rcvctrlpipe(gspca_dev->dev, 0),
606 reg,
607 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
608 (__u16) 0, /* value */
609 (__u16) index,
610 gspca_dev->usb_buf, length,
611 500); /* timeout */
612 if (ret < 0) {
613 PDEBUG(D_ERR, "reg_read err %d", ret);
614 return -1;
615 }
616 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
617}
618
619static int write_vector(struct gspca_dev *gspca_dev,
620 const __u16 data[][3])
621{
622 struct usb_device *dev = gspca_dev->dev;
623 int ret, i = 0;
624
625 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
626 ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
627 if (ret < 0) {
628 PDEBUG(D_ERR,
629 "Register write failed for 0x%x,0x%x,0x%x",
630 data[i][0], data[i][1], data[i][2]);
631 return ret;
632 }
633 i++;
634 }
635 return 0;
636}
637
638/* this function is called at probe time */
639static int sd_config(struct gspca_dev *gspca_dev,
640 const struct usb_device_id *id)
641{
642 struct sd *sd = (struct sd *) gspca_dev;
643 struct cam *cam;
644 __u16 vendor;
645 __u16 product;
646
647 vendor = id->idVendor;
648 product = id->idProduct;
649 switch (vendor) {
650 case 0x041e: /* Creative cameras */
651/* switch (product) { */
652/* case 0x401d: * here505b */
653 sd->subtype = Nxultra;
654/* break; */
655/* } */
656 break;
657 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
658/* switch (product) { */
659/* case 0x0430: */
660/* fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
661 sd->subtype = IntelPCCameraPro;
662/* break; */
663/* } */
664 break;
665 }
666
667 cam = &gspca_dev->cam;
668 cam->dev_name = (char *) id->driver_info;
669 cam->epaddr = 0x01;
670 cam->cam_mode = vga_mode;
671 if (sd->subtype != IntelPCCameraPro)
672 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
673 else /* no 640x480 for IntelPCCameraPro */
674 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0] - 1;
675 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
676
677 if (sd->subtype == Nxultra) {
678 if (write_vector(gspca_dev, spca505b_init_data))
679 return -EIO;
680 } else {
681 if (write_vector(gspca_dev, spca505_init_data))
682 return -EIO;
683 }
684 return 0;
685}
686
687/* this function is called at open time */
688static int sd_open(struct gspca_dev *gspca_dev)
689{
690 struct sd *sd = (struct sd *) gspca_dev;
691 int ret;
692
693 PDEBUG(D_STREAM, "Initializing SPCA505");
694 if (sd->subtype == Nxultra)
695 write_vector(gspca_dev, spca505b_open_data_ccd);
696 else
697 write_vector(gspca_dev, spca505_open_data_ccd);
698 ret = reg_read(gspca_dev, 6, 0x16, 2);
699
700 if (ret < 0) {
701 PDEBUG(D_ERR|D_STREAM,
702 "register read failed for after vector read err = %d",
703 ret);
704 return -EIO;
705 }
706 PDEBUG(D_STREAM,
707 "After vector read returns : 0x%x should be 0x0101",
708 ret & 0xffff);
709
710 ret = reg_write(gspca_dev->dev, 6, 0x16, 0x0a);
711 if (ret < 0) {
712 PDEBUG(D_ERR, "register write failed for (6,0xa,0x16) err=%d",
713 ret);
714 return -EIO;
715 }
716 reg_write(gspca_dev->dev, 5, 0xc2, 18);
717 return 0;
718}
719
720static void sd_start(struct gspca_dev *gspca_dev)
721{
722 struct usb_device *dev = gspca_dev->dev;
723 int ret;
724
725 /* necessary because without it we can see stream
726 * only once after loading module */
727 /* stopping usb registers Tomasz change */
728 reg_write(dev, 0x02, 0x0, 0x0);
729 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
730 case 0:
731 reg_write(dev, 0x04, 0x00, 0x00);
732 reg_write(dev, 0x04, 0x06, 0x10);
733 reg_write(dev, 0x04, 0x07, 0x10);
734 break;
735 case 1:
736 reg_write(dev, 0x04, 0x00, 0x01);
737 reg_write(dev, 0x04, 0x06, 0x1a);
738 reg_write(dev, 0x04, 0x07, 0x1a);
739 break;
740 case 2:
741 reg_write(dev, 0x04, 0x00, 0x02);
742 reg_write(dev, 0x04, 0x06, 0x1c);
743 reg_write(dev, 0x04, 0x07, 0x1d);
744 break;
745 case 4:
746 reg_write(dev, 0x04, 0x00, 0x04);
747 reg_write(dev, 0x04, 0x06, 0x34);
748 reg_write(dev, 0x04, 0x07, 0x34);
749 break;
750 default:
751/* case 5: */
752 reg_write(dev, 0x04, 0x00, 0x05);
753 reg_write(dev, 0x04, 0x06, 0x40);
754 reg_write(dev, 0x04, 0x07, 0x40);
755 break;
756 }
757/* Enable ISO packet machine - should we do this here or in ISOC init ? */
758 ret = reg_write(dev, SPCA50X_REG_USB,
759 SPCA50X_USB_CTRL,
760 SPCA50X_CUSB_ENABLE);
761
762/* reg_write(dev, 0x5, 0x0, 0x0); */
763/* reg_write(dev, 0x5, 0x0, 0x1); */
764/* reg_write(dev, 0x5, 0x11, 0x2); */
765}
766
767static void sd_stopN(struct gspca_dev *gspca_dev)
768{
769 /* Disable ISO packet machine */
770 reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
771}
772
773static void sd_stop0(struct gspca_dev *gspca_dev)
774{
775}
776
777/* this function is called at close time */
778static void sd_close(struct gspca_dev *gspca_dev)
779{
780 /* This maybe reset or power control */
781 reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
782 reg_write(gspca_dev->dev, 0x03, 0x01, 0x0);
783 reg_write(gspca_dev->dev, 0x03, 0x00, 0x1);
784 reg_write(gspca_dev->dev, 0x05, 0x10, 0x1);
785 reg_write(gspca_dev->dev, 0x05, 0x11, 0xf);
786}
787
788/* convert YYUV per line to YUYV (YUV 4:2:2) */
789static void yyuv_decode(unsigned char *out,
790 unsigned char *in,
791 int width,
792 int height)
793{
794 unsigned char *Ui, *Vi, *yi, *yi1;
795 unsigned char *out1;
796 int i, j;
797
798 yi = in;
799 for (i = height / 2; --i >= 0; ) {
800 out1 = out + width * 2; /* next line */
801 yi1 = yi + width;
802 Ui = yi1 + width;
803 Vi = Ui + width / 2;
804 for (j = width / 2; --j >= 0; ) {
805 *out++ = 128 + *yi++;
806 *out++ = 128 + *Ui;
807 *out++ = 128 + *yi++;
808 *out++ = 128 + *Vi;
809
810 *out1++ = 128 + *yi1++;
811 *out1++ = 128 + *Ui++;
812 *out1++ = 128 + *yi1++;
813 *out1++ = 128 + *Vi++;
814 }
815 yi += width * 2;
816 out = out1;
817 }
818}
819
820static void sd_pkt_scan(struct gspca_dev *gspca_dev,
821 struct gspca_frame *frame, /* target */
822 __u8 *data, /* isoc packet */
823 int len) /* iso packet length */
824{
825 struct sd *sd = (struct sd *) gspca_dev;
826
827 switch (data[0]) {
828 case 0: /* start of frame */
829 if (gspca_dev->last_packet_type == FIRST_PACKET) {
830 yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
831 gspca_dev->width,
832 gspca_dev->height);
833 frame = gspca_frame_add(gspca_dev,
834 LAST_PACKET,
835 frame,
836 sd->tmpbuf2,
837 gspca_dev->width
838 * gspca_dev->height
839 * 2);
840 }
841 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
842 data, 0);
843 data += SPCA50X_OFFSET_DATA;
844 len -= SPCA50X_OFFSET_DATA;
845 if (len > 0)
846 memcpy(sd->tmpbuf, data, len);
847 else
848 len = 0;
849 sd->buflen = len;
850 return;
851 case 0xff: /* drop */
852/* gspca_dev->last_packet_type = DISCARD_PACKET; */
853 return;
854 }
855 data += 1;
856 len -= 1;
857 memcpy(&sd->tmpbuf[sd->buflen], data, len);
858 sd->buflen += len;
859}
860
861static void setbrightness(struct gspca_dev *gspca_dev)
862{
863 struct sd *sd = (struct sd *) gspca_dev;
864
865 __u8 brightness = sd->brightness;
866 reg_write(gspca_dev->dev, 5, 0x00, (255 - brightness) >> 6);
867 reg_write(gspca_dev->dev, 5, 0x01, (255 - brightness) << 2);
868
869}
870static void getbrightness(struct gspca_dev *gspca_dev)
871{
872 struct sd *sd = (struct sd *) gspca_dev;
873
874 sd->brightness = 255
875 - ((reg_read(gspca_dev, 5, 0x01, 1) >> 2)
876 + (reg_read(gspca_dev, 5, 0x0, 1) << 6));
877}
878
879static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
880{
881 struct sd *sd = (struct sd *) gspca_dev;
882
883 sd->brightness = val;
884 if (gspca_dev->streaming)
885 setbrightness(gspca_dev);
886 return 0;
887}
888
889static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
890{
891 struct sd *sd = (struct sd *) gspca_dev;
892
893 getbrightness(gspca_dev);
894 *val = sd->brightness;
895 return 0;
896}
897
898/* sub-driver description */
899static const struct sd_desc sd_desc = {
900 .name = MODULE_NAME,
901 .ctrls = sd_ctrls,
902 .nctrls = ARRAY_SIZE(sd_ctrls),
903 .config = sd_config,
904 .open = sd_open,
905 .start = sd_start,
906 .stopN = sd_stopN,
907 .stop0 = sd_stop0,
908 .close = sd_close,
909 .pkt_scan = sd_pkt_scan,
910};
911
912/* -- module initialisation -- */
913#define DVNM(name) .driver_info = (kernel_ulong_t) name
914static const __devinitdata struct usb_device_id device_table[] = {
915 {USB_DEVICE(0x041e, 0x401d), DVNM("Creative Webcam NX ULTRA")},
916 {USB_DEVICE(0x0733, 0x0430), DVNM("Intel PC Camera Pro")},
917 {}
918};
919MODULE_DEVICE_TABLE(usb, device_table);
920
921/* -- device connect -- */
922static int sd_probe(struct usb_interface *intf,
923 const struct usb_device_id *id)
924{
925 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
926 THIS_MODULE);
927}
928
929static struct usb_driver sd_driver = {
930 .name = MODULE_NAME,
931 .id_table = device_table,
932 .probe = sd_probe,
933 .disconnect = gspca_disconnect,
934};
935
936/* -- module insert / remove -- */
937static int __init sd_mod_init(void)
938{
939 if (usb_register(&sd_driver) < 0)
940 return -1;
941 PDEBUG(D_PROBE, "v%s registered", version);
942 return 0;
943}
944static void __exit sd_mod_exit(void)
945{
946 usb_deregister(&sd_driver);
947 PDEBUG(D_PROBE, "deregistered");
948}
949
950module_init(sd_mod_init);
951module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
new file mode 100644
index 000000000000..143203c1fd9f
--- /dev/null
+++ b/drivers/media/video/gspca/spca506.c
@@ -0,0 +1,847 @@
1/*
2 * SPCA506 chip based cameras function
3 * M Xhaard 15/04/2004 based on different work Mark Taylor and others
4 * and my own snoopy file on a pv-321c donate by a german compagny
5 * "Firma Frank Gmbh" from Saarbruecken
6 *
7 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#define MODULE_NAME "spca506"
25
26#include "gspca.h"
27
28#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
29static const char version[] = "2.1.7";
30
31MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
32MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
33MODULE_LICENSE("GPL");
34
35/* specific webcam descriptor */
36struct sd {
37 struct gspca_dev gspca_dev; /* !! must be the first item */
38
39 int buflen;
40 __u8 tmpbuf[640 * 480 * 3]; /* YYUV per line */
41 __u8 tmpbuf2[640 * 480 * 2]; /* YUYV */
42
43 unsigned char brightness;
44 unsigned char contrast;
45 unsigned char colors;
46 unsigned char hue;
47 char norme;
48 char channel;
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
55static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
56static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
57static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
58static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val);
59static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val);
60
61static struct ctrl sd_ctrls[] = {
62#define SD_BRIGHTNESS 0
63 {
64 {
65 .id = V4L2_CID_BRIGHTNESS,
66 .type = V4L2_CTRL_TYPE_INTEGER,
67 .name = "Brightness",
68 .minimum = 0,
69 .maximum = 0xff,
70 .step = 1,
71 .default_value = 0x80,
72 },
73 .set = sd_setbrightness,
74 .get = sd_getbrightness,
75 },
76#define SD_CONTRAST 1
77 {
78 {
79 .id = V4L2_CID_CONTRAST,
80 .type = V4L2_CTRL_TYPE_INTEGER,
81 .name = "Contrast",
82 .minimum = 0,
83 .maximum = 0xff,
84 .step = 1,
85 .default_value = 0x47,
86 },
87 .set = sd_setcontrast,
88 .get = sd_getcontrast,
89 },
90#define SD_COLOR 2
91 {
92 {
93 .id = V4L2_CID_SATURATION,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Saturation",
96 .minimum = 0,
97 .maximum = 0xff,
98 .step = 1,
99 .default_value = 0x40,
100 },
101 .set = sd_setcolors,
102 .get = sd_getcolors,
103 },
104#define SD_HUE 3
105 {
106 {
107 .id = V4L2_CID_HUE,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Hue",
110 .minimum = 0,
111 .maximum = 0xff,
112 .step = 1,
113 .default_value = 0,
114 },
115 .set = sd_sethue,
116 .get = sd_gethue,
117 },
118};
119
120static struct v4l2_pix_format vga_mode[] = {
121 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
122 .bytesperline = 160 * 2,
123 .sizeimage = 160 * 120 * 2,
124 .colorspace = V4L2_COLORSPACE_SRGB,
125 .priv = 5},
126 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
127 .bytesperline = 176 * 2,
128 .sizeimage = 176 * 144 * 2,
129 .colorspace = V4L2_COLORSPACE_SRGB,
130 .priv = 4},
131 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
132 .bytesperline = 320 * 2,
133 .sizeimage = 320 * 240 * 2,
134 .colorspace = V4L2_COLORSPACE_SRGB,
135 .priv = 2},
136 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
137 .bytesperline = 352 * 2,
138 .sizeimage = 352 * 288 * 2,
139 .colorspace = V4L2_COLORSPACE_SRGB,
140 .priv = 1},
141 {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
142 .bytesperline = 640 * 2,
143 .sizeimage = 640 * 480 * 2,
144 .colorspace = V4L2_COLORSPACE_SRGB,
145 .priv = 0},
146};
147
148#define SPCA50X_OFFSET_DATA 10
149
150#define SAA7113_bright 0x0a /* defaults 0x80 */
151#define SAA7113_contrast 0x0b /* defaults 0x47 */
152#define SAA7113_saturation 0x0c /* defaults 0x40 */
153#define SAA7113_hue 0x0d /* defaults 0x00 */
154#define SAA7113_I2C_BASE_WRITE 0x4a
155
156/* read 'len' bytes to gspca_dev->usb_buf */
157static void reg_r(struct gspca_dev *gspca_dev,
158 __u16 req,
159 __u16 index,
160 __u16 length)
161{
162 usb_control_msg(gspca_dev->dev,
163 usb_rcvctrlpipe(gspca_dev->dev, 0),
164 req,
165 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
166 0, /* value */
167 index, gspca_dev->usb_buf, length,
168 500);
169}
170
171static void reg_w(struct usb_device *dev,
172 __u16 req,
173 __u16 value,
174 __u16 index)
175{
176 usb_control_msg(dev,
177 usb_sndctrlpipe(dev, 0),
178 req,
179 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
180 value, index,
181 NULL, 0, 500);
182}
183
184static void spca506_Initi2c(struct gspca_dev *gspca_dev)
185{
186 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
187}
188
189static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
190 __u16 reg)
191{
192 int retry = 60;
193
194 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
195 reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
196 while (retry--) {
197 reg_r(gspca_dev, 0x07, 0x0003, 2);
198 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
199 break;
200 }
201}
202
203static int spca506_ReadI2c(struct gspca_dev *gspca_dev, __u16 reg)
204{
205 int retry = 60;
206
207 reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
208 reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
209 reg_w(gspca_dev->dev, 0x07, 0x01, 0x0002);
210 while (--retry) {
211 reg_r(gspca_dev, 0x07, 0x0003, 2);
212 if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
213 break;
214 }
215 if (retry == 0)
216 return -1;
217 reg_r(gspca_dev, 0x07, 0x0000, 1);
218 return gspca_dev->usb_buf[0];
219}
220
221static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
222 __u16 norme,
223 __u16 channel)
224{
225 struct sd *sd = (struct sd *) gspca_dev;
226/* fixme: check if channel == 0..3 and 6..9 (8 values) */
227 __u8 setbit0 = 0x00;
228 __u8 setbit1 = 0x00;
229 __u8 videomask = 0x00;
230
231 PDEBUG(D_STREAM, "** Open Set Norme **");
232 spca506_Initi2c(gspca_dev);
233 /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
234 /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
235 /* and exclude SAA7113 reserved channel set default 0 otherwise */
236 if (norme & V4L2_STD_NTSC)
237 setbit0 = 0x01;
238 if (channel == 4 || channel == 5 || channel > 9)
239 channel = 0;
240 if (channel < 4)
241 setbit1 = 0x02;
242 videomask = (0x48 | setbit0 | setbit1);
243 reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
244 spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
245
246 if (norme & V4L2_STD_NTSC)
247 spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
248 /* Chrominance Control NTSC N */
249 else if (norme & V4L2_STD_SECAM)
250 spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
251 /* Chrominance Control SECAM */
252 else
253 spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
254 /* Chrominance Control PAL BGHIV */
255
256 sd->norme = norme;
257 sd->channel = channel;
258 PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
259 PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
260}
261
262static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
263 __u16 *norme, __u16 *channel)
264{
265 struct sd *sd = (struct sd *) gspca_dev;
266
267 /* Read the register is not so good value change so
268 we use your own copy in spca50x struct */
269 *norme = sd->norme;
270 *channel = sd->channel;
271 PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
272}
273
274static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
275 __u16 xmult, __u16 ymult)
276{
277 struct usb_device *dev = gspca_dev->dev;
278
279 PDEBUG(D_STREAM, "** SetSize **");
280 reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
281 /* Soft snap 0x40 Hard 0x41 */
282 reg_w(dev, 0x04, 0x41, 0x0001);
283 reg_w(dev, 0x04, 0x00, 0x0002);
284 /* reserved */
285 reg_w(dev, 0x04, 0x00, 0x0003);
286
287 /* reserved */
288 reg_w(dev, 0x04, 0x00, 0x0004);
289 /* reserved */
290 reg_w(dev, 0x04, 0x01, 0x0005);
291 /* reserced */
292 reg_w(dev, 0x04, xmult, 0x0006);
293 /* reserved */
294 reg_w(dev, 0x04, ymult, 0x0007);
295 /* compression 1 */
296 reg_w(dev, 0x04, 0x00, 0x0008);
297 /* T=64 -> 2 */
298 reg_w(dev, 0x04, 0x00, 0x0009);
299 /* threshold2D */
300 reg_w(dev, 0x04, 0x21, 0x000a);
301 /* quantization */
302 reg_w(dev, 0x04, 0x00, 0x000b);
303}
304
305/* this function is called at probe time */
306static int sd_config(struct gspca_dev *gspca_dev,
307 const struct usb_device_id *id)
308{
309 struct sd *sd = (struct sd *) gspca_dev;
310 struct cam *cam;
311
312 cam = &gspca_dev->cam;
313 cam->dev_name = (char *) id->driver_info;
314 cam->epaddr = 0x01;
315 cam->cam_mode = vga_mode;
316 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
317 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
318 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
319 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
320 sd->hue = sd_ctrls[SD_HUE].qctrl.default_value;
321 return 0;
322}
323
324/* this function is called at open time */
325static int sd_open(struct gspca_dev *gspca_dev)
326{
327 struct usb_device *dev = gspca_dev->dev;
328
329 reg_w(dev, 0x03, 0x00, 0x0004);
330 reg_w(dev, 0x03, 0xFF, 0x0003);
331 reg_w(dev, 0x03, 0x00, 0x0000);
332 reg_w(dev, 0x03, 0x1c, 0x0001);
333 reg_w(dev, 0x03, 0x18, 0x0001);
334 /* Init on PAL and composite input0 */
335 spca506_SetNormeInput(gspca_dev, 0, 0);
336 reg_w(dev, 0x03, 0x1c, 0x0001);
337 reg_w(dev, 0x03, 0x18, 0x0001);
338 reg_w(dev, 0x05, 0x00, 0x0000);
339 reg_w(dev, 0x05, 0xef, 0x0001);
340 reg_w(dev, 0x05, 0x00, 0x00c1);
341 reg_w(dev, 0x05, 0x00, 0x00c2);
342 reg_w(dev, 0x06, 0x18, 0x0002);
343 reg_w(dev, 0x06, 0xf5, 0x0011);
344 reg_w(dev, 0x06, 0x02, 0x0012);
345 reg_w(dev, 0x06, 0xfb, 0x0013);
346 reg_w(dev, 0x06, 0x00, 0x0014);
347 reg_w(dev, 0x06, 0xa4, 0x0051);
348 reg_w(dev, 0x06, 0x40, 0x0052);
349 reg_w(dev, 0x06, 0x71, 0x0053);
350 reg_w(dev, 0x06, 0x40, 0x0054);
351 /************************************************/
352 reg_w(dev, 0x03, 0x00, 0x0004);
353 reg_w(dev, 0x03, 0x00, 0x0003);
354 reg_w(dev, 0x03, 0x00, 0x0004);
355 reg_w(dev, 0x03, 0xFF, 0x0003);
356 reg_w(dev, 0x02, 0x00, 0x0000);
357 reg_w(dev, 0x03, 0x60, 0x0000);
358 reg_w(dev, 0x03, 0x18, 0x0001);
359 /* for a better reading mx :) */
360 /*sdca506_WriteI2c(value,register) */
361 spca506_Initi2c(gspca_dev);
362 spca506_WriteI2c(gspca_dev, 0x08, 0x01);
363 spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
364 /* input composite video */
365 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
366 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
367 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
368 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
369 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
370 spca506_WriteI2c(gspca_dev, 0x98, 0x08);
371 spca506_WriteI2c(gspca_dev, 0x03, 0x09);
372 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
373 spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
374 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
375 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
376 spca506_WriteI2c(gspca_dev, 0x03, 0x0e); /* Chroma Pal adjust */
377 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
378 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
379 spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
380 spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
381 spca506_WriteI2c(gspca_dev, 0x01, 0x13);
382 spca506_WriteI2c(gspca_dev, 0x00, 0x14);
383 spca506_WriteI2c(gspca_dev, 0x00, 0x15);
384 spca506_WriteI2c(gspca_dev, 0x00, 0x16);
385 spca506_WriteI2c(gspca_dev, 0x00, 0x17);
386 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
387 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
388 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
389 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
390 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
391 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
392 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
393 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
394 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
395 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
396 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
397 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
398 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
399 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
400 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
401 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
402 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
403 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
404 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
405 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
406 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
407 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
408 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
409 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
410 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
411 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
412 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
413 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
414 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
415 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
416 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
417 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
418 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
419 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
420 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
421 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
422 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
423 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
424 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
425 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
426 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
427 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
428 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
429 PDEBUG(D_STREAM, "** Close Init *");
430 return 0;
431}
432
433static void sd_start(struct gspca_dev *gspca_dev)
434{
435 struct usb_device *dev = gspca_dev->dev;
436 __u16 norme;
437 __u16 channel;
438
439 /**************************************/
440 reg_w(dev, 0x03, 0x00, 0x0004);
441 reg_w(dev, 0x03, 0x00, 0x0003);
442 reg_w(dev, 0x03, 0x00, 0x0004);
443 reg_w(dev, 0x03, 0xFF, 0x0003);
444 reg_w(dev, 0x02, 0x00, 0x0000);
445 reg_w(dev, 0x03, 0x60, 0x0000);
446 reg_w(dev, 0x03, 0x18, 0x0001);
447
448 /*sdca506_WriteI2c(value,register) */
449 spca506_Initi2c(gspca_dev);
450 spca506_WriteI2c(gspca_dev, 0x08, 0x01); /* Increment Delay */
451/* spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
452 spca506_WriteI2c(gspca_dev, 0x33, 0x03);
453 /* Analog Input Control 2 */
454 spca506_WriteI2c(gspca_dev, 0x00, 0x04);
455 /* Analog Input Control 3 */
456 spca506_WriteI2c(gspca_dev, 0x00, 0x05);
457 /* Analog Input Control 4 */
458 spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
459 /* Horizontal Sync Start 0xe9-0x0d */
460 spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
461 /* Horizontal Sync Stop 0x0d-0xf0 */
462
463 spca506_WriteI2c(gspca_dev, 0x98, 0x08); /* Sync Control */
464/* Defaults value */
465 spca506_WriteI2c(gspca_dev, 0x03, 0x09); /* Luminance Control */
466 spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
467 /* Luminance Brightness */
468 spca506_WriteI2c(gspca_dev, 0x47, 0x0b); /* Luminance Contrast */
469 spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
470 /* Chrominance Saturation */
471 spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
472 /* Chrominance Hue Control */
473 spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
474 /* Chrominance Gain Control */
475 /**************************************/
476 spca506_WriteI2c(gspca_dev, 0x00, 0x10);
477 /* Format/Delay Control */
478 spca506_WriteI2c(gspca_dev, 0x0c, 0x11); /* Output Control 1 */
479 spca506_WriteI2c(gspca_dev, 0xb8, 0x12); /* Output Control 2 */
480 spca506_WriteI2c(gspca_dev, 0x01, 0x13); /* Output Control 3 */
481 spca506_WriteI2c(gspca_dev, 0x00, 0x14); /* reserved */
482 spca506_WriteI2c(gspca_dev, 0x00, 0x15); /* VGATE START */
483 spca506_WriteI2c(gspca_dev, 0x00, 0x16); /* VGATE STOP */
484 spca506_WriteI2c(gspca_dev, 0x00, 0x17); /* VGATE Control (MSB) */
485 spca506_WriteI2c(gspca_dev, 0x00, 0x18);
486 spca506_WriteI2c(gspca_dev, 0x00, 0x19);
487 spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
488 spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
489 spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
490 spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
491 spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
492 spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
493 spca506_WriteI2c(gspca_dev, 0x02, 0x40);
494 spca506_WriteI2c(gspca_dev, 0xff, 0x41);
495 spca506_WriteI2c(gspca_dev, 0xff, 0x42);
496 spca506_WriteI2c(gspca_dev, 0xff, 0x43);
497 spca506_WriteI2c(gspca_dev, 0xff, 0x44);
498 spca506_WriteI2c(gspca_dev, 0xff, 0x45);
499 spca506_WriteI2c(gspca_dev, 0xff, 0x46);
500 spca506_WriteI2c(gspca_dev, 0xff, 0x47);
501 spca506_WriteI2c(gspca_dev, 0xff, 0x48);
502 spca506_WriteI2c(gspca_dev, 0xff, 0x49);
503 spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
504 spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
505 spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
506 spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
507 spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
508 spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
509 spca506_WriteI2c(gspca_dev, 0xff, 0x50);
510 spca506_WriteI2c(gspca_dev, 0xff, 0x51);
511 spca506_WriteI2c(gspca_dev, 0xff, 0x52);
512 spca506_WriteI2c(gspca_dev, 0xff, 0x53);
513 spca506_WriteI2c(gspca_dev, 0xff, 0x54);
514 spca506_WriteI2c(gspca_dev, 0xff, 0x55);
515 spca506_WriteI2c(gspca_dev, 0xff, 0x56);
516 spca506_WriteI2c(gspca_dev, 0xff, 0x57);
517 spca506_WriteI2c(gspca_dev, 0x00, 0x58);
518 spca506_WriteI2c(gspca_dev, 0x54, 0x59);
519 spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
520 spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
521 spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
522 spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
523 spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
524 spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
525 spca506_WriteI2c(gspca_dev, 0x00, 0x60);
526 spca506_WriteI2c(gspca_dev, 0x05, 0x61);
527 spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
528 /**************************************/
529 reg_w(dev, 0x05, 0x00, 0x0003);
530 reg_w(dev, 0x05, 0x00, 0x0004);
531 reg_w(dev, 0x03, 0x10, 0x0001);
532 reg_w(dev, 0x03, 0x78, 0x0000);
533 switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
534 case 0:
535 spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
536 break;
537 case 1:
538 spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
539 break;
540 case 2:
541 spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
542 break;
543 case 4:
544 spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
545 break;
546 default:
547/* case 5: */
548 spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
549 break;
550 }
551
552 /* compress setting and size */
553 /* set i2c luma */
554 reg_w(dev, 0x02, 0x01, 0x0000);
555 reg_w(dev, 0x03, 0x12, 0x0000);
556 reg_r(gspca_dev, 0x04, 0x0001, 2);
557 PDEBUG(D_STREAM, "webcam started");
558 spca506_GetNormeInput(gspca_dev, &norme, &channel);
559 spca506_SetNormeInput(gspca_dev, norme, channel);
560}
561
562static void sd_stopN(struct gspca_dev *gspca_dev)
563{
564 struct usb_device *dev = gspca_dev->dev;
565
566 reg_w(dev, 0x02, 0x00, 0x0000);
567 reg_w(dev, 0x03, 0x00, 0x0004);
568 reg_w(dev, 0x03, 0x00, 0x0003);
569}
570
571static void sd_stop0(struct gspca_dev *gspca_dev)
572{
573}
574
575static void sd_close(struct gspca_dev *gspca_dev)
576{
577}
578
579/* convert YYUV per line to YUYV (YUV 4:2:2) */
580static void yyuv_decode(unsigned char *out,
581 unsigned char *in,
582 int width,
583 int height)
584{
585 unsigned char *Ui, *Vi, *yi, *yi1;
586 unsigned char *out1;
587 int i, j;
588
589 yi = in;
590 for (i = height / 2; --i >= 0; ) {
591 out1 = out + width * 2; /* next line */
592 yi1 = yi + width;
593 Ui = yi1 + width;
594 Vi = Ui + width / 2;
595 for (j = width / 2; --j >= 0; ) {
596 *out++ = 128 + *yi++;
597 *out++ = 128 + *Ui;
598 *out++ = 128 + *yi++;
599 *out++ = 128 + *Vi;
600
601 *out1++ = 128 + *yi1++;
602 *out1++ = 128 + *Ui++;
603 *out1++ = 128 + *yi1++;
604 *out1++ = 128 + *Vi++;
605 }
606 yi += width * 2;
607 out = out1;
608 }
609}
610
611static void sd_pkt_scan(struct gspca_dev *gspca_dev,
612 struct gspca_frame *frame, /* target */
613 __u8 *data, /* isoc packet */
614 int len) /* iso packet length */
615{
616 struct sd *sd = (struct sd *) gspca_dev;
617
618 switch (data[0]) {
619 case 0: /* start of frame */
620 if (gspca_dev->last_packet_type == FIRST_PACKET) {
621 yyuv_decode(sd->tmpbuf2, sd->tmpbuf,
622 gspca_dev->width,
623 gspca_dev->height);
624 frame = gspca_frame_add(gspca_dev,
625 LAST_PACKET,
626 frame,
627 sd->tmpbuf2,
628 gspca_dev->width
629 * gspca_dev->height
630 * 2);
631 }
632 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
633 data, 0);
634 data += SPCA50X_OFFSET_DATA;
635 len -= SPCA50X_OFFSET_DATA;
636 if (len > 0)
637 memcpy(sd->tmpbuf, data, len);
638 else
639 len = 0;
640 sd->buflen = len;
641 return;
642 case 0xff: /* drop */
643/* gspca_dev->last_packet_type = DISCARD_PACKET; */
644 return;
645 }
646 data += 1;
647 len -= 1;
648 memcpy(&sd->tmpbuf[sd->buflen], data, len);
649 sd->buflen += len;
650}
651
652static void setbrightness(struct gspca_dev *gspca_dev)
653{
654 struct sd *sd = (struct sd *) gspca_dev;
655
656 spca506_Initi2c(gspca_dev);
657 spca506_WriteI2c(gspca_dev, sd->brightness, SAA7113_bright);
658 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
659}
660
661static void getbrightness(struct gspca_dev *gspca_dev)
662{
663 struct sd *sd = (struct sd *) gspca_dev;
664
665 sd->brightness = spca506_ReadI2c(gspca_dev, SAA7113_bright);
666}
667
668static void setcontrast(struct gspca_dev *gspca_dev)
669{
670 struct sd *sd = (struct sd *) gspca_dev;
671
672 spca506_Initi2c(gspca_dev);
673 spca506_WriteI2c(gspca_dev, sd->contrast, SAA7113_contrast);
674 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
675}
676
677static void getcontrast(struct gspca_dev *gspca_dev)
678{
679 struct sd *sd = (struct sd *) gspca_dev;
680
681 sd->contrast = spca506_ReadI2c(gspca_dev, SAA7113_contrast);
682}
683
684static void setcolors(struct gspca_dev *gspca_dev)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 spca506_Initi2c(gspca_dev);
689 spca506_WriteI2c(gspca_dev, sd->colors, SAA7113_saturation);
690 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
691}
692
693static void getcolors(struct gspca_dev *gspca_dev)
694{
695 struct sd *sd = (struct sd *) gspca_dev;
696
697 sd->colors = spca506_ReadI2c(gspca_dev, SAA7113_saturation);
698}
699
700static void sethue(struct gspca_dev *gspca_dev)
701{
702 struct sd *sd = (struct sd *) gspca_dev;
703
704 spca506_Initi2c(gspca_dev);
705 spca506_WriteI2c(gspca_dev, sd->hue, SAA7113_hue);
706 spca506_WriteI2c(gspca_dev, 0x01, 0x09);
707}
708
709static void gethue(struct gspca_dev *gspca_dev)
710{
711 struct sd *sd = (struct sd *) gspca_dev;
712
713 sd->hue = spca506_ReadI2c(gspca_dev, SAA7113_hue);
714}
715
716static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
717{
718 struct sd *sd = (struct sd *) gspca_dev;
719
720 sd->brightness = val;
721 if (gspca_dev->streaming)
722 setbrightness(gspca_dev);
723 return 0;
724}
725
726static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
727{
728 struct sd *sd = (struct sd *) gspca_dev;
729
730 getbrightness(gspca_dev);
731 *val = sd->brightness;
732 return 0;
733}
734
735static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
736{
737 struct sd *sd = (struct sd *) gspca_dev;
738
739 sd->contrast = val;
740 if (gspca_dev->streaming)
741 setcontrast(gspca_dev);
742 return 0;
743}
744
745static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
746{
747 struct sd *sd = (struct sd *) gspca_dev;
748
749 getcontrast(gspca_dev);
750 *val = sd->contrast;
751 return 0;
752}
753
754static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
755{
756 struct sd *sd = (struct sd *) gspca_dev;
757
758 sd->colors = val;
759 if (gspca_dev->streaming)
760 setcolors(gspca_dev);
761 return 0;
762}
763
764static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
765{
766 struct sd *sd = (struct sd *) gspca_dev;
767
768 getcolors(gspca_dev);
769 *val = sd->colors;
770 return 0;
771}
772
773static int sd_sethue(struct gspca_dev *gspca_dev, __s32 val)
774{
775 struct sd *sd = (struct sd *) gspca_dev;
776
777 sd->hue = val;
778 if (gspca_dev->streaming)
779 sethue(gspca_dev);
780 return 0;
781}
782
783static int sd_gethue(struct gspca_dev *gspca_dev, __s32 *val)
784{
785 struct sd *sd = (struct sd *) gspca_dev;
786
787 gethue(gspca_dev);
788 *val = sd->hue;
789 return 0;
790}
791
792/* sub-driver description */
793static struct sd_desc sd_desc = {
794 .name = MODULE_NAME,
795 .ctrls = sd_ctrls,
796 .nctrls = ARRAY_SIZE(sd_ctrls),
797 .config = sd_config,
798 .open = sd_open,
799 .start = sd_start,
800 .stopN = sd_stopN,
801 .stop0 = sd_stop0,
802 .close = sd_close,
803 .pkt_scan = sd_pkt_scan,
804};
805
806/* -- module initialisation -- */
807#define DVNM(name) .driver_info = (kernel_ulong_t) name
808static __devinitdata struct usb_device_id device_table[] = {
809 {USB_DEVICE(0x06e1, 0xa190), DVNM("ADS Instant VCD")},
810/* {USB_DEVICE(0x0733, 0x0430), DVNM("UsbGrabber PV321c")}, */
811 {USB_DEVICE(0x0734, 0x043b), DVNM("3DeMon USB Capture aka")},
812 {USB_DEVICE(0x99fa, 0x8988), DVNM("Grandtec V.cap")},
813 {}
814};
815MODULE_DEVICE_TABLE(usb, device_table);
816
817/* -- device connect -- */
818static int sd_probe(struct usb_interface *intf,
819 const struct usb_device_id *id)
820{
821 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
822 THIS_MODULE);
823}
824
825static struct usb_driver sd_driver = {
826 .name = MODULE_NAME,
827 .id_table = device_table,
828 .probe = sd_probe,
829 .disconnect = gspca_disconnect,
830};
831
832/* -- module insert / remove -- */
833static int __init sd_mod_init(void)
834{
835 if (usb_register(&sd_driver) < 0)
836 return -1;
837 PDEBUG(D_PROBE, "v%s registered", version);
838 return 0;
839}
840static void __exit sd_mod_exit(void)
841{
842 usb_deregister(&sd_driver);
843 PDEBUG(D_PROBE, "deregistered");
844}
845
846module_init(sd_mod_init);
847module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
new file mode 100644
index 000000000000..d8cd93866a4a
--- /dev/null
+++ b/drivers/media/video/gspca/spca508.c
@@ -0,0 +1,1791 @@
1/*
2 * SPCA508 chip based cameras subdriver
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "spca508"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 int buflen;
37 unsigned char tmpbuf[352 * 288 * 3 / 2]; /* YUVY per line */
38 unsigned char tmpbuf2[352 * 288 * 2]; /* YUYV */
39
40 unsigned char brightness;
41
42 char subtype;
43#define CreativeVista 0
44#define HamaUSBSightcam 1
45#define HamaUSBSightcam2 2
46#define IntelEasyPCCamera 3
47#define MicroInnovationIC200 4
48#define ViewQuestVQ110 5
49};
50
51/* V4L2 controls supported by the driver */
52static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
54
55static struct ctrl sd_ctrls[] = {
56 {
57 {
58 .id = V4L2_CID_BRIGHTNESS,
59 .type = V4L2_CTRL_TYPE_INTEGER,
60 .name = "Brightness",
61 .minimum = 0,
62 .maximum = 255,
63 .step = 1,
64#define BRIGHTNESS_DEF 128
65 .default_value = BRIGHTNESS_DEF,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70};
71
72static struct v4l2_pix_format sif_mode[] = {
73 {160, 120, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
74 .bytesperline = 160 * 2,
75 .sizeimage = 160 * 120 * 2,
76 .colorspace = V4L2_COLORSPACE_SRGB,
77 .priv = 3},
78 {176, 144, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
79 .bytesperline = 176 * 2,
80 .sizeimage = 176 * 144 * 2,
81 .colorspace = V4L2_COLORSPACE_SRGB,
82 .priv = 2},
83 {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
84 .bytesperline = 320 * 2,
85 .sizeimage = 320 * 240 * 2,
86 .colorspace = V4L2_COLORSPACE_SRGB,
87 .priv = 1},
88 {352, 288, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
89 .bytesperline = 352 * 2,
90 .sizeimage = 352 * 288 * 2,
91 .colorspace = V4L2_COLORSPACE_SRGB,
92 .priv = 0},
93};
94
95/* Frame packet header offsets for the spca508 */
96#define SPCA508_OFFSET_TYPE 1
97#define SPCA508_OFFSET_COMPRESS 2
98#define SPCA508_OFFSET_FRAMSEQ 8
99#define SPCA508_OFFSET_WIN1LUM 11
100#define SPCA508_OFFSET_DATA 37
101
102#define SPCA508_SNAPBIT 0x20
103#define SPCA508_SNAPCTRL 0x40
104/*************** I2c ****************/
105#define SPCA508_INDEX_I2C_BASE 0x8800
106
107/*
108 * Initialization data: this is the first set-up data written to the
109 * device (before the open data).
110 */
111static const __u16 spca508_init_data[][3] =
112#define IGN(x) /* nothing */
113{
114 /* line URB value, index */
115 /* 44274 1804 */ {0x0000, 0x870b},
116
117 /* 44299 1805 */ {0x0020, 0x8112},
118 /* Video drop enable, ISO streaming disable */
119 /* 44324 1806 */ {0x0003, 0x8111},
120 /* Reset compression & memory */
121 /* 44349 1807 */ {0x0000, 0x8110},
122 /* Disable all outputs */
123 /* 44372 1808 */ /* READ {0x0000, 0x8114} -> 0000: 00 */
124 /* 44398 1809 */ {0x0000, 0x8114},
125 /* SW GPIO data */
126 /* 44423 1810 */ {0x0008, 0x8110},
127 /* Enable charge pump output */
128 /* 44527 1811 */ {0x0002, 0x8116},
129 /* 200 kHz pump clock */
130 /* 44555 1812 */
131 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
132 /* 44590 1813 */ {0x0003, 0x8111},
133 /* Reset compression & memory */
134 /* 44615 1814 */ {0x0000, 0x8111},
135 /* Normal mode (not reset) */
136 /* 44640 1815 */ {0x0098, 0x8110},
137 /* Enable charge pump output, sync.serial,external 2x clock */
138 /* 44665 1816 */ {0x000d, 0x8114},
139 /* SW GPIO data */
140 /* 44690 1817 */ {0x0002, 0x8116},
141 /* 200 kHz pump clock */
142 /* 44715 1818 */ {0x0020, 0x8112},
143 /* Video drop enable, ISO streaming disable */
144/* --------------------------------------- */
145 /* 44740 1819 */ {0x000f, 0x8402},
146 /* memory bank */
147 /* 44765 1820 */ {0x0000, 0x8403},
148 /* ... address */
149/* --------------------------------------- */
150/* 0x88__ is Synchronous Serial Interface. */
151/* TBD: This table could be expressed more compactly */
152/* using spca508_write_i2c_vector(). */
153/* TBD: Should see if the values in spca50x_i2c_data */
154/* would work with the VQ110 instead of the values */
155/* below. */
156 /* 44790 1821 */ {0x00c0, 0x8804},
157 /* SSI slave addr */
158 /* 44815 1822 */ {0x0008, 0x8802},
159 /* 375 Khz SSI clock */
160 /* 44838 1823 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
161 /* 44862 1824 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
162 /* 44888 1825 */ {0x0008, 0x8802},
163 /* 375 Khz SSI clock */
164 /* 44913 1826 */ {0x0012, 0x8801},
165 /* SSI reg addr */
166 /* 44938 1827 */ {0x0080, 0x8800},
167 /* SSI data to write */
168 /* 44961 1828 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
169 /* 44985 1829 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
170 /* 45009 1830 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
171 /* 45035 1831 */ {0x0008, 0x8802},
172 /* 375 Khz SSI clock */
173 /* 45060 1832 */ {0x0012, 0x8801},
174 /* SSI reg addr */
175 /* 45085 1833 */ {0x0000, 0x8800},
176 /* SSI data to write */
177 /* 45108 1834 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
178 /* 45132 1835 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
179 /* 45156 1836 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
180 /* 45182 1837 */ {0x0008, 0x8802},
181 /* 375 Khz SSI clock */
182 /* 45207 1838 */ {0x0011, 0x8801},
183 /* SSI reg addr */
184 /* 45232 1839 */ {0x0040, 0x8800},
185 /* SSI data to write */
186 /* 45255 1840 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
187 /* 45279 1841 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
188 /* 45303 1842 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
189 /* 45329 1843 */ {0x0008, 0x8802},
190 /* 45354 1844 */ {0x0013, 0x8801},
191 /* 45379 1845 */ {0x0000, 0x8800},
192 /* 45402 1846 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
193 /* 45426 1847 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
194 /* 45450 1848 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
195 /* 45476 1849 */ {0x0008, 0x8802},
196 /* 45501 1850 */ {0x0014, 0x8801},
197 /* 45526 1851 */ {0x0000, 0x8800},
198 /* 45549 1852 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
199 /* 45573 1853 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
200 /* 45597 1854 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
201 /* 45623 1855 */ {0x0008, 0x8802},
202 /* 45648 1856 */ {0x0015, 0x8801},
203 /* 45673 1857 */ {0x0001, 0x8800},
204 /* 45696 1858 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
205 /* 45720 1859 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
206 /* 45744 1860 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
207 /* 45770 1861 */ {0x0008, 0x8802},
208 /* 45795 1862 */ {0x0016, 0x8801},
209 /* 45820 1863 */ {0x0003, 0x8800},
210 /* 45843 1864 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
211 /* 45867 1865 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
212 /* 45891 1866 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
213 /* 45917 1867 */ {0x0008, 0x8802},
214 /* 45942 1868 */ {0x0017, 0x8801},
215 /* 45967 1869 */ {0x0036, 0x8800},
216 /* 45990 1870 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
217 /* 46014 1871 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
218 /* 46038 1872 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
219 /* 46064 1873 */ {0x0008, 0x8802},
220 /* 46089 1874 */ {0x0018, 0x8801},
221 /* 46114 1875 */ {0x00ec, 0x8800},
222 /* 46137 1876 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
223 /* 46161 1877 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
224 /* 46185 1878 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
225 /* 46211 1879 */ {0x0008, 0x8802},
226 /* 46236 1880 */ {0x001a, 0x8801},
227 /* 46261 1881 */ {0x0094, 0x8800},
228 /* 46284 1882 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
229 /* 46308 1883 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
230 /* 46332 1884 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
231 /* 46358 1885 */ {0x0008, 0x8802},
232 /* 46383 1886 */ {0x001b, 0x8801},
233 /* 46408 1887 */ {0x0000, 0x8800},
234 /* 46431 1888 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
235 /* 46455 1889 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
236 /* 46479 1890 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
237 /* 46505 1891 */ {0x0008, 0x8802},
238 /* 46530 1892 */ {0x0027, 0x8801},
239 /* 46555 1893 */ {0x00a2, 0x8800},
240 /* 46578 1894 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
241 /* 46602 1895 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
242 /* 46626 1896 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
243 /* 46652 1897 */ {0x0008, 0x8802},
244 /* 46677 1898 */ {0x0028, 0x8801},
245 /* 46702 1899 */ {0x0040, 0x8800},
246 /* 46725 1900 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
247 /* 46749 1901 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
248 /* 46773 1902 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
249 /* 46799 1903 */ {0x0008, 0x8802},
250 /* 46824 1904 */ {0x002a, 0x8801},
251 /* 46849 1905 */ {0x0084, 0x8800},
252 /* 46872 1906 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
253 /* 46896 1907 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
254 /* 46920 1908 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
255 /* 46946 1909 */ {0x0008, 0x8802},
256 /* 46971 1910 */ {0x002b, 0x8801},
257 /* 46996 1911 */ {0x00a8, 0x8800},
258 /* 47019 1912 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
259 /* 47043 1913 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
260 /* 47067 1914 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
261 /* 47093 1915 */ {0x0008, 0x8802},
262 /* 47118 1916 */ {0x002c, 0x8801},
263 /* 47143 1917 */ {0x00fe, 0x8800},
264 /* 47166 1918 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
265 /* 47190 1919 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
266 /* 47214 1920 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
267 /* 47240 1921 */ {0x0008, 0x8802},
268 /* 47265 1922 */ {0x002d, 0x8801},
269 /* 47290 1923 */ {0x0003, 0x8800},
270 /* 47313 1924 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
271 /* 47337 1925 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
272 /* 47361 1926 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
273 /* 47387 1927 */ {0x0008, 0x8802},
274 /* 47412 1928 */ {0x0038, 0x8801},
275 /* 47437 1929 */ {0x0083, 0x8800},
276 /* 47460 1930 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
277 /* 47484 1931 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
278 /* 47508 1932 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
279 /* 47534 1933 */ {0x0008, 0x8802},
280 /* 47559 1934 */ {0x0033, 0x8801},
281 /* 47584 1935 */ {0x0081, 0x8800},
282 /* 47607 1936 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
283 /* 47631 1937 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
284 /* 47655 1938 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
285 /* 47681 1939 */ {0x0008, 0x8802},
286 /* 47706 1940 */ {0x0034, 0x8801},
287 /* 47731 1941 */ {0x004a, 0x8800},
288 /* 47754 1942 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
289 /* 47778 1943 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
290 /* 47802 1944 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
291 /* 47828 1945 */ {0x0008, 0x8802},
292 /* 47853 1946 */ {0x0039, 0x8801},
293 /* 47878 1947 */ {0x0000, 0x8800},
294 /* 47901 1948 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
295 /* 47925 1949 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
296 /* 47949 1950 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
297 /* 47975 1951 */ {0x0008, 0x8802},
298 /* 48000 1952 */ {0x0010, 0x8801},
299 /* 48025 1953 */ {0x00a8, 0x8800},
300 /* 48048 1954 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
301 /* 48072 1955 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
302 /* 48096 1956 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
303 /* 48122 1957 */ {0x0008, 0x8802},
304 /* 48147 1958 */ {0x0006, 0x8801},
305 /* 48172 1959 */ {0x0058, 0x8800},
306 /* 48195 1960 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
307 /* 48219 1961 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
308 /* 48243 1962 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
309 /* 48269 1963 */ {0x0008, 0x8802},
310 /* 48294 1964 */ {0x0000, 0x8801},
311 /* 48319 1965 */ {0x0004, 0x8800},
312 /* 48342 1966 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
313 /* 48366 1967 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
314 /* 48390 1968 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
315 /* 48416 1969 */ {0x0008, 0x8802},
316 /* 48441 1970 */ {0x0040, 0x8801},
317 /* 48466 1971 */ {0x0080, 0x8800},
318 /* 48489 1972 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
319 /* 48513 1973 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
320 /* 48537 1974 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
321 /* 48563 1975 */ {0x0008, 0x8802},
322 /* 48588 1976 */ {0x0041, 0x8801},
323 /* 48613 1977 */ {0x000c, 0x8800},
324 /* 48636 1978 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
325 /* 48660 1979 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
326 /* 48684 1980 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
327 /* 48710 1981 */ {0x0008, 0x8802},
328 /* 48735 1982 */ {0x0042, 0x8801},
329 /* 48760 1983 */ {0x000c, 0x8800},
330 /* 48783 1984 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
331 /* 48807 1985 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
332 /* 48831 1986 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
333 /* 48857 1987 */ {0x0008, 0x8802},
334 /* 48882 1988 */ {0x0043, 0x8801},
335 /* 48907 1989 */ {0x0028, 0x8800},
336 /* 48930 1990 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
337 /* 48954 1991 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
338 /* 48978 1992 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
339 /* 49004 1993 */ {0x0008, 0x8802},
340 /* 49029 1994 */ {0x0044, 0x8801},
341 /* 49054 1995 */ {0x0080, 0x8800},
342 /* 49077 1996 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
343 /* 49101 1997 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
344 /* 49125 1998 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
345 /* 49151 1999 */ {0x0008, 0x8802},
346 /* 49176 2000 */ {0x0045, 0x8801},
347 /* 49201 2001 */ {0x0020, 0x8800},
348 /* 49224 2002 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
349 /* 49248 2003 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
350 /* 49272 2004 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
351 /* 49298 2005 */ {0x0008, 0x8802},
352 /* 49323 2006 */ {0x0046, 0x8801},
353 /* 49348 2007 */ {0x0020, 0x8800},
354 /* 49371 2008 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
355 /* 49395 2009 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
356 /* 49419 2010 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
357 /* 49445 2011 */ {0x0008, 0x8802},
358 /* 49470 2012 */ {0x0047, 0x8801},
359 /* 49495 2013 */ {0x0080, 0x8800},
360 /* 49518 2014 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
361 /* 49542 2015 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
362 /* 49566 2016 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
363 /* 49592 2017 */ {0x0008, 0x8802},
364 /* 49617 2018 */ {0x0048, 0x8801},
365 /* 49642 2019 */ {0x004c, 0x8800},
366 /* 49665 2020 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
367 /* 49689 2021 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
368 /* 49713 2022 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
369 /* 49739 2023 */ {0x0008, 0x8802},
370 /* 49764 2024 */ {0x0049, 0x8801},
371 /* 49789 2025 */ {0x0084, 0x8800},
372 /* 49812 2026 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
373 /* 49836 2027 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
374 /* 49860 2028 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
375 /* 49886 2029 */ {0x0008, 0x8802},
376 /* 49911 2030 */ {0x004a, 0x8801},
377 /* 49936 2031 */ {0x0084, 0x8800},
378 /* 49959 2032 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
379 /* 49983 2033 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
380 /* 50007 2034 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
381 /* 50033 2035 */ {0x0008, 0x8802},
382 /* 50058 2036 */ {0x004b, 0x8801},
383 /* 50083 2037 */ {0x0084, 0x8800},
384 /* 50106 2038 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
385 /* --------------------------------------- */
386 /* 50132 2039 */ {0x0012, 0x8700},
387 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
388 /* 50157 2040 */ {0x0000, 0x8701},
389 /* CKx1 clock delay adj */
390 /* 50182 2041 */ {0x0000, 0x8701},
391 /* CKx1 clock delay adj */
392 /* 50207 2042 */ {0x0001, 0x870c},
393 /* CKOx2 output */
394 /* --------------------------------------- */
395 /* 50232 2043 */ {0x0080, 0x8600},
396 /* Line memory read counter (L) */
397 /* 50257 2044 */ {0x0001, 0x8606},
398 /* reserved */
399 /* 50282 2045 */ {0x0064, 0x8607},
400 /* Line memory read counter (H) 0x6480=25,728 */
401 /* 50307 2046 */ {0x002a, 0x8601},
402 /* CDSP sharp interpolation mode,
403 * line sel for color sep, edge enhance enab */
404 /* 50332 2047 */ {0x0000, 0x8602},
405 /* optical black level for user settng = 0 */
406 /* 50357 2048 */ {0x0080, 0x8600},
407 /* Line memory read counter (L) */
408 /* 50382 2049 */ {0x000a, 0x8603},
409 /* optical black level calc mode: auto; optical black offset = 10 */
410 /* 50407 2050 */ {0x00df, 0x865b},
411 /* Horiz offset for valid pixels (L)=0xdf */
412 /* 50432 2051 */ {0x0012, 0x865c},
413 /* Vert offset for valid lines (L)=0x12 */
414
415/* The following two lines seem to be the "wrong" resolution. */
416/* But perhaps these indicate the actual size of the sensor */
417/* rather than the size of the current video mode. */
418 /* 50457 2052 */ {0x0058, 0x865d},
419 /* Horiz valid pixels (*4) (L) = 352 */
420 /* 50482 2053 */ {0x0048, 0x865e},
421 /* Vert valid lines (*4) (L) = 288 */
422
423 /* 50507 2054 */ {0x0015, 0x8608},
424 /* A11 Coef ... */
425 /* 50532 2055 */ {0x0030, 0x8609},
426 /* 50557 2056 */ {0x00fb, 0x860a},
427 /* 50582 2057 */ {0x003e, 0x860b},
428 /* 50607 2058 */ {0x00ce, 0x860c},
429 /* 50632 2059 */ {0x00f4, 0x860d},
430 /* 50657 2060 */ {0x00eb, 0x860e},
431 /* 50682 2061 */ {0x00dc, 0x860f},
432 /* 50707 2062 */ {0x0039, 0x8610},
433 /* 50732 2063 */ {0x0001, 0x8611},
434 /* R offset for white balance ... */
435 /* 50757 2064 */ {0x0000, 0x8612},
436 /* 50782 2065 */ {0x0001, 0x8613},
437 /* 50807 2066 */ {0x0000, 0x8614},
438 /* 50832 2067 */ {0x005b, 0x8651},
439 /* R gain for white balance ... */
440 /* 50857 2068 */ {0x0040, 0x8652},
441 /* 50882 2069 */ {0x0060, 0x8653},
442 /* 50907 2070 */ {0x0040, 0x8654},
443 /* 50932 2071 */ {0x0000, 0x8655},
444 /* 50957 2072 */ {0x0001, 0x863f},
445 /* Fixed gamma correction enable, USB control,
446 * lum filter disable, lum noise clip disable */
447 /* 50982 2073 */ {0x00a1, 0x8656},
448 /* Window1 size 256x256, Windows2 size 64x64,
449 * gamma look-up disable, new edge enhancement enable */
450 /* 51007 2074 */ {0x0018, 0x8657},
451 /* Edge gain high thresh */
452 /* 51032 2075 */ {0x0020, 0x8658},
453 /* Edge gain low thresh */
454 /* 51057 2076 */ {0x000a, 0x8659},
455 /* Edge bandwidth high threshold */
456 /* 51082 2077 */ {0x0005, 0x865a},
457 /* Edge bandwidth low threshold */
458 /* -------------------------------- */
459 /* 51107 2078 */ {0x0030, 0x8112},
460 /* Video drop enable, ISO streaming enable */
461 /* 51130 2079 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
462 /* 51154 2080 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
463 /* 51180 2081 */ {0xa908, 0x8802},
464 /* 51205 2082 */ {0x0034, 0x8801},
465 /* SSI reg addr */
466 /* 51230 2083 */ {0x00ca, 0x8800},
467 /* SSI data to write */
468 /* 51253 2084 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
469 /* 51277 2085 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
470 /* 51301 2086 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
471 /* 51327 2087 */ {0x1f08, 0x8802},
472 /* 51352 2088 */ {0x0006, 0x8801},
473 /* 51377 2089 */ {0x0080, 0x8800},
474 /* 51400 2090 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
475
476/* ----- Read back coefs we wrote earlier. */
477 /* 51424 2091 */ /* READ { 0, 0x0000, 0x8608 } -> 0000: 15 */
478 /* 51448 2092 */ /* READ { 0, 0x0000, 0x8609 } -> 0000: 30 */
479 /* 51472 2093 */ /* READ { 0, 0x0000, 0x860a } -> 0000: fb */
480 /* 51496 2094 */ /* READ { 0, 0x0000, 0x860b } -> 0000: 3e */
481 /* 51520 2095 */ /* READ { 0, 0x0000, 0x860c } -> 0000: ce */
482 /* 51544 2096 */ /* READ { 0, 0x0000, 0x860d } -> 0000: f4 */
483 /* 51568 2097 */ /* READ { 0, 0x0000, 0x860e } -> 0000: eb */
484 /* 51592 2098 */ /* READ { 0, 0x0000, 0x860f } -> 0000: dc */
485 /* 51616 2099 */ /* READ { 0, 0x0000, 0x8610 } -> 0000: 39 */
486 /* 51640 2100 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
487 /* 51664 2101 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 08 */
488 /* 51690 2102 */ {0xb008, 0x8802},
489 /* 51715 2103 */ {0x0006, 0x8801},
490 /* 51740 2104 */ {0x007d, 0x8800},
491 /* 51763 2105 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
492
493
494 /* This chunk is seemingly redundant with */
495 /* earlier commands (A11 Coef...), but if I disable it, */
496 /* the image appears too dark. Maybe there was some kind of */
497 /* reset since the earlier commands, so this is necessary again. */
498 /* 51789 2106 */ {0x0015, 0x8608},
499 /* 51814 2107 */ {0x0030, 0x8609},
500 /* 51839 2108 */ {0xfffb, 0x860a},
501 /* 51864 2109 */ {0x003e, 0x860b},
502 /* 51889 2110 */ {0xffce, 0x860c},
503 /* 51914 2111 */ {0xfff4, 0x860d},
504 /* 51939 2112 */ {0xffeb, 0x860e},
505 /* 51964 2113 */ {0xffdc, 0x860f},
506 /* 51989 2114 */ {0x0039, 0x8610},
507 /* 52014 2115 */ {0x0018, 0x8657},
508
509 /* 52039 2116 */ {0x0000, 0x8508},
510 /* Disable compression. */
511 /* Previous line was:
512 * 52039 2116 * { 0, 0x0021, 0x8508 }, * Enable compression. */
513 /* 52064 2117 */ {0x0032, 0x850b},
514 /* compression stuff */
515 /* 52089 2118 */ {0x0003, 0x8509},
516 /* compression stuff */
517 /* 52114 2119 */ {0x0011, 0x850a},
518 /* compression stuff */
519 /* 52139 2120 */ {0x0021, 0x850d},
520 /* compression stuff */
521 /* 52164 2121 */ {0x0010, 0x850c},
522 /* compression stuff */
523 /* 52189 2122 */ {0x0003, 0x8500},
524 /* *** Video mode: 160x120 */
525 /* 52214 2123 */ {0x0001, 0x8501},
526 /* Hardware-dominated snap control */
527 /* 52239 2124 */ {0x0061, 0x8656},
528 /* Window1 size 128x128, Windows2 size 128x128,
529 * gamma look-up disable, new edge enhancement enable */
530 /* 52264 2125 */ {0x0018, 0x8617},
531 /* Window1 start X (*2) */
532 /* 52289 2126 */ {0x0008, 0x8618},
533 /* Window1 start Y (*2) */
534 /* 52314 2127 */ {0x0061, 0x8656},
535 /* Window1 size 128x128, Windows2 size 128x128,
536 * gamma look-up disable, new edge enhancement enable */
537 /* 52339 2128 */ {0x0058, 0x8619},
538 /* Window2 start X (*2) */
539 /* 52364 2129 */ {0x0008, 0x861a},
540 /* Window2 start Y (*2) */
541 /* 52389 2130 */ {0x00ff, 0x8615},
542 /* High lum thresh for white balance */
543 /* 52414 2131 */ {0x0000, 0x8616},
544 /* Low lum thresh for white balance */
545 /* 52439 2132 */ {0x0012, 0x8700},
546 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
547 /* 52464 2133 */ {0x0012, 0x8700},
548 /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
549 /* 52487 2134 */ /* READ { 0, 0x0000, 0x8656 } -> 0000: 61 */
550 /* 52513 2135 */ {0x0028, 0x8802},
551 /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
552 /* 52536 2136 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
553 /* 52560 2137 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
554 /* 52586 2138 */ {0x1f28, 0x8802},
555 /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
556 /* 52611 2139 */ {0x0010, 0x8801},
557 /* SSI reg addr */
558 /* 52636 2140 */ {0x003e, 0x8800},
559 /* SSI data to write */
560 /* 52659 2141 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
561 /* 52685 2142 */ {0x0028, 0x8802},
562 /* 52708 2143 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
563 /* 52732 2144 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
564 /* 52758 2145 */ {0x1f28, 0x8802},
565 /* 52783 2146 */ {0x0000, 0x8801},
566 /* 52808 2147 */ {0x001f, 0x8800},
567 /* 52831 2148 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
568 /* 52857 2149 */ {0x0001, 0x8602},
569 /* optical black level for user settning = 1 */
570
571 /* Original: */
572 /* 52882 2150 */ {0x0023, 0x8700},
573 /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
574 /* 52907 2151 */ {0x000f, 0x8602},
575 /* optical black level for user settning = 15 */
576
577 /* 52932 2152 */ {0x0028, 0x8802},
578 /* 52955 2153 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
579 /* 52979 2154 */ /* READ { 0, 0x0001, 0x8802 } -> 0000: 28 */
580 /* 53005 2155 */ {0x1f28, 0x8802},
581 /* 53030 2156 */ {0x0010, 0x8801},
582 /* 53055 2157 */ {0x007b, 0x8800},
583 /* 53078 2158 */ /* READ { 0, 0x0001, 0x8803 } -> 0000: 00 */
584 /* 53104 2159 */ {0x002f, 0x8651},
585 /* R gain for white balance ... */
586 /* 53129 2160 */ {0x0080, 0x8653},
587 /* 53152 2161 */ /* READ { 0, 0x0000, 0x8655 } -> 0000: 00 */
588 /* 53178 2162 */ {0x0000, 0x8655},
589
590 /* 53203 2163 */ {0x0030, 0x8112},
591 /* Video drop enable, ISO streaming enable */
592 /* 53228 2164 */ {0x0020, 0x8112},
593 /* Video drop enable, ISO streaming disable */
594 /* 53252 2165 */
595 /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
596 {}
597};
598
599
600/*
601 * Initialization data for Intel EasyPC Camera CS110
602 */
603static const __u16 spca508cs110_init_data[][3] = {
604 {0x0000, 0x870b}, /* Reset CTL3 */
605 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
606 {0x0000, 0x8111}, /* Normal operation on reset */
607 {0x0090, 0x8110},
608 /* External Clock 2x & Synchronous Serial Interface Output */
609 {0x0020, 0x8112}, /* Video Drop packet enable */
610 {0x0000, 0x8114}, /* Software GPIO output data */
611 {0x0001, 0x8114},
612 {0x0001, 0x8114},
613 {0x0001, 0x8114},
614 {0x0003, 0x8114},
615
616 /* Initial sequence Synchronous Serial Interface */
617 {0x000f, 0x8402}, /* Memory bank Address */
618 {0x0000, 0x8403}, /* Memory bank Address */
619 {0x00ba, 0x8804}, /* SSI Slave address */
620 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
621 {0x0010, 0x8802}, /* 93.75kHz SSI Clock two DataByte */
622
623 {0x0001, 0x8801},
624 {0x000a, 0x8805},/* a - NWG: Dunno what this is about */
625 {0x0000, 0x8800},
626 {0x0010, 0x8802},
627
628 {0x0002, 0x8801},
629 {0x0000, 0x8805},
630 {0x0000, 0x8800},
631 {0x0010, 0x8802},
632
633 {0x0003, 0x8801},
634 {0x0027, 0x8805},
635 {0x0001, 0x8800},
636 {0x0010, 0x8802},
637
638 {0x0004, 0x8801},
639 {0x0065, 0x8805},
640 {0x0001, 0x8800},
641 {0x0010, 0x8802},
642
643 {0x0005, 0x8801},
644 {0x0003, 0x8805},
645 {0x0000, 0x8800},
646 {0x0010, 0x8802},
647
648 {0x0006, 0x8801},
649 {0x001c, 0x8805},
650 {0x0000, 0x8800},
651 {0x0010, 0x8802},
652
653 {0x0007, 0x8801},
654 {0x002a, 0x8805},
655 {0x0000, 0x8800},
656 {0x0010, 0x8802},
657
658 {0x0002, 0x8704}, /* External input CKIx1 */
659 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
660 {0x009a, 0x8600}, /* Line memory Read Counter (L) */
661 {0x0001, 0x865b}, /* 1 Horizontal Offset for Valid Pixel(L) */
662 {0x0003, 0x865c}, /* 3 Vertical Offset for Valid Lines(L) */
663 {0x0058, 0x865d}, /* 58 Horizontal Valid Pixel Window(L) */
664
665 {0x0006, 0x8660}, /* Nibble data + input order */
666
667 {0x000a, 0x8602}, /* Optical black level set to 0x0a */
668/* 1945 */ {0x0000, 0x8603}, /* Optical black level Offset */
669
670/* 1962 * {0, 0x0000, 0x8611}, * 0 R Offset for white Balance */
671/* 1963 * {0, 0x0000, 0x8612}, * 1 Gr Offset for white Balance */
672/* 1964 * {0, 0x0000, 0x8613}, * 1f B Offset for white Balance */
673/* 1965 * {0, 0x0000, 0x8614}, * f0 Gb Offset for white Balance */
674
675 {0x0040, 0x8651}, /* 2b BLUE gain for white balance good at all 60 */
676 {0x0030, 0x8652}, /* 41 Gr Gain for white Balance (L) */
677 {0x0035, 0x8653}, /* 26 RED gain for white balance */
678 {0x0035, 0x8654}, /* 40Gb Gain for white Balance (L) */
679 {0x0041, 0x863f},
680 /* Fixed Gamma correction enabled (makes colours look better) */
681
682/* 2422 */ {0x0000, 0x8655},
683 /* High bits for white balance*****brightness control*** */
684 {}
685};
686
687static const __u16 spca508_sightcam_init_data[][3] = {
688/* This line seems to setup the frame/canvas */
689 /*368 */ {0x000f, 0x8402},
690
691/* Theese 6 lines are needed to startup the webcam */
692 /*398 */ {0x0090, 0x8110},
693 /*399 */ {0x0001, 0x8114},
694 /*400 */ {0x0001, 0x8114},
695 /*401 */ {0x0001, 0x8114},
696 /*402 */ {0x0003, 0x8114},
697 /*403 */ {0x0080, 0x8804},
698
699/* This part seems to make the pictures darker? (autobrightness?) */
700 /*436 */ {0x0001, 0x8801},
701 /*437 */ {0x0004, 0x8800},
702 /*439 */ {0x0003, 0x8801},
703 /*440 */ {0x00e0, 0x8800},
704 /*442 */ {0x0004, 0x8801},
705 /*443 */ {0x00b4, 0x8800},
706 /*445 */ {0x0005, 0x8801},
707 /*446 */ {0x0000, 0x8800},
708
709 /*448 */ {0x0006, 0x8801},
710 /*449 */ {0x00e0, 0x8800},
711 /*451 */ {0x0007, 0x8801},
712 /*452 */ {0x000c, 0x8800},
713
714/* This section is just needed, it probably
715 * does something like the previous section,
716 * but the cam won't start if it's not included.
717 */
718 /*484 */ {0x0014, 0x8801},
719 /*485 */ {0x0008, 0x8800},
720 /*487 */ {0x0015, 0x8801},
721 /*488 */ {0x0067, 0x8800},
722 /*490 */ {0x0016, 0x8801},
723 /*491 */ {0x0000, 0x8800},
724 /*493 */ {0x0017, 0x8801},
725 /*494 */ {0x0020, 0x8800},
726 /*496 */ {0x0018, 0x8801},
727 /*497 */ {0x0044, 0x8800},
728
729/* Makes the picture darker - and the
730 * cam won't start if not included
731 */
732 /*505 */ {0x001e, 0x8801},
733 /*506 */ {0x00ea, 0x8800},
734 /*508 */ {0x001f, 0x8801},
735 /*509 */ {0x0001, 0x8800},
736 /*511 */ {0x0003, 0x8801},
737 /*512 */ {0x00e0, 0x8800},
738
739/* seems to place the colors ontop of each other #1 */
740 /*517 */ {0x0006, 0x8704},
741 /*518 */ {0x0001, 0x870c},
742 /*519 */ {0x0016, 0x8600},
743 /*520 */ {0x0002, 0x8606},
744
745/* if not included the pictures becomes _very_ dark */
746 /*521 */ {0x0064, 0x8607},
747 /*522 */ {0x003a, 0x8601},
748 /*523 */ {0x0000, 0x8602},
749
750/* seems to place the colors ontop of each other #2 */
751 /*524 */ {0x0016, 0x8600},
752 /*525 */ {0x0018, 0x8617},
753 /*526 */ {0x0008, 0x8618},
754 /*527 */ {0x00a1, 0x8656},
755
756/* webcam won't start if not included */
757 /*528 */ {0x0007, 0x865b},
758 /*529 */ {0x0001, 0x865c},
759 /*530 */ {0x0058, 0x865d},
760 /*531 */ {0x0048, 0x865e},
761
762/* adjusts the colors */
763 /*541 */ {0x0049, 0x8651},
764 /*542 */ {0x0040, 0x8652},
765 /*543 */ {0x004c, 0x8653},
766 /*544 */ {0x0040, 0x8654},
767 {}
768};
769
770static const __u16 spca508_sightcam2_init_data[][3] = {
771/* 35 */ {0x0020, 0x8112},
772
773/* 36 */ {0x000f, 0x8402},
774/* 37 */ {0x0000, 0x8403},
775
776/* 38 */ {0x0008, 0x8201},
777/* 39 */ {0x0008, 0x8200},
778/* 40 */ {0x0001, 0x8200},
779/* 43 */ {0x0009, 0x8201},
780/* 44 */ {0x0008, 0x8200},
781/* 45 */ {0x0001, 0x8200},
782/* 48 */ {0x000a, 0x8201},
783/* 49 */ {0x0008, 0x8200},
784/* 50 */ {0x0001, 0x8200},
785/* 53 */ {0x000b, 0x8201},
786/* 54 */ {0x0008, 0x8200},
787/* 55 */ {0x0001, 0x8200},
788/* 58 */ {0x000c, 0x8201},
789/* 59 */ {0x0008, 0x8200},
790/* 60 */ {0x0001, 0x8200},
791/* 63 */ {0x000d, 0x8201},
792/* 64 */ {0x0008, 0x8200},
793/* 65 */ {0x0001, 0x8200},
794/* 68 */ {0x000e, 0x8201},
795/* 69 */ {0x0008, 0x8200},
796/* 70 */ {0x0001, 0x8200},
797/* 73 */ {0x0007, 0x8201},
798/* 74 */ {0x0008, 0x8200},
799/* 75 */ {0x0001, 0x8200},
800/* 78 */ {0x000f, 0x8201},
801/* 79 */ {0x0008, 0x8200},
802/* 80 */ {0x0001, 0x8200},
803
804/* 84 */ {0x0018, 0x8660},
805/* 85 */ {0x0010, 0x8201},
806
807/* 86 */ {0x0008, 0x8200},
808/* 87 */ {0x0001, 0x8200},
809/* 90 */ {0x0011, 0x8201},
810/* 91 */ {0x0008, 0x8200},
811/* 92 */ {0x0001, 0x8200},
812
813/* 95 */ {0x0000, 0x86b0},
814/* 96 */ {0x0034, 0x86b1},
815/* 97 */ {0x0000, 0x86b2},
816/* 98 */ {0x0049, 0x86b3},
817/* 99 */ {0x0000, 0x86b4},
818/* 100 */ {0x0000, 0x86b4},
819
820/* 101 */ {0x0012, 0x8201},
821/* 102 */ {0x0008, 0x8200},
822/* 103 */ {0x0001, 0x8200},
823/* 106 */ {0x0013, 0x8201},
824/* 107 */ {0x0008, 0x8200},
825/* 108 */ {0x0001, 0x8200},
826
827/* 111 */ {0x0001, 0x86b0},
828/* 112 */ {0x00aa, 0x86b1},
829/* 113 */ {0x0000, 0x86b2},
830/* 114 */ {0x00e4, 0x86b3},
831/* 115 */ {0x0000, 0x86b4},
832/* 116 */ {0x0000, 0x86b4},
833
834/* 118 */ {0x0018, 0x8660},
835
836/* 119 */ {0x0090, 0x8110},
837/* 120 */ {0x0001, 0x8114},
838/* 121 */ {0x0001, 0x8114},
839/* 122 */ {0x0001, 0x8114},
840/* 123 */ {0x0003, 0x8114},
841
842/* 124 */ {0x0080, 0x8804},
843/* 157 */ {0x0003, 0x8801},
844/* 158 */ {0x0012, 0x8800},
845/* 160 */ {0x0004, 0x8801},
846/* 161 */ {0x0005, 0x8800},
847/* 163 */ {0x0005, 0x8801},
848/* 164 */ {0x0000, 0x8800},
849/* 166 */ {0x0006, 0x8801},
850/* 167 */ {0x0000, 0x8800},
851/* 169 */ {0x0007, 0x8801},
852/* 170 */ {0x0000, 0x8800},
853/* 172 */ {0x0008, 0x8801},
854/* 173 */ {0x0005, 0x8800},
855/* 175 */ {0x000a, 0x8700},
856/* 176 */ {0x000e, 0x8801},
857/* 177 */ {0x0004, 0x8800},
858/* 179 */ {0x0005, 0x8801},
859/* 180 */ {0x0047, 0x8800},
860/* 182 */ {0x0006, 0x8801},
861/* 183 */ {0x0000, 0x8800},
862/* 185 */ {0x0007, 0x8801},
863/* 186 */ {0x00c0, 0x8800},
864/* 188 */ {0x0008, 0x8801},
865/* 189 */ {0x0003, 0x8800},
866/* 191 */ {0x0013, 0x8801},
867/* 192 */ {0x0001, 0x8800},
868/* 194 */ {0x0009, 0x8801},
869/* 195 */ {0x0000, 0x8800},
870/* 197 */ {0x000a, 0x8801},
871/* 198 */ {0x0000, 0x8800},
872/* 200 */ {0x000b, 0x8801},
873/* 201 */ {0x0000, 0x8800},
874/* 203 */ {0x000c, 0x8801},
875/* 204 */ {0x0000, 0x8800},
876/* 206 */ {0x000e, 0x8801},
877/* 207 */ {0x0004, 0x8800},
878/* 209 */ {0x000f, 0x8801},
879/* 210 */ {0x0000, 0x8800},
880/* 212 */ {0x0010, 0x8801},
881/* 213 */ {0x0006, 0x8800},
882/* 215 */ {0x0011, 0x8801},
883/* 216 */ {0x0006, 0x8800},
884/* 218 */ {0x0012, 0x8801},
885/* 219 */ {0x0000, 0x8800},
886/* 221 */ {0x0013, 0x8801},
887/* 222 */ {0x0001, 0x8800},
888
889/* 224 */ {0x000a, 0x8700},
890/* 225 */ {0x0000, 0x8702},
891/* 226 */ {0x0000, 0x8703},
892/* 227 */ {0x00c2, 0x8704},
893/* 228 */ {0x0001, 0x870c},
894
895/* 229 */ {0x0044, 0x8600},
896/* 230 */ {0x0002, 0x8606},
897/* 231 */ {0x0064, 0x8607},
898/* 232 */ {0x003a, 0x8601},
899/* 233 */ {0x0008, 0x8602},
900/* 234 */ {0x0044, 0x8600},
901/* 235 */ {0x0018, 0x8617},
902/* 236 */ {0x0008, 0x8618},
903/* 237 */ {0x00a1, 0x8656},
904/* 238 */ {0x0004, 0x865b},
905/* 239 */ {0x0002, 0x865c},
906/* 240 */ {0x0058, 0x865d},
907/* 241 */ {0x0048, 0x865e},
908/* 242 */ {0x0012, 0x8608},
909/* 243 */ {0x002c, 0x8609},
910/* 244 */ {0x0002, 0x860a},
911/* 245 */ {0x002c, 0x860b},
912/* 246 */ {0x00db, 0x860c},
913/* 247 */ {0x00f9, 0x860d},
914/* 248 */ {0x00f1, 0x860e},
915/* 249 */ {0x00e3, 0x860f},
916/* 250 */ {0x002c, 0x8610},
917/* 251 */ {0x006c, 0x8651},
918/* 252 */ {0x0041, 0x8652},
919/* 253 */ {0x0059, 0x8653},
920/* 254 */ {0x0040, 0x8654},
921/* 255 */ {0x00fa, 0x8611},
922/* 256 */ {0x00ff, 0x8612},
923/* 257 */ {0x00f8, 0x8613},
924/* 258 */ {0x0000, 0x8614},
925/* 259 */ {0x0001, 0x863f},
926/* 260 */ {0x0000, 0x8640},
927/* 261 */ {0x0026, 0x8641},
928/* 262 */ {0x0045, 0x8642},
929/* 263 */ {0x0060, 0x8643},
930/* 264 */ {0x0075, 0x8644},
931/* 265 */ {0x0088, 0x8645},
932/* 266 */ {0x009b, 0x8646},
933/* 267 */ {0x00b0, 0x8647},
934/* 268 */ {0x00c5, 0x8648},
935/* 269 */ {0x00d2, 0x8649},
936/* 270 */ {0x00dc, 0x864a},
937/* 271 */ {0x00e5, 0x864b},
938/* 272 */ {0x00eb, 0x864c},
939/* 273 */ {0x00f0, 0x864d},
940/* 274 */ {0x00f6, 0x864e},
941/* 275 */ {0x00fa, 0x864f},
942/* 276 */ {0x00ff, 0x8650},
943/* 277 */ {0x0060, 0x8657},
944/* 278 */ {0x0010, 0x8658},
945/* 279 */ {0x0018, 0x8659},
946/* 280 */ {0x0005, 0x865a},
947/* 281 */ {0x0018, 0x8660},
948/* 282 */ {0x0003, 0x8509},
949/* 283 */ {0x0011, 0x850a},
950/* 284 */ {0x0032, 0x850b},
951/* 285 */ {0x0010, 0x850c},
952/* 286 */ {0x0021, 0x850d},
953/* 287 */ {0x0001, 0x8500},
954/* 288 */ {0x0000, 0x8508},
955/* 289 */ {0x0012, 0x8608},
956/* 290 */ {0x002c, 0x8609},
957/* 291 */ {0x0002, 0x860a},
958/* 292 */ {0x0039, 0x860b},
959/* 293 */ {0x00d0, 0x860c},
960/* 294 */ {0x00f7, 0x860d},
961/* 295 */ {0x00ed, 0x860e},
962/* 296 */ {0x00db, 0x860f},
963/* 297 */ {0x0039, 0x8610},
964/* 298 */ {0x0012, 0x8657},
965/* 299 */ {0x000c, 0x8619},
966/* 300 */ {0x0004, 0x861a},
967/* 301 */ {0x00a1, 0x8656},
968/* 302 */ {0x00c8, 0x8615},
969/* 303 */ {0x0032, 0x8616},
970
971/* 306 */ {0x0030, 0x8112},
972/* 313 */ {0x0020, 0x8112},
973/* 314 */ {0x0020, 0x8112},
974/* 315 */ {0x000f, 0x8402},
975/* 316 */ {0x0000, 0x8403},
976
977/* 317 */ {0x0090, 0x8110},
978/* 318 */ {0x0001, 0x8114},
979/* 319 */ {0x0001, 0x8114},
980/* 320 */ {0x0001, 0x8114},
981/* 321 */ {0x0003, 0x8114},
982/* 322 */ {0x0080, 0x8804},
983
984/* 355 */ {0x0003, 0x8801},
985/* 356 */ {0x0012, 0x8800},
986/* 358 */ {0x0004, 0x8801},
987/* 359 */ {0x0005, 0x8800},
988/* 361 */ {0x0005, 0x8801},
989/* 362 */ {0x0047, 0x8800},
990/* 364 */ {0x0006, 0x8801},
991/* 365 */ {0x0000, 0x8800},
992/* 367 */ {0x0007, 0x8801},
993/* 368 */ {0x00c0, 0x8800},
994/* 370 */ {0x0008, 0x8801},
995/* 371 */ {0x0003, 0x8800},
996/* 373 */ {0x000a, 0x8700},
997/* 374 */ {0x000e, 0x8801},
998/* 375 */ {0x0004, 0x8800},
999/* 377 */ {0x0005, 0x8801},
1000/* 378 */ {0x0047, 0x8800},
1001/* 380 */ {0x0006, 0x8801},
1002/* 381 */ {0x0000, 0x8800},
1003/* 383 */ {0x0007, 0x8801},
1004/* 384 */ {0x00c0, 0x8800},
1005/* 386 */ {0x0008, 0x8801},
1006/* 387 */ {0x0003, 0x8800},
1007/* 389 */ {0x0013, 0x8801},
1008/* 390 */ {0x0001, 0x8800},
1009/* 392 */ {0x0009, 0x8801},
1010/* 393 */ {0x0000, 0x8800},
1011/* 395 */ {0x000a, 0x8801},
1012/* 396 */ {0x0000, 0x8800},
1013/* 398 */ {0x000b, 0x8801},
1014/* 399 */ {0x0000, 0x8800},
1015/* 401 */ {0x000c, 0x8801},
1016/* 402 */ {0x0000, 0x8800},
1017/* 404 */ {0x000e, 0x8801},
1018/* 405 */ {0x0004, 0x8800},
1019/* 407 */ {0x000f, 0x8801},
1020/* 408 */ {0x0000, 0x8800},
1021/* 410 */ {0x0010, 0x8801},
1022/* 411 */ {0x0006, 0x8800},
1023/* 413 */ {0x0011, 0x8801},
1024/* 414 */ {0x0006, 0x8800},
1025/* 416 */ {0x0012, 0x8801},
1026/* 417 */ {0x0000, 0x8800},
1027/* 419 */ {0x0013, 0x8801},
1028/* 420 */ {0x0001, 0x8800},
1029/* 422 */ {0x000a, 0x8700},
1030/* 423 */ {0x0000, 0x8702},
1031/* 424 */ {0x0000, 0x8703},
1032/* 425 */ {0x00c2, 0x8704},
1033/* 426 */ {0x0001, 0x870c},
1034/* 427 */ {0x0044, 0x8600},
1035/* 428 */ {0x0002, 0x8606},
1036/* 429 */ {0x0064, 0x8607},
1037/* 430 */ {0x003a, 0x8601},
1038/* 431 */ {0x0008, 0x8602},
1039/* 432 */ {0x0044, 0x8600},
1040/* 433 */ {0x0018, 0x8617},
1041/* 434 */ {0x0008, 0x8618},
1042/* 435 */ {0x00a1, 0x8656},
1043/* 436 */ {0x0004, 0x865b},
1044/* 437 */ {0x0002, 0x865c},
1045/* 438 */ {0x0058, 0x865d},
1046/* 439 */ {0x0048, 0x865e},
1047/* 440 */ {0x0012, 0x8608},
1048/* 441 */ {0x002c, 0x8609},
1049/* 442 */ {0x0002, 0x860a},
1050/* 443 */ {0x002c, 0x860b},
1051/* 444 */ {0x00db, 0x860c},
1052/* 445 */ {0x00f9, 0x860d},
1053/* 446 */ {0x00f1, 0x860e},
1054/* 447 */ {0x00e3, 0x860f},
1055/* 448 */ {0x002c, 0x8610},
1056/* 449 */ {0x006c, 0x8651},
1057/* 450 */ {0x0041, 0x8652},
1058/* 451 */ {0x0059, 0x8653},
1059/* 452 */ {0x0040, 0x8654},
1060/* 453 */ {0x00fa, 0x8611},
1061/* 454 */ {0x00ff, 0x8612},
1062/* 455 */ {0x00f8, 0x8613},
1063/* 456 */ {0x0000, 0x8614},
1064/* 457 */ {0x0001, 0x863f},
1065/* 458 */ {0x0000, 0x8640},
1066/* 459 */ {0x0026, 0x8641},
1067/* 460 */ {0x0045, 0x8642},
1068/* 461 */ {0x0060, 0x8643},
1069/* 462 */ {0x0075, 0x8644},
1070/* 463 */ {0x0088, 0x8645},
1071/* 464 */ {0x009b, 0x8646},
1072/* 465 */ {0x00b0, 0x8647},
1073/* 466 */ {0x00c5, 0x8648},
1074/* 467 */ {0x00d2, 0x8649},
1075/* 468 */ {0x00dc, 0x864a},
1076/* 469 */ {0x00e5, 0x864b},
1077/* 470 */ {0x00eb, 0x864c},
1078/* 471 */ {0x00f0, 0x864d},
1079/* 472 */ {0x00f6, 0x864e},
1080/* 473 */ {0x00fa, 0x864f},
1081/* 474 */ {0x00ff, 0x8650},
1082/* 475 */ {0x0060, 0x8657},
1083/* 476 */ {0x0010, 0x8658},
1084/* 477 */ {0x0018, 0x8659},
1085/* 478 */ {0x0005, 0x865a},
1086/* 479 */ {0x0018, 0x8660},
1087/* 480 */ {0x0003, 0x8509},
1088/* 481 */ {0x0011, 0x850a},
1089/* 482 */ {0x0032, 0x850b},
1090/* 483 */ {0x0010, 0x850c},
1091/* 484 */ {0x0021, 0x850d},
1092/* 485 */ {0x0001, 0x8500},
1093/* 486 */ {0x0000, 0x8508},
1094
1095/* 487 */ {0x0012, 0x8608},
1096/* 488 */ {0x002c, 0x8609},
1097/* 489 */ {0x0002, 0x860a},
1098/* 490 */ {0x0039, 0x860b},
1099/* 491 */ {0x00d0, 0x860c},
1100/* 492 */ {0x00f7, 0x860d},
1101/* 493 */ {0x00ed, 0x860e},
1102/* 494 */ {0x00db, 0x860f},
1103/* 495 */ {0x0039, 0x8610},
1104/* 496 */ {0x0012, 0x8657},
1105/* 497 */ {0x0064, 0x8619},
1106
1107/* This line starts it all, it is not needed here */
1108/* since it has been build into the driver */
1109/* jfm: don't start now */
1110/* 590 * {0x0030, 0x8112}, */
1111 {}
1112};
1113
1114/*
1115 * Initialization data for Creative Webcam Vista
1116 */
1117static const __u16 spca508_vista_init_data[][3] = {
1118 {0x0008, 0x8200}, /* Clear register */
1119 {0x0000, 0x870b}, /* Reset CTL3 */
1120 {0x0020, 0x8112}, /* Video Drop packet enable */
1121 {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
1122 {0x0000, 0x8110}, /* Disable everything */
1123 {0x0000, 0x8114}, /* Software GPIO output data */
1124 {0x0000, 0x8114},
1125
1126 {0x0003, 0x8111},
1127 {0x0000, 0x8111},
1128 {0x0090, 0x8110}, /* Enable: SSI output, External 2X clock output */
1129 {0x0020, 0x8112},
1130 {0x0000, 0x8114},
1131 {0x0001, 0x8114},
1132 {0x0001, 0x8114},
1133 {0x0001, 0x8114},
1134 {0x0003, 0x8114},
1135
1136 {0x000f, 0x8402}, /* Memory bank Address */
1137 {0x0000, 0x8403}, /* Memory bank Address */
1138 {0x00ba, 0x8804}, /* SSI Slave address */
1139 {0x0010, 0x8802}, /* 93.75kHz SSI Clock Two DataByte */
1140
1141 /* READ { 0, 0x0001, 0x8803 } ->
1142 0000: 00 */
1143 /* READ { 0, 0x0001, 0x8802 } ->
1144 0000: 10 */
1145 {0x0010, 0x8802}, /* Will write 2 bytes (DATA1+DATA2) */
1146 {0x0020, 0x8801}, /* Register address for SSI read/write */
1147 {0x0044, 0x8805}, /* DATA2 */
1148 {0x0004, 0x8800}, /* DATA1 -> write triggered */
1149 /* READ { 0, 0x0001, 0x8803 } ->
1150 0000: 00 */
1151
1152 /* READ { 0, 0x0001, 0x8803 } ->
1153 0000: 00 */
1154 /* READ { 0, 0x0001, 0x8802 } ->
1155 0000: 10 */
1156 {0x0010, 0x8802},
1157 {0x0009, 0x8801},
1158 {0x0042, 0x8805},
1159 {0x0001, 0x8800},
1160 /* READ { 0, 0x0001, 0x8803 } ->
1161 0000: 00 */
1162
1163 /* READ { 0, 0x0001, 0x8803 } ->
1164 0000: 00 */
1165 /* READ { 0, 0x0001, 0x8802 } ->
1166 0000: 10 */
1167 {0x0010, 0x8802},
1168 {0x003c, 0x8801},
1169 {0x0001, 0x8805},
1170 {0x0000, 0x8800},
1171 /* READ { 0, 0x0001, 0x8803 } ->
1172 0000: 00 */
1173
1174 /* READ { 0, 0x0001, 0x8803 } ->
1175 0000: 00 */
1176 /* READ { 0, 0x0001, 0x8802 } ->
1177 0000: 10 */
1178 {0x0010, 0x8802},
1179 {0x0001, 0x8801},
1180 {0x000a, 0x8805},
1181 {0x0000, 0x8800},
1182 /* READ { 0, 0x0001, 0x8803 } ->
1183 0000: 00 */
1184
1185 /* READ { 0, 0x0001, 0x8803 } ->
1186 0000: 00 */
1187 /* READ { 0, 0x0001, 0x8802 } ->
1188 0000: 10 */
1189 {0x0010, 0x8802},
1190 {0x0002, 0x8801},
1191 {0x0000, 0x8805},
1192 {0x0000, 0x8800},
1193 /* READ { 0, 0x0001, 0x8803 } ->
1194 0000: 00 */
1195
1196 /* READ { 0, 0x0001, 0x8803 } ->
1197 0000: 00 */
1198 /* READ { 0, 0x0001, 0x8802 } ->
1199 0000: 10 */
1200 {0x0010, 0x8802},
1201 {0x0003, 0x8801},
1202 {0x0027, 0x8805},
1203 {0x0001, 0x8800},
1204 /* READ { 0, 0x0001, 0x8803 } ->
1205 0000: 00 */
1206
1207 /* READ { 0, 0x0001, 0x8803 } ->
1208 0000: 00 */
1209 /* READ { 0, 0x0001, 0x8802 } ->
1210 0000: 10 */
1211 {0x0010, 0x8802},
1212 {0x0004, 0x8801},
1213 {0x0065, 0x8805},
1214 {0x0001, 0x8800},
1215 /* READ { 0, 0x0001, 0x8803 } ->
1216 0000: 00 */
1217
1218 /* READ { 0, 0x0001, 0x8803 } ->
1219 0000: 00 */
1220 /* READ { 0, 0x0001, 0x8802 } ->
1221 0000: 10 */
1222 {0x0010, 0x8802},
1223 {0x0005, 0x8801},
1224 {0x0003, 0x8805},
1225 {0x0000, 0x8800},
1226 /* READ { 0, 0x0001, 0x8803 } ->
1227 0000: 00 */
1228
1229 /* READ { 0, 0x0001, 0x8803 } ->
1230 0000: 00 */
1231 /* READ { 0, 0x0001, 0x8802 } ->
1232 0000: 10 */
1233 {0x0010, 0x8802},
1234 {0x0006, 0x8801},
1235 {0x001c, 0x8805},
1236 {0x0000, 0x8800},
1237 /* READ { 0, 0x0001, 0x8803 } ->
1238 0000: 00 */
1239
1240 /* READ { 0, 0x0001, 0x8803 } ->
1241 0000: 00 */
1242 /* READ { 0, 0x0001, 0x8802 } ->
1243 0000: 10 */
1244 {0x0010, 0x8802},
1245 {0x0007, 0x8801},
1246 {0x002a, 0x8805},
1247 {0x0000, 0x8800},
1248 /* READ { 0, 0x0001, 0x8803 } ->
1249 0000: 00 */
1250
1251 /* READ { 0, 0x0001, 0x8803 } ->
1252 0000: 00 */
1253 /* READ { 0, 0x0001, 0x8802 } ->
1254 0000: 10 */
1255 {0x0010, 0x8802},
1256 {0x000e, 0x8801},
1257 {0x0000, 0x8805},
1258 {0x0000, 0x8800},
1259 /* READ { 0, 0x0001, 0x8803 } ->
1260 0000: 00 */
1261
1262 /* READ { 0, 0x0001, 0x8803 } ->
1263 0000: 00 */
1264 /* READ { 0, 0x0001, 0x8802 } ->
1265 0000: 10 */
1266 {0x0010, 0x8802},
1267 {0x0028, 0x8801},
1268 {0x002e, 0x8805},
1269 {0x0000, 0x8800},
1270 /* READ { 0, 0x0001, 0x8803 } ->
1271 0000: 00 */
1272
1273 /* READ { 0, 0x0001, 0x8803 } ->
1274 0000: 00 */
1275 /* READ { 0, 0x0001, 0x8802 } ->
1276 0000: 10 */
1277 {0x0010, 0x8802},
1278 {0x0039, 0x8801},
1279 {0x0013, 0x8805},
1280 {0x0000, 0x8800},
1281 /* READ { 0, 0x0001, 0x8803 } ->
1282 0000: 00 */
1283
1284 /* READ { 0, 0x0001, 0x8803 } ->
1285 0000: 00 */
1286 /* READ { 0, 0x0001, 0x8802 } ->
1287 0000: 10 */
1288 {0x0010, 0x8802},
1289 {0x003b, 0x8801},
1290 {0x000c, 0x8805},
1291 {0x0000, 0x8800},
1292 /* READ { 0, 0x0001, 0x8803 } ->
1293 0000: 00 */
1294
1295 /* READ { 0, 0x0001, 0x8803 } ->
1296 0000: 00 */
1297 /* READ { 0, 0x0001, 0x8802 } ->
1298 0000: 10 */
1299 {0x0010, 0x8802},
1300 {0x0035, 0x8801},
1301 {0x0028, 0x8805},
1302 {0x0000, 0x8800},
1303 /* READ { 0, 0x0001, 0x8803 } ->
1304 0000: 00 */
1305
1306 /* READ { 0, 0x0001, 0x8803 } ->
1307 0000: 00 */
1308 /* READ { 0, 0x0001, 0x8802 } ->
1309 0000: 10 */
1310 {0x0010, 0x8802},
1311 {0x0009, 0x8801},
1312 {0x0042, 0x8805},
1313 {0x0001, 0x8800},
1314 /* READ { 0, 0x0001, 0x8803 } ->
1315 0000: 00 */
1316
1317 {0x0050, 0x8703},
1318 {0x0002, 0x8704}, /* External input CKIx1 */
1319 {0x0001, 0x870C}, /* Select CKOx2 output */
1320 {0x009A, 0x8600}, /* Line memory Read Counter (L) */
1321 {0x0001, 0x8606}, /* 1 Line memory Read Counter (H) Result: (d)410 */
1322 {0x0023, 0x8601},
1323 {0x0010, 0x8602},
1324 {0x000A, 0x8603},
1325 {0x009A, 0x8600},
1326 {0x0001, 0x865B}, /* 1 Horizontal Offset for Valid Pixel(L) */
1327 {0x0003, 0x865C}, /* Vertical offset for valid lines (L) */
1328 {0x0058, 0x865D}, /* Horizontal valid pixels window (L) */
1329 {0x0048, 0x865E}, /* Vertical valid lines window (L) */
1330 {0x0000, 0x865F},
1331
1332 {0x0006, 0x8660},
1333 /* Enable nibble data input, select nibble input order */
1334
1335 {0x0013, 0x8608}, /* A11 Coeficients for color correction */
1336 {0x0028, 0x8609},
1337 /* Note: these values are confirmed at the end of array */
1338 {0x0005, 0x860A}, /* ... */
1339 {0x0025, 0x860B},
1340 {0x00E1, 0x860C},
1341 {0x00FA, 0x860D},
1342 {0x00F4, 0x860E},
1343 {0x00E8, 0x860F},
1344 {0x0025, 0x8610}, /* A33 Coef. */
1345 {0x00FC, 0x8611}, /* White balance offset: R */
1346 {0x0001, 0x8612}, /* White balance offset: Gr */
1347 {0x00FE, 0x8613}, /* White balance offset: B */
1348 {0x0000, 0x8614}, /* White balance offset: Gb */
1349
1350 {0x0064, 0x8651}, /* R gain for white balance (L) */
1351 {0x0040, 0x8652}, /* Gr gain for white balance (L) */
1352 {0x0066, 0x8653}, /* B gain for white balance (L) */
1353 {0x0040, 0x8654}, /* Gb gain for white balance (L) */
1354 {0x0001, 0x863F}, /* Enable fixed gamma correction */
1355
1356 {0x00A1, 0x8656}, /* Size - Window1: 256x256, Window2: 128x128 */
1357 /* UV division: UV no change, Enable New edge enhancement */
1358 {0x0018, 0x8657}, /* Edge gain high threshold */
1359 {0x0020, 0x8658}, /* Edge gain low threshold */
1360 {0x000A, 0x8659}, /* Edge bandwidth high threshold */
1361 {0x0005, 0x865A}, /* Edge bandwidth low threshold */
1362 {0x0064, 0x8607}, /* UV filter enable */
1363
1364 {0x0016, 0x8660},
1365 {0x0000, 0x86B0}, /* Bad pixels compensation address */
1366 {0x00DC, 0x86B1}, /* X coord for bad pixels compensation (L) */
1367 {0x0000, 0x86B2},
1368 {0x0009, 0x86B3}, /* Y coord for bad pixels compensation (L) */
1369 {0x0000, 0x86B4},
1370
1371 {0x0001, 0x86B0},
1372 {0x00F5, 0x86B1},
1373 {0x0000, 0x86B2},
1374 {0x00C6, 0x86B3},
1375 {0x0000, 0x86B4},
1376
1377 {0x0002, 0x86B0},
1378 {0x001C, 0x86B1},
1379 {0x0001, 0x86B2},
1380 {0x00D7, 0x86B3},
1381 {0x0000, 0x86B4},
1382
1383 {0x0003, 0x86B0},
1384 {0x001C, 0x86B1},
1385 {0x0001, 0x86B2},
1386 {0x00D8, 0x86B3},
1387 {0x0000, 0x86B4},
1388
1389 {0x0004, 0x86B0},
1390 {0x001D, 0x86B1},
1391 {0x0001, 0x86B2},
1392 {0x00D8, 0x86B3},
1393 {0x0000, 0x86B4},
1394 {0x001E, 0x8660},
1395
1396 /* READ { 0, 0x0000, 0x8608 } ->
1397 0000: 13 */
1398 /* READ { 0, 0x0000, 0x8609 } ->
1399 0000: 28 */
1400 /* READ { 0, 0x0000, 0x8610 } ->
1401 0000: 05 */
1402 /* READ { 0, 0x0000, 0x8611 } ->
1403 0000: 25 */
1404 /* READ { 0, 0x0000, 0x8612 } ->
1405 0000: e1 */
1406 /* READ { 0, 0x0000, 0x8613 } ->
1407 0000: fa */
1408 /* READ { 0, 0x0000, 0x8614 } ->
1409 0000: f4 */
1410 /* READ { 0, 0x0000, 0x8615 } ->
1411 0000: e8 */
1412 /* READ { 0, 0x0000, 0x8616 } ->
1413 0000: 25 */
1414 {}
1415};
1416
1417static int reg_write(struct usb_device *dev,
1418 __u16 index, __u16 value)
1419{
1420 int ret;
1421
1422 ret = usb_control_msg(dev,
1423 usb_sndctrlpipe(dev, 0),
1424 0, /* request */
1425 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1426 value, index, NULL, 0, 500);
1427 PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
1428 index, value);
1429 if (ret < 0)
1430 PDEBUG(D_ERR|D_USBO, "reg write: error %d", ret);
1431 return ret;
1432}
1433
1434/* read 1 byte */
1435/* returns: negative is error, pos or zero is data */
1436static int reg_read(struct gspca_dev *gspca_dev,
1437 __u16 index) /* wIndex */
1438{
1439 int ret;
1440
1441 ret = usb_control_msg(gspca_dev->dev,
1442 usb_rcvctrlpipe(gspca_dev->dev, 0),
1443 0, /* register */
1444 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1445 0, /* value */
1446 index,
1447 gspca_dev->usb_buf, 1,
1448 500); /* timeout */
1449 PDEBUG(D_USBI, "reg read i:%04x --> %02x",
1450 index, gspca_dev->usb_buf[0]);
1451 if (ret < 0) {
1452 PDEBUG(D_ERR|D_USBI, "reg_read err %d", ret);
1453 return ret;
1454 }
1455 return gspca_dev->usb_buf[0];
1456}
1457
1458static int write_vector(struct gspca_dev *gspca_dev,
1459 const __u16 data[][3])
1460{
1461 struct usb_device *dev = gspca_dev->dev;
1462 int ret, i = 0;
1463
1464 while (data[i][1] != 0) {
1465 ret = reg_write(dev, data[i][1], data[i][0]);
1466 if (ret < 0)
1467 return ret;
1468 i++;
1469 }
1470 return 0;
1471}
1472
1473/* this function is called at probe time */
1474static int sd_config(struct gspca_dev *gspca_dev,
1475 const struct usb_device_id *id)
1476{
1477 struct sd *sd = (struct sd *) gspca_dev;
1478 struct cam *cam;
1479 __u16 product;
1480 int data1, data2;
1481
1482 product = id->idProduct;
1483 switch (id->idVendor) {
1484 case 0x0130: /* Clone webcam */
1485/* switch (product) { */
1486/* case 0x0130: */
1487 sd->subtype = HamaUSBSightcam; /* same as Hama 0010 */
1488/* break; */
1489/* } */
1490 break;
1491 case 0x041e: /* Creative cameras */
1492/* switch (product) { */
1493/* case 0x4018: */
1494 sd->subtype = CreativeVista;
1495/* break; */
1496/* } */
1497 break;
1498 case 0x0461: /* MicroInnovation */
1499/* switch (product) { */
1500/* case 0x0815: */
1501 sd->subtype = MicroInnovationIC200;
1502/* break; */
1503/* } */
1504 break;
1505 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
1506/* switch (product) { */
1507/* case 0x110: */
1508 sd->subtype = ViewQuestVQ110;
1509/* break; */
1510/* } */
1511 break;
1512 case 0x0af9: /* Hama cameras */
1513 switch (product) {
1514 case 0x0010:
1515 sd->subtype = HamaUSBSightcam;
1516 break;
1517 case 0x0011:
1518 sd->subtype = HamaUSBSightcam2;
1519 break;
1520 }
1521 break;
1522 case 0x8086: /* Intel */
1523/* switch (product) { */
1524/* case 0x0110: */
1525 sd->subtype = IntelEasyPCCamera;
1526/* break; */
1527/* } */
1528 break;
1529 }
1530
1531 /* Read from global register the USB product and vendor IDs, just to
1532 * prove that we can communicate with the device. This works, which
1533 * confirms at we are communicating properly and that the device
1534 * is a 508. */
1535 data1 = reg_read(gspca_dev, 0x8104);
1536 data2 = reg_read(gspca_dev, 0x8105);
1537 PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
1538
1539 data1 = reg_read(gspca_dev, 0x8106);
1540 data2 = reg_read(gspca_dev, 0x8107);
1541 PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
1542
1543 data1 = reg_read(gspca_dev, 0x8621);
1544 PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
1545
1546 cam = &gspca_dev->cam;
1547 cam->dev_name = (char *) id->driver_info;
1548 cam->epaddr = 0x01;
1549 cam->cam_mode = sif_mode;
1550 cam->nmodes = ARRAY_SIZE(sif_mode);
1551 sd->brightness = BRIGHTNESS_DEF;
1552
1553 switch (sd->subtype) {
1554 case ViewQuestVQ110:
1555 if (write_vector(gspca_dev, spca508_init_data))
1556 return -1;
1557 break;
1558 default:
1559/* case MicroInnovationIC200: */
1560/* case IntelEasyPCCamera: */
1561 if (write_vector(gspca_dev, spca508cs110_init_data))
1562 return -1;
1563 break;
1564 case HamaUSBSightcam:
1565 if (write_vector(gspca_dev, spca508_sightcam_init_data))
1566 return -1;
1567 break;
1568 case HamaUSBSightcam2:
1569 if (write_vector(gspca_dev, spca508_sightcam2_init_data))
1570 return -1;
1571 break;
1572 case CreativeVista:
1573 if (write_vector(gspca_dev, spca508_vista_init_data))
1574 return -1;
1575 break;
1576 }
1577 return 0; /* success */
1578}
1579
1580/* this function is called at open time */
1581static int sd_open(struct gspca_dev *gspca_dev)
1582{
1583/* write_vector(gspca_dev, spca508_open_data); */
1584 return 0;
1585}
1586
1587static void sd_start(struct gspca_dev *gspca_dev)
1588{
1589 int mode;
1590
1591 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1592 reg_write(gspca_dev->dev, 0x8500, mode);
1593 switch (mode) {
1594 case 0:
1595 case 1:
1596 reg_write(gspca_dev->dev, 0x8700, 0x28); /* clock */
1597 break;
1598 default:
1599/* case 2: */
1600/* case 3: */
1601 reg_write(gspca_dev->dev, 0x8700, 0x23); /* clock */
1602 break;
1603 }
1604 reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
1605}
1606
1607static void sd_stopN(struct gspca_dev *gspca_dev)
1608{
1609 /* Video ISO disable, Video Drop Packet enable: */
1610 reg_write(gspca_dev->dev, 0x8112, 0x20);
1611}
1612
1613static void sd_stop0(struct gspca_dev *gspca_dev)
1614{
1615}
1616
1617/* this function is called at close time */
1618static void sd_close(struct gspca_dev *gspca_dev)
1619{
1620}
1621
1622/* convert YUVY per line to YUYV (YUV 4:2:2) */
1623static void yuvy_decode(unsigned char *out,
1624 unsigned char *in,
1625 int width,
1626 int height)
1627{
1628 unsigned char *Ui, *Vi, *yi, *yi1;
1629 unsigned char *out1;
1630 int i, j;
1631
1632 yi = in;
1633 for (i = height / 2; --i >= 0; ) {
1634 out1 = out + width * 2; /* next line */
1635 Ui = yi + width;
1636 Vi = Ui + width / 2;
1637 yi1 = Vi + width / 2;
1638 for (j = width / 2; --j >= 0; ) {
1639 *out++ = 128 + *yi++;
1640 *out++ = 128 + *Ui;
1641 *out++ = 128 + *yi++;
1642 *out++ = 128 + *Vi;
1643
1644 *out1++ = 128 + *yi1++;
1645 *out1++ = 128 + *Ui++;
1646 *out1++ = 128 + *yi1++;
1647 *out1++ = 128 + *Vi++;
1648 }
1649 yi += width * 2;
1650 out = out1;
1651 }
1652}
1653
1654static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1655 struct gspca_frame *frame, /* target */
1656 __u8 *data, /* isoc packet */
1657 int len) /* iso packet length */
1658{
1659 struct sd *sd = (struct sd *) gspca_dev;
1660
1661 switch (data[0]) {
1662 case 0: /* start of frame */
1663 if (gspca_dev->last_packet_type == FIRST_PACKET) {
1664 yuvy_decode(sd->tmpbuf2, sd->tmpbuf,
1665 gspca_dev->width,
1666 gspca_dev->height);
1667 frame = gspca_frame_add(gspca_dev,
1668 LAST_PACKET,
1669 frame,
1670 sd->tmpbuf2,
1671 gspca_dev->width
1672 * gspca_dev->height
1673 * 2);
1674 }
1675 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1676 data, 0);
1677 data += SPCA508_OFFSET_DATA;
1678 len -= SPCA508_OFFSET_DATA;
1679 if (len > 0)
1680 memcpy(sd->tmpbuf, data, len);
1681 else
1682 len = 0;
1683 sd->buflen = len;
1684 return;
1685 case 0xff: /* drop */
1686/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1687 return;
1688 }
1689 data += 1;
1690 len -= 1;
1691 memcpy(&sd->tmpbuf[sd->buflen], data, len);
1692 sd->buflen += len;
1693}
1694
1695static void setbrightness(struct gspca_dev *gspca_dev)
1696{
1697 struct sd *sd = (struct sd *) gspca_dev;
1698 __u8 brightness = sd->brightness;
1699
1700 /* MX seem contrast */
1701 reg_write(gspca_dev->dev, 0x8651, brightness);
1702 reg_write(gspca_dev->dev, 0x8652, brightness);
1703 reg_write(gspca_dev->dev, 0x8653, brightness);
1704 reg_write(gspca_dev->dev, 0x8654, brightness);
1705}
1706
1707static void getbrightness(struct gspca_dev *gspca_dev)
1708{
1709 struct sd *sd = (struct sd *) gspca_dev;
1710
1711 sd->brightness = reg_read(gspca_dev, 0x8651);
1712}
1713
1714static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1715{
1716 struct sd *sd = (struct sd *) gspca_dev;
1717
1718 sd->brightness = val;
1719 if (gspca_dev->streaming)
1720 setbrightness(gspca_dev);
1721 return 0;
1722}
1723
1724static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1725{
1726 struct sd *sd = (struct sd *) gspca_dev;
1727
1728 getbrightness(gspca_dev);
1729 *val = sd->brightness;
1730 return 0;
1731}
1732
1733/* sub-driver description */
1734static const struct sd_desc sd_desc = {
1735 .name = MODULE_NAME,
1736 .ctrls = sd_ctrls,
1737 .nctrls = ARRAY_SIZE(sd_ctrls),
1738 .config = sd_config,
1739 .open = sd_open,
1740 .start = sd_start,
1741 .stopN = sd_stopN,
1742 .stop0 = sd_stop0,
1743 .close = sd_close,
1744 .pkt_scan = sd_pkt_scan,
1745};
1746
1747/* -- module initialisation -- */
1748#define DVNM(name) .driver_info = (kernel_ulong_t) name
1749static const __devinitdata struct usb_device_id device_table[] = {
1750 {USB_DEVICE(0x0130, 0x0130), DVNM("Clone Digital Webcam 11043")},
1751 {USB_DEVICE(0x041e, 0x4018), DVNM("Creative Webcam Vista (PD1100)")},
1752 {USB_DEVICE(0x0461, 0x0815), DVNM("Micro Innovation IC200")},
1753 {USB_DEVICE(0x0733, 0x0110), DVNM("ViewQuest VQ110")},
1754 {USB_DEVICE(0x0af9, 0x0010), DVNM("Hama USB Sightcam 100")},
1755 {USB_DEVICE(0x0af9, 0x0011), DVNM("Hama USB Sightcam 100")},
1756 {USB_DEVICE(0x8086, 0x0110), DVNM("Intel Easy PC Camera")},
1757 {}
1758};
1759MODULE_DEVICE_TABLE(usb, device_table);
1760
1761/* -- device connect -- */
1762static int sd_probe(struct usb_interface *intf,
1763 const struct usb_device_id *id)
1764{
1765 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1766 THIS_MODULE);
1767}
1768
1769static struct usb_driver sd_driver = {
1770 .name = MODULE_NAME,
1771 .id_table = device_table,
1772 .probe = sd_probe,
1773 .disconnect = gspca_disconnect,
1774};
1775
1776/* -- module insert / remove -- */
1777static int __init sd_mod_init(void)
1778{
1779 if (usb_register(&sd_driver) < 0)
1780 return -1;
1781 PDEBUG(D_PROBE, "v%s registered", version);
1782 return 0;
1783}
1784static void __exit sd_mod_exit(void)
1785{
1786 usb_deregister(&sd_driver);
1787 PDEBUG(D_PROBE, "deregistered");
1788}
1789
1790module_init(sd_mod_init);
1791module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
new file mode 100644
index 000000000000..b659bd0f788d
--- /dev/null
+++ b/drivers/media/video/gspca/spca561.c
@@ -0,0 +1,1052 @@
1/*
2 * Sunplus spca561 subdriver
3 *
4 * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
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 "spca561"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA561 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
38 unsigned short contrast;
39 __u8 brightness;
40 __u8 autogain;
41
42 __u8 chip_revision;
43 signed char ag_cnt;
44#define AG_CNT_START 13
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
53static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
54
55static struct ctrl sd_ctrls[] = {
56#define SD_BRIGHTNESS 0
57 {
58 {
59 .id = V4L2_CID_BRIGHTNESS,
60 .type = V4L2_CTRL_TYPE_INTEGER,
61 .name = "Brightness",
62 .minimum = 0,
63 .maximum = 63,
64 .step = 1,
65 .default_value = 32,
66 },
67 .set = sd_setbrightness,
68 .get = sd_getbrightness,
69 },
70#define SD_CONTRAST 1
71 {
72 {
73 .id = V4L2_CID_CONTRAST,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Contrast",
76 .minimum = 0,
77 .maximum = 0x3fff,
78 .step = 1,
79 .default_value = 0x2000,
80 },
81 .set = sd_setcontrast,
82 .get = sd_getcontrast,
83 },
84#define SD_AUTOGAIN 2
85 {
86 {
87 .id = V4L2_CID_AUTOGAIN,
88 .type = V4L2_CTRL_TYPE_BOOLEAN,
89 .name = "Auto Gain",
90 .minimum = 0,
91 .maximum = 1,
92 .step = 1,
93 .default_value = 1,
94 },
95 .set = sd_setautogain,
96 .get = sd_getautogain,
97 },
98};
99
100static struct v4l2_pix_format sif_mode[] = {
101 {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
102 .bytesperline = 160,
103 .sizeimage = 160 * 120,
104 .colorspace = V4L2_COLORSPACE_SRGB,
105 .priv = 3},
106 {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
107 .bytesperline = 176,
108 .sizeimage = 176 * 144,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = 2},
111 {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
112 .bytesperline = 320,
113 .sizeimage = 320 * 240 * 4 / 8,
114 .colorspace = V4L2_COLORSPACE_SRGB,
115 .priv = 1},
116 {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
117 .bytesperline = 352,
118 .sizeimage = 352 * 288 * 4 / 8,
119 .colorspace = V4L2_COLORSPACE_SRGB,
120 .priv = 0},
121};
122
123/*
124 * Initialization data
125 * I'm not very sure how to split initialization from open data
126 * chunks. For now, we'll consider everything as initialization
127 */
128/* Frame packet header offsets for the spca561 */
129#define SPCA561_OFFSET_SNAP 1
130#define SPCA561_OFFSET_TYPE 2
131#define SPCA561_OFFSET_COMPRESS 3
132#define SPCA561_OFFSET_FRAMSEQ 4
133#define SPCA561_OFFSET_GPIO 5
134#define SPCA561_OFFSET_USBBUFF 6
135#define SPCA561_OFFSET_WIN2GRAVE 7
136#define SPCA561_OFFSET_WIN2RAVE 8
137#define SPCA561_OFFSET_WIN2BAVE 9
138#define SPCA561_OFFSET_WIN2GBAVE 10
139#define SPCA561_OFFSET_WIN1GRAVE 11
140#define SPCA561_OFFSET_WIN1RAVE 12
141#define SPCA561_OFFSET_WIN1BAVE 13
142#define SPCA561_OFFSET_WIN1GBAVE 14
143#define SPCA561_OFFSET_FREQ 15
144#define SPCA561_OFFSET_VSYNC 16
145#define SPCA561_OFFSET_DATA 1
146#define SPCA561_INDEX_I2C_BASE 0x8800
147#define SPCA561_SNAPBIT 0x20
148#define SPCA561_SNAPCTRL 0x40
149enum {
150 Rev072A = 0,
151 Rev012A,
152};
153
154static void reg_w_val(struct usb_device *dev, __u16 index, __u16 value)
155{
156 int ret;
157
158 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
159 0, /* request */
160 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
161 value, index, NULL, 0, 500);
162 PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
163 if (ret < 0)
164 PDEBUG(D_ERR, "reg write: error %d", ret);
165}
166
167static void write_vector(struct gspca_dev *gspca_dev,
168 const __u16 data[][2])
169{
170 struct usb_device *dev = gspca_dev->dev;
171 int i;
172
173 i = 0;
174 while (data[i][1] != 0) {
175 reg_w_val(dev, data[i][1], data[i][0]);
176 i++;
177 }
178}
179
180/* read 'len' bytes to gspca_dev->usb_buf */
181static void reg_r(struct gspca_dev *gspca_dev,
182 __u16 index, __u16 length)
183{
184 usb_control_msg(gspca_dev->dev,
185 usb_rcvctrlpipe(gspca_dev->dev, 0),
186 0, /* request */
187 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
188 0, /* value */
189 index, gspca_dev->usb_buf, length, 500);
190}
191
192static void reg_w_buf(struct gspca_dev *gspca_dev,
193 __u16 index, const __u8 *buffer, __u16 len)
194{
195 memcpy(gspca_dev->usb_buf, buffer, len);
196 usb_control_msg(gspca_dev->dev,
197 usb_sndctrlpipe(gspca_dev->dev, 0),
198 0, /* request */
199 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
200 0, /* value */
201 index, gspca_dev->usb_buf, len, 500);
202}
203
204static void i2c_init(struct gspca_dev *gspca_dev, __u8 mode)
205{
206 reg_w_val(gspca_dev->dev, 0x92, 0x8804);
207 reg_w_val(gspca_dev->dev, mode, 0x8802);
208}
209
210static void i2c_write(struct gspca_dev *gspca_dev, __u16 valeur, __u16 reg)
211{
212 int retry = 60;
213 __u8 DataLow;
214 __u8 DataHight;
215
216 DataLow = valeur;
217 DataHight = valeur >> 8;
218 reg_w_val(gspca_dev->dev, reg, 0x8801);
219 reg_w_val(gspca_dev->dev, DataLow, 0x8805);
220 reg_w_val(gspca_dev->dev, DataHight, 0x8800);
221 while (retry--) {
222 reg_r(gspca_dev, 0x8803, 1);
223 if (!gspca_dev->usb_buf[0])
224 break;
225 }
226}
227
228static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
229{
230 int retry = 60;
231 __u8 value;
232 __u8 vallsb;
233
234 reg_w_val(gspca_dev->dev, 0x92, 0x8804);
235 reg_w_val(gspca_dev->dev, reg, 0x8801);
236 reg_w_val(gspca_dev->dev, (mode | 0x01), 0x8802);
237 while (retry--) {
238 reg_r(gspca_dev, 0x8803, 1);
239 if (!gspca_dev->usb_buf)
240 break;
241 }
242 if (retry == 0)
243 return -1;
244 reg_r(gspca_dev, 0x8800, 1);
245 value = gspca_dev->usb_buf[0];
246 reg_r(gspca_dev, 0x8805, 1);
247 vallsb = gspca_dev->usb_buf[0];
248 return ((int) value << 8) | vallsb;
249}
250
251static const __u16 spca561_init_data[][2] = {
252 {0x0000, 0x8114}, /* Software GPIO output data */
253 {0x0001, 0x8114}, /* Software GPIO output data */
254 {0x0000, 0x8112}, /* Some kind of reset */
255 {0x0003, 0x8701}, /* PCLK clock delay adjustment */
256 {0x0001, 0x8703}, /* HSYNC from cmos inverted */
257 {0x0011, 0x8118}, /* Enable and conf sensor */
258 {0x0001, 0x8118}, /* Conf sensor */
259 {0x0092, 0x8804}, /* I know nothing about these */
260 {0x0010, 0x8802}, /* 0x88xx registers, so I won't */
261 /***************/
262 {0x000d, 0x8805}, /* sensor default setting */
263 {0x0001, 0x8801}, /* 1 <- 0x0d */
264 {0x0000, 0x8800},
265 {0x0018, 0x8805},
266 {0x0002, 0x8801}, /* 2 <- 0x18 */
267 {0x0000, 0x8800},
268 {0x0065, 0x8805},
269 {0x0004, 0x8801}, /* 4 <- 0x01 0x65 */
270 {0x0001, 0x8800},
271 {0x0021, 0x8805},
272 {0x0005, 0x8801}, /* 5 <- 0x21 */
273 {0x0000, 0x8800},
274 {0x00aa, 0x8805},
275 {0x0007, 0x8801}, /* 7 <- 0xaa */
276 {0x0000, 0x8800},
277 {0x0004, 0x8805},
278 {0x0020, 0x8801}, /* 0x20 <- 0x15 0x04 */
279 {0x0015, 0x8800},
280 {0x0002, 0x8805},
281 {0x0039, 0x8801}, /* 0x39 <- 0x02 */
282 {0x0000, 0x8800},
283 {0x0010, 0x8805},
284 {0x0035, 0x8801}, /* 0x35 <- 0x10 */
285 {0x0000, 0x8800},
286 {0x0049, 0x8805},
287 {0x0009, 0x8801}, /* 0x09 <- 0x10 0x49 */
288 {0x0010, 0x8800},
289 {0x000b, 0x8805},
290 {0x0028, 0x8801}, /* 0x28 <- 0x0b */
291 {0x0000, 0x8800},
292 {0x000f, 0x8805},
293 {0x003b, 0x8801}, /* 0x3b <- 0x0f */
294 {0x0000, 0x8800},
295 {0x0000, 0x8805},
296 {0x003c, 0x8801}, /* 0x3c <- 0x00 */
297 {0x0000, 0x8800},
298 /***************/
299 {0x0018, 0x8601}, /* Pixel/line selection for color separation */
300 {0x0000, 0x8602}, /* Optical black level for user setting */
301 {0x0060, 0x8604}, /* Optical black horizontal offset */
302 {0x0002, 0x8605}, /* Optical black vertical offset */
303 {0x0000, 0x8603}, /* Non-automatic optical black level */
304 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
305 {0x0000, 0x865f}, /* Vertical valid pixels window (x2) */
306 {0x00b0, 0x865d}, /* Horizontal valid pixels window (x2) */
307 {0x0090, 0x865e}, /* Vertical valid lines window (x2) */
308 {0x00e0, 0x8406}, /* Memory buffer threshold */
309 {0x0000, 0x8660}, /* Compensation memory stuff */
310 {0x0002, 0x8201}, /* Output address for r/w serial EEPROM */
311 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
312 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
313 {0x0007, 0x8201}, /* Output address for r/w serial EEPROM */
314 {0x0008, 0x8200}, /* Clear valid bit for serial EEPROM */
315 {0x0001, 0x8200}, /* OprMode to be executed by hardware */
316 {0x0010, 0x8660}, /* Compensation memory stuff */
317 {0x0018, 0x8660}, /* Compensation memory stuff */
318
319 {0x0004, 0x8611}, /* R offset for white balance */
320 {0x0004, 0x8612}, /* Gr offset for white balance */
321 {0x0007, 0x8613}, /* B offset for white balance */
322 {0x0000, 0x8614}, /* Gb offset for white balance */
323 {0x008c, 0x8651}, /* R gain for white balance */
324 {0x008c, 0x8652}, /* Gr gain for white balance */
325 {0x00b5, 0x8653}, /* B gain for white balance */
326 {0x008c, 0x8654}, /* Gb gain for white balance */
327 {0x0002, 0x8502}, /* Maximum average bit rate stuff */
328
329 {0x0011, 0x8802},
330 {0x0087, 0x8700}, /* Set master clock (96Mhz????) */
331 {0x0081, 0x8702}, /* Master clock output enable */
332
333 {0x0000, 0x8500}, /* Set image type (352x288 no compression) */
334 /* Originally was 0x0010 (352x288 compression) */
335
336 {0x0002, 0x865b}, /* Horizontal offset for valid pixels */
337 {0x0003, 0x865c}, /* Vertical offset for valid lines */
338 /***************//* sensor active */
339 {0x0003, 0x8801}, /* 0x03 <- 0x01 0x21 //289 */
340 {0x0021, 0x8805},
341 {0x0001, 0x8800},
342 {0x0004, 0x8801}, /* 0x04 <- 0x01 0x65 //357 */
343 {0x0065, 0x8805},
344 {0x0001, 0x8800},
345 {0x0005, 0x8801}, /* 0x05 <- 0x2f */
346 {0x002f, 0x8805},
347 {0x0000, 0x8800},
348 {0x0006, 0x8801}, /* 0x06 <- 0 */
349 {0x0000, 0x8805},
350 {0x0000, 0x8800},
351 {0x000a, 0x8801}, /* 0x0a <- 2 */
352 {0x0002, 0x8805},
353 {0x0000, 0x8800},
354 {0x0009, 0x8801}, /* 0x09 <- 0x1061 */
355 {0x0061, 0x8805},
356 {0x0010, 0x8800},
357 {0x0035, 0x8801}, /* 0x35 <-0x14 */
358 {0x0014, 0x8805},
359 {0x0000, 0x8800},
360 {0x0030, 0x8112}, /* ISO and drop packet enable */
361 {0x0000, 0x8112}, /* Some kind of reset ???? */
362 {0x0009, 0x8118}, /* Enable sensor and set standby */
363 {0x0000, 0x8114}, /* Software GPIO output data */
364 {0x0000, 0x8114}, /* Software GPIO output data */
365 {0x0001, 0x8114}, /* Software GPIO output data */
366 {0x0000, 0x8112}, /* Some kind of reset ??? */
367 {0x0003, 0x8701},
368 {0x0001, 0x8703},
369 {0x0011, 0x8118},
370 {0x0001, 0x8118},
371 /***************/
372 {0x0092, 0x8804},
373 {0x0010, 0x8802},
374 {0x000d, 0x8805},
375 {0x0001, 0x8801},
376 {0x0000, 0x8800},
377 {0x0018, 0x8805},
378 {0x0002, 0x8801},
379 {0x0000, 0x8800},
380 {0x0065, 0x8805},
381 {0x0004, 0x8801},
382 {0x0001, 0x8800},
383 {0x0021, 0x8805},
384 {0x0005, 0x8801},
385 {0x0000, 0x8800},
386 {0x00aa, 0x8805},
387 {0x0007, 0x8801}, /* mode 0xaa */
388 {0x0000, 0x8800},
389 {0x0004, 0x8805},
390 {0x0020, 0x8801},
391 {0x0015, 0x8800}, /* mode 0x0415 */
392 {0x0002, 0x8805},
393 {0x0039, 0x8801},
394 {0x0000, 0x8800},
395 {0x0010, 0x8805},
396 {0x0035, 0x8801},
397 {0x0000, 0x8800},
398 {0x0049, 0x8805},
399 {0x0009, 0x8801},
400 {0x0010, 0x8800},
401 {0x000b, 0x8805},
402 {0x0028, 0x8801},
403 {0x0000, 0x8800},
404 {0x000f, 0x8805},
405 {0x003b, 0x8801},
406 {0x0000, 0x8800},
407 {0x0000, 0x8805},
408 {0x003c, 0x8801},
409 {0x0000, 0x8800},
410 {0x0002, 0x8502},
411 {0x0039, 0x8801},
412 {0x0000, 0x8805},
413 {0x0000, 0x8800},
414
415 {0x0087, 0x8700}, /* overwrite by start */
416 {0x0081, 0x8702},
417 {0x0000, 0x8500},
418/* {0x0010, 0x8500}, -- Previous line was this */
419 {0x0002, 0x865b},
420 {0x0003, 0x865c},
421 /***************/
422 {0x0003, 0x8801}, /* 0x121-> 289 */
423 {0x0021, 0x8805},
424 {0x0001, 0x8800},
425 {0x0004, 0x8801}, /* 0x165 -> 357 */
426 {0x0065, 0x8805},
427 {0x0001, 0x8800},
428 {0x0005, 0x8801}, /* 0x2f //blanking control colonne */
429 {0x002f, 0x8805},
430 {0x0000, 0x8800},
431 {0x0006, 0x8801}, /* 0x00 //blanking mode row */
432 {0x0000, 0x8805},
433 {0x0000, 0x8800},
434 {0x000a, 0x8801}, /* 0x01 //0x02 */
435 {0x0001, 0x8805},
436 {0x0000, 0x8800},
437 {0x0009, 0x8801}, /* 0x1061 - setexposure times && pixel clock
438 * 0001 0 | 000 0110 0001 */
439 {0x0061, 0x8805}, /* 61 31 */
440 {0x0008, 0x8800}, /* 08 */
441 {0x0035, 0x8801}, /* 0x14 - set gain general */
442 {0x001f, 0x8805}, /* 0x14 */
443 {0x0000, 0x8800},
444 {0x0030, 0x8112},
445 {}
446};
447
448static void sensor_reset(struct gspca_dev *gspca_dev)
449{
450 reg_w_val(gspca_dev->dev, 0x8631, 0xc8);
451 reg_w_val(gspca_dev->dev, 0x8634, 0xc8);
452 reg_w_val(gspca_dev->dev, 0x8112, 0x00);
453 reg_w_val(gspca_dev->dev, 0x8114, 0x00);
454 reg_w_val(gspca_dev->dev, 0x8118, 0x21);
455 i2c_init(gspca_dev, 0x14);
456 i2c_write(gspca_dev, 1, 0x0d);
457 i2c_write(gspca_dev, 0, 0x0d);
458}
459
460/******************** QC Express etch2 stuff ********************/
461static const __u16 Pb100_1map8300[][2] = {
462 /* reg, value */
463 {0x8320, 0x3304},
464
465 {0x8303, 0x0125}, /* image area */
466 {0x8304, 0x0169},
467 {0x8328, 0x000b},
468 {0x833c, 0x0001},
469
470 {0x832f, 0x0419},
471 {0x8307, 0x00aa},
472 {0x8301, 0x0003},
473 {0x8302, 0x000e},
474 {}
475};
476static const __u16 Pb100_2map8300[][2] = {
477 /* reg, value */
478 {0x8339, 0x0000},
479 {0x8307, 0x00aa},
480 {}
481};
482
483static const __u16 spca561_161rev12A_data1[][2] = {
484 {0x21, 0x8118},
485 {0x01, 0x8114},
486 {0x00, 0x8112},
487 {0x92, 0x8804},
488 {0x04, 0x8802}, /* windows uses 08 */
489 {}
490};
491static const __u16 spca561_161rev12A_data2[][2] = {
492 {0x21, 0x8118},
493 {0x10, 0x8500},
494 {0x07, 0x8601},
495 {0x07, 0x8602},
496 {0x04, 0x8501},
497 {0x21, 0x8118},
498
499 {0x07, 0x8201}, /* windows uses 02 */
500 {0x08, 0x8200},
501 {0x01, 0x8200},
502
503 {0x00, 0x8114},
504 {0x01, 0x8114}, /* windows uses 00 */
505
506 {0x90, 0x8604},
507 {0x00, 0x8605},
508 {0xb0, 0x8603},
509
510 /* sensor gains */
511 {0x00, 0x8610}, /* *red */
512 {0x00, 0x8611}, /* 3f *green */
513 {0x00, 0x8612}, /* green *blue */
514 {0x00, 0x8613}, /* blue *green */
515 {0x35, 0x8614}, /* green *red */
516 {0x35, 0x8615}, /* 40 *green */
517 {0x35, 0x8616}, /* 7a *blue */
518 {0x35, 0x8617}, /* 40 *green */
519
520 {0x0c, 0x8620}, /* 0c */
521 {0xc8, 0x8631}, /* c8 */
522 {0xc8, 0x8634}, /* c8 */
523 {0x23, 0x8635}, /* 23 */
524 {0x1f, 0x8636}, /* 1f */
525 {0xdd, 0x8637}, /* dd */
526 {0xe1, 0x8638}, /* e1 */
527 {0x1d, 0x8639}, /* 1d */
528 {0x21, 0x863a}, /* 21 */
529 {0xe3, 0x863b}, /* e3 */
530 {0xdf, 0x863c}, /* df */
531 {0xf0, 0x8505},
532 {0x32, 0x850a},
533 {}
534};
535
536static void sensor_mapwrite(struct gspca_dev *gspca_dev,
537 const __u16 sensormap[][2])
538{
539 int i = 0;
540 __u8 usbval[2];
541
542 while (sensormap[i][0]) {
543 usbval[0] = sensormap[i][1];
544 usbval[1] = sensormap[i][1] >> 8;
545 reg_w_buf(gspca_dev, sensormap[i][0], usbval, 2);
546 i++;
547 }
548}
549static void init_161rev12A(struct gspca_dev *gspca_dev)
550{
551 sensor_reset(gspca_dev);
552 write_vector(gspca_dev, spca561_161rev12A_data1);
553 sensor_mapwrite(gspca_dev, Pb100_1map8300);
554 write_vector(gspca_dev, spca561_161rev12A_data2);
555 sensor_mapwrite(gspca_dev, Pb100_2map8300);
556}
557
558/* this function is called at probe time */
559static int sd_config(struct gspca_dev *gspca_dev,
560 const struct usb_device_id *id)
561{
562 struct sd *sd = (struct sd *) gspca_dev;
563 struct cam *cam;
564 __u16 vendor, product;
565 __u8 data1, data2;
566
567 /* Read frm global register the USB product and vendor IDs, just to
568 * prove that we can communicate with the device. This works, which
569 * confirms at we are communicating properly and that the device
570 * is a 561. */
571 reg_r(gspca_dev, 0x8104, 1);
572 data1 = gspca_dev->usb_buf[0];
573 reg_r(gspca_dev, 0x8105, 1);
574 data2 = gspca_dev->usb_buf[0];
575 vendor = (data2 << 8) | data1;
576 reg_r(gspca_dev, 0x8106, 1);
577 data1 = gspca_dev->usb_buf[0];
578 reg_r(gspca_dev, 0x8107, 1);
579 data2 = gspca_dev->usb_buf[0];
580 product = (data2 << 8) | data1;
581 if (vendor != id->idVendor || product != id->idProduct) {
582 PDEBUG(D_PROBE, "Bad vendor / product from device");
583 return -EINVAL;
584 }
585 switch (product) {
586 case 0x0928:
587 case 0x0929:
588 case 0x092a:
589 case 0x092b:
590 case 0x092c:
591 case 0x092d:
592 case 0x092e:
593 case 0x092f:
594 case 0x403b:
595 sd->chip_revision = Rev012A;
596 break;
597 default:
598/* case 0x0561:
599 case 0x0815: * ?? in spca508.c
600 case 0x401a:
601 case 0x7004:
602 case 0x7e50:
603 case 0xa001:
604 case 0xcdee: */
605 sd->chip_revision = Rev072A;
606 break;
607 }
608 cam = &gspca_dev->cam;
609 cam->dev_name = (char *) id->driver_info;
610 cam->epaddr = 0x01;
611 gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */
612 cam->cam_mode = sif_mode;
613 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
614 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
615 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
616 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
617 return 0;
618}
619
620/* this function is called at open time */
621static int sd_open(struct gspca_dev *gspca_dev)
622{
623 struct sd *sd = (struct sd *) gspca_dev;
624
625 switch (sd->chip_revision) {
626 case Rev072A:
627 PDEBUG(D_STREAM, "Chip revision id: 072a");
628 write_vector(gspca_dev, spca561_init_data);
629 break;
630 default:
631/* case Rev012A: */
632 PDEBUG(D_STREAM, "Chip revision id: 012a");
633 init_161rev12A(gspca_dev);
634 break;
635 }
636 return 0;
637}
638
639static void setcontrast(struct gspca_dev *gspca_dev)
640{
641 struct sd *sd = (struct sd *) gspca_dev;
642 struct usb_device *dev = gspca_dev->dev;
643 __u8 lowb;
644 int expotimes;
645
646 switch (sd->chip_revision) {
647 case Rev072A:
648 lowb = sd->contrast >> 8;
649 reg_w_val(dev, lowb, 0x8651);
650 reg_w_val(dev, lowb, 0x8652);
651 reg_w_val(dev, lowb, 0x8653);
652 reg_w_val(dev, lowb, 0x8654);
653 break;
654 case Rev012A: {
655 __u8 Reg8391[] =
656 { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 };
657
658 /* Write camera sensor settings */
659 expotimes = (sd->contrast >> 5) & 0x07ff;
660 Reg8391[0] = expotimes & 0xff; /* exposure */
661 Reg8391[1] = 0x18 | (expotimes >> 8);
662 Reg8391[2] = sd->brightness; /* gain */
663 reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
664 reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
665 break;
666 }
667 }
668}
669
670static void sd_start(struct gspca_dev *gspca_dev)
671{
672 struct sd *sd = (struct sd *) gspca_dev;
673 struct usb_device *dev = gspca_dev->dev;
674 int Clck;
675 __u8 Reg8307[] = { 0xaa, 0x00 };
676 int mode;
677
678 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
679 switch (sd->chip_revision) {
680 case Rev072A:
681 switch (mode) {
682 default:
683/* case 0:
684 case 1: */
685 Clck = 0x25;
686 break;
687 case 2:
688 Clck = 0x22;
689 break;
690 case 3:
691 Clck = 0x21;
692 break;
693 }
694 reg_w_val(dev, 0x8500, mode); /* mode */
695 reg_w_val(dev, 0x8700, Clck); /* 0x27 clock */
696 reg_w_val(dev, 0x8112, 0x10 | 0x20);
697 break;
698 default:
699/* case Rev012A: */
700 switch (mode) {
701 case 0:
702 case 1:
703 Clck = 0x8a;
704 break;
705 case 2:
706 Clck = 0x85;
707 break;
708 default:
709 Clck = 0x83;
710 break;
711 }
712 if (mode <= 1) {
713 /* Use compression on 320x240 and above */
714 reg_w_val(dev, 0x8500, 0x10 | mode);
715 } else {
716 /* I couldn't get the compression to work below 320x240
717 * Fortunately at these resolutions the bandwidth
718 * is sufficient to push raw frames at ~20fps */
719 reg_w_val(dev, 0x8500, mode);
720 } /* -- qq@kuku.eu.org */
721 reg_w_buf(gspca_dev, 0x8307, Reg8307, 2);
722 reg_w_val(gspca_dev->dev, 0x8700, Clck);
723 /* 0x8f 0x85 0x27 clock */
724 reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
725 reg_w_val(gspca_dev->dev, 0x850b, 0x03);
726 setcontrast(gspca_dev);
727 break;
728 }
729}
730
731static void sd_stopN(struct gspca_dev *gspca_dev)
732{
733 reg_w_val(gspca_dev->dev, 0x8112, 0x20);
734}
735
736static void sd_stop0(struct gspca_dev *gspca_dev)
737{
738}
739
740/* this function is called at close time */
741static void sd_close(struct gspca_dev *gspca_dev)
742{
743 reg_w_val(gspca_dev->dev, 0x8114, 0);
744}
745
746static void setautogain(struct gspca_dev *gspca_dev)
747{
748 struct sd *sd = (struct sd *) gspca_dev;
749 int expotimes = 0;
750 int pixelclk = 0;
751 int gainG = 0;
752 __u8 R, Gr, Gb, B;
753 int y;
754 __u8 luma_mean = 110;
755 __u8 luma_delta = 20;
756 __u8 spring = 4;
757
758 switch (sd->chip_revision) {
759 case Rev072A:
760 reg_r(gspca_dev, 0x8621, 1);
761 Gr = gspca_dev->usb_buf[0];
762 reg_r(gspca_dev, 0x8622, 1);
763 R = gspca_dev->usb_buf[0];
764 reg_r(gspca_dev, 0x8623, 1);
765 B = gspca_dev->usb_buf[0];
766 reg_r(gspca_dev, 0x8624, 1);
767 Gb = gspca_dev->usb_buf[0];
768 y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
769 /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
770 /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
771 /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
772
773 if (y < luma_mean - luma_delta ||
774 y > luma_mean + luma_delta) {
775 expotimes = i2c_read(gspca_dev, 0x09, 0x10);
776 pixelclk = 0x0800;
777 expotimes = expotimes & 0x07ff;
778 /* PDEBUG(D_PACK,
779 "Exposition Times 0x%03X Clock 0x%04X ",
780 expotimes,pixelclk); */
781 gainG = i2c_read(gspca_dev, 0x35, 0x10);
782 /* PDEBUG(D_PACK,
783 "reading Gain register %d", gainG); */
784
785 expotimes += (luma_mean - y) >> spring;
786 gainG += (luma_mean - y) / 50;
787 /* PDEBUG(D_PACK,
788 "compute expotimes %d gain %d",
789 expotimes,gainG); */
790
791 if (gainG > 0x3f)
792 gainG = 0x3f;
793 else if (gainG < 4)
794 gainG = 3;
795 i2c_write(gspca_dev, gainG, 0x35);
796
797 if (expotimes >= 0x0256)
798 expotimes = 0x0256;
799 else if (expotimes < 4)
800 expotimes = 3;
801 i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
802 }
803 break;
804 case Rev012A:
805 /* sensor registers is access and memory mapped to 0x8300 */
806 /* readind all 0x83xx block the sensor */
807 /*
808 * The data from the header seem wrong where is the luma
809 * and chroma mean value
810 * at the moment set exposure in contrast set
811 */
812 break;
813 }
814}
815
816static void sd_pkt_scan(struct gspca_dev *gspca_dev,
817 struct gspca_frame *frame, /* target */
818 __u8 *data, /* isoc packet */
819 int len) /* iso packet length */
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822
823 switch (data[0]) {
824 case 0: /* start of frame */
825 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
826 data, 0);
827 if (sd->ag_cnt >= 0) {
828 if (--sd->ag_cnt < 0) {
829 sd->ag_cnt = AG_CNT_START;
830 setautogain(gspca_dev);
831 }
832 }
833 data += SPCA561_OFFSET_DATA;
834 len -= SPCA561_OFFSET_DATA;
835 if (data[1] & 0x10) {
836 /* compressed bayer */
837 gspca_frame_add(gspca_dev, FIRST_PACKET,
838 frame, data, len);
839 } else {
840 /* raw bayer (with a header, which we skip) */
841 data += 20;
842 len -= 20;
843 gspca_frame_add(gspca_dev, FIRST_PACKET,
844 frame, data, len);
845 }
846 return;
847 case 0xff: /* drop */
848/* gspca_dev->last_packet_type = DISCARD_PACKET; */
849 return;
850 }
851 data++;
852 len--;
853 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
854}
855
856static void setbrightness(struct gspca_dev *gspca_dev)
857{
858 struct sd *sd = (struct sd *) gspca_dev;
859 __u8 value;
860
861 switch (sd->chip_revision) {
862 case Rev072A:
863 value = sd->brightness;
864 reg_w_val(gspca_dev->dev, value, 0x8611);
865 reg_w_val(gspca_dev->dev, value, 0x8612);
866 reg_w_val(gspca_dev->dev, value, 0x8613);
867 reg_w_val(gspca_dev->dev, value, 0x8614);
868 break;
869 default:
870/* case Rev012A: */
871 setcontrast(gspca_dev);
872 break;
873 }
874}
875
876static void getbrightness(struct gspca_dev *gspca_dev)
877{
878 struct sd *sd = (struct sd *) gspca_dev;
879 __u16 tot;
880
881 switch (sd->chip_revision) {
882 case Rev072A:
883 tot = 0;
884 reg_r(gspca_dev, 0x8611, 1);
885 tot += gspca_dev->usb_buf[0];
886 reg_r(gspca_dev, 0x8612, 1);
887 tot += gspca_dev->usb_buf[0];
888 reg_r(gspca_dev, 0x8613, 1);
889 tot += gspca_dev->usb_buf[0];
890 reg_r(gspca_dev, 0x8614, 1);
891 tot += gspca_dev->usb_buf[0];
892 sd->brightness = tot >> 2;
893 break;
894 default:
895/* case Rev012A: */
896 /* no way to read sensor settings */
897 break;
898 }
899}
900
901static void getcontrast(struct gspca_dev *gspca_dev)
902{
903 struct sd *sd = (struct sd *) gspca_dev;
904 __u16 tot;
905
906 switch (sd->chip_revision) {
907 case Rev072A:
908 tot = 0;
909 reg_r(gspca_dev, 0x8651, 1);
910 tot += gspca_dev->usb_buf[0];
911 reg_r(gspca_dev, 0x8652, 1);
912 tot += gspca_dev->usb_buf[0];
913 reg_r(gspca_dev, 0x8653, 1);
914 tot += gspca_dev->usb_buf[0];
915 reg_r(gspca_dev, 0x8654, 1);
916 tot += gspca_dev->usb_buf[0];
917 sd->contrast = tot << 6;
918 break;
919 default:
920/* case Rev012A: */
921 /* no way to read sensor settings */
922 break;
923 }
924 PDEBUG(D_CONF, "get contrast %d", sd->contrast);
925}
926
927static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
928{
929 struct sd *sd = (struct sd *) gspca_dev;
930
931 sd->brightness = val;
932 if (gspca_dev->streaming)
933 setbrightness(gspca_dev);
934 return 0;
935}
936
937static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
938{
939 struct sd *sd = (struct sd *) gspca_dev;
940
941 getbrightness(gspca_dev);
942 *val = sd->brightness;
943 return 0;
944}
945
946static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
947{
948 struct sd *sd = (struct sd *) gspca_dev;
949
950 sd->contrast = val;
951 if (gspca_dev->streaming)
952 setcontrast(gspca_dev);
953 return 0;
954}
955
956static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
957{
958 struct sd *sd = (struct sd *) gspca_dev;
959
960 getcontrast(gspca_dev);
961 *val = sd->contrast;
962 return 0;
963}
964
965static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
966{
967 struct sd *sd = (struct sd *) gspca_dev;
968
969 sd->autogain = val;
970 if (val)
971 sd->ag_cnt = AG_CNT_START;
972 else
973 sd->ag_cnt = -1;
974 return 0;
975}
976
977static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
978{
979 struct sd *sd = (struct sd *) gspca_dev;
980
981 *val = sd->autogain;
982 return 0;
983}
984
985/* sub-driver description */
986static const struct sd_desc sd_desc = {
987 .name = MODULE_NAME,
988 .ctrls = sd_ctrls,
989 .nctrls = ARRAY_SIZE(sd_ctrls),
990 .config = sd_config,
991 .open = sd_open,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .stop0 = sd_stop0,
995 .close = sd_close,
996 .pkt_scan = sd_pkt_scan,
997};
998
999/* -- module initialisation -- */
1000#define DVNM(name) .driver_info = (kernel_ulong_t) name
1001static const __devinitdata struct usb_device_id device_table[] = {
1002 {USB_DEVICE(0x041e, 0x401a), DVNM("Creative Webcam Vista (PD1100)")},
1003 {USB_DEVICE(0x041e, 0x403b), DVNM("Creative Webcam Vista (VF0010)")},
1004 {USB_DEVICE(0x0458, 0x7004), DVNM("Genius VideoCAM Express V2")},
1005 {USB_DEVICE(0x046d, 0x0928), DVNM("Logitech QC Express Etch2")},
1006 {USB_DEVICE(0x046d, 0x0929), DVNM("Labtec Webcam Elch2")},
1007 {USB_DEVICE(0x046d, 0x092a), DVNM("Logitech QC for Notebook")},
1008 {USB_DEVICE(0x046d, 0x092b), DVNM("Labtec Webcam Plus")},
1009 {USB_DEVICE(0x046d, 0x092c), DVNM("Logitech QC chat Elch2")},
1010 {USB_DEVICE(0x046d, 0x092d), DVNM("Logitech QC Elch2")},
1011 {USB_DEVICE(0x046d, 0x092e), DVNM("Logitech QC Elch2")},
1012 {USB_DEVICE(0x046d, 0x092f), DVNM("Logitech QC Elch2")},
1013 {USB_DEVICE(0x04fc, 0x0561), DVNM("Flexcam 100")},
1014 {USB_DEVICE(0x060b, 0xa001), DVNM("Maxell Compact Pc PM3")},
1015 {USB_DEVICE(0x10fd, 0x7e50), DVNM("FlyCam Usb 100")},
1016 {USB_DEVICE(0xabcd, 0xcdee), DVNM("Petcam")},
1017 {}
1018};
1019
1020MODULE_DEVICE_TABLE(usb, device_table);
1021
1022/* -- device connect -- */
1023static int sd_probe(struct usb_interface *intf,
1024 const struct usb_device_id *id)
1025{
1026 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1027 THIS_MODULE);
1028}
1029
1030static struct usb_driver sd_driver = {
1031 .name = MODULE_NAME,
1032 .id_table = device_table,
1033 .probe = sd_probe,
1034 .disconnect = gspca_disconnect,
1035};
1036
1037/* -- module insert / remove -- */
1038static int __init sd_mod_init(void)
1039{
1040 if (usb_register(&sd_driver) < 0)
1041 return -1;
1042 PDEBUG(D_PROBE, "v%s registered", version);
1043 return 0;
1044}
1045static void __exit sd_mod_exit(void)
1046{
1047 usb_deregister(&sd_driver);
1048 PDEBUG(D_PROBE, "deregistered");
1049}
1050
1051module_init(sd_mod_init);
1052module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
new file mode 100644
index 000000000000..c78ee0d3e59b
--- /dev/null
+++ b/drivers/media/video/gspca/stk014.c
@@ -0,0 +1,592 @@
1/*
2 * Syntek DV4000 (STK014) subdriver
3 *
4 * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#define MODULE_NAME "stk014"
22
23#include "gspca.h"
24#include "jpeg.h"
25
26#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
27static const char version[] = "2.1.7";
28
29MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
30MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
31MODULE_LICENSE("GPL");
32
33/* specific webcam descriptor */
34struct sd {
35 struct gspca_dev gspca_dev; /* !! must be the first item */
36
37 unsigned char brightness;
38 unsigned char contrast;
39 unsigned char colors;
40 unsigned char lightfreq;
41};
42
43/* global parameters */
44static int sd_quant = 7; /* <= 4 KO - 7: good (enough!) */
45
46/* V4L2 controls supported by the driver */
47static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
48static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
49static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
50static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
51static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
52static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
53static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
54static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
55
56static struct ctrl sd_ctrls[] = {
57 {
58 {
59 .id = V4L2_CID_BRIGHTNESS,
60 .type = V4L2_CTRL_TYPE_INTEGER,
61 .name = "Brightness",
62 .minimum = 0,
63 .maximum = 255,
64 .step = 1,
65#define BRIGHTNESS_DEF 127
66 .default_value = BRIGHTNESS_DEF,
67 },
68 .set = sd_setbrightness,
69 .get = sd_getbrightness,
70 },
71 {
72 {
73 .id = V4L2_CID_CONTRAST,
74 .type = V4L2_CTRL_TYPE_INTEGER,
75 .name = "Contrast",
76 .minimum = 0,
77 .maximum = 255,
78 .step = 1,
79#define CONTRAST_DEF 127
80 .default_value = CONTRAST_DEF,
81 },
82 .set = sd_setcontrast,
83 .get = sd_getcontrast,
84 },
85 {
86 {
87 .id = V4L2_CID_SATURATION,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Color",
90 .minimum = 0,
91 .maximum = 255,
92 .step = 1,
93#define COLOR_DEF 127
94 .default_value = COLOR_DEF,
95 },
96 .set = sd_setcolors,
97 .get = sd_getcolors,
98 },
99 {
100 {
101 .id = V4L2_CID_POWER_LINE_FREQUENCY,
102 .type = V4L2_CTRL_TYPE_MENU,
103 .name = "Light frequency filter",
104 .minimum = 1,
105 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
106 .step = 1,
107#define FREQ_DEF 1
108 .default_value = FREQ_DEF,
109 },
110 .set = sd_setfreq,
111 .get = sd_getfreq,
112 },
113};
114
115static struct v4l2_pix_format vga_mode[] = {
116 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
117 .bytesperline = 320,
118 .sizeimage = 320 * 240 * 3 / 8 + 590,
119 .colorspace = V4L2_COLORSPACE_JPEG,
120 .priv = 1},
121 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
122 .bytesperline = 640,
123 .sizeimage = 640 * 480 * 3 / 8 + 590,
124 .colorspace = V4L2_COLORSPACE_JPEG,
125 .priv = 0},
126};
127
128/* -- read a register -- */
129static int reg_r(struct gspca_dev *gspca_dev,
130 __u16 index)
131{
132 struct usb_device *dev = gspca_dev->dev;
133 int ret;
134
135 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
136 0x00,
137 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
138 0x00,
139 index,
140 gspca_dev->usb_buf, 1,
141 500);
142 if (ret < 0) {
143 PDEBUG(D_ERR, "reg_r err %d", ret);
144 return ret;
145 }
146 return gspca_dev->usb_buf[0];
147}
148
149/* -- write a register -- */
150static int reg_w(struct gspca_dev *gspca_dev,
151 __u16 index, __u16 value)
152{
153 struct usb_device *dev = gspca_dev->dev;
154 int ret;
155
156 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
157 0x01,
158 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
159 value,
160 index,
161 NULL,
162 0,
163 500);
164 if (ret < 0)
165 PDEBUG(D_ERR, "reg_w err %d", ret);
166 return ret;
167}
168
169/* -- get a bulk value (4 bytes) -- */
170static int rcv_val(struct gspca_dev *gspca_dev,
171 int ads)
172{
173 struct usb_device *dev = gspca_dev->dev;
174 int alen, ret;
175
176 reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
177 reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
178 reg_w(gspca_dev, 0x636, ads & 0xff);
179 reg_w(gspca_dev, 0x637, 0);
180 reg_w(gspca_dev, 0x638, 4); /* len & 0xff */
181 reg_w(gspca_dev, 0x639, 0); /* len >> 8 */
182 reg_w(gspca_dev, 0x63a, 0);
183 reg_w(gspca_dev, 0x63b, 0);
184 reg_w(gspca_dev, 0x630, 5);
185 ret = usb_bulk_msg(dev,
186 usb_rcvbulkpipe(dev, 5),
187 gspca_dev->usb_buf,
188 4, /* length */
189 &alen,
190 500); /* timeout in milliseconds */
191 return ret;
192}
193
194/* -- send a bulk value -- */
195static int snd_val(struct gspca_dev *gspca_dev,
196 int ads,
197 unsigned int val)
198{
199 struct usb_device *dev = gspca_dev->dev;
200 int alen, ret;
201 __u8 seq = 0;
202
203 if (ads == 0x003f08) {
204 ret = reg_r(gspca_dev, 0x0704);
205 if (ret < 0)
206 goto ko;
207 ret = reg_r(gspca_dev, 0x0705);
208 if (ret < 0)
209 goto ko;
210 seq = ret; /* keep the sequence number */
211 ret = reg_r(gspca_dev, 0x0650);
212 if (ret < 0)
213 goto ko;
214 reg_w(gspca_dev, 0x654, seq);
215 } else {
216 reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
217 }
218 reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
219 reg_w(gspca_dev, 0x656, ads & 0xff);
220 reg_w(gspca_dev, 0x657, 0);
221 reg_w(gspca_dev, 0x658, 0x04); /* size */
222 reg_w(gspca_dev, 0x659, 0);
223 reg_w(gspca_dev, 0x65a, 0);
224 reg_w(gspca_dev, 0x65b, 0);
225 reg_w(gspca_dev, 0x650, 5);
226 gspca_dev->usb_buf[0] = val >> 24;
227 gspca_dev->usb_buf[1] = val >> 16;
228 gspca_dev->usb_buf[2] = val >> 8;
229 gspca_dev->usb_buf[3] = val;
230 ret = usb_bulk_msg(dev,
231 usb_sndbulkpipe(dev, 6),
232 gspca_dev->usb_buf,
233 4,
234 &alen,
235 500); /* timeout in milliseconds */
236 if (ret < 0)
237 goto ko;
238 if (ads == 0x003f08) {
239 seq += 4;
240 seq &= 0x3f;
241 reg_w(gspca_dev, 0x705, seq);
242 }
243 return ret;
244ko:
245 PDEBUG(D_ERR, "snd_val err %d", ret);
246 return ret;
247}
248
249/* set a camera parameter */
250static int set_par(struct gspca_dev *gspca_dev,
251 int parval)
252{
253 return snd_val(gspca_dev, 0x003f08, parval);
254}
255
256static void setbrightness(struct gspca_dev *gspca_dev)
257{
258 struct sd *sd = (struct sd *) gspca_dev;
259 int parval;
260
261 parval = 0x06000000 /* whiteness */
262 + (sd->brightness << 16);
263 set_par(gspca_dev, parval);
264}
265
266static void setcontrast(struct gspca_dev *gspca_dev)
267{
268 struct sd *sd = (struct sd *) gspca_dev;
269 int parval;
270
271 parval = 0x07000000 /* contrast */
272 + (sd->contrast << 16);
273 set_par(gspca_dev, parval);
274}
275
276static void setcolors(struct gspca_dev *gspca_dev)
277{
278 struct sd *sd = (struct sd *) gspca_dev;
279 int parval;
280
281 parval = 0x08000000 /* saturation */
282 + (sd->colors << 16);
283 set_par(gspca_dev, parval);
284}
285
286static void setfreq(struct gspca_dev *gspca_dev)
287{
288 struct sd *sd = (struct sd *) gspca_dev;
289
290 set_par(gspca_dev, sd->lightfreq == 1
291 ? 0x33640000 /* 50 Hz */
292 : 0x33780000); /* 60 Hz */
293}
294
295/* this function is called at probe time */
296static int sd_config(struct gspca_dev *gspca_dev,
297 const struct usb_device_id *id)
298{
299 struct sd *sd = (struct sd *) gspca_dev;
300 struct cam *cam = &gspca_dev->cam;
301
302 cam->dev_name = (char *) id->driver_info;
303 cam->epaddr = 0x02;
304 gspca_dev->cam.cam_mode = vga_mode;
305 gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
306 sd->brightness = BRIGHTNESS_DEF;
307 sd->contrast = CONTRAST_DEF;
308 sd->colors = COLOR_DEF;
309 sd->lightfreq = FREQ_DEF;
310 return 0;
311}
312
313/* this function is called at open time */
314static int sd_open(struct gspca_dev *gspca_dev)
315{
316 int ret;
317
318 /* check if the device responds */
319 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
320 ret = reg_r(gspca_dev, 0x0740);
321 if (ret < 0)
322 return ret;
323 if (ret != 0xff) {
324 PDEBUG(D_ERR|D_STREAM, "init reg: 0x%02x", ret);
325 return -1;
326 }
327 return 0;
328}
329
330/* -- start the camera -- */
331static void sd_start(struct gspca_dev *gspca_dev)
332{
333 int ret, value;
334
335 /* work on alternate 1 */
336 usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
337
338 set_par(gspca_dev, 0x10000000);
339 set_par(gspca_dev, 0x00000000);
340 set_par(gspca_dev, 0x8002e001);
341 set_par(gspca_dev, 0x14000000);
342 if (gspca_dev->width > 320)
343 value = 0x8002e001; /* 640x480 */
344 else
345 value = 0x4001f000; /* 320x240 */
346 set_par(gspca_dev, value);
347 ret = usb_set_interface(gspca_dev->dev,
348 gspca_dev->iface,
349 gspca_dev->alt);
350 if (ret < 0) {
351 PDEBUG(D_ERR|D_STREAM, "set intf %d %d failed",
352 gspca_dev->iface, gspca_dev->alt);
353 goto out;
354 }
355 ret = reg_r(gspca_dev, 0x0630);
356 if (ret < 0)
357 goto out;
358 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
359 ret = reg_r(gspca_dev, 0x0650);
360 if (ret < 0)
361 goto out;
362 snd_val(gspca_dev, 0x000020, 0xffffffff);
363 reg_w(gspca_dev, 0x0620, 0);
364 reg_w(gspca_dev, 0x0630, 0);
365 reg_w(gspca_dev, 0x0640, 0);
366 reg_w(gspca_dev, 0x0650, 0);
367 reg_w(gspca_dev, 0x0660, 0);
368 setbrightness(gspca_dev); /* whiteness */
369 setcontrast(gspca_dev); /* contrast */
370 setcolors(gspca_dev); /* saturation */
371 set_par(gspca_dev, 0x09800000); /* Red ? */
372 set_par(gspca_dev, 0x0a800000); /* Green ? */
373 set_par(gspca_dev, 0x0b800000); /* Blue ? */
374 set_par(gspca_dev, 0x0d030000); /* Gamma ? */
375 setfreq(gspca_dev); /* light frequency */
376
377 /* start the video flow */
378 set_par(gspca_dev, 0x01000000);
379 set_par(gspca_dev, 0x01000000);
380 PDEBUG(D_STREAM, "camera started alt: 0x%02x", gspca_dev->alt);
381 return;
382out:
383 PDEBUG(D_ERR|D_STREAM, "camera start err %d", ret);
384}
385
386static void sd_stopN(struct gspca_dev *gspca_dev)
387{
388 struct usb_device *dev = gspca_dev->dev;
389
390 set_par(gspca_dev, 0x02000000);
391 set_par(gspca_dev, 0x02000000);
392 usb_set_interface(dev, gspca_dev->iface, 1);
393 reg_r(gspca_dev, 0x0630);
394 rcv_val(gspca_dev, 0x000020); /* << (value ff ff ff ff) */
395 reg_r(gspca_dev, 0x0650);
396 snd_val(gspca_dev, 0x000020, 0xffffffff);
397 reg_w(gspca_dev, 0x0620, 0);
398 reg_w(gspca_dev, 0x0630, 0);
399 reg_w(gspca_dev, 0x0640, 0);
400 reg_w(gspca_dev, 0x0650, 0);
401 reg_w(gspca_dev, 0x0660, 0);
402 PDEBUG(D_STREAM, "camera stopped");
403}
404
405static void sd_stop0(struct gspca_dev *gspca_dev)
406{
407}
408
409static void sd_close(struct gspca_dev *gspca_dev)
410{
411}
412
413static void sd_pkt_scan(struct gspca_dev *gspca_dev,
414 struct gspca_frame *frame, /* target */
415 __u8 *data, /* isoc packet */
416 int len) /* iso packet length */
417{
418 static unsigned char ffd9[] = {0xff, 0xd9};
419
420 /* a frame starts with:
421 * - 0xff 0xfe
422 * - 0x08 0x00 - length (little endian ?!)
423 * - 4 bytes = size of whole frame (BE - including header)
424 * - 0x00 0x0c
425 * - 0xff 0xd8
426 * - .. JPEG image with escape sequences (ff 00)
427 * (without ending - ff d9)
428 */
429 if (data[0] == 0xff && data[1] == 0xfe) {
430 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
431 ffd9, 2);
432
433 /* put the JPEG 411 header */
434 jpeg_put_header(gspca_dev, frame, sd_quant, 0x22);
435
436 /* beginning of the frame */
437#define STKHDRSZ 12
438 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
439 data + STKHDRSZ, len - STKHDRSZ);
440#undef STKHDRSZ
441 return;
442 }
443 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
444}
445
446static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
447{
448 struct sd *sd = (struct sd *) gspca_dev;
449
450 sd->brightness = val;
451 if (gspca_dev->streaming)
452 setbrightness(gspca_dev);
453 return 0;
454}
455
456static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
457{
458 struct sd *sd = (struct sd *) gspca_dev;
459
460 *val = sd->brightness;
461 return 0;
462}
463
464static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
465{
466 struct sd *sd = (struct sd *) gspca_dev;
467
468 sd->contrast = val;
469 if (gspca_dev->streaming)
470 setcontrast(gspca_dev);
471 return 0;
472}
473
474static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
475{
476 struct sd *sd = (struct sd *) gspca_dev;
477
478 *val = sd->contrast;
479 return 0;
480}
481
482static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
483{
484 struct sd *sd = (struct sd *) gspca_dev;
485
486 sd->colors = val;
487 if (gspca_dev->streaming)
488 setcolors(gspca_dev);
489 return 0;
490}
491
492static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
493{
494 struct sd *sd = (struct sd *) gspca_dev;
495
496 *val = sd->colors;
497 return 0;
498}
499
500static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
501{
502 struct sd *sd = (struct sd *) gspca_dev;
503
504 sd->lightfreq = val;
505 if (gspca_dev->streaming)
506 setfreq(gspca_dev);
507 return 0;
508}
509
510static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
511{
512 struct sd *sd = (struct sd *) gspca_dev;
513
514 *val = sd->lightfreq;
515 return 0;
516}
517
518static int sd_querymenu(struct gspca_dev *gspca_dev,
519 struct v4l2_querymenu *menu)
520{
521 switch (menu->id) {
522 case V4L2_CID_POWER_LINE_FREQUENCY:
523 switch (menu->index) {
524 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
525 strcpy((char *) menu->name, "50 Hz");
526 return 0;
527 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
528 strcpy((char *) menu->name, "60 Hz");
529 return 0;
530 }
531 break;
532 }
533 return -EINVAL;
534}
535
536/* sub-driver description */
537static const struct sd_desc sd_desc = {
538 .name = MODULE_NAME,
539 .ctrls = sd_ctrls,
540 .nctrls = ARRAY_SIZE(sd_ctrls),
541 .config = sd_config,
542 .open = sd_open,
543 .start = sd_start,
544 .stopN = sd_stopN,
545 .stop0 = sd_stop0,
546 .close = sd_close,
547 .pkt_scan = sd_pkt_scan,
548 .querymenu = sd_querymenu,
549};
550
551/* -- module initialisation -- */
552#define DVNM(name) .driver_info = (kernel_ulong_t) name
553static const __devinitdata struct usb_device_id device_table[] = {
554 {USB_DEVICE(0x05e1, 0x0893), DVNM("Syntek DV4000")},
555 {}
556};
557MODULE_DEVICE_TABLE(usb, device_table);
558
559/* -- device connect -- */
560static int sd_probe(struct usb_interface *intf,
561 const struct usb_device_id *id)
562{
563 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
564 THIS_MODULE);
565}
566
567static struct usb_driver sd_driver = {
568 .name = MODULE_NAME,
569 .id_table = device_table,
570 .probe = sd_probe,
571 .disconnect = gspca_disconnect,
572};
573
574/* -- module insert / remove -- */
575static int __init sd_mod_init(void)
576{
577 if (usb_register(&sd_driver) < 0)
578 return -1;
579 info("v%s registered", version);
580 return 0;
581}
582static void __exit sd_mod_exit(void)
583{
584 usb_deregister(&sd_driver);
585 info("deregistered");
586}
587
588module_init(sd_mod_init);
589module_exit(sd_mod_exit);
590
591module_param_named(quant, sd_quant, int, 0644);
592MODULE_PARM_DESC(quant, "Quantization index (0..8)");
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
new file mode 100644
index 000000000000..abd7bef9b3d1
--- /dev/null
+++ b/drivers/media/video/gspca/sunplus.c
@@ -0,0 +1,1677 @@
1/*
2 * Sunplus spca504(abc) spca533 spca536 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 "sunplus"
23
24#include "gspca.h"
25#include "jpeg.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 8)
28static const char version[] = "2.1.8";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/SPCA5xx 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
38 __u8 packet[ISO_MAX_SIZE + 128];
39 /* !! no more than 128 ff in an ISO packet */
40
41 unsigned char brightness;
42 unsigned char contrast;
43 unsigned char colors;
44 unsigned char autogain;
45
46 char qindex;
47 char bridge;
48#define BRIDGE_SPCA504 0
49#define BRIDGE_SPCA504B 1
50#define BRIDGE_SPCA504C 2
51#define BRIDGE_SPCA533 3
52#define BRIDGE_SPCA536 4
53 char subtype;
54#define AiptekMiniPenCam13 1
55#define LogitechClickSmart420 2
56#define LogitechClickSmart820 3
57#define MegapixV4 4
58};
59
60/* V4L2 controls supported by the driver */
61static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
69
70static struct ctrl sd_ctrls[] = {
71#define SD_BRIGHTNESS 0
72 {
73 {
74 .id = V4L2_CID_BRIGHTNESS,
75 .type = V4L2_CTRL_TYPE_INTEGER,
76 .name = "Brightness",
77 .minimum = 0,
78 .maximum = 0xff,
79 .step = 1,
80 .default_value = 0,
81 },
82 .set = sd_setbrightness,
83 .get = sd_getbrightness,
84 },
85#define SD_CONTRAST 1
86 {
87 {
88 .id = V4L2_CID_CONTRAST,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Contrast",
91 .minimum = 0,
92 .maximum = 0xff,
93 .step = 1,
94 .default_value = 0x20,
95 },
96 .set = sd_setcontrast,
97 .get = sd_getcontrast,
98 },
99#define SD_COLOR 2
100 {
101 {
102 .id = V4L2_CID_SATURATION,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Color",
105 .minimum = 0,
106 .maximum = 0xff,
107 .step = 1,
108 .default_value = 0x1a,
109 },
110 .set = sd_setcolors,
111 .get = sd_getcolors,
112 },
113#define SD_AUTOGAIN 3
114 {
115 {
116 .id = V4L2_CID_AUTOGAIN,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Auto Gain",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 1,
123 },
124 .set = sd_setautogain,
125 .get = sd_getautogain,
126 },
127};
128
129static struct v4l2_pix_format vga_mode[] = {
130 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
131 .bytesperline = 320,
132 .sizeimage = 320 * 240 * 3 / 8 + 590,
133 .colorspace = V4L2_COLORSPACE_JPEG,
134 .priv = 2},
135 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
136 .bytesperline = 640,
137 .sizeimage = 640 * 480 * 3 / 8 + 590,
138 .colorspace = V4L2_COLORSPACE_JPEG,
139 .priv = 1},
140};
141
142static struct v4l2_pix_format custom_mode[] = {
143 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
144 .bytesperline = 320,
145 .sizeimage = 320 * 240 * 3 / 8 + 590,
146 .colorspace = V4L2_COLORSPACE_JPEG,
147 .priv = 2},
148 {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
149 .bytesperline = 464,
150 .sizeimage = 464 * 480 * 3 / 8 + 590,
151 .colorspace = V4L2_COLORSPACE_JPEG,
152 .priv = 1},
153};
154
155static struct v4l2_pix_format vga_mode2[] = {
156 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
157 .bytesperline = 176,
158 .sizeimage = 176 * 144 * 3 / 8 + 590,
159 .colorspace = V4L2_COLORSPACE_JPEG,
160 .priv = 4},
161 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
162 .bytesperline = 320,
163 .sizeimage = 320 * 240 * 3 / 8 + 590,
164 .colorspace = V4L2_COLORSPACE_JPEG,
165 .priv = 3},
166 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
167 .bytesperline = 352,
168 .sizeimage = 352 * 288 * 3 / 8 + 590,
169 .colorspace = V4L2_COLORSPACE_JPEG,
170 .priv = 2},
171 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
172 .bytesperline = 640,
173 .sizeimage = 640 * 480 * 3 / 8 + 590,
174 .colorspace = V4L2_COLORSPACE_JPEG,
175 .priv = 1},
176};
177
178#define SPCA50X_OFFSET_DATA 10
179#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
180#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
181#define SPCA504_PCCAM600_OFFSET_MODE 5
182#define SPCA504_PCCAM600_OFFSET_DATA 14
183 /* Frame packet header offsets for the spca533 */
184#define SPCA533_OFFSET_DATA 16
185#define SPCA533_OFFSET_FRAMSEQ 15
186/* Frame packet header offsets for the spca536 */
187#define SPCA536_OFFSET_DATA 4
188#define SPCA536_OFFSET_FRAMSEQ 1
189
190/* Initialisation data for the Creative PC-CAM 600 */
191static const __u16 spca504_pccam600_init_data[][3] = {
192/* {0xa0, 0x0000, 0x0503}, * capture mode */
193 {0x00, 0x0000, 0x2000},
194 {0x00, 0x0013, 0x2301},
195 {0x00, 0x0003, 0x2000},
196 {0x00, 0x0001, 0x21ac},
197 {0x00, 0x0001, 0x21a6},
198 {0x00, 0x0000, 0x21a7}, /* brightness */
199 {0x00, 0x0020, 0x21a8}, /* contrast */
200 {0x00, 0x0001, 0x21ac}, /* sat/hue */
201 {0x00, 0x0000, 0x21ad}, /* hue */
202 {0x00, 0x001a, 0x21ae}, /* saturation */
203 {0x00, 0x0002, 0x21a3}, /* gamma */
204 {0x30, 0x0154, 0x0008},
205 {0x30, 0x0004, 0x0006},
206 {0x30, 0x0258, 0x0009},
207 {0x30, 0x0004, 0x0000},
208 {0x30, 0x0093, 0x0004},
209 {0x30, 0x0066, 0x0005},
210 {0x00, 0x0000, 0x2000},
211 {0x00, 0x0013, 0x2301},
212 {0x00, 0x0003, 0x2000},
213 {0x00, 0x0013, 0x2301},
214 {0x00, 0x0003, 0x2000},
215 {}
216};
217
218/* Creative PC-CAM 600 specific open data, sent before using the
219 * generic initialisation data from spca504_open_data.
220 */
221static const __u16 spca504_pccam600_open_data[][3] = {
222 {0x00, 0x0001, 0x2501},
223 {0x20, 0x0500, 0x0001}, /* snapshot mode */
224 {0x00, 0x0003, 0x2880},
225 {0x00, 0x0001, 0x2881},
226 {}
227};
228
229/* Initialisation data for the logitech clicksmart 420 */
230static const __u16 spca504A_clicksmart420_init_data[][3] = {
231/* {0xa0, 0x0000, 0x0503}, * capture mode */
232 {0x00, 0x0000, 0x2000},
233 {0x00, 0x0013, 0x2301},
234 {0x00, 0x0003, 0x2000},
235 {0x00, 0x0001, 0x21ac},
236 {0x00, 0x0001, 0x21a6},
237 {0x00, 0x0000, 0x21a7}, /* brightness */
238 {0x00, 0x0020, 0x21a8}, /* contrast */
239 {0x00, 0x0001, 0x21ac}, /* sat/hue */
240 {0x00, 0x0000, 0x21ad}, /* hue */
241 {0x00, 0x001a, 0x21ae}, /* saturation */
242 {0x00, 0x0002, 0x21a3}, /* gamma */
243 {0x30, 0x0004, 0x000a},
244 {0xb0, 0x0001, 0x0000},
245
246
247 {0x0a1, 0x0080, 0x0001},
248 {0x30, 0x0049, 0x0000},
249 {0x30, 0x0060, 0x0005},
250 {0x0c, 0x0004, 0x0000},
251 {0x00, 0x0000, 0x0000},
252 {0x00, 0x0000, 0x2000},
253 {0x00, 0x0013, 0x2301},
254 {0x00, 0x0003, 0x2000},
255 {0x00, 0x0000, 0x2000},
256
257 {}
258};
259
260/* clicksmart 420 open data ? */
261static const __u16 spca504A_clicksmart420_open_data[][3] = {
262 {0x00, 0x0001, 0x2501},
263 {0x20, 0x0502, 0x0000},
264 {0x06, 0x0000, 0x0000},
265 {0x00, 0x0004, 0x2880},
266 {0x00, 0x0001, 0x2881},
267/* look like setting a qTable */
268 {0x00, 0x0006, 0x2800},
269 {0x00, 0x0004, 0x2801},
270 {0x00, 0x0004, 0x2802},
271 {0x00, 0x0006, 0x2803},
272 {0x00, 0x000a, 0x2804},
273 {0x00, 0x0010, 0x2805},
274 {0x00, 0x0014, 0x2806},
275 {0x00, 0x0018, 0x2807},
276 {0x00, 0x0005, 0x2808},
277 {0x00, 0x0005, 0x2809},
278 {0x00, 0x0006, 0x280a},
279 {0x00, 0x0008, 0x280b},
280 {0x00, 0x000a, 0x280c},
281 {0x00, 0x0017, 0x280d},
282 {0x00, 0x0018, 0x280e},
283 {0x00, 0x0016, 0x280f},
284
285 {0x00, 0x0006, 0x2810},
286 {0x00, 0x0005, 0x2811},
287 {0x00, 0x0006, 0x2812},
288 {0x00, 0x000a, 0x2813},
289 {0x00, 0x0010, 0x2814},
290 {0x00, 0x0017, 0x2815},
291 {0x00, 0x001c, 0x2816},
292 {0x00, 0x0016, 0x2817},
293 {0x00, 0x0006, 0x2818},
294 {0x00, 0x0007, 0x2819},
295 {0x00, 0x0009, 0x281a},
296 {0x00, 0x000c, 0x281b},
297 {0x00, 0x0014, 0x281c},
298 {0x00, 0x0023, 0x281d},
299 {0x00, 0x0020, 0x281e},
300 {0x00, 0x0019, 0x281f},
301
302 {0x00, 0x0007, 0x2820},
303 {0x00, 0x0009, 0x2821},
304 {0x00, 0x000f, 0x2822},
305 {0x00, 0x0016, 0x2823},
306 {0x00, 0x001b, 0x2824},
307 {0x00, 0x002c, 0x2825},
308 {0x00, 0x0029, 0x2826},
309 {0x00, 0x001f, 0x2827},
310 {0x00, 0x000a, 0x2828},
311 {0x00, 0x000e, 0x2829},
312 {0x00, 0x0016, 0x282a},
313 {0x00, 0x001a, 0x282b},
314 {0x00, 0x0020, 0x282c},
315 {0x00, 0x002a, 0x282d},
316 {0x00, 0x002d, 0x282e},
317 {0x00, 0x0025, 0x282f},
318
319 {0x00, 0x0014, 0x2830},
320 {0x00, 0x001a, 0x2831},
321 {0x00, 0x001f, 0x2832},
322 {0x00, 0x0023, 0x2833},
323 {0x00, 0x0029, 0x2834},
324 {0x00, 0x0030, 0x2835},
325 {0x00, 0x0030, 0x2836},
326 {0x00, 0x0028, 0x2837},
327 {0x00, 0x001d, 0x2838},
328 {0x00, 0x0025, 0x2839},
329 {0x00, 0x0026, 0x283a},
330 {0x00, 0x0027, 0x283b},
331 {0x00, 0x002d, 0x283c},
332 {0x00, 0x0028, 0x283d},
333 {0x00, 0x0029, 0x283e},
334 {0x00, 0x0028, 0x283f},
335
336 {0x00, 0x0007, 0x2840},
337 {0x00, 0x0007, 0x2841},
338 {0x00, 0x000a, 0x2842},
339 {0x00, 0x0013, 0x2843},
340 {0x00, 0x0028, 0x2844},
341 {0x00, 0x0028, 0x2845},
342 {0x00, 0x0028, 0x2846},
343 {0x00, 0x0028, 0x2847},
344 {0x00, 0x0007, 0x2848},
345 {0x00, 0x0008, 0x2849},
346 {0x00, 0x000a, 0x284a},
347 {0x00, 0x001a, 0x284b},
348 {0x00, 0x0028, 0x284c},
349 {0x00, 0x0028, 0x284d},
350 {0x00, 0x0028, 0x284e},
351 {0x00, 0x0028, 0x284f},
352
353 {0x00, 0x000a, 0x2850},
354 {0x00, 0x000a, 0x2851},
355 {0x00, 0x0016, 0x2852},
356 {0x00, 0x0028, 0x2853},
357 {0x00, 0x0028, 0x2854},
358 {0x00, 0x0028, 0x2855},
359 {0x00, 0x0028, 0x2856},
360 {0x00, 0x0028, 0x2857},
361 {0x00, 0x0013, 0x2858},
362 {0x00, 0x001a, 0x2859},
363 {0x00, 0x0028, 0x285a},
364 {0x00, 0x0028, 0x285b},
365 {0x00, 0x0028, 0x285c},
366 {0x00, 0x0028, 0x285d},
367 {0x00, 0x0028, 0x285e},
368 {0x00, 0x0028, 0x285f},
369
370 {0x00, 0x0028, 0x2860},
371 {0x00, 0x0028, 0x2861},
372 {0x00, 0x0028, 0x2862},
373 {0x00, 0x0028, 0x2863},
374 {0x00, 0x0028, 0x2864},
375 {0x00, 0x0028, 0x2865},
376 {0x00, 0x0028, 0x2866},
377 {0x00, 0x0028, 0x2867},
378 {0x00, 0x0028, 0x2868},
379 {0x00, 0x0028, 0x2869},
380 {0x00, 0x0028, 0x286a},
381 {0x00, 0x0028, 0x286b},
382 {0x00, 0x0028, 0x286c},
383 {0x00, 0x0028, 0x286d},
384 {0x00, 0x0028, 0x286e},
385 {0x00, 0x0028, 0x286f},
386
387 {0x00, 0x0028, 0x2870},
388 {0x00, 0x0028, 0x2871},
389 {0x00, 0x0028, 0x2872},
390 {0x00, 0x0028, 0x2873},
391 {0x00, 0x0028, 0x2874},
392 {0x00, 0x0028, 0x2875},
393 {0x00, 0x0028, 0x2876},
394 {0x00, 0x0028, 0x2877},
395 {0x00, 0x0028, 0x2878},
396 {0x00, 0x0028, 0x2879},
397 {0x00, 0x0028, 0x287a},
398 {0x00, 0x0028, 0x287b},
399 {0x00, 0x0028, 0x287c},
400 {0x00, 0x0028, 0x287d},
401 {0x00, 0x0028, 0x287e},
402 {0x00, 0x0028, 0x287f},
403
404 {0xa0, 0x0000, 0x0503},
405 {}
406};
407
408static const __u8 qtable_creative_pccam[2][64] = {
409 { /* Q-table Y-components */
410 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
411 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
412 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
413 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
414 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
415 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
416 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
417 0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
418 { /* Q-table C-components */
419 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
420 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
421 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
422 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
423 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
424 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
425 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
426 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
427};
428
429/* FIXME: This Q-table is identical to the Creative PC-CAM one,
430 * except for one byte. Possibly a typo?
431 * NWG: 18/05/2003.
432 */
433static const __u8 qtable_spca504_default[2][64] = {
434 { /* Q-table Y-components */
435 0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
436 0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
437 0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
438 0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
439 0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
440 0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
441 0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
442 0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
443 },
444 { /* Q-table C-components */
445 0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
446 0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
447 0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
448 0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
449 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
450 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
451 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
452 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
453};
454
455static void reg_r(struct usb_device *dev,
456 __u16 req,
457 __u16 index,
458 __u8 *buffer, __u16 length)
459{
460 usb_control_msg(dev,
461 usb_rcvctrlpipe(dev, 0),
462 req,
463 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
464 0, /* value */
465 index, buffer, length,
466 500);
467}
468
469static void reg_w(struct usb_device *dev,
470 __u16 req,
471 __u16 value,
472 __u16 index,
473 __u8 *buffer, __u16 length)
474{
475 usb_control_msg(dev,
476 usb_sndctrlpipe(dev, 0),
477 req,
478 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
479 value, index, buffer, length,
480 500);
481}
482
483/* write req / index / value */
484static int reg_w_riv(struct usb_device *dev,
485 __u16 req, __u16 index, __u16 value)
486{
487 int ret;
488
489 ret = usb_control_msg(dev,
490 usb_sndctrlpipe(dev, 0),
491 req,
492 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
493 value, index, NULL, 0, 500);
494 PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
495 req, index, value, ret);
496 if (ret < 0)
497 PDEBUG(D_ERR, "reg write: error %d", ret);
498 return ret;
499}
500
501/* read 1 byte */
502static int reg_r_1(struct gspca_dev *gspca_dev,
503 __u16 value) /* wValue */
504{
505 int ret;
506
507 ret = usb_control_msg(gspca_dev->dev,
508 usb_rcvctrlpipe(gspca_dev->dev, 0),
509 0x20, /* request */
510 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
511 value,
512 0, /* index */
513 gspca_dev->usb_buf, 1,
514 500); /* timeout */
515 if (ret < 0) {
516 PDEBUG(D_ERR, "reg_r_1 err %d", ret);
517 return 0;
518 }
519 return gspca_dev->usb_buf[0];
520}
521
522/* read 1 or 2 bytes - returns < 0 if error */
523static int reg_r_12(struct gspca_dev *gspca_dev,
524 __u16 req, /* bRequest */
525 __u16 index, /* wIndex */
526 __u16 length) /* wLength (1 or 2 only) */
527{
528 int ret;
529
530 gspca_dev->usb_buf[1] = 0;
531 ret = usb_control_msg(gspca_dev->dev,
532 usb_rcvctrlpipe(gspca_dev->dev, 0),
533 req,
534 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
535 0, /* value */
536 index,
537 gspca_dev->usb_buf, length,
538 500);
539 if (ret < 0) {
540 PDEBUG(D_ERR, "reg_read err %d", ret);
541 return -1;
542 }
543 return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
544}
545
546static int write_vector(struct gspca_dev *gspca_dev,
547 const __u16 data[][3])
548{
549 struct usb_device *dev = gspca_dev->dev;
550 int ret, i = 0;
551
552 while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
553 ret = reg_w_riv(dev, data[i][0], data[i][2], data[i][1]);
554 if (ret < 0) {
555 PDEBUG(D_ERR,
556 "Register write failed for 0x%x,0x%x,0x%x",
557 data[i][0], data[i][1], data[i][2]);
558 return ret;
559 }
560 i++;
561 }
562 return 0;
563}
564
565static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
566 unsigned int request,
567 unsigned int ybase,
568 unsigned int cbase,
569 const __u8 qtable[2][64])
570{
571 struct usb_device *dev = gspca_dev->dev;
572 int i, err;
573
574 /* loop over y components */
575 for (i = 0; i < 64; i++) {
576 err = reg_w_riv(dev, request, ybase + i, qtable[0][i]);
577 if (err < 0)
578 return err;
579 }
580
581 /* loop over c components */
582 for (i = 0; i < 64; i++) {
583 err = reg_w_riv(dev, request, cbase + i, qtable[1][i]);
584 if (err < 0)
585 return err;
586 }
587 return 0;
588}
589
590static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
591 __u16 req, __u16 idx, __u16 val)
592{
593 struct usb_device *dev = gspca_dev->dev;
594 __u8 notdone;
595
596 reg_w_riv(dev, req, idx, val);
597 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
598 reg_w_riv(dev, req, idx, val);
599
600 PDEBUG(D_FRAM, "before wait 0x%x", notdone);
601
602 msleep(200);
603 notdone = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
604 PDEBUG(D_FRAM, "after wait 0x%x", notdone);
605}
606
607static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
608 __u16 req,
609 __u16 idx, __u16 val, __u8 stat, __u8 count)
610{
611 struct usb_device *dev = gspca_dev->dev;
612 __u8 status;
613 __u8 endcode;
614
615 reg_w_riv(dev, req, idx, val);
616 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
617 endcode = stat;
618 PDEBUG(D_FRAM, "Status 0x%x Need 0x%x", status, stat);
619 if (!count)
620 return;
621 count = 200;
622 while (--count > 0) {
623 msleep(10);
624 /* gsmart mini2 write a each wait setting 1 ms is enought */
625/* reg_w_riv(dev, req, idx, val); */
626 status = reg_r_12(gspca_dev, 0x01, 0x0001, 1);
627 if (status == endcode) {
628 PDEBUG(D_FRAM, "status 0x%x after wait 0x%x",
629 status, 200 - count);
630 break;
631 }
632 }
633}
634
635static int spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
636{
637 int count = 10;
638
639 while (--count > 0) {
640 reg_r(gspca_dev->dev, 0x21, 0, gspca_dev->usb_buf, 1);
641 if ((gspca_dev->usb_buf[0] & 0x01) == 0)
642 break;
643 msleep(10);
644 }
645 return gspca_dev->usb_buf[0];
646}
647
648static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
649{
650 struct usb_device *dev = gspca_dev->dev;
651 int count = 50;
652
653 while (--count > 0) {
654 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
655 if (gspca_dev->usb_buf[0] != 0) {
656 gspca_dev->usb_buf[0] = 0;
657 reg_w(dev, 0x21, 0, 1, gspca_dev->usb_buf, 1);
658 reg_r(dev, 0x21, 1, gspca_dev->usb_buf, 1);
659 spca504B_PollingDataReady(gspca_dev);
660 break;
661 }
662 msleep(10);
663 }
664}
665
666static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
667{
668 struct usb_device *dev = gspca_dev->dev;
669 __u8 *data;
670
671 data = kmalloc(64, GFP_KERNEL);
672 reg_r(dev, 0x20, 0, data, 5);
673 PDEBUG(D_STREAM, "FirmWare : %d %d %d %d %d ",
674 data[0], data[1], data[2], data[3], data[4]);
675 reg_r(dev, 0x23, 0, data, 64);
676 reg_r(dev, 0x23, 1, data, 64);
677 kfree(data);
678}
679
680static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
681{
682 struct sd *sd = (struct sd *) gspca_dev;
683 struct usb_device *dev = gspca_dev->dev;
684 __u8 Size;
685 __u8 Type;
686 int rc;
687
688 Size = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
689 Type = 0;
690 switch (sd->bridge) {
691 case BRIDGE_SPCA533:
692 reg_w(dev, 0x31, 0, 0, NULL, 0);
693 spca504B_WaitCmdStatus(gspca_dev);
694 rc = spca504B_PollingDataReady(gspca_dev);
695 spca50x_GetFirmware(gspca_dev);
696 gspca_dev->usb_buf[0] = 2; /* type */
697 reg_w(dev, 0x24, 0, 8, gspca_dev->usb_buf, 1);
698 reg_r(dev, 0x24, 8, gspca_dev->usb_buf, 1);
699
700 gspca_dev->usb_buf[0] = Size;
701 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
702 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
703 rc = spca504B_PollingDataReady(gspca_dev);
704
705 /* Init the cam width height with some values get on init ? */
706 reg_w(dev, 0x31, 0, 4, NULL, 0);
707 spca504B_WaitCmdStatus(gspca_dev);
708 rc = spca504B_PollingDataReady(gspca_dev);
709 break;
710 default:
711/* case BRIDGE_SPCA504B: */
712/* case BRIDGE_SPCA536: */
713 gspca_dev->usb_buf[0] = Size;
714 reg_w(dev, 0x25, 0, 4, gspca_dev->usb_buf, 1);
715 reg_r(dev, 0x25, 4, gspca_dev->usb_buf, 1); /* size */
716 Type = 6;
717 gspca_dev->usb_buf[0] = Type;
718 reg_w(dev, 0x27, 0, 0, gspca_dev->usb_buf, 1);
719 reg_r(dev, 0x27, 0, gspca_dev->usb_buf, 1); /* type */
720 rc = spca504B_PollingDataReady(gspca_dev);
721 break;
722 case BRIDGE_SPCA504:
723 Size += 3;
724 if (sd->subtype == AiptekMiniPenCam13) {
725 /* spca504a aiptek */
726 spca504A_acknowledged_command(gspca_dev,
727 0x08, Size, 0,
728 0x80 | (Size & 0x0f), 1);
729 spca504A_acknowledged_command(gspca_dev,
730 1, 3, 0, 0x9f, 0);
731 } else {
732 spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
733 }
734 break;
735 case BRIDGE_SPCA504C:
736 /* capture mode */
737 reg_w_riv(dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
738 reg_w_riv(dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
739 break;
740 }
741}
742
743static void spca504_wait_status(struct gspca_dev *gspca_dev)
744{
745 int cnt;
746
747 cnt = 256;
748 while (--cnt > 0) {
749 /* With this we get the status, when return 0 it's all ok */
750 if (reg_r_12(gspca_dev, 0x06, 0x00, 1) == 0)
751 return;
752 msleep(10);
753 }
754}
755
756static void spca504B_setQtable(struct gspca_dev *gspca_dev)
757{
758 struct usb_device *dev = gspca_dev->dev;
759
760 gspca_dev->usb_buf[0] = 3;
761 reg_w(dev, 0x26, 0, 0, gspca_dev->usb_buf, 1);
762 reg_r(dev, 0x26, 0, gspca_dev->usb_buf, 1);
763 spca504B_PollingDataReady(gspca_dev);
764}
765
766static void sp5xx_initContBrigHueRegisters(struct gspca_dev *gspca_dev)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769 struct usb_device *dev = gspca_dev->dev;
770 int pollreg = 1;
771
772 switch (sd->bridge) {
773 case BRIDGE_SPCA504:
774 case BRIDGE_SPCA504C:
775 pollreg = 0;
776 /* fall thru */
777 default:
778/* case BRIDGE_SPCA533: */
779/* case BRIDGE_SPCA504B: */
780 reg_w(dev, 0, 0, 0x21a7, NULL, 0); /* brightness */
781 reg_w(dev, 0, 0x20, 0x21a8, NULL, 0); /* contrast */
782 reg_w(dev, 0, 0, 0x21ad, NULL, 0); /* hue */
783 reg_w(dev, 0, 1, 0x21ac, NULL, 0); /* sat/hue */
784 reg_w(dev, 0, 0x20, 0x21ae, NULL, 0); /* saturation */
785 reg_w(dev, 0, 0, 0x21a3, NULL, 0); /* gamma */
786 break;
787 case BRIDGE_SPCA536:
788 reg_w(dev, 0, 0, 0x20f0, NULL, 0);
789 reg_w(dev, 0, 0x21, 0x20f1, NULL, 0);
790 reg_w(dev, 0, 0x40, 0x20f5, NULL, 0);
791 reg_w(dev, 0, 1, 0x20f4, NULL, 0);
792 reg_w(dev, 0, 0x40, 0x20f6, NULL, 0);
793 reg_w(dev, 0, 0, 0x2089, NULL, 0);
794 break;
795 }
796 if (pollreg)
797 spca504B_PollingDataReady(gspca_dev);
798}
799
800/* this function is called at probe time */
801static int sd_config(struct gspca_dev *gspca_dev,
802 const struct usb_device_id *id)
803{
804 struct sd *sd = (struct sd *) gspca_dev;
805 struct usb_device *dev = gspca_dev->dev;
806 struct cam *cam;
807 __u16 vendor;
808 __u16 product;
809 __u8 fw;
810
811 vendor = id->idVendor;
812 product = id->idProduct;
813 switch (vendor) {
814 case 0x041e: /* Creative cameras */
815/* switch (product) { */
816/* case 0x400b: */
817/* case 0x4012: */
818/* case 0x4013: */
819/* sd->bridge = BRIDGE_SPCA504C; */
820/* break; */
821/* } */
822 break;
823 case 0x0458: /* Genius KYE cameras */
824/* switch (product) { */
825/* case 0x7006: */
826 sd->bridge = BRIDGE_SPCA504B;
827/* break; */
828/* } */
829 break;
830 case 0x0461: /* MicroInnovation */
831/* switch (product) { */
832/* case 0x0821: */
833 sd->bridge = BRIDGE_SPCA533;
834/* break; */
835/* } */
836 break;
837 case 0x046d: /* Logitech Labtec */
838 switch (product) {
839 case 0x0905:
840 sd->subtype = LogitechClickSmart820;
841 sd->bridge = BRIDGE_SPCA533;
842 break;
843 case 0x0960:
844 sd->subtype = LogitechClickSmart420;
845 sd->bridge = BRIDGE_SPCA504C;
846 break;
847 }
848 break;
849 case 0x0471: /* Philips */
850/* switch (product) { */
851/* case 0x0322: */
852 sd->bridge = BRIDGE_SPCA504B;
853/* break; */
854/* } */
855 break;
856 case 0x04a5: /* Benq */
857 switch (product) {
858 case 0x3003:
859 sd->bridge = BRIDGE_SPCA504B;
860 break;
861 case 0x3008:
862 case 0x300a:
863 sd->bridge = BRIDGE_SPCA533;
864 break;
865 }
866 break;
867 case 0x04f1: /* JVC */
868/* switch (product) { */
869/* case 0x1001: */
870 sd->bridge = BRIDGE_SPCA504B;
871/* break; */
872/* } */
873 break;
874 case 0x04fc: /* SunPlus */
875 switch (product) {
876 case 0x500c:
877 sd->bridge = BRIDGE_SPCA504B;
878 break;
879 case 0x504a:
880/* try to get the firmware as some cam answer 2.0.1.2.2
881 * and should be a spca504b then overwrite that setting */
882 reg_r(dev, 0x20, 0, gspca_dev->usb_buf, 1);
883 fw = gspca_dev->usb_buf[0];
884 if (fw == 1) {
885 sd->subtype = AiptekMiniPenCam13;
886 sd->bridge = BRIDGE_SPCA504;
887 } else if (fw == 2) {
888 sd->bridge = BRIDGE_SPCA504B;
889 } else
890 return -ENODEV;
891 break;
892 case 0x504b:
893 sd->bridge = BRIDGE_SPCA504B;
894 break;
895 case 0x5330:
896 sd->bridge = BRIDGE_SPCA533;
897 break;
898 case 0x5360:
899 sd->bridge = BRIDGE_SPCA536;
900 break;
901 case 0xffff:
902 sd->bridge = BRIDGE_SPCA504B;
903 break;
904 }
905 break;
906 case 0x052b: /* ?? Megapix */
907/* switch (product) { */
908/* case 0x1513: */
909 sd->subtype = MegapixV4;
910 sd->bridge = BRIDGE_SPCA533;
911/* break; */
912/* } */
913 break;
914 case 0x0546: /* Polaroid */
915 switch (product) {
916 case 0x3155:
917 sd->bridge = BRIDGE_SPCA533;
918 break;
919 case 0x3191:
920 case 0x3273:
921 sd->bridge = BRIDGE_SPCA504B;
922 break;
923 }
924 break;
925 case 0x055f: /* Mustek cameras */
926 switch (product) {
927 case 0xc211:
928 sd->bridge = BRIDGE_SPCA536;
929 break;
930 case 0xc230:
931 case 0xc232:
932 sd->bridge = BRIDGE_SPCA533;
933 break;
934 case 0xc360:
935 sd->bridge = BRIDGE_SPCA536;
936 break;
937 case 0xc420:
938 sd->bridge = BRIDGE_SPCA504;
939 break;
940 case 0xc430:
941 case 0xc440:
942 sd->bridge = BRIDGE_SPCA533;
943 break;
944 case 0xc520:
945 sd->bridge = BRIDGE_SPCA504;
946 break;
947 case 0xc530:
948 case 0xc540:
949 case 0xc630:
950 case 0xc650:
951 sd->bridge = BRIDGE_SPCA533;
952 break;
953 }
954 break;
955 case 0x05da: /* Digital Dream cameras */
956/* switch (product) { */
957/* case 0x1018: */
958 sd->bridge = BRIDGE_SPCA504B;
959/* break; */
960/* } */
961 break;
962 case 0x06d6: /* Trust */
963/* switch (product) { */
964/* case 0x0031: */
965 sd->bridge = BRIDGE_SPCA533; /* SPCA533A */
966/* break; */
967/* } */
968 break;
969 case 0x0733: /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
970 switch (product) {
971 case 0x1311:
972 case 0x1314:
973 case 0x2211:
974 case 0x2221:
975 sd->bridge = BRIDGE_SPCA533;
976 break;
977 case 0x3261:
978 case 0x3281:
979 sd->bridge = BRIDGE_SPCA536;
980 break;
981 }
982 break;
983 case 0x08ca: /* Aiptek */
984 switch (product) {
985 case 0x0104:
986 case 0x0106:
987 sd->bridge = BRIDGE_SPCA533;
988 break;
989 case 0x2008:
990 sd->bridge = BRIDGE_SPCA504B;
991 break;
992 case 0x2010:
993 sd->bridge = BRIDGE_SPCA533;
994 break;
995 case 0x2016:
996 case 0x2018:
997 sd->bridge = BRIDGE_SPCA504B;
998 break;
999 case 0x2020:
1000 case 0x2022:
1001 sd->bridge = BRIDGE_SPCA533;
1002 break;
1003 case 0x2024:
1004 sd->bridge = BRIDGE_SPCA536;
1005 break;
1006 case 0x2028:
1007 sd->bridge = BRIDGE_SPCA533;
1008 break;
1009 case 0x2040:
1010 case 0x2042:
1011 case 0x2050:
1012 case 0x2060:
1013 sd->bridge = BRIDGE_SPCA536;
1014 break;
1015 }
1016 break;
1017 case 0x0d64: /* SunPlus */
1018/* switch (product) { */
1019/* case 0x0303: */
1020 sd->bridge = BRIDGE_SPCA536;
1021/* break; */
1022/* } */
1023 break;
1024 }
1025
1026 cam = &gspca_dev->cam;
1027 cam->dev_name = (char *) id->driver_info;
1028 cam->epaddr = 0x01;
1029
1030 switch (sd->bridge) {
1031 default:
1032/* case BRIDGE_SPCA504B: */
1033/* case BRIDGE_SPCA504: */
1034/* case BRIDGE_SPCA536: */
1035 cam->cam_mode = vga_mode;
1036 cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
1037 break;
1038 case BRIDGE_SPCA533:
1039 cam->cam_mode = custom_mode;
1040 cam->nmodes = sizeof custom_mode / sizeof custom_mode[0];
1041 break;
1042 case BRIDGE_SPCA504C:
1043 cam->cam_mode = vga_mode2;
1044 cam->nmodes = sizeof vga_mode2 / sizeof vga_mode2[0];
1045 break;
1046 }
1047 sd->qindex = 5; /* set the quantization table */
1048 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
1049 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
1050 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
1051 return 0;
1052}
1053
1054/* this function is called at open time */
1055static int sd_open(struct gspca_dev *gspca_dev)
1056{
1057 struct sd *sd = (struct sd *) gspca_dev;
1058 struct usb_device *dev = gspca_dev->dev;
1059 int rc;
1060 __u8 i;
1061 __u8 info[6];
1062 int err_code;
1063
1064 switch (sd->bridge) {
1065 case BRIDGE_SPCA504B:
1066 reg_w(dev, 0x1d, 0, 0, NULL, 0);
1067 reg_w(dev, 0, 1, 0x2306, NULL, 0);
1068 reg_w(dev, 0, 0, 0x0d04, NULL, 0);
1069 reg_w(dev, 0, 0, 0x2000, NULL, 0);
1070 reg_w(dev, 0, 0x13, 0x2301, NULL, 0);
1071 reg_w(dev, 0, 0, 0x2306, NULL, 0);
1072 /* fall thru */
1073 case BRIDGE_SPCA533:
1074 rc = spca504B_PollingDataReady(gspca_dev);
1075 spca50x_GetFirmware(gspca_dev);
1076 break;
1077 case BRIDGE_SPCA536:
1078 spca50x_GetFirmware(gspca_dev);
1079 reg_r(dev, 0x00, 0x5002, gspca_dev->usb_buf, 1);
1080 gspca_dev->usb_buf[0] = 0;
1081 reg_w(dev, 0x24, 0, 0, gspca_dev->usb_buf, 1);
1082 reg_r(dev, 0x24, 0, gspca_dev->usb_buf, 1);
1083 rc = spca504B_PollingDataReady(gspca_dev);
1084 reg_w(dev, 0x34, 0, 0, NULL, 0);
1085 spca504B_WaitCmdStatus(gspca_dev);
1086 break;
1087 case BRIDGE_SPCA504C: /* pccam600 */
1088 PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
1089 reg_w_riv(dev, 0xe0, 0x0000, 0x0000);
1090 reg_w_riv(dev, 0xe0, 0x0000, 0x0001); /* reset */
1091 spca504_wait_status(gspca_dev);
1092 if (sd->subtype == LogitechClickSmart420)
1093 write_vector(gspca_dev,
1094 spca504A_clicksmart420_open_data);
1095 else
1096 write_vector(gspca_dev, spca504_pccam600_open_data);
1097 err_code = spca50x_setup_qtable(gspca_dev,
1098 0x00, 0x2800,
1099 0x2840, qtable_creative_pccam);
1100 if (err_code < 0) {
1101 PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed");
1102 return err_code;
1103 }
1104 break;
1105 default:
1106/* case BRIDGE_SPCA504: */
1107 PDEBUG(D_STREAM, "Opening SPCA504");
1108 if (sd->subtype == AiptekMiniPenCam13) {
1109 /*****************************/
1110 for (i = 0; i < 6; i++)
1111 info[i] = reg_r_1(gspca_dev, i);
1112 PDEBUG(D_STREAM,
1113 "Read info: %d %d %d %d %d %d."
1114 " Should be 1,0,2,2,0,0",
1115 info[0], info[1], info[2],
1116 info[3], info[4], info[5]);
1117 /* spca504a aiptek */
1118 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1119 spca504A_acknowledged_command(gspca_dev, 0x24,
1120 8, 3, 0x9e, 1);
1121 /* Twice sequencial need status 0xff->0x9e->0x9d */
1122 spca504A_acknowledged_command(gspca_dev, 0x24,
1123 8, 3, 0x9e, 0);
1124
1125 spca504A_acknowledged_command(gspca_dev, 0x24,
1126 0, 0, 0x9d, 1);
1127 /******************************/
1128 /* spca504a aiptek */
1129 spca504A_acknowledged_command(gspca_dev, 0x08,
1130 6, 0, 0x86, 1);
1131/* reg_write (dev, 0, 0x2000, 0); */
1132/* reg_write (dev, 0, 0x2883, 1); */
1133/* spca504A_acknowledged_command (gspca_dev, 0x08,
1134 6, 0, 0x86, 1); */
1135/* spca504A_acknowledged_command (gspca_dev, 0x24,
1136 0, 0, 0x9D, 1); */
1137 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1138 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1139 spca504A_acknowledged_command(gspca_dev, 0x01,
1140 0x0f, 0, 0xff, 0);
1141 }
1142 /* setup qtable */
1143 reg_w_riv(dev, 0, 0x2000, 0);
1144 reg_w_riv(dev, 0, 0x2883, 1);
1145 err_code = spca50x_setup_qtable(gspca_dev,
1146 0x00, 0x2800,
1147 0x2840,
1148 qtable_spca504_default);
1149 if (err_code < 0) {
1150 PDEBUG(D_ERR, "spca50x_setup_qtable failed");
1151 return err_code;
1152 }
1153 break;
1154 }
1155 return 0;
1156}
1157
1158static void sd_start(struct gspca_dev *gspca_dev)
1159{
1160 struct sd *sd = (struct sd *) gspca_dev;
1161 struct usb_device *dev = gspca_dev->dev;
1162 int rc;
1163 int enable;
1164 __u8 i;
1165 __u8 info[6];
1166
1167 if (sd->bridge == BRIDGE_SPCA504B)
1168 spca504B_setQtable(gspca_dev);
1169 spca504B_SetSizeType(gspca_dev);
1170 switch (sd->bridge) {
1171 default:
1172/* case BRIDGE_SPCA504B: */
1173/* case BRIDGE_SPCA533: */
1174/* case BRIDGE_SPCA536: */
1175 if (sd->subtype == MegapixV4 ||
1176 sd->subtype == LogitechClickSmart820) {
1177 reg_w(dev, 0xf0, 0, 0, NULL, 0);
1178 spca504B_WaitCmdStatus(gspca_dev);
1179 reg_r(dev, 0xf0, 4, NULL, 0);
1180 spca504B_WaitCmdStatus(gspca_dev);
1181 } else {
1182 reg_w(dev, 0x31, 0, 4, NULL, 0);
1183 spca504B_WaitCmdStatus(gspca_dev);
1184 rc = spca504B_PollingDataReady(gspca_dev);
1185 }
1186 break;
1187 case BRIDGE_SPCA504:
1188 if (sd->subtype == AiptekMiniPenCam13) {
1189 for (i = 0; i < 6; i++)
1190 info[i] = reg_r_1(gspca_dev, i);
1191 PDEBUG(D_STREAM,
1192 "Read info: %d %d %d %d %d %d."
1193 " Should be 1,0,2,2,0,0",
1194 info[0], info[1], info[2],
1195 info[3], info[4], info[5]);
1196 /* spca504a aiptek */
1197 /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
1198 spca504A_acknowledged_command(gspca_dev, 0x24,
1199 8, 3, 0x9e, 1);
1200 /* Twice sequencial need status 0xff->0x9e->0x9d */
1201 spca504A_acknowledged_command(gspca_dev, 0x24,
1202 8, 3, 0x9e, 0);
1203 spca504A_acknowledged_command(gspca_dev, 0x24,
1204 0, 0, 0x9d, 1);
1205 } else {
1206 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1207 for (i = 0; i < 6; i++)
1208 info[i] = reg_r_1(gspca_dev, i);
1209 PDEBUG(D_STREAM,
1210 "Read info: %d %d %d %d %d %d."
1211 " Should be 1,0,2,2,0,0",
1212 info[0], info[1], info[2],
1213 info[3], info[4], info[5]);
1214 spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
1215 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1216 }
1217 spca504B_SetSizeType(gspca_dev);
1218 reg_w_riv(dev, 0x0, 0x270c, 0x05); /* L92 sno1t.txt */
1219 reg_w_riv(dev, 0x0, 0x2310, 0x05);
1220 break;
1221 case BRIDGE_SPCA504C:
1222 if (sd->subtype == LogitechClickSmart420) {
1223 write_vector(gspca_dev,
1224 spca504A_clicksmart420_init_data);
1225 } else {
1226 write_vector(gspca_dev, spca504_pccam600_init_data);
1227 }
1228 enable = (sd->autogain ? 0x04 : 0x01);
1229 reg_w_riv(dev, 0x0c, 0x0000, enable); /* auto exposure */
1230 reg_w_riv(dev, 0xb0, 0x0000, enable); /* auto whiteness */
1231
1232 /* set default exposure compensation and whiteness balance */
1233 reg_w_riv(dev, 0x30, 0x0001, 800); /* ~ 20 fps */
1234 reg_w_riv(dev, 0x30, 0x0002, 1600);
1235 spca504B_SetSizeType(gspca_dev);
1236 break;
1237 }
1238 sp5xx_initContBrigHueRegisters(gspca_dev);
1239}
1240
1241static void sd_stopN(struct gspca_dev *gspca_dev)
1242{
1243 struct sd *sd = (struct sd *) gspca_dev;
1244 struct usb_device *dev = gspca_dev->dev;
1245
1246 switch (sd->bridge) {
1247 default:
1248/* case BRIDGE_SPCA533: */
1249/* case BRIDGE_SPCA536: */
1250/* case BRIDGE_SPCA504B: */
1251 reg_w(dev, 0x31, 0, 0, NULL, 0);
1252 spca504B_WaitCmdStatus(gspca_dev);
1253 spca504B_PollingDataReady(gspca_dev);
1254 break;
1255 case BRIDGE_SPCA504:
1256 case BRIDGE_SPCA504C:
1257 reg_w_riv(dev, 0x00, 0x2000, 0x0000);
1258
1259 if (sd->subtype == AiptekMiniPenCam13) {
1260 /* spca504a aiptek */
1261/* spca504A_acknowledged_command(gspca_dev, 0x08,
1262 6, 0, 0x86, 1); */
1263 spca504A_acknowledged_command(gspca_dev, 0x24,
1264 0x00, 0x00, 0x9d, 1);
1265 spca504A_acknowledged_command(gspca_dev, 0x01,
1266 0x0f, 0x00, 0xff, 1);
1267 } else {
1268 spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
1269 reg_w_riv(dev, 0x01, 0x000f, 0x00);
1270 }
1271 break;
1272 }
1273}
1274
1275static void sd_stop0(struct gspca_dev *gspca_dev)
1276{
1277}
1278
1279static void sd_close(struct gspca_dev *gspca_dev)
1280{
1281}
1282
1283static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1284 struct gspca_frame *frame, /* target */
1285 __u8 *data, /* isoc packet */
1286 int len) /* iso packet length */
1287{
1288 struct sd *sd = (struct sd *) gspca_dev;
1289 int i, sof = 0;
1290 unsigned char *s, *d;
1291 static unsigned char ffd9[] = {0xff, 0xd9};
1292
1293/* frames are jpeg 4.1.1 without 0xff escape */
1294 switch (sd->bridge) {
1295 case BRIDGE_SPCA533:
1296 if (data[0] == 0xff) {
1297 if (data[1] != 0x01) { /* drop packet */
1298/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1299 return;
1300 }
1301 sof = 1;
1302 data += SPCA533_OFFSET_DATA;
1303 len -= SPCA533_OFFSET_DATA;
1304 } else {
1305 data += 1;
1306 len -= 1;
1307 }
1308 break;
1309 case BRIDGE_SPCA536:
1310 if (data[0] == 0xff) {
1311 sof = 1;
1312 data += SPCA536_OFFSET_DATA;
1313 len -= SPCA536_OFFSET_DATA;
1314 } else {
1315 data += 2;
1316 len -= 2;
1317 }
1318 break;
1319 default:
1320/* case BRIDGE_SPCA504: */
1321/* case BRIDGE_SPCA504B: */
1322 switch (data[0]) {
1323 case 0xfe: /* start of frame */
1324 sof = 1;
1325 data += SPCA50X_OFFSET_DATA;
1326 len -= SPCA50X_OFFSET_DATA;
1327 break;
1328 case 0xff: /* drop packet */
1329/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1330 return;
1331 default:
1332 data += 1;
1333 len -= 1;
1334 break;
1335 }
1336 break;
1337 case BRIDGE_SPCA504C:
1338 switch (data[0]) {
1339 case 0xfe: /* start of frame */
1340 sof = 1;
1341 data += SPCA504_PCCAM600_OFFSET_DATA;
1342 len -= SPCA504_PCCAM600_OFFSET_DATA;
1343 break;
1344 case 0xff: /* drop packet */
1345/* gspca_dev->last_packet_type = DISCARD_PACKET; */
1346 return;
1347 default:
1348 data += 1;
1349 len -= 1;
1350 break;
1351 }
1352 break;
1353 }
1354 if (sof) { /* start of frame */
1355 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1356 ffd9, 2);
1357
1358 /* put the JPEG header in the new frame */
1359 jpeg_put_header(gspca_dev, frame,
1360 ((struct sd *) gspca_dev)->qindex,
1361 0x22);
1362 }
1363
1364 /* add 0x00 after 0xff */
1365 for (i = len; --i >= 0; )
1366 if (data[i] == 0xff)
1367 break;
1368 if (i < 0) { /* no 0xff */
1369 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1370 return;
1371 }
1372 s = data;
1373 d = sd->packet;
1374 for (i = 0; i < len; i++) {
1375 *d++ = *s++;
1376 if (s[-1] == 0xff)
1377 *d++ = 0x00;
1378 }
1379 gspca_frame_add(gspca_dev, INTER_PACKET, frame,
1380 sd->packet, d - sd->packet);
1381}
1382
1383static void setbrightness(struct gspca_dev *gspca_dev)
1384{
1385 struct sd *sd = (struct sd *) gspca_dev;
1386 struct usb_device *dev = gspca_dev->dev;
1387
1388 switch (sd->bridge) {
1389 default:
1390/* case BRIDGE_SPCA533: */
1391/* case BRIDGE_SPCA504B: */
1392/* case BRIDGE_SPCA504: */
1393/* case BRIDGE_SPCA504C: */
1394 reg_w_riv(dev, 0x0, 0x21a7, sd->brightness);
1395 break;
1396 case BRIDGE_SPCA536:
1397 reg_w_riv(dev, 0x0, 0x20f0, sd->brightness);
1398 break;
1399 }
1400}
1401
1402static void getbrightness(struct gspca_dev *gspca_dev)
1403{
1404 struct sd *sd = (struct sd *) gspca_dev;
1405 __u16 brightness = 0;
1406
1407 switch (sd->bridge) {
1408 default:
1409/* case BRIDGE_SPCA533: */
1410/* case BRIDGE_SPCA504B: */
1411/* case BRIDGE_SPCA504: */
1412/* case BRIDGE_SPCA504C: */
1413 brightness = reg_r_12(gspca_dev, 0x00, 0x21a7, 2);
1414 break;
1415 case BRIDGE_SPCA536:
1416 brightness = reg_r_12(gspca_dev, 0x00, 0x20f0, 2);
1417 break;
1418 }
1419 sd->brightness = ((brightness & 0xff) - 128) % 255;
1420}
1421
1422static void setcontrast(struct gspca_dev *gspca_dev)
1423{
1424 struct sd *sd = (struct sd *) gspca_dev;
1425 struct usb_device *dev = gspca_dev->dev;
1426
1427 switch (sd->bridge) {
1428 default:
1429/* case BRIDGE_SPCA533: */
1430/* case BRIDGE_SPCA504B: */
1431/* case BRIDGE_SPCA504: */
1432/* case BRIDGE_SPCA504C: */
1433 reg_w_riv(dev, 0x0, 0x21a8, sd->contrast);
1434 break;
1435 case BRIDGE_SPCA536:
1436 reg_w_riv(dev, 0x0, 0x20f1, sd->contrast);
1437 break;
1438 }
1439}
1440
1441static void getcontrast(struct gspca_dev *gspca_dev)
1442{
1443 struct sd *sd = (struct sd *) gspca_dev;
1444
1445 switch (sd->bridge) {
1446 default:
1447/* case BRIDGE_SPCA533: */
1448/* case BRIDGE_SPCA504B: */
1449/* case BRIDGE_SPCA504: */
1450/* case BRIDGE_SPCA504C: */
1451 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x21a8, 2);
1452 break;
1453 case BRIDGE_SPCA536:
1454 sd->contrast = reg_r_12(gspca_dev, 0x00, 0x20f1, 2);
1455 break;
1456 }
1457}
1458
1459static void setcolors(struct gspca_dev *gspca_dev)
1460{
1461 struct sd *sd = (struct sd *) gspca_dev;
1462 struct usb_device *dev = gspca_dev->dev;
1463
1464 switch (sd->bridge) {
1465 default:
1466/* case BRIDGE_SPCA533: */
1467/* case BRIDGE_SPCA504B: */
1468/* case BRIDGE_SPCA504: */
1469/* case BRIDGE_SPCA504C: */
1470 reg_w_riv(dev, 0x0, 0x21ae, sd->colors);
1471 break;
1472 case BRIDGE_SPCA536:
1473 reg_w_riv(dev, 0x0, 0x20f6, sd->colors);
1474 break;
1475 }
1476}
1477
1478static void getcolors(struct gspca_dev *gspca_dev)
1479{
1480 struct sd *sd = (struct sd *) gspca_dev;
1481
1482 switch (sd->bridge) {
1483 default:
1484/* case BRIDGE_SPCA533: */
1485/* case BRIDGE_SPCA504B: */
1486/* case BRIDGE_SPCA504: */
1487/* case BRIDGE_SPCA504C: */
1488 sd->colors = reg_r_12(gspca_dev, 0x00, 0x21ae, 2) >> 1;
1489 break;
1490 case BRIDGE_SPCA536:
1491 sd->colors = reg_r_12(gspca_dev, 0x00, 0x20f6, 2) >> 1;
1492 break;
1493 }
1494}
1495
1496static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
1497{
1498 struct sd *sd = (struct sd *) gspca_dev;
1499
1500 sd->brightness = val;
1501 if (gspca_dev->streaming)
1502 setbrightness(gspca_dev);
1503 return 0;
1504}
1505
1506static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
1507{
1508 struct sd *sd = (struct sd *) gspca_dev;
1509
1510 getbrightness(gspca_dev);
1511 *val = sd->brightness;
1512 return 0;
1513}
1514
1515static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
1516{
1517 struct sd *sd = (struct sd *) gspca_dev;
1518
1519 sd->contrast = val;
1520 if (gspca_dev->streaming)
1521 setcontrast(gspca_dev);
1522 return 0;
1523}
1524
1525static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528
1529 getcontrast(gspca_dev);
1530 *val = sd->contrast;
1531 return 0;
1532}
1533
1534static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
1535{
1536 struct sd *sd = (struct sd *) gspca_dev;
1537
1538 sd->colors = val;
1539 if (gspca_dev->streaming)
1540 setcolors(gspca_dev);
1541 return 0;
1542}
1543
1544static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
1545{
1546 struct sd *sd = (struct sd *) gspca_dev;
1547
1548 getcolors(gspca_dev);
1549 *val = sd->colors;
1550 return 0;
1551}
1552
1553static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1554{
1555 struct sd *sd = (struct sd *) gspca_dev;
1556
1557 sd->autogain = val;
1558 return 0;
1559}
1560
1561static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1562{
1563 struct sd *sd = (struct sd *) gspca_dev;
1564
1565 *val = sd->autogain;
1566 return 0;
1567}
1568
1569/* sub-driver description */
1570static const struct sd_desc sd_desc = {
1571 .name = MODULE_NAME,
1572 .ctrls = sd_ctrls,
1573 .nctrls = ARRAY_SIZE(sd_ctrls),
1574 .config = sd_config,
1575 .open = sd_open,
1576 .start = sd_start,
1577 .stopN = sd_stopN,
1578 .stop0 = sd_stop0,
1579 .close = sd_close,
1580 .pkt_scan = sd_pkt_scan,
1581};
1582
1583/* -- module initialisation -- */
1584#define DVNM(name) .driver_info = (kernel_ulong_t) name
1585static const __devinitdata struct usb_device_id device_table[] = {
1586 {USB_DEVICE(0x041e, 0x400b), DVNM("Creative PC-CAM 600")},
1587 {USB_DEVICE(0x041e, 0x4012), DVNM("PC-Cam350")},
1588 {USB_DEVICE(0x041e, 0x4013), DVNM("Creative Pccam750")},
1589 {USB_DEVICE(0x0458, 0x7006), DVNM("Genius Dsc 1.3 Smart")},
1590 {USB_DEVICE(0x0461, 0x0821), DVNM("Fujifilm MV-1")},
1591 {USB_DEVICE(0x046d, 0x0905), DVNM("Logitech ClickSmart 820")},
1592 {USB_DEVICE(0x046d, 0x0960), DVNM("Logitech ClickSmart 420")},
1593 {USB_DEVICE(0x0471, 0x0322), DVNM("Philips DMVC1300K")},
1594 {USB_DEVICE(0x04a5, 0x3003), DVNM("Benq DC 1300")},
1595 {USB_DEVICE(0x04a5, 0x3008), DVNM("Benq DC 1500")},
1596 {USB_DEVICE(0x04a5, 0x300a), DVNM("Benq DC3410")},
1597 {USB_DEVICE(0x04f1, 0x1001), DVNM("JVC GC A50")},
1598 {USB_DEVICE(0x04fc, 0x500c), DVNM("Sunplus CA500C")},
1599 {USB_DEVICE(0x04fc, 0x504a), DVNM("Aiptek Mini PenCam 1.3")},
1600 {USB_DEVICE(0x04fc, 0x504b), DVNM("Maxell MaxPocket LE 1.3")},
1601 {USB_DEVICE(0x04fc, 0x5330), DVNM("Digitrex 2110")},
1602 {USB_DEVICE(0x04fc, 0x5360), DVNM("Sunplus Generic")},
1603 {USB_DEVICE(0x04fc, 0xffff), DVNM("Pure DigitalDakota")},
1604 {USB_DEVICE(0x052b, 0x1513), DVNM("Megapix V4")},
1605 {USB_DEVICE(0x0546, 0x3155), DVNM("Polaroid PDC3070")},
1606 {USB_DEVICE(0x0546, 0x3191), DVNM("Polaroid Ion 80")},
1607 {USB_DEVICE(0x0546, 0x3273), DVNM("Polaroid PDC2030")},
1608 {USB_DEVICE(0x055f, 0xc211), DVNM("Kowa Bs888e Microcamera")},
1609 {USB_DEVICE(0x055f, 0xc230), DVNM("Mustek Digicam 330K")},
1610 {USB_DEVICE(0x055f, 0xc232), DVNM("Mustek MDC3500")},
1611 {USB_DEVICE(0x055f, 0xc360), DVNM("Mustek DV4000 Mpeg4 ")},
1612 {USB_DEVICE(0x055f, 0xc420), DVNM("Mustek gSmart Mini 2")},
1613 {USB_DEVICE(0x055f, 0xc430), DVNM("Mustek Gsmart LCD 2")},
1614 {USB_DEVICE(0x055f, 0xc440), DVNM("Mustek DV 3000")},
1615 {USB_DEVICE(0x055f, 0xc520), DVNM("Mustek gSmart Mini 3")},
1616 {USB_DEVICE(0x055f, 0xc530), DVNM("Mustek Gsmart LCD 3")},
1617 {USB_DEVICE(0x055f, 0xc540), DVNM("Gsmart D30")},
1618 {USB_DEVICE(0x055f, 0xc630), DVNM("Mustek MDC4000")},
1619 {USB_DEVICE(0x055f, 0xc650), DVNM("Mustek MDC5500Z")},
1620 {USB_DEVICE(0x05da, 0x1018), DVNM("Digital Dream Enigma 1.3")},
1621 {USB_DEVICE(0x06d6, 0x0031), DVNM("Trust 610 LCD PowerC@m Zoom")},
1622 {USB_DEVICE(0x0733, 0x1311), DVNM("Digital Dream Epsilon 1.3")},
1623 {USB_DEVICE(0x0733, 0x1314), DVNM("Mercury 2.1MEG Deluxe Classic Cam")},
1624 {USB_DEVICE(0x0733, 0x2211), DVNM("Jenoptik jdc 21 LCD")},
1625 {USB_DEVICE(0x0733, 0x2221), DVNM("Mercury Digital Pro 3.1p")},
1626 {USB_DEVICE(0x0733, 0x3261), DVNM("Concord 3045 spca536a")},
1627 {USB_DEVICE(0x0733, 0x3281), DVNM("Cyberpix S550V")},
1628 {USB_DEVICE(0x08ca, 0x0104), DVNM("Aiptek PocketDVII 1.3")},
1629 {USB_DEVICE(0x08ca, 0x0106), DVNM("Aiptek Pocket DV3100+")},
1630 {USB_DEVICE(0x08ca, 0x2008), DVNM("Aiptek Mini PenCam 2 M")},
1631 {USB_DEVICE(0x08ca, 0x2010), DVNM("Aiptek PocketCam 3M")},
1632 {USB_DEVICE(0x08ca, 0x2016), DVNM("Aiptek PocketCam 2 Mega")},
1633 {USB_DEVICE(0x08ca, 0x2018), DVNM("Aiptek Pencam SD 2M")},
1634 {USB_DEVICE(0x08ca, 0x2020), DVNM("Aiptek Slim 3000F")},
1635 {USB_DEVICE(0x08ca, 0x2022), DVNM("Aiptek Slim 3200")},
1636 {USB_DEVICE(0x08ca, 0x2024), DVNM("Aiptek DV3500 Mpeg4 ")},
1637 {USB_DEVICE(0x08ca, 0x2028), DVNM("Aiptek PocketCam4M")},
1638 {USB_DEVICE(0x08ca, 0x2040), DVNM("Aiptek PocketDV4100M")},
1639 {USB_DEVICE(0x08ca, 0x2042), DVNM("Aiptek PocketDV5100")},
1640 {USB_DEVICE(0x08ca, 0x2050), DVNM("Medion MD 41437")},
1641 {USB_DEVICE(0x08ca, 0x2060), DVNM("Aiptek PocketDV5300")},
1642 {USB_DEVICE(0x0d64, 0x0303), DVNM("Sunplus FashionCam DXG")},
1643 {}
1644};
1645MODULE_DEVICE_TABLE(usb, device_table);
1646
1647/* -- device connect -- */
1648static int sd_probe(struct usb_interface *intf,
1649 const struct usb_device_id *id)
1650{
1651 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1652 THIS_MODULE);
1653}
1654
1655static struct usb_driver sd_driver = {
1656 .name = MODULE_NAME,
1657 .id_table = device_table,
1658 .probe = sd_probe,
1659 .disconnect = gspca_disconnect,
1660};
1661
1662/* -- module insert / remove -- */
1663static int __init sd_mod_init(void)
1664{
1665 if (usb_register(&sd_driver) < 0)
1666 return -1;
1667 PDEBUG(D_PROBE, "v%s registered", version);
1668 return 0;
1669}
1670static void __exit sd_mod_exit(void)
1671{
1672 usb_deregister(&sd_driver);
1673 PDEBUG(D_PROBE, "deregistered");
1674}
1675
1676module_init(sd_mod_init);
1677module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
new file mode 100644
index 000000000000..00f47e463a05
--- /dev/null
+++ b/drivers/media/video/gspca/t613.c
@@ -0,0 +1,1038 @@
1/*
2 *Notes: * t613 + tas5130A
3 * * Focus to light do not balance well as in win.
4 * Quality in win is not good, but its kinda better.
5 * * Fix some "extraneous bytes", most of apps will show the image anyway
6 * * Gamma table, is there, but its really doing something?
7 * * 7~8 Fps, its ok, max on win its 10.
8 * Costantino Leandro
9 *
10 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27#define MODULE_NAME "t613"
28#include "gspca.h"
29#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
30static const char version[] = "2.1.7";
31
32#define MAX_GAMMA 0x10 /* 0 to 15 */
33
34/* From LUVCVIEW */
35#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
36
37MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
38MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
39MODULE_LICENSE("GPL");
40
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 unsigned char brightness;
45 unsigned char contrast;
46 unsigned char colors;
47 unsigned char autogain;
48 unsigned char gamma;
49 unsigned char sharpness;
50 unsigned char freq;
51 unsigned char whitebalance;
52 unsigned char mirror;
53 unsigned char effect;
54};
55
56/* V4L2 controls supported by the driver */
57static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
59static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
60static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
61static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
62static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
63static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
64static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
65static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
66static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
67static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
68static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
69static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
70static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
71static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
72static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
73static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
74static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
75static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
76static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
77static int sd_querymenu(struct gspca_dev *gspca_dev,
78 struct v4l2_querymenu *menu);
79
80static struct ctrl sd_ctrls[] = {
81#define SD_BRIGHTNESS 0
82 {
83 {
84 .id = V4L2_CID_BRIGHTNESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Brightness",
87 .minimum = 0,
88 .maximum = 0x0f,
89 .step = 1,
90 .default_value = 0x09,
91 },
92 .set = sd_setbrightness,
93 .get = sd_getbrightness,
94 },
95#define SD_CONTRAST 1
96 {
97 {
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0x0d,
103 .step = 1,
104 .default_value = 0x07,
105 },
106 .set = sd_setcontrast,
107 .get = sd_getcontrast,
108 },
109#define SD_COLOR 2
110 {
111 {
112 .id = V4L2_CID_SATURATION,
113 .type = V4L2_CTRL_TYPE_INTEGER,
114 .name = "Color",
115 .minimum = 0,
116 .maximum = 0x0f,
117 .step = 1,
118 .default_value = 0x05,
119 },
120 .set = sd_setcolors,
121 .get = sd_getcolors,
122 },
123#define SD_GAMMA 3
124 {
125 {
126 .id = V4L2_CID_GAMMA, /* (gamma on win) */
127 .type = V4L2_CTRL_TYPE_INTEGER,
128 .name = "Gamma (Untested)",
129 .minimum = 0,
130 .maximum = MAX_GAMMA,
131 .step = 1,
132 .default_value = 0x09,
133 },
134 .set = sd_setgamma,
135 .get = sd_getgamma,
136 },
137#define SD_AUTOGAIN 4
138 {
139 {
140 .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
141 * some apps dont bring up the
142 * backligth_compensation control) */
143 .type = V4L2_CTRL_TYPE_INTEGER,
144 .name = "Low Light",
145 .minimum = 0,
146 .maximum = 1,
147 .step = 1,
148 .default_value = 0x01,
149 },
150 .set = sd_setlowlight,
151 .get = sd_getlowlight,
152 },
153#define SD_MIRROR 5
154 {
155 {
156 .id = V4L2_CID_HFLIP,
157 .type = V4L2_CTRL_TYPE_BOOLEAN,
158 .name = "Mirror Image",
159 .minimum = 0,
160 .maximum = 1,
161 .step = 1,
162 .default_value = 0,
163 },
164 .set = sd_setflip,
165 .get = sd_getflip
166 },
167#define SD_LIGHTFREQ 6
168 {
169 {
170 .id = V4L2_CID_POWER_LINE_FREQUENCY,
171 .type = V4L2_CTRL_TYPE_MENU,
172 .name = "Light Frequency Filter",
173 .minimum = 1, /* 1 -> 0x50, 2->0x60 */
174 .maximum = 2,
175 .step = 1,
176 .default_value = 1,
177 },
178 .set = sd_setfreq,
179 .get = sd_getfreq},
180
181#define SD_WHITE_BALANCE 7
182 {
183 {
184 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
185 .type = V4L2_CTRL_TYPE_INTEGER,
186 .name = "White Balance",
187 .minimum = 0,
188 .maximum = 1,
189 .step = 1,
190 .default_value = 1,
191 },
192 .set = sd_setwhitebalance,
193 .get = sd_getwhitebalance
194 },
195#define SD_SHARPNESS 8 /* (aka definition on win) */
196 {
197 {
198 .id = V4L2_CID_SHARPNESS,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Sharpness",
201 .minimum = 0,
202 .maximum = MAX_GAMMA, /* 0 to 16 */
203 .step = 1,
204 .default_value = 0x06,
205 },
206 .set = sd_setsharpness,
207 .get = sd_getsharpness,
208 },
209#define SD_EFFECTS 9
210 {
211 {
212 .id = V4L2_CID_EFFECTS,
213 .type = V4L2_CTRL_TYPE_MENU,
214 .name = "Webcam Effects",
215 .minimum = 0,
216 .maximum = 4,
217 .step = 1,
218 .default_value = 0,
219 },
220 .set = sd_seteffect,
221 .get = sd_geteffect
222 },
223};
224
225static char *effects_control[] = {
226 "Normal",
227 "Emboss", /* disabled */
228 "Monochrome",
229 "Sepia",
230 "Sketch",
231 "Sun Effect", /* disabled */
232 "Negative",
233};
234
235static struct v4l2_pix_format vga_mode_t16[] = {
236 {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
237 .bytesperline = 160,
238 .sizeimage = 160 * 120 * 3 / 8 + 590,
239 .colorspace = V4L2_COLORSPACE_JPEG,
240 .priv = 4},
241 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
242 .bytesperline = 176,
243 .sizeimage = 176 * 144 * 3 / 8 + 590,
244 .colorspace = V4L2_COLORSPACE_JPEG,
245 .priv = 3},
246 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
247 .bytesperline = 320,
248 .sizeimage = 320 * 240 * 3 / 8 + 590,
249 .colorspace = V4L2_COLORSPACE_JPEG,
250 .priv = 2},
251 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
252 .bytesperline = 352,
253 .sizeimage = 352 * 288 * 3 / 8 + 590,
254 .colorspace = V4L2_COLORSPACE_JPEG,
255 .priv = 1},
256 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
257 .bytesperline = 640,
258 .sizeimage = 640 * 480 * 3 / 8 + 590,
259 .colorspace = V4L2_COLORSPACE_JPEG,
260 .priv = 0},
261};
262
263#define T16_OFFSET_DATA 631
264#define MAX_EFFECTS 7
265/* easily done by soft, this table could be removed,
266 * i keep it here just in case */
267static const __u8 effects_table[MAX_EFFECTS][6] = {
268 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
269 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
270 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
271 {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
272 {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
273 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
274 {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
275};
276
277static const __u8 gamma_table[MAX_GAMMA][34] = {
278 {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
279 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
280 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
281 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
282 0xa0, 0xff},
283 {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
284 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
285 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
286 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
287 0xa0, 0xff},
288 {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
289 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
290 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
291 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
292 0xa0, 0xff},
293 {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
294 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
295 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
296 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
297 0xa0, 0xff},
298 {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
299 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
300 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
301 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
302 0xa0, 0xff},
303 {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
304 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
305 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
306 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
307 0xa0, 0xff},
308 {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
309 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
310 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
311 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
312 0xa0, 0xff},
313 {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
314 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
315 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
316 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
317 0xa0, 0xff},
318 {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
319 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
320 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
321 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
322 0xa0, 0xff},
323 {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
324 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
325 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
326 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
327 0xa0, 0xff},
328 {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
329 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
330 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
331 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
332 0xa0, 0xff},
333 {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
334 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
335 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
336 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
337 0xa0, 0xff},
338 {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
339 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
340 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
341 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
342 0xA0, 0xFF},
343 {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
344 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
345 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
346 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
347 0xa0, 0xff},
348 {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
349 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
350 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
351 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
352 0xa0, 0xff},
353 {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
354 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
355 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
356 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
357 0xA0, 0xFF}
358};
359
360static const __u8 tas5130a_sensor_init[][8] = {
361 {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
362 {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
363 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
364 {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
365 {},
366};
367
368/* read 1 byte */
369static int reg_r_1(struct gspca_dev *gspca_dev,
370 __u16 index)
371{
372 usb_control_msg(gspca_dev->dev,
373 usb_rcvctrlpipe(gspca_dev->dev, 0),
374 0, /* request */
375 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
376 0, /* value */
377 index,
378 gspca_dev->usb_buf, 1, 500);
379 return gspca_dev->usb_buf[0];
380}
381
382static void reg_w(struct gspca_dev *gspca_dev,
383 __u16 value,
384 __u16 index,
385 const __u8 *buffer, __u16 len)
386{
387 if (buffer == NULL) {
388 usb_control_msg(gspca_dev->dev,
389 usb_sndctrlpipe(gspca_dev->dev, 0),
390 0,
391 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
392 value, index,
393 NULL, 0, 500);
394 return;
395 }
396 if (len <= sizeof gspca_dev->usb_buf) {
397 memcpy(gspca_dev->usb_buf, buffer, len);
398 usb_control_msg(gspca_dev->dev,
399 usb_sndctrlpipe(gspca_dev->dev, 0),
400 0,
401 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
402 value, index,
403 gspca_dev->usb_buf, len, 500);
404 } else {
405 __u8 *tmpbuf;
406
407 tmpbuf = kmalloc(len, GFP_KERNEL);
408 memcpy(tmpbuf, buffer, len);
409 usb_control_msg(gspca_dev->dev,
410 usb_sndctrlpipe(gspca_dev->dev, 0),
411 0,
412 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
413 value, index,
414 tmpbuf, len, 500);
415 kfree(tmpbuf);
416 }
417}
418
419/* this function is called at probe time */
420static int sd_config(struct gspca_dev *gspca_dev,
421 const struct usb_device_id *id)
422{
423 struct sd *sd = (struct sd *) gspca_dev;
424 struct cam *cam;
425
426 cam = &gspca_dev->cam;
427 cam->dev_name = (char *) id->driver_info;
428 cam->epaddr = 0x01;
429
430 cam->cam_mode = vga_mode_t16;
431 cam->nmodes = ARRAY_SIZE(vga_mode_t16);
432
433 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
434 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
435 sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
436 sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
437 sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
438 sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
439 sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
440 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
441 sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
442 return 0;
443}
444
445static int init_default_parameters(struct gspca_dev *gspca_dev)
446{
447 /* some of this registers are not really neded, because
448 * they are overriden by setbrigthness, setcontrast, etc,
449 * but wont hurt anyway, and can help someone with similar webcam
450 * to see the initial parameters.*/
451 int i = 0;
452 __u8 test_byte;
453
454 static const __u8 read_indexs[] =
455 { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
456 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
457 static const __u8 n1[6] =
458 {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
459 static const __u8 n2[2] =
460 {0x08, 0x00};
461 static const __u8 nset[6] =
462 { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
463 static const __u8 n3[6] =
464 {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
465 static const __u8 n4[0x46] =
466 {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
467 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
468 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
469 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
470 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
471 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
472 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
473 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
474 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
475 static const __u8 nset4[18] = {
476 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
477 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
478 0xe8, 0xe0
479 };
480 /* ojo puede ser 0xe6 en vez de 0xe9 */
481 static const __u8 nset2[20] = {
482 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
483 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
484 0xd8, 0xc8, 0xd9, 0xfc
485 };
486 static const __u8 missing[8] =
487 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
488 static const __u8 nset3[18] = {
489 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
490 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
491 0xcf, 0xe0
492 };
493 static const __u8 nset5[4] =
494 { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
495 static const __u8 nset6[34] = {
496 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
497 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
498 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
499 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
500 0xa0, 0xff
501 }; /* Gamma */
502 static const __u8 nset7[4] =
503 { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
504 static const __u8 nset9[4] =
505 { 0x0b, 0x04, 0x0a, 0x78 };
506 static const __u8 nset8[6] =
507 { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
508 static const __u8 nset10[6] =
509 { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
510
511 reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
512 reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
513 reg_r_1(gspca_dev, 0x0063);
514 reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
515
516 while (read_indexs[i] != 0x00) {
517 test_byte = reg_r_1(gspca_dev, read_indexs[i]);
518 PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
519 test_byte);
520 i++;
521 }
522
523 reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
524 reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
525 reg_r_1(gspca_dev, 0x0080);
526 reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
527 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
528 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
529 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
530 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
531 reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
532 reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
533 reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
534 reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
535 reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
536 reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
537 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
538
539 reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
540
541 reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
542 reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
543 reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
544
545 reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
546 reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
547 reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
548 reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
549
550 reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
551 reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
552 reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
553 reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
554
555 return 0;
556}
557
558static void setbrightness(struct gspca_dev *gspca_dev)
559{
560 struct sd *sd = (struct sd *) gspca_dev;
561 unsigned int brightness;
562 __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
563 brightness = sd->brightness;
564
565 if (brightness < 7) {
566 set6[3] = 0x70 - (brightness * 0xa);
567 } else {
568 set6[1] = 0x24;
569 set6[3] = 0x00 + ((brightness - 7) * 0xa);
570 }
571
572 reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
573}
574
575static void setflip(struct gspca_dev *gspca_dev)
576{
577 struct sd *sd = (struct sd *) gspca_dev;
578
579 __u8 flipcmd[8] =
580 { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
581
582 if (sd->mirror == 1)
583 flipcmd[3] = 0x01;
584
585 reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
586}
587
588static void seteffect(struct gspca_dev *gspca_dev)
589{
590 struct sd *sd = (struct sd *) gspca_dev;
591
592 reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
593 if (sd->effect == 1 || sd->effect == 5) {
594 PDEBUG(D_CONF,
595 "This effect have been disabled for webcam \"safety\"");
596 return;
597 }
598
599 if (sd->effect == 1 || sd->effect == 4)
600 reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
601 else
602 reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
603}
604
605static void setwhitebalance(struct gspca_dev *gspca_dev)
606{
607 struct sd *sd = (struct sd *) gspca_dev;
608
609 __u8 white_balance[8] =
610 { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
611
612 if (sd->whitebalance == 1)
613 white_balance[7] = 0x3c;
614
615 reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
616}
617
618static void setlightfreq(struct gspca_dev *gspca_dev)
619{
620 struct sd *sd = (struct sd *) gspca_dev;
621 __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
622
623 if (sd->freq == 2) /* 60hz */
624 freq[1] = 0x00;
625
626 reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
627}
628
629static void setcontrast(struct gspca_dev *gspca_dev)
630{
631 struct sd *sd = (struct sd *) gspca_dev;
632 unsigned int contrast = sd->contrast;
633 __u16 reg_to_write = 0x00;
634
635 if (contrast < 7)
636 reg_to_write = 0x8ea9 - (0x200 * contrast);
637 else
638 reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
639
640 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
641}
642
643static void setcolors(struct gspca_dev *gspca_dev)
644{
645 struct sd *sd = (struct sd *) gspca_dev;
646 __u16 reg_to_write;
647
648 reg_to_write = 0xc0bb + sd->colors * 0x100;
649 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
650}
651
652static void setgamma(struct gspca_dev *gspca_dev)
653{
654}
655
656static void setsharpness(struct gspca_dev *gspca_dev)
657{
658 struct sd *sd = (struct sd *) gspca_dev;
659 __u16 reg_to_write;
660
661 reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
662
663 reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
664}
665
666static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
667{
668 struct sd *sd = (struct sd *) gspca_dev;
669
670 sd->brightness = val;
671 if (gspca_dev->streaming)
672 setbrightness(gspca_dev);
673 return 0;
674}
675
676static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
677{
678 struct sd *sd = (struct sd *) gspca_dev;
679
680 *val = sd->brightness;
681 return *val;
682}
683
684static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
685{
686 struct sd *sd = (struct sd *) gspca_dev;
687
688 sd->whitebalance = val;
689 if (gspca_dev->streaming)
690 setwhitebalance(gspca_dev);
691 return 0;
692}
693
694static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
695{
696 struct sd *sd = (struct sd *) gspca_dev;
697
698 *val = sd->whitebalance;
699 return *val;
700}
701
702static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
703{
704 struct sd *sd = (struct sd *) gspca_dev;
705
706 sd->mirror = val;
707 if (gspca_dev->streaming)
708 setflip(gspca_dev);
709 return 0;
710}
711
712static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
713{
714 struct sd *sd = (struct sd *) gspca_dev;
715
716 *val = sd->mirror;
717 return *val;
718}
719
720static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
721{
722 struct sd *sd = (struct sd *) gspca_dev;
723
724 sd->effect = val;
725 if (gspca_dev->streaming)
726 seteffect(gspca_dev);
727 return 0;
728}
729
730static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
731{
732 struct sd *sd = (struct sd *) gspca_dev;
733
734 *val = sd->effect;
735 return *val;
736}
737
738static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
739{
740 struct sd *sd = (struct sd *) gspca_dev;
741
742 sd->contrast = val;
743 if (gspca_dev->streaming)
744 setcontrast(gspca_dev);
745 return 0;
746}
747
748static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
749{
750 struct sd *sd = (struct sd *) gspca_dev;
751
752 *val = sd->contrast;
753 return *val;
754}
755
756static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
757{
758 struct sd *sd = (struct sd *) gspca_dev;
759
760 sd->colors = val;
761 if (gspca_dev->streaming)
762 setcolors(gspca_dev);
763 return 0;
764}
765
766static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
767{
768 struct sd *sd = (struct sd *) gspca_dev;
769
770 *val = sd->colors;
771 return 0;
772}
773
774static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
775{
776 struct sd *sd = (struct sd *) gspca_dev;
777
778 sd->gamma = val;
779 if (gspca_dev->streaming)
780 setgamma(gspca_dev);
781 return 0;
782}
783
784static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
785{
786 struct sd *sd = (struct sd *) gspca_dev;
787 *val = sd->gamma;
788 return 0;
789}
790
791static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
792{
793 struct sd *sd = (struct sd *) gspca_dev;
794
795 sd->freq = val;
796 if (gspca_dev->streaming)
797 setlightfreq(gspca_dev);
798 return 0;
799}
800
801static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
802{
803 struct sd *sd = (struct sd *) gspca_dev;
804
805 *val = sd->freq;
806 return 0;
807}
808
809static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
810{
811 struct sd *sd = (struct sd *) gspca_dev;
812
813 sd->sharpness = val;
814 if (gspca_dev->streaming)
815 setsharpness(gspca_dev);
816 return 0;
817}
818
819static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
820{
821 struct sd *sd = (struct sd *) gspca_dev;
822
823 *val = sd->sharpness;
824 return 0;
825}
826
827/* Low Light set here......*/
828static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
829{
830 struct sd *sd = (struct sd *) gspca_dev;
831
832 sd->autogain = val;
833 if (val != 0)
834 reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
835 else
836 reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
837 return 0;
838}
839
840static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
841{
842 struct sd *sd = (struct sd *) gspca_dev;
843
844 *val = sd->autogain;
845 return 0;
846}
847
848static void sd_start(struct gspca_dev *gspca_dev)
849{
850 int mode;
851
852 static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
853 __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
854 static const __u8 t3[] =
855 { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
856 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
857 static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
858
859 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
860 switch (mode) {
861 case 1: /* 352x288 */
862 t2[1] = 0x40;
863 break;
864 case 2: /* 320x240 */
865 t2[1] = 0x10;
866 break;
867 case 3: /* 176x144 */
868 t2[1] = 0x50;
869 break;
870 case 4: /* 160x120 */
871 t2[1] = 0x20;
872 break;
873 default: /* 640x480 (0x00) */
874 break;
875 }
876
877 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
878 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
879 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
880 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
881 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
882 /* just in case and to keep sync with logs (for mine) */
883 reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
884 reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
885 /* just in case and to keep sync with logs (for mine) */
886 reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
887 reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
888 reg_r_1(gspca_dev, 0x0012);
889 reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
890 reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
891 reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
892 /* restart on each start, just in case, sometimes regs goes wrong
893 * when using controls from app */
894 setbrightness(gspca_dev);
895 setcontrast(gspca_dev);
896 setcolors(gspca_dev);
897}
898
899static void sd_stopN(struct gspca_dev *gspca_dev)
900{
901}
902
903static void sd_stop0(struct gspca_dev *gspca_dev)
904{
905}
906
907static void sd_close(struct gspca_dev *gspca_dev)
908{
909}
910
911static void sd_pkt_scan(struct gspca_dev *gspca_dev,
912 struct gspca_frame *frame, /* target */
913 __u8 *data, /* isoc packet */
914 int len) /* iso packet length */
915{
916 int sof = 0;
917 static __u8 ffd9[] = { 0xff, 0xd9 };
918
919 if (data[0] == 0x5a) {
920 /* Control Packet, after this came the header again,
921 * but extra bytes came in the packet before this,
922 * sometimes an EOF arrives, sometimes not... */
923 return;
924 }
925
926 if (data[len - 1] == 0xff && data[len] == 0xd9) {
927 /* Just in case, i have seen packets with the marker,
928 * other's do not include it... */
929 data += 2;
930 len -= 4;
931 } else if (data[2] == 0xff && data[3] == 0xd8) {
932 sof = 1;
933 data += 2;
934 len -= 2;
935 } else {
936 data += 2;
937 len -= 2;
938 }
939
940 if (sof) {
941 /* extra bytes....., could be processed too but would be
942 * a waste of time, right now leave the application and
943 * libjpeg do it for ourserlves.. */
944 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
945 ffd9, 2);
946 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
947 return;
948 }
949
950 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
951}
952
953static int sd_querymenu(struct gspca_dev *gspca_dev,
954 struct v4l2_querymenu *menu)
955{
956 switch (menu->id) {
957 case V4L2_CID_POWER_LINE_FREQUENCY:
958 switch (menu->index) {
959 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
960 strcpy((char *) menu->name, "50 Hz");
961 return 0;
962 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
963 strcpy((char *) menu->name, "60 Hz");
964 return 0;
965 }
966 break;
967 case V4L2_CID_EFFECTS:
968 if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
969 strncpy((char *) menu->name,
970 effects_control[menu->index], 32);
971 return 0;
972 }
973 break;
974 }
975 return -EINVAL;
976}
977
978/* this function is called at open time */
979static int sd_open(struct gspca_dev *gspca_dev)
980{
981 init_default_parameters(gspca_dev);
982 return 0;
983}
984
985/* sub-driver description */
986static const struct sd_desc sd_desc = {
987 .name = MODULE_NAME,
988 .ctrls = sd_ctrls,
989 .nctrls = ARRAY_SIZE(sd_ctrls),
990 .config = sd_config,
991 .open = sd_open,
992 .start = sd_start,
993 .stopN = sd_stopN,
994 .stop0 = sd_stop0,
995 .close = sd_close,
996 .pkt_scan = sd_pkt_scan,
997 .querymenu = sd_querymenu,
998};
999
1000/* -- module initialisation -- */
1001#define DVNM(name) .driver_info = (kernel_ulong_t) name
1002static const __devinitdata struct usb_device_id device_table[] = {
1003 {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
1004 {}
1005};
1006MODULE_DEVICE_TABLE(usb, device_table);
1007
1008/* -- device connect -- */
1009static int sd_probe(struct usb_interface *intf,
1010 const struct usb_device_id *id)
1011{
1012 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1013 THIS_MODULE);
1014}
1015
1016static struct usb_driver sd_driver = {
1017 .name = MODULE_NAME,
1018 .id_table = device_table,
1019 .probe = sd_probe,
1020 .disconnect = gspca_disconnect,
1021};
1022
1023/* -- module insert / remove -- */
1024static int __init sd_mod_init(void)
1025{
1026 if (usb_register(&sd_driver) < 0)
1027 return -1;
1028 PDEBUG(D_PROBE, "v%s registered", version);
1029 return 0;
1030}
1031static void __exit sd_mod_exit(void)
1032{
1033 usb_deregister(&sd_driver);
1034 PDEBUG(D_PROBE, "deregistered");
1035}
1036
1037module_init(sd_mod_init);
1038module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
new file mode 100644
index 000000000000..0b793899095f
--- /dev/null
+++ b/drivers/media/video/gspca/tv8532.c
@@ -0,0 +1,670 @@
1/*
2 * Quickcam cameras initialization data
3 *
4 * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#define MODULE_NAME "tv8532"
22
23#include "gspca.h"
24
25#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
26static const char version[] = "2.1.7";
27
28MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
29MODULE_DESCRIPTION("TV8532 USB Camera Driver");
30MODULE_LICENSE("GPL");
31
32/* specific webcam descriptor */
33struct sd {
34 struct gspca_dev gspca_dev; /* !! must be the first item */
35
36 int buflen; /* current length of tmpbuf */
37 __u8 tmpbuf[352 * 288 + 10 * 288]; /* no protection... */
38 __u8 tmpbuf2[352 * 288]; /* no protection... */
39
40 unsigned short brightness;
41 unsigned short contrast;
42
43 char packet;
44 char synchro;
45};
46
47/* V4L2 controls supported by the driver */
48static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
49static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
50static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
51static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
52
53static struct ctrl sd_ctrls[] = {
54#define SD_BRIGHTNESS 0
55 {
56 {
57 .id = V4L2_CID_BRIGHTNESS,
58 .type = V4L2_CTRL_TYPE_INTEGER,
59 .name = "Brightness",
60 .minimum = 1,
61 .maximum = 0x2ff,
62 .step = 1,
63 .default_value = 0x18f,
64 },
65 .set = sd_setbrightness,
66 .get = sd_getbrightness,
67 },
68#define SD_CONTRAST 1
69 {
70 {
71 .id = V4L2_CID_CONTRAST,
72 .type = V4L2_CTRL_TYPE_INTEGER,
73 .name = "Contrast",
74 .minimum = 0,
75 .maximum = 0xffff,
76 .step = 1,
77 .default_value = 0x7fff,
78 },
79 .set = sd_setcontrast,
80 .get = sd_getcontrast,
81 },
82};
83
84static struct v4l2_pix_format sif_mode[] = {
85 {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
86 .bytesperline = 176,
87 .sizeimage = 176 * 144,
88 .colorspace = V4L2_COLORSPACE_SRGB,
89 .priv = 1},
90 {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
91 .bytesperline = 352,
92 .sizeimage = 352 * 288,
93 .colorspace = V4L2_COLORSPACE_SRGB,
94 .priv = 0},
95};
96
97/*
98 * Initialization data: this is the first set-up data written to the
99 * device (before the open data).
100 */
101#define TESTCLK 0x10 /* reg 0x2c -> 0x12 //10 */
102#define TESTCOMP 0x90 /* reg 0x28 -> 0x80 */
103#define TESTLINE 0x81 /* reg 0x29 -> 0x81 */
104#define QCIFLINE 0x41 /* reg 0x29 -> 0x81 */
105#define TESTPTL 0x14 /* reg 0x2D -> 0x14 */
106#define TESTPTH 0x01 /* reg 0x2E -> 0x01 */
107#define TESTPTBL 0x12 /* reg 0x2F -> 0x0a */
108#define TESTPTBH 0x01 /* reg 0x30 -> 0x01 */
109#define ADWIDTHL 0xe8 /* reg 0x0c -> 0xe8 */
110#define ADWIDTHH 0x03 /* reg 0x0d -> 0x03 */
111#define ADHEIGHL 0x90 /* reg 0x0e -> 0x91 //93 */
112#define ADHEIGHH 0x01 /* reg 0x0f -> 0x01 */
113#define EXPOL 0x8f /* reg 0x1c -> 0x8f */
114#define EXPOH 0x01 /* reg 0x1d -> 0x01 */
115#define ADCBEGINL 0x44 /* reg 0x10 -> 0x46 //47 */
116#define ADCBEGINH 0x00 /* reg 0x11 -> 0x00 */
117#define ADRBEGINL 0x0a /* reg 0x14 -> 0x0b //0x0c */
118#define ADRBEGINH 0x00 /* reg 0x15 -> 0x00 */
119#define TV8532_CMD_UPDATE 0x84
120
121#define TV8532_EEprom_Add 0x03
122#define TV8532_EEprom_DataL 0x04
123#define TV8532_EEprom_DataM 0x05
124#define TV8532_EEprom_DataH 0x06
125#define TV8532_EEprom_TableLength 0x07
126#define TV8532_EEprom_Write 0x08
127#define TV8532_PART_CTRL 0x00
128#define TV8532_CTRL 0x01
129#define TV8532_CMD_EEprom_Open 0x30
130#define TV8532_CMD_EEprom_Close 0x29
131#define TV8532_UDP_UPDATE 0x31
132#define TV8532_GPIO 0x39
133#define TV8532_GPIO_OE 0x3B
134#define TV8532_REQ_RegWrite 0x02
135#define TV8532_REQ_RegRead 0x03
136
137#define TV8532_ADWIDTH_L 0x0C
138#define TV8532_ADWIDTH_H 0x0D
139#define TV8532_ADHEIGHT_L 0x0E
140#define TV8532_ADHEIGHT_H 0x0F
141#define TV8532_EXPOSURE 0x1C
142#define TV8532_QUANT_COMP 0x28
143#define TV8532_MODE_PACKET 0x29
144#define TV8532_SETCLK 0x2C
145#define TV8532_POINT_L 0x2D
146#define TV8532_POINT_H 0x2E
147#define TV8532_POINTB_L 0x2F
148#define TV8532_POINTB_H 0x30
149#define TV8532_BUDGET_L 0x2A
150#define TV8532_BUDGET_H 0x2B
151#define TV8532_VID_L 0x34
152#define TV8532_VID_H 0x35
153#define TV8532_PID_L 0x36
154#define TV8532_PID_H 0x37
155#define TV8532_DeviceID 0x83
156#define TV8532_AD_SLOPE 0x91
157#define TV8532_AD_BITCTRL 0x94
158#define TV8532_AD_COLBEGIN_L 0x10
159#define TV8532_AD_COLBEGIN_H 0x11
160#define TV8532_AD_ROWBEGIN_L 0x14
161#define TV8532_AD_ROWBEGIN_H 0x15
162
163static const __u32 tv_8532_eeprom_data[] = {
164/* add dataL dataM dataH */
165 0x00010001, 0x01018011, 0x02050014, 0x0305001c,
166 0x040d001e, 0x0505001f, 0x06050519, 0x0705011b,
167 0x0805091e, 0x090d892e, 0x0a05892f, 0x0b050dd9,
168 0x0c0509f1, 0
169};
170
171static int reg_r(struct gspca_dev *gspca_dev,
172 __u16 index)
173{
174 usb_control_msg(gspca_dev->dev,
175 usb_rcvctrlpipe(gspca_dev->dev, 0),
176 TV8532_REQ_RegRead,
177 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
178 0, /* value */
179 index, gspca_dev->usb_buf, 1,
180 500);
181 return gspca_dev->usb_buf[0];
182}
183
184/* write 1 byte */
185static void reg_w_1(struct gspca_dev *gspca_dev,
186 __u16 index, __u8 value)
187{
188 gspca_dev->usb_buf[0] = value;
189 usb_control_msg(gspca_dev->dev,
190 usb_sndctrlpipe(gspca_dev->dev, 0),
191 TV8532_REQ_RegWrite,
192 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
193 0, /* value */
194 index, gspca_dev->usb_buf, 1, 500);
195}
196
197/* write 2 bytes */
198static void reg_w_2(struct gspca_dev *gspca_dev,
199 __u16 index, __u8 val1, __u8 val2)
200{
201 gspca_dev->usb_buf[0] = val1;
202 gspca_dev->usb_buf[1] = val2;
203 usb_control_msg(gspca_dev->dev,
204 usb_sndctrlpipe(gspca_dev->dev, 0),
205 TV8532_REQ_RegWrite,
206 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
207 0, /* value */
208 index, gspca_dev->usb_buf, 2, 500);
209}
210
211static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
212{
213 int i = 0;
214 __u8 reg, data0, data1, data2;
215
216 reg_w_1(gspca_dev, TV8532_GPIO, 0xb0);
217 reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Open);
218/* msleep(1); */
219 while (tv_8532_eeprom_data[i]) {
220 reg = (tv_8532_eeprom_data[i] & 0xff000000) >> 24;
221 reg_w_1(gspca_dev, TV8532_EEprom_Add, reg);
222 /* msleep(1); */
223 data0 = (tv_8532_eeprom_data[i] & 0x000000ff);
224 reg_w_1(gspca_dev, TV8532_EEprom_DataL, data0);
225 /* msleep(1); */
226 data1 = (tv_8532_eeprom_data[i] & 0x0000ff00) >> 8;
227 reg_w_1(gspca_dev, TV8532_EEprom_DataM, data1);
228 /* msleep(1); */
229 data2 = (tv_8532_eeprom_data[i] & 0x00ff0000) >> 16;
230 reg_w_1(gspca_dev, TV8532_EEprom_DataH, data2);
231 /* msleep(1); */
232 reg_w_1(gspca_dev, TV8532_EEprom_Write, 0);
233 /* msleep(10); */
234 i++;
235 }
236 reg_w_1(gspca_dev, TV8532_EEprom_TableLength, i);
237/* msleep(1); */
238 reg_w_1(gspca_dev, TV8532_CTRL, TV8532_CMD_EEprom_Close);
239 msleep(10);
240}
241
242/* this function is called at probe time */
243static int sd_config(struct gspca_dev *gspca_dev,
244 const struct usb_device_id *id)
245{
246 struct sd *sd = (struct sd *) gspca_dev;
247 struct cam *cam;
248
249 tv_8532WriteEEprom(gspca_dev);
250
251 cam = &gspca_dev->cam;
252 cam->dev_name = (char *) id->driver_info;
253 cam->epaddr = 1;
254 cam->cam_mode = sif_mode;
255 cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
256
257 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
258 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
259 return 0;
260}
261
262static void tv_8532ReadRegisters(struct gspca_dev *gspca_dev)
263{
264 __u8 data;
265
266 data = reg_r(gspca_dev, 0x0001);
267 PDEBUG(D_USBI, "register 0x01-> %x", data);
268 data = reg_r(gspca_dev, 0x0002);
269 PDEBUG(D_USBI, "register 0x02-> %x", data);
270 reg_r(gspca_dev, TV8532_ADWIDTH_L);
271 reg_r(gspca_dev, TV8532_ADWIDTH_H);
272 reg_r(gspca_dev, TV8532_QUANT_COMP);
273 reg_r(gspca_dev, TV8532_MODE_PACKET);
274 reg_r(gspca_dev, TV8532_SETCLK);
275 reg_r(gspca_dev, TV8532_POINT_L);
276 reg_r(gspca_dev, TV8532_POINT_H);
277 reg_r(gspca_dev, TV8532_POINTB_L);
278 reg_r(gspca_dev, TV8532_POINTB_H);
279 reg_r(gspca_dev, TV8532_BUDGET_L);
280 reg_r(gspca_dev, TV8532_BUDGET_H);
281 reg_r(gspca_dev, TV8532_VID_L);
282 reg_r(gspca_dev, TV8532_VID_H);
283 reg_r(gspca_dev, TV8532_PID_L);
284 reg_r(gspca_dev, TV8532_PID_H);
285 reg_r(gspca_dev, TV8532_DeviceID);
286 reg_r(gspca_dev, TV8532_AD_COLBEGIN_L);
287 reg_r(gspca_dev, TV8532_AD_COLBEGIN_H);
288 reg_r(gspca_dev, TV8532_AD_ROWBEGIN_L);
289 reg_r(gspca_dev, TV8532_AD_ROWBEGIN_H);
290}
291
292static void tv_8532_setReg(struct gspca_dev *gspca_dev)
293{
294 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
295 ADCBEGINL); /* 0x10 */
296 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
297 ADCBEGINH); /* also digital gain */
298 reg_w_1(gspca_dev, TV8532_PART_CTRL,
299 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
300
301 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0a);
302 /******************************************************/
303 reg_w_1(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL); /* 0e */
304 reg_w_1(gspca_dev, TV8532_ADHEIGHT_H, ADHEIGHH); /* 0f */
305 reg_w_2(gspca_dev, TV8532_EXPOSURE,
306 EXPOL, EXPOH); /* 350d 0x014c; 1c */
307 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_L,
308 ADCBEGINL); /* 0x10 */
309 reg_w_1(gspca_dev, TV8532_AD_COLBEGIN_H,
310 ADCBEGINH); /* also digital gain */
311 reg_w_1(gspca_dev, TV8532_AD_ROWBEGIN_L,
312 ADRBEGINL); /* 0x14 */
313
314 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */
315 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x02); /* 0x94 */
316
317 reg_w_1(gspca_dev, TV8532_CTRL,
318 TV8532_CMD_EEprom_Close); /* 0x01 */
319
320 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x00); /* 0x91 */
321 reg_w_1(gspca_dev, TV8532_PART_CTRL,
322 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
323}
324
325static void tv_8532_PollReg(struct gspca_dev *gspca_dev)
326{
327 int i;
328
329 /* strange polling from tgc */
330 for (i = 0; i < 10; i++) {
331 reg_w_1(gspca_dev, TV8532_SETCLK,
332 TESTCLK); /* 0x48; //0x08; 0x2c */
333 reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
334 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
335 }
336}
337
338/* this function is called at open time */
339static int sd_open(struct gspca_dev *gspca_dev)
340{
341 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
342 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
343 tv_8532ReadRegisters(gspca_dev);
344 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
345 reg_w_2(gspca_dev, TV8532_ADHEIGHT_L, ADHEIGHL,
346 ADHEIGHH); /* 401d 0x0169; 0e */
347 reg_w_2(gspca_dev, TV8532_EXPOSURE, EXPOL,
348 EXPOH); /* 350d 0x014c; 1c */
349 reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */
350 reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */
351
352 /*******************************************************************/
353 reg_w_1(gspca_dev, TV8532_QUANT_COMP,
354 TESTCOMP); /* 0x72 compressed mode 0x28 */
355 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
356 TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */
357
358 /************************************************/
359 reg_w_1(gspca_dev, TV8532_SETCLK,
360 TESTCLK); /* 0x48; //0x08; 0x2c */
361 reg_w_1(gspca_dev, TV8532_POINT_L,
362 TESTPTL); /* 0x38; 0x2d */
363 reg_w_1(gspca_dev, TV8532_POINT_H,
364 TESTPTH); /* 0x04; 0x2e */
365 reg_w_1(gspca_dev, TV8532_POINTB_L,
366 TESTPTBL); /* 0x04; 0x2f */
367 reg_w_1(gspca_dev, TV8532_POINTB_H,
368 TESTPTBH); /* 0x04; 0x30 */
369 reg_w_1(gspca_dev, TV8532_PART_CTRL,
370 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
371 /*************************************************/
372 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
373 msleep(200);
374 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
375 /*************************************************/
376 tv_8532_setReg(gspca_dev);
377 /*************************************************/
378 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
379 /*************************************************/
380 tv_8532_setReg(gspca_dev);
381 /*************************************************/
382 tv_8532_PollReg(gspca_dev);
383 return 0;
384}
385
386static void setbrightness(struct gspca_dev *gspca_dev)
387{
388 struct sd *sd = (struct sd *) gspca_dev;
389 int brightness = sd->brightness;
390
391 reg_w_2(gspca_dev, TV8532_EXPOSURE,
392 brightness >> 8, brightness); /* 1c */
393 reg_w_1(gspca_dev, TV8532_PART_CTRL, TV8532_CMD_UPDATE);
394}
395
396/* -- start the camera -- */
397static void sd_start(struct gspca_dev *gspca_dev)
398{
399 reg_w_1(gspca_dev, TV8532_AD_SLOPE, 0x32);
400 reg_w_1(gspca_dev, TV8532_AD_BITCTRL, 0x00);
401 tv_8532ReadRegisters(gspca_dev);
402 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
403 reg_w_2(gspca_dev, TV8532_ADHEIGHT_L,
404 ADHEIGHL, ADHEIGHH); /* 401d 0x0169; 0e */
405/* reg_w_2(gspca_dev, TV8532_EXPOSURE,
406 EXPOL, EXPOH); * 350d 0x014c; 1c */
407 setbrightness(gspca_dev);
408
409 reg_w_1(gspca_dev, TV8532_ADWIDTH_L, ADWIDTHL); /* 0x20; 0x0c */
410 reg_w_1(gspca_dev, TV8532_ADWIDTH_H, ADWIDTHH); /* 0x0d */
411
412 /************************************************/
413 reg_w_1(gspca_dev, TV8532_QUANT_COMP,
414 TESTCOMP); /* 0x72 compressed mode 0x28 */
415 if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
416 /* 176x144 */
417 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
418 QCIFLINE); /* 0x84; // CIF | 4 packet 0x29 */
419 } else {
420 /* 352x288 */
421 reg_w_1(gspca_dev, TV8532_MODE_PACKET,
422 TESTLINE); /* 0x84; // CIF | 4 packet 0x29 */
423 }
424 /************************************************/
425 reg_w_1(gspca_dev, TV8532_SETCLK,
426 TESTCLK); /* 0x48; //0x08; 0x2c */
427 reg_w_1(gspca_dev, TV8532_POINT_L,
428 TESTPTL); /* 0x38; 0x2d */
429 reg_w_1(gspca_dev, TV8532_POINT_H,
430 TESTPTH); /* 0x04; 0x2e */
431 reg_w_1(gspca_dev, TV8532_POINTB_L,
432 TESTPTBL); /* 0x04; 0x2f */
433 reg_w_1(gspca_dev, TV8532_POINTB_H,
434 TESTPTBH); /* 0x04; 0x30 */
435 reg_w_1(gspca_dev, TV8532_PART_CTRL,
436 TV8532_CMD_UPDATE); /* 0x00<-0x84 */
437 /************************************************/
438 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x01); /* 0x31 */
439 msleep(200);
440 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
441 /************************************************/
442 tv_8532_setReg(gspca_dev);
443 /************************************************/
444 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
445 /************************************************/
446 tv_8532_setReg(gspca_dev);
447 /************************************************/
448 tv_8532_PollReg(gspca_dev);
449 reg_w_1(gspca_dev, TV8532_UDP_UPDATE, 0x00); /* 0x31 */
450}
451
452static void sd_stopN(struct gspca_dev *gspca_dev)
453{
454 reg_w_1(gspca_dev, TV8532_GPIO_OE, 0x0b);
455}
456
457static void sd_stop0(struct gspca_dev *gspca_dev)
458{
459}
460
461static void sd_close(struct gspca_dev *gspca_dev)
462{
463}
464
465static void tv8532_preprocess(struct gspca_dev *gspca_dev)
466{
467 struct sd *sd = (struct sd *) gspca_dev;
468/* we should received a whole frame with header and EOL marker
469 * in gspca_dev->tmpbuf and return a GBRG pattern in gspca_dev->tmpbuf2
470 * sequence 2bytes header the Alternate pixels bayer GB 4 bytes
471 * Alternate pixels bayer RG 4 bytes EOL */
472 int width = gspca_dev->width;
473 int height = gspca_dev->height;
474 unsigned char *dst = sd->tmpbuf2;
475 unsigned char *data = sd->tmpbuf;
476 int i;
477
478 /* precompute where is the good bayer line */
479 if (((data[3] + data[width + 7]) >> 1)
480 + (data[4] >> 2)
481 + (data[width + 6] >> 1) >= ((data[2] + data[width + 6]) >> 1)
482 + (data[3] >> 2)
483 + (data[width + 5] >> 1))
484 data += 3;
485 else
486 data += 2;
487 for (i = 0; i < height / 2; i++) {
488 memcpy(dst, data, width);
489 data += width + 3;
490 dst += width;
491 memcpy(dst, data, width);
492 data += width + 7;
493 dst += width;
494 }
495}
496
497static void sd_pkt_scan(struct gspca_dev *gspca_dev,
498 struct gspca_frame *frame, /* target */
499 __u8 *data, /* isoc packet */
500 int len) /* iso packet length */
501{
502 struct sd *sd = (struct sd *) gspca_dev;
503
504 if (data[0] != 0x80) {
505 sd->packet++;
506 if (sd->buflen + len > sizeof sd->tmpbuf) {
507 if (gspca_dev->last_packet_type != DISCARD_PACKET) {
508 PDEBUG(D_PACK, "buffer overflow");
509 gspca_dev->last_packet_type = DISCARD_PACKET;
510 }
511 return;
512 }
513 memcpy(&sd->tmpbuf[sd->buflen], data, len);
514 sd->buflen += len;
515 return;
516 }
517
518 /* here we detect 0x80 */
519 /* counter is limited so we need few header for a frame :) */
520
521 /* header 0x80 0x80 0x80 0x80 0x80 */
522 /* packet 00 63 127 145 00 */
523 /* sof 0 1 1 0 0 */
524
525 /* update sequence */
526 if (sd->packet == 63 || sd->packet == 127)
527 sd->synchro = 1;
528
529 /* is there a frame start ? */
530 if (sd->packet >= (gspca_dev->height >> 1) - 1) {
531 PDEBUG(D_PACK, "SOF > %d packet %d", sd->synchro,
532 sd->packet);
533 if (!sd->synchro) { /* start of frame */
534 if (gspca_dev->last_packet_type == FIRST_PACKET) {
535 tv8532_preprocess(gspca_dev);
536 frame = gspca_frame_add(gspca_dev,
537 LAST_PACKET,
538 frame, sd->tmpbuf2,
539 gspca_dev->width *
540 gspca_dev->width);
541 }
542 gspca_frame_add(gspca_dev, FIRST_PACKET,
543 frame, data, 0);
544 memcpy(sd->tmpbuf, data, len);
545 sd->buflen = len;
546 sd->packet = 0;
547 return;
548 }
549 if (gspca_dev->last_packet_type != DISCARD_PACKET) {
550 PDEBUG(D_PACK,
551 "Warning wrong TV8532 frame detection %d",
552 sd->packet);
553 gspca_dev->last_packet_type = DISCARD_PACKET;
554 }
555 return;
556 }
557
558 if (!sd->synchro) {
559 /* Drop packet frame corrupt */
560 PDEBUG(D_PACK, "DROP SOF %d packet %d",
561 sd->synchro, sd->packet);
562 sd->packet = 0;
563 gspca_dev->last_packet_type = DISCARD_PACKET;
564 return;
565 }
566 sd->synchro = 1;
567 sd->packet++;
568 memcpy(&sd->tmpbuf[sd->buflen], data, len);
569 sd->buflen += len;
570}
571
572static void setcontrast(struct gspca_dev *gspca_dev)
573{
574}
575
576static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
577{
578 struct sd *sd = (struct sd *) gspca_dev;
579
580 sd->brightness = val;
581 if (gspca_dev->streaming)
582 setbrightness(gspca_dev);
583 return 0;
584}
585
586static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
587{
588 struct sd *sd = (struct sd *) gspca_dev;
589
590 *val = sd->brightness;
591 return 0;
592}
593
594static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
595{
596 struct sd *sd = (struct sd *) gspca_dev;
597
598 sd->contrast = val;
599 if (gspca_dev->streaming)
600 setcontrast(gspca_dev);
601 return 0;
602}
603
604static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
605{
606 struct sd *sd = (struct sd *) gspca_dev;
607
608 *val = sd->contrast;
609 return 0;
610}
611
612/* sub-driver description */
613static const struct sd_desc sd_desc = {
614 .name = MODULE_NAME,
615 .ctrls = sd_ctrls,
616 .nctrls = ARRAY_SIZE(sd_ctrls),
617 .config = sd_config,
618 .open = sd_open,
619 .start = sd_start,
620 .stopN = sd_stopN,
621 .stop0 = sd_stop0,
622 .close = sd_close,
623 .pkt_scan = sd_pkt_scan,
624};
625
626/* -- module initialisation -- */
627#define DVNM(name) .driver_info = (kernel_ulong_t) name
628static const __devinitdata struct usb_device_id device_table[] = {
629 {USB_DEVICE(0x046d, 0x0920), DVNM("QC Express")},
630 {USB_DEVICE(0x046d, 0x0921), DVNM("Labtec Webcam")},
631 {USB_DEVICE(0x0545, 0x808b), DVNM("Veo Stingray")},
632 {USB_DEVICE(0x0545, 0x8333), DVNM("Veo Stingray")},
633 {USB_DEVICE(0x0923, 0x010f), DVNM("ICM532 cams")},
634 {}
635};
636
637MODULE_DEVICE_TABLE(usb, device_table);
638
639/* -- device connect -- */
640static int sd_probe(struct usb_interface *intf,
641 const struct usb_device_id *id)
642{
643 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
644 THIS_MODULE);
645}
646
647static struct usb_driver sd_driver = {
648 .name = MODULE_NAME,
649 .id_table = device_table,
650 .probe = sd_probe,
651 .disconnect = gspca_disconnect,
652};
653
654/* -- module insert / remove -- */
655static int __init sd_mod_init(void)
656{
657 if (usb_register(&sd_driver) < 0)
658 return -1;
659 PDEBUG(D_PROBE, "v%s registered", version);
660 return 0;
661}
662
663static void __exit sd_mod_exit(void)
664{
665 usb_deregister(&sd_driver);
666 PDEBUG(D_PROBE, "deregistered");
667}
668
669module_init(sd_mod_init);
670module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
new file mode 100644
index 000000000000..fcf2c9e32573
--- /dev/null
+++ b/drivers/media/video/gspca/vc032x.c
@@ -0,0 +1,1818 @@
1/*
2 * Z-star vc0321 library
3 * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl
4 * Copyright (C) 2006 Michel Xhaard
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 "vc032x"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
31MODULE_DESCRIPTION("GSPCA/VC032X 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
38 unsigned char autogain;
39 unsigned char lightfreq;
40
41 char qindex;
42 char bridge;
43#define BRIDGE_VC0321 0
44#define BRIDGE_VC0323 1
45 char sensor;
46#define SENSOR_HV7131R 0
47#define SENSOR_MI1320 1
48#define SENSOR_MI1310_SOC 2
49#define SENSOR_OV7660 3
50#define SENSOR_OV7670 4
51#define SENSOR_PO3130NC 5
52};
53
54/* V4L2 controls supported by the driver */
55static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
56static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
57static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
58static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
59
60static struct ctrl sd_ctrls[] = {
61 {
62 {
63 .id = V4L2_CID_AUTOGAIN,
64 .type = V4L2_CTRL_TYPE_BOOLEAN,
65 .name = "Auto Gain",
66 .minimum = 0,
67 .maximum = 1,
68 .step = 1,
69#define AUTOGAIN_DEF 1
70 .default_value = AUTOGAIN_DEF,
71 },
72 .set = sd_setautogain,
73 .get = sd_getautogain,
74 },
75 {
76 {
77 .id = V4L2_CID_POWER_LINE_FREQUENCY,
78 .type = V4L2_CTRL_TYPE_MENU,
79 .name = "Light frequency filter",
80 .minimum = 0,
81 .maximum = 2, /* 0: No, 1: 50Hz, 2:60Hz */
82 .step = 1,
83#define FREQ_DEF 1
84 .default_value = FREQ_DEF,
85 .default_value = 1,
86 },
87 .set = sd_setfreq,
88 .get = sd_getfreq,
89 },
90};
91
92static struct v4l2_pix_format vc0321_mode[] = {
93 {320, 240, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
94 .bytesperline = 320 * 2,
95 .sizeimage = 320 * 240 * 2,
96 .colorspace = V4L2_COLORSPACE_SRGB,
97 .priv = 1},
98 {640, 480, V4L2_PIX_FMT_YUV420, V4L2_FIELD_NONE,
99 .bytesperline = 640 * 2,
100 .sizeimage = 640 * 480 * 2,
101 .colorspace = V4L2_COLORSPACE_SRGB,
102 .priv = 0},
103};
104static struct v4l2_pix_format vc0323_mode[] = {
105 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
106 .bytesperline = 320,
107 .sizeimage = 320 * 240 * 3 / 8 + 590,
108 .colorspace = V4L2_COLORSPACE_JPEG,
109 .priv = 1},
110 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
111 .bytesperline = 640,
112 .sizeimage = 640 * 480 * 3 / 8 + 590,
113 .colorspace = V4L2_COLORSPACE_JPEG,
114 .priv = 0},
115};
116
117static const __u8 mi1310_socinitVGA_JPG[][4] = {
118 {0xb0, 0x03, 0x19, 0xcc},
119 {0xb0, 0x04, 0x02, 0xcc},
120 {0xb3, 0x00, 0x64, 0xcc},
121 {0xb3, 0x00, 0x65, 0xcc},
122 {0xb3, 0x05, 0x00, 0xcc},
123 {0xb3, 0x06, 0x00, 0xcc},
124 {0xb3, 0x08, 0x01, 0xcc},
125 {0xb3, 0x09, 0x0c, 0xcc},
126 {0xb3, 0x34, 0x02, 0xcc},
127 {0xb3, 0x35, 0xdd, 0xcc},
128 {0xb3, 0x02, 0x00, 0xcc},
129 {0xb3, 0x03, 0x0a, 0xcc},
130 {0xb3, 0x04, 0x05, 0xcc},
131 {0xb3, 0x20, 0x00, 0xcc},
132 {0xb3, 0x21, 0x00, 0xcc},
133 {0xb3, 0x22, 0x03, 0xcc},
134 {0xb3, 0x23, 0xc0, 0xcc},
135 {0xb3, 0x14, 0x00, 0xcc},
136 {0xb3, 0x15, 0x00, 0xcc},
137 {0xb3, 0x16, 0x04, 0xcc},
138 {0xb3, 0x17, 0xff, 0xcc},
139 {0xb3, 0x00, 0x65, 0xcc},
140 {0xb8, 0x00, 0x00, 0xcc},
141 {0xbc, 0x00, 0xd0, 0xcc},
142 {0xbc, 0x01, 0x01, 0xcc},
143 {0xf0, 0x00, 0x02, 0xbb},
144 {0xc8, 0x9f, 0x0b, 0xbb},
145 {0x5b, 0x00, 0x01, 0xbb},
146 {0x2f, 0xde, 0x20, 0xbb},
147 {0xf0, 0x00, 0x00, 0xbb},
148 {0x20, 0x03, 0x02, 0xbb},
149 {0xf0, 0x00, 0x01, 0xbb},
150 {0x05, 0x00, 0x07, 0xbb},
151 {0x34, 0x00, 0x00, 0xbb},
152 {0x35, 0xff, 0x00, 0xbb},
153 {0xdc, 0x07, 0x02, 0xbb},
154 {0xdd, 0x3c, 0x18, 0xbb},
155 {0xde, 0x92, 0x6d, 0xbb},
156 {0xdf, 0xcd, 0xb1, 0xbb},
157 {0xe0, 0xff, 0xe7, 0xbb},
158 {0x06, 0xf0, 0x0d, 0xbb},
159 {0x06, 0x70, 0x0e, 0xbb},
160 {0x4c, 0x00, 0x01, 0xbb},
161 {0x4d, 0x00, 0x01, 0xbb},
162 {0xf0, 0x00, 0x02, 0xbb},
163 {0x2e, 0x0c, 0x55, 0xbb},
164 {0x21, 0xb6, 0x6e, 0xbb},
165 {0x36, 0x30, 0x10, 0xbb},
166 {0x37, 0x00, 0xc1, 0xbb},
167 {0xf0, 0x00, 0x00, 0xbb},
168 {0x07, 0x00, 0x84, 0xbb},
169 {0x08, 0x02, 0x4a, 0xbb},
170 {0x05, 0x01, 0x10, 0xbb},
171 {0x06, 0x00, 0x39, 0xbb},
172 {0xf0, 0x00, 0x02, 0xbb},
173 {0x58, 0x02, 0x67, 0xbb},
174 {0x57, 0x02, 0x00, 0xbb},
175 {0x5a, 0x02, 0x67, 0xbb},
176 {0x59, 0x02, 0x00, 0xbb},
177 {0x5c, 0x12, 0x0d, 0xbb},
178 {0x5d, 0x16, 0x11, 0xbb},
179 {0x39, 0x06, 0x18, 0xbb},
180 {0x3a, 0x06, 0x18, 0xbb},
181 {0x3b, 0x06, 0x18, 0xbb},
182 {0x3c, 0x06, 0x18, 0xbb},
183 {0x64, 0x7b, 0x5b, 0xbb},
184 {0xf0, 0x00, 0x02, 0xbb},
185 {0x36, 0x30, 0x10, 0xbb},
186 {0x37, 0x00, 0xc0, 0xbb},
187 {0xbc, 0x0e, 0x00, 0xcc},
188 {0xbc, 0x0f, 0x05, 0xcc},
189 {0xbc, 0x10, 0xc0, 0xcc},
190 {0xbc, 0x11, 0x03, 0xcc},
191 {0xb6, 0x00, 0x00, 0xcc},
192 {0xb6, 0x03, 0x02, 0xcc},
193 {0xb6, 0x02, 0x80, 0xcc},
194 {0xb6, 0x05, 0x01, 0xcc},
195 {0xb6, 0x04, 0xe0, 0xcc},
196 {0xb6, 0x12, 0xf8, 0xcc},
197 {0xb6, 0x13, 0x25, 0xcc},
198 {0xb6, 0x18, 0x02, 0xcc},
199 {0xb6, 0x17, 0x58, 0xcc},
200 {0xb6, 0x16, 0x00, 0xcc},
201 {0xb6, 0x22, 0x12, 0xcc},
202 {0xb6, 0x23, 0x0b, 0xcc},
203 {0xbf, 0xc0, 0x39, 0xcc},
204 {0xbf, 0xc1, 0x04, 0xcc},
205 {0xbf, 0xcc, 0x00, 0xcc},
206 {0xbc, 0x02, 0x18, 0xcc},
207 {0xbc, 0x03, 0x50, 0xcc},
208 {0xbc, 0x04, 0x18, 0xcc},
209 {0xbc, 0x05, 0x00, 0xcc},
210 {0xbc, 0x06, 0x00, 0xcc},
211 {0xbc, 0x08, 0x30, 0xcc},
212 {0xbc, 0x09, 0x40, 0xcc},
213 {0xbc, 0x0a, 0x10, 0xcc},
214 {0xbc, 0x0b, 0x00, 0xcc},
215 {0xbc, 0x0c, 0x00, 0xcc},
216 {0xb3, 0x5c, 0x01, 0xcc},
217 {0xf0, 0x00, 0x01, 0xbb},
218 {0x80, 0x00, 0x03, 0xbb},
219 {0x81, 0xc7, 0x14, 0xbb},
220 {0x82, 0xeb, 0xe8, 0xbb},
221 {0x83, 0xfe, 0xf4, 0xbb},
222 {0x84, 0xcd, 0x10, 0xbb},
223 {0x85, 0xf3, 0xee, 0xbb},
224 {0x86, 0xff, 0xf1, 0xbb},
225 {0x87, 0xcd, 0x10, 0xbb},
226 {0x88, 0xf3, 0xee, 0xbb},
227 {0x89, 0x01, 0xf1, 0xbb},
228 {0x8a, 0xe5, 0x17, 0xbb},
229 {0x8b, 0xe8, 0xe2, 0xbb},
230 {0x8c, 0xf7, 0xed, 0xbb},
231 {0x8d, 0x00, 0xff, 0xbb},
232 {0x8e, 0xec, 0x10, 0xbb},
233 {0x8f, 0xf0, 0xed, 0xbb},
234 {0x90, 0xf9, 0xf2, 0xbb},
235 {0x91, 0x00, 0x00, 0xbb},
236 {0x92, 0xe9, 0x0d, 0xbb},
237 {0x93, 0xf4, 0xf2, 0xbb},
238 {0x94, 0xfb, 0xf5, 0xbb},
239 {0x95, 0x00, 0xff, 0xbb},
240 {0xb6, 0x0f, 0x08, 0xbb},
241 {0xb7, 0x3d, 0x16, 0xbb},
242 {0xb8, 0x0c, 0x04, 0xbb},
243 {0xb9, 0x1c, 0x07, 0xbb},
244 {0xba, 0x0a, 0x03, 0xbb},
245 {0xbb, 0x1b, 0x09, 0xbb},
246 {0xbc, 0x17, 0x0d, 0xbb},
247 {0xbd, 0x23, 0x1d, 0xbb},
248 {0xbe, 0x00, 0x28, 0xbb},
249 {0xbf, 0x11, 0x09, 0xbb},
250 {0xc0, 0x16, 0x15, 0xbb},
251 {0xc1, 0x00, 0x1b, 0xbb},
252 {0xc2, 0x0e, 0x07, 0xbb},
253 {0xc3, 0x14, 0x10, 0xbb},
254 {0xc4, 0x00, 0x17, 0xbb},
255 {0x06, 0x74, 0x8e, 0xbb},
256 {0xf0, 0x00, 0x01, 0xbb},
257 {0x06, 0xf4, 0x8e, 0xbb},
258 {0x00, 0x00, 0x50, 0xdd},
259 {0x06, 0x74, 0x8e, 0xbb},
260 {0xf0, 0x00, 0x02, 0xbb},
261 {0x24, 0x50, 0x20, 0xbb},
262 {0xf0, 0x00, 0x02, 0xbb},
263 {0x34, 0x0c, 0x50, 0xbb},
264 {0xb3, 0x01, 0x41, 0xcc},
265 {0xf0, 0x00, 0x00, 0xbb},
266 {0x03, 0x03, 0xc0, 0xbb},
267 {},
268};
269static const __u8 mi1310_socinitQVGA_JPG[][4] = {
270 {0xb0, 0x03, 0x19, 0xcc}, {0xb0, 0x04, 0x02, 0xcc},
271 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
272 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x00, 0xcc},
273 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
274 {0xb3, 0x34, 0x02, 0xcc}, {0xb3, 0x35, 0xdd, 0xcc},
275 {0xb3, 0x02, 0x00, 0xcc}, {0xb3, 0x03, 0x0a, 0xcc},
276 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
277 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x03, 0xcc},
278 {0xb3, 0x23, 0xc0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
279 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x04, 0xcc},
280 {0xb3, 0x17, 0xff, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
281 {0xb8, 0x00, 0x00, 0xcc}, {0xbc, 0x00, 0xf0, 0xcc},
282 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x02, 0xbb},
283 {0xc8, 0x9f, 0x0b, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
284 {0x2f, 0xde, 0x20, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
285 {0x20, 0x03, 0x02, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
286 {0x05, 0x00, 0x07, 0xbb}, {0x34, 0x00, 0x00, 0xbb},
287 {0x35, 0xff, 0x00, 0xbb}, {0xdc, 0x07, 0x02, 0xbb},
288 {0xdd, 0x3c, 0x18, 0xbb}, {0xde, 0x92, 0x6d, 0xbb},
289 {0xdf, 0xcd, 0xb1, 0xbb}, {0xe0, 0xff, 0xe7, 0xbb},
290 {0x06, 0xf0, 0x0d, 0xbb}, {0x06, 0x70, 0x0e, 0xbb},
291 {0x4c, 0x00, 0x01, 0xbb}, {0x4d, 0x00, 0x01, 0xbb},
292 {0xf0, 0x00, 0x02, 0xbb}, {0x2e, 0x0c, 0x55, 0xbb},
293 {0x21, 0xb6, 0x6e, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
294 {0x37, 0x00, 0xc1, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
295 {0x07, 0x00, 0x84, 0xbb}, {0x08, 0x02, 0x4a, 0xbb},
296 {0x05, 0x01, 0x10, 0xbb}, {0x06, 0x00, 0x39, 0xbb},
297 {0xf0, 0x00, 0x02, 0xbb}, {0x58, 0x02, 0x67, 0xbb},
298 {0x57, 0x02, 0x00, 0xbb}, {0x5a, 0x02, 0x67, 0xbb},
299 {0x59, 0x02, 0x00, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
300 {0x5d, 0x16, 0x11, 0xbb}, {0x39, 0x06, 0x18, 0xbb},
301 {0x3a, 0x06, 0x18, 0xbb}, {0x3b, 0x06, 0x18, 0xbb},
302 {0x3c, 0x06, 0x18, 0xbb}, {0x64, 0x7b, 0x5b, 0xbb},
303 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x30, 0x10, 0xbb},
304 {0x37, 0x00, 0xc0, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
305 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
306 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
307 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
308 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
309 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x25, 0xcc},
310 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
311 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
312 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
313 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
314 {0xb3, 0x5c, 0x01, 0xcc}, {0xf0, 0x00, 0x01, 0xbb},
315 {0x80, 0x00, 0x03, 0xbb}, {0x81, 0xc7, 0x14, 0xbb},
316 {0x82, 0xeb, 0xe8, 0xbb}, {0x83, 0xfe, 0xf4, 0xbb},
317 {0x84, 0xcd, 0x10, 0xbb}, {0x85, 0xf3, 0xee, 0xbb},
318 {0x86, 0xff, 0xf1, 0xbb}, {0x87, 0xcd, 0x10, 0xbb},
319 {0x88, 0xf3, 0xee, 0xbb}, {0x89, 0x01, 0xf1, 0xbb},
320 {0x8a, 0xe5, 0x17, 0xbb}, {0x8b, 0xe8, 0xe2, 0xbb},
321 {0x8c, 0xf7, 0xed, 0xbb}, {0x8d, 0x00, 0xff, 0xbb},
322 {0x8e, 0xec, 0x10, 0xbb}, {0x8f, 0xf0, 0xed, 0xbb},
323 {0x90, 0xf9, 0xf2, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
324 {0x92, 0xe9, 0x0d, 0xbb}, {0x93, 0xf4, 0xf2, 0xbb},
325 {0x94, 0xfb, 0xf5, 0xbb}, {0x95, 0x00, 0xff, 0xbb},
326 {0xb6, 0x0f, 0x08, 0xbb}, {0xb7, 0x3d, 0x16, 0xbb},
327 {0xb8, 0x0c, 0x04, 0xbb}, {0xb9, 0x1c, 0x07, 0xbb},
328 {0xba, 0x0a, 0x03, 0xbb}, {0xbb, 0x1b, 0x09, 0xbb},
329 {0xbc, 0x17, 0x0d, 0xbb}, {0xbd, 0x23, 0x1d, 0xbb},
330 {0xbe, 0x00, 0x28, 0xbb}, {0xbf, 0x11, 0x09, 0xbb},
331 {0xc0, 0x16, 0x15, 0xbb}, {0xc1, 0x00, 0x1b, 0xbb},
332 {0xc2, 0x0e, 0x07, 0xbb}, {0xc3, 0x14, 0x10, 0xbb},
333 {0xc4, 0x00, 0x17, 0xbb}, {0x06, 0x74, 0x8e, 0xbb},
334 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0xf4, 0x8e, 0xbb},
335 {0x00, 0x00, 0x50, 0xdd}, {0x06, 0x74, 0x8e, 0xbb},
336 {0xf0, 0x00, 0x02, 0xbb}, {0x24, 0x50, 0x20, 0xbb},
337 {0xf0, 0x00, 0x02, 0xbb}, {0x34, 0x0c, 0x50, 0xbb},
338 {0xb3, 0x01, 0x41, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
339 {0x03, 0x03, 0xc0, 0xbb},
340 {},
341};
342
343static const __u8 mi1320_gamma[17] = {
344 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
345 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
346};
347static const __u8 mi1320_matrix[9] = {
348 0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
349};
350static const __u8 mi1320_initVGA_data[][4] = {
351 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
352 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
353 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
354 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
355 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
356 {0xb3, 0x06, 0x00, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
357 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
358 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
359 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
360 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
361 {0xb3, 0x22, 0x03, 0xcc}, {0xb3, 0x23, 0xc0, 0xcc},
362 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
363 {0xb3, 0x16, 0x04, 0xcc}, {0xb3, 0x17, 0xff, 0xcc},
364 {0xb3, 0x00, 0x67, 0xcc}, {0xbc, 0x00, 0xd0, 0xcc},
365 {0xbc, 0x01, 0x01, 0xcc}, {0xf0, 0x00, 0x00, 0xbb},
366 {0x0d, 0x00, 0x09, 0xbb}, {0x00, 0x01, 0x00, 0xdd},
367 {0x0d, 0x00, 0x08, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
368 {0xa1, 0x05, 0x00, 0xbb}, {0xa4, 0x03, 0xc0, 0xbb},
369 {0xf0, 0x00, 0x02, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
370 {0xc8, 0x9f, 0x0b, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
371 {0xf0, 0x00, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
372 {0x20, 0x01, 0x00, 0xbb}, {0x00, 0x00, 0x10, 0xdd},
373 {0xf0, 0x00, 0x01, 0xbb}, {0x9d, 0x3c, 0xa0, 0xbb},
374 {0x47, 0x30, 0x30, 0xbb}, {0xf0, 0x00, 0x00, 0xbb},
375 {0x0a, 0x80, 0x11, 0xbb}, {0x35, 0x00, 0x22, 0xbb},
376 {0xf0, 0x00, 0x02, 0xbb}, {0x9d, 0xc5, 0x05, 0xbb},
377 {0xdc, 0x0f, 0xfc, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
378 {0x06, 0x74, 0x0e, 0xbb}, {0x80, 0x00, 0x06, 0xbb},
379 {0x81, 0x04, 0x00, 0xbb}, {0x82, 0x01, 0x02, 0xbb},
380 {0x83, 0x03, 0x02, 0xbb}, {0x84, 0x05, 0x00, 0xbb},
381 {0x85, 0x01, 0x00, 0xbb}, {0x86, 0x03, 0x02, 0xbb},
382 {0x87, 0x05, 0x00, 0xbb}, {0x88, 0x01, 0x00, 0xbb},
383 {0x89, 0x02, 0x02, 0xbb}, {0x8a, 0xfd, 0x04, 0xbb},
384 {0x8b, 0xfc, 0xfd, 0xbb}, {0x8c, 0xff, 0xfd, 0xbb},
385 {0x8d, 0x00, 0x00, 0xbb}, {0x8e, 0xfe, 0x05, 0xbb},
386 {0x8f, 0xfc, 0xfd, 0xbb}, {0x90, 0xfe, 0xfd, 0xbb},
387 {0x91, 0x00, 0x00, 0xbb}, {0x92, 0xfe, 0x03, 0xbb},
388 {0x93, 0xfd, 0xfe, 0xbb}, {0x94, 0xff, 0xfd, 0xbb},
389 {0x95, 0x00, 0x00, 0xbb}, {0xb6, 0x07, 0x05, 0xbb},
390 {0xb7, 0x13, 0x06, 0xbb}, {0xb8, 0x08, 0x06, 0xbb},
391 {0xb9, 0x14, 0x08, 0xbb}, {0xba, 0x06, 0x05, 0xbb},
392 {0xbb, 0x13, 0x06, 0xbb}, {0xbc, 0x03, 0x01, 0xbb},
393 {0xbd, 0x03, 0x04, 0xbb}, {0xbe, 0x00, 0x02, 0xbb},
394 {0xbf, 0x03, 0x01, 0xbb}, {0xc0, 0x02, 0x04, 0xbb},
395 {0xc1, 0x00, 0x04, 0xbb}, {0xc2, 0x02, 0x01, 0xbb},
396 {0xc3, 0x01, 0x03, 0xbb}, {0xc4, 0x00, 0x04, 0xbb},
397 {0xf0, 0x00, 0x00, 0xbb}, {0x05, 0x01, 0x13, 0xbb},
398 {0x06, 0x00, 0x11, 0xbb}, {0x07, 0x00, 0x85, 0xbb},
399 {0x08, 0x00, 0x27, 0xbb}, {0x20, 0x01, 0x03, 0xbb},
400 {0x21, 0x80, 0x00, 0xbb}, {0x22, 0x0d, 0x0f, 0xbb},
401 {0x24, 0x80, 0x00, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
402 {0xf0, 0x00, 0x02, 0xbb}, {0x39, 0x03, 0x0d, 0xbb},
403 {0x3a, 0x06, 0x1b, 0xbb}, {0x3b, 0x00, 0x95, 0xbb},
404 {0x3c, 0x04, 0xdb, 0xbb}, {0x57, 0x02, 0x00, 0xbb},
405 {0x58, 0x02, 0x66, 0xbb}, {0x59, 0x00, 0xff, 0xbb},
406 {0x5a, 0x01, 0x33, 0xbb}, {0x5c, 0x12, 0x0d, 0xbb},
407 {0x5d, 0x16, 0x11, 0xbb}, {0x64, 0x5e, 0x1c, 0xbb},
408 {0xf0, 0x00, 0x02, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
409 {0x5b, 0x00, 0x01, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
410 {0x36, 0x68, 0x10, 0xbb}, {0x00, 0x00, 0x30, 0xdd},
411 {0x37, 0x82, 0x00, 0xbb}, {0xbc, 0x0e, 0x00, 0xcc},
412 {0xbc, 0x0f, 0x05, 0xcc}, {0xbc, 0x10, 0xc0, 0xcc},
413 {0xbc, 0x11, 0x03, 0xcc}, {0xb6, 0x00, 0x00, 0xcc},
414 {0xb6, 0x03, 0x05, 0xcc}, {0xb6, 0x02, 0x00, 0xcc},
415 {0xb6, 0x05, 0x04, 0xcc}, {0xb6, 0x04, 0x00, 0xcc},
416 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x29, 0xcc},
417 {0xb6, 0x18, 0x0a, 0xcc}, {0xb6, 0x17, 0x00, 0xcc},
418 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
419 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x26, 0xcc},
420 {0xbf, 0xc1, 0x02, 0xcc}, {0xbf, 0xcc, 0x04, 0xcc},
421 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
422 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
423 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
424 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
425 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
426 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
427 {}
428};
429static const __u8 mi1320_initQVGA_data[][4] = {
430 {0xb3, 0x01, 0x01, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
431 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
432 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x33, 0xdd},
433 {0xb3, 0x00, 0x64, 0xcc}, {0xb3, 0x00, 0x65, 0xcc},
434 {0xb0, 0x16, 0x03, 0xcc}, {0xb3, 0x05, 0x01, 0xcc},
435 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
436 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x34, 0x02, 0xcc},
437 {0xb3, 0x35, 0xc8, 0xcc}, {0xb3, 0x02, 0x00, 0xcc},
438 {0xb3, 0x03, 0x0a, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
439 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
440 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
441 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
442 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
443 {0xb3, 0x00, 0x65, 0xcc}, {0xb8, 0x00, 0x00, 0xcc},
444 {0xbc, 0x00, 0xd0, 0xcc}, {0xbc, 0x01, 0x01, 0xcc},
445 {0xf0, 0x00, 0x00, 0xbb}, {0x0d, 0x00, 0x09, 0xbb},
446 {0x00, 0x01, 0x00, 0xdd}, {0x0d, 0x00, 0x08, 0xbb},
447 {0xf0, 0x00, 0x00, 0xbb}, {0x02, 0x00, 0x64, 0xbb},
448 {0x05, 0x01, 0x78, 0xbb}, {0x06, 0x00, 0x11, 0xbb},
449 {0x07, 0x01, 0x42, 0xbb}, {0x08, 0x00, 0x11, 0xbb},
450 {0x20, 0x01, 0x00, 0xbb}, {0x21, 0x80, 0x00, 0xbb},
451 {0x22, 0x0d, 0x0f, 0xbb}, {0x24, 0x80, 0x00, 0xbb},
452 {0x59, 0x00, 0xff, 0xbb}, {0xf0, 0x00, 0x01, 0xbb},
453 {0x9d, 0x3c, 0xa0, 0xbb}, {0x47, 0x30, 0x30, 0xbb},
454 {0xf0, 0x00, 0x00, 0xbb}, {0x0a, 0x80, 0x11, 0xbb},
455 {0x35, 0x00, 0x22, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
456 {0x9d, 0xc5, 0x05, 0xbb}, {0xdc, 0x0f, 0xfc, 0xbb},
457 {0xf0, 0x00, 0x01, 0xbb}, {0x06, 0x74, 0x0e, 0xbb},
458 {0x80, 0x00, 0x06, 0xbb}, {0x81, 0x04, 0x00, 0xbb},
459 {0x82, 0x01, 0x02, 0xbb}, {0x83, 0x03, 0x02, 0xbb},
460 {0x84, 0x05, 0x00, 0xbb}, {0x85, 0x01, 0x00, 0xbb},
461 {0x86, 0x03, 0x02, 0xbb}, {0x87, 0x05, 0x00, 0xbb},
462 {0x88, 0x01, 0x00, 0xbb}, {0x89, 0x02, 0x02, 0xbb},
463 {0x8a, 0xfd, 0x04, 0xbb}, {0x8b, 0xfc, 0xfd, 0xbb},
464 {0x8c, 0xff, 0xfd, 0xbb}, {0x8d, 0x00, 0x00, 0xbb},
465 {0x8e, 0xfe, 0x05, 0xbb}, {0x8f, 0xfc, 0xfd, 0xbb},
466 {0x90, 0xfe, 0xfd, 0xbb}, {0x91, 0x00, 0x00, 0xbb},
467 {0x92, 0xfe, 0x03, 0xbb}, {0x93, 0xfd, 0xfe, 0xbb},
468 {0x94, 0xff, 0xfd, 0xbb}, {0x95, 0x00, 0x00, 0xbb},
469 {0xb6, 0x07, 0x05, 0xbb}, {0xb7, 0x13, 0x06, 0xbb},
470 {0xb8, 0x08, 0x06, 0xbb}, {0xb9, 0x14, 0x08, 0xbb},
471 {0xba, 0x06, 0x05, 0xbb}, {0xbb, 0x13, 0x06, 0xbb},
472 {0xbc, 0x03, 0x01, 0xbb}, {0xbd, 0x03, 0x04, 0xbb},
473 {0xbe, 0x00, 0x02, 0xbb}, {0xbf, 0x03, 0x01, 0xbb},
474 {0xc0, 0x02, 0x04, 0xbb}, {0xc1, 0x00, 0x04, 0xbb},
475 {0xc2, 0x02, 0x01, 0xbb}, {0xc3, 0x01, 0x03, 0xbb},
476 {0xc4, 0x00, 0x04, 0xbb}, {0xf0, 0x00, 0x02, 0xbb},
477 {0xc8, 0x00, 0x00, 0xbb}, {0x2e, 0x00, 0x00, 0xbb},
478 {0x2e, 0x0c, 0x5b, 0xbb}, {0x2f, 0xd1, 0x00, 0xbb},
479 {0x39, 0x03, 0xca, 0xbb}, {0x3a, 0x06, 0x80, 0xbb},
480 {0x3b, 0x01, 0x52, 0xbb}, {0x3c, 0x05, 0x40, 0xbb},
481 {0x57, 0x01, 0x9c, 0xbb}, {0x58, 0x01, 0xee, 0xbb},
482 {0x59, 0x00, 0xf0, 0xbb}, {0x5a, 0x01, 0x20, 0xbb},
483 {0x5c, 0x1d, 0x17, 0xbb}, {0x5d, 0x22, 0x1c, 0xbb},
484 {0x64, 0x1e, 0x1c, 0xbb}, {0x5b, 0x00, 0x01, 0xbb},
485 {0xf0, 0x00, 0x02, 0xbb}, {0x36, 0x68, 0x10, 0xbb},
486 {0x00, 0x00, 0x30, 0xdd}, {0x37, 0x81, 0x00, 0xbb},
487 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
488 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
489 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
490 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
491 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
492 {0xbf, 0xc0, 0x26, 0xcc}, {0xbf, 0xc1, 0x02, 0xcc},
493 {0xbf, 0xcc, 0x04, 0xcc}, {0xb3, 0x5c, 0x01, 0xcc},
494 {0xb3, 0x01, 0x41, 0xcc},
495 {}
496};
497
498static const __u8 po3130_gamma[17] = {
499 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
500 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
501};
502static const __u8 po3130_matrix[9] = {
503 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
504};
505
506static const __u8 po3130_initVGA_data[][4] = {
507 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
508 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
509 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
510 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
511 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
512 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
513 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
514 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
515 {0xb3, 0x23, 0xe8, 0xcc}, {0xb8, 0x08, 0xe8, 0xcc},
516 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
517 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
518 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
519 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0x71, 0xcc},
520 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
521 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
522 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
523 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
524 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
525 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
526 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
527 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
528 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
529 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
530 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
531 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
532 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
533 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
534 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
535 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
536 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
537 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
538 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
539 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
540 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
541 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
542 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
543 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
544 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
545 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
546 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
547 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
548 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
549 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
550 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
551 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
552 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
553 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
554 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
555 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
556 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
557 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
558 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
559 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
560 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
561 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
562 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
563 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
564 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
565 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
566 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
567 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
568 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
569 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
570 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
571 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
572 {0x00, 0x7e, 0xea, 0xaa},
573 {0x00, 0x4c, 0x07, 0xaa},
574 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
575 {0x00, 0x59, 0x02, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
576/* {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
577 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc}, */
578 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
579 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
580 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
581 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
582 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
583 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
584 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
585 {0xb9, 0x08, 0x3c, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
586 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
587 {}
588};
589static const __u8 po3130_rundata[][4] = {
590 {0x00, 0x47, 0x45, 0xaa}, {0x00, 0x48, 0x9b, 0xaa},
591 {0x00, 0x49, 0x3a, 0xaa}, {0x00, 0x4a, 0x01, 0xaa},
592 {0x00, 0x44, 0x40, 0xaa},
593/* {0x00, 0xd5, 0x7c, 0xaa}, */
594 {0x00, 0xad, 0x04, 0xaa}, {0x00, 0xae, 0x00, 0xaa},
595 {0x00, 0xb0, 0x78, 0xaa}, {0x00, 0x98, 0x02, 0xaa},
596 {0x00, 0x94, 0x25, 0xaa}, {0x00, 0x95, 0x25, 0xaa},
597 {0x00, 0x59, 0x68, 0xaa}, {0x00, 0x44, 0x20, 0xaa},
598 {0x00, 0x17, 0x50, 0xaa}, {0x00, 0x19, 0x50, 0xaa},
599 {0x00, 0xd1, 0x3c, 0xaa}, {0x00, 0xd1, 0x3c, 0xaa},
600 {0x00, 0x1e, 0x06, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
601 {}
602};
603
604static const __u8 po3130_initQVGA_data[][4] = {
605 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
606 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x09, 0xcc},
607 {0xb3, 0x00, 0x04, 0xcc}, {0xb3, 0x00, 0x24, 0xcc},
608 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
609 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
610 {0xb3, 0x06, 0x01, 0xcc}, {0xb3, 0x03, 0x1a, 0xcc},
611 {0xb3, 0x04, 0x15, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
612 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
613 {0xb3, 0x23, 0xe0, 0xcc}, {0xb8, 0x08, 0xe0, 0xcc},
614 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
615 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
616 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0xf6, 0xcc},
617 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
618 {0xb8, 0x00, 0x21, 0xcc}, {0xb8, 0x27, 0x20, 0xcc},
619 {0xb8, 0x01, 0x79, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
620 {0xb8, 0x2c, 0x50, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
621 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
622 {0xb8, 0x30, 0x50, 0xcc}, {0xb8, 0x31, 0xf8, 0xcc},
623 {0xb8, 0x32, 0xf8, 0xcc}, {0xb8, 0x33, 0xf8, 0xcc},
624 {0xb8, 0x34, 0x50, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
625 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
626 {0x00, 0x1e, 0xc6, 0xaa}, {0x00, 0x20, 0x44, 0xaa},
627 {0x00, 0xad, 0x02, 0xaa}, {0x00, 0xae, 0x2c, 0xaa},
628 {0x00, 0x12, 0x08, 0xaa}, {0x00, 0x17, 0x41, 0xaa},
629 {0x00, 0x19, 0x41, 0xaa}, {0x00, 0x1e, 0x06, 0xaa},
630 {0x00, 0x21, 0x00, 0xaa}, {0x00, 0x36, 0xc0, 0xaa},
631 {0x00, 0x37, 0xc8, 0xaa}, {0x00, 0x3b, 0x36, 0xaa},
632 {0x00, 0x4b, 0xfe, 0xaa}, {0x00, 0x51, 0x1c, 0xaa},
633 {0x00, 0x52, 0x01, 0xaa}, {0x00, 0x55, 0x0a, 0xaa},
634 {0x00, 0x59, 0x6f, 0xaa}, {0x00, 0x5a, 0x04, 0xaa},
635 {0x00, 0x5c, 0x10, 0xaa}, {0x00, 0x5d, 0x10, 0xaa},
636 {0x00, 0x5e, 0x10, 0xaa}, {0x00, 0x5f, 0x10, 0xaa},
637 {0x00, 0x61, 0x00, 0xaa}, {0x00, 0x62, 0x18, 0xaa},
638 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x70, 0x68, 0xaa},
639 {0x00, 0x80, 0x71, 0xaa}, {0x00, 0x81, 0x08, 0xaa},
640 {0x00, 0x82, 0x00, 0xaa}, {0x00, 0x83, 0x55, 0xaa},
641 {0x00, 0x84, 0x06, 0xaa}, {0x00, 0x85, 0x06, 0xaa},
642 {0x00, 0x86, 0x13, 0xaa}, {0x00, 0x87, 0x18, 0xaa},
643 {0x00, 0xaa, 0x3f, 0xaa}, {0x00, 0xab, 0x44, 0xaa},
644 {0x00, 0xb0, 0x68, 0xaa}, {0x00, 0xb5, 0x10, 0xaa},
645 {0x00, 0xb8, 0x20, 0xaa}, {0x00, 0xb9, 0xa0, 0xaa},
646 {0x00, 0xbc, 0x04, 0xaa}, {0x00, 0x8b, 0x40, 0xaa},
647 {0x00, 0x8c, 0x91, 0xaa}, {0x00, 0x8d, 0x8f, 0xaa},
648 {0x00, 0x8e, 0x91, 0xaa}, {0x00, 0x8f, 0x43, 0xaa},
649 {0x00, 0x90, 0x92, 0xaa}, {0x00, 0x91, 0x89, 0xaa},
650 {0x00, 0x92, 0x9d, 0xaa}, {0x00, 0x93, 0x46, 0xaa},
651 {0x00, 0xd6, 0x22, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
652 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
653 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
654 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
655 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
656 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
657 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0xd6, 0x62, 0xaa},
658 {0x00, 0x73, 0x00, 0xaa}, {0x00, 0x74, 0x10, 0xaa},
659 {0x00, 0x75, 0x20, 0xaa}, {0x00, 0x76, 0x2b, 0xaa},
660 {0x00, 0x77, 0x36, 0xaa}, {0x00, 0x78, 0x49, 0xaa},
661 {0x00, 0x79, 0x5a, 0xaa}, {0x00, 0x7a, 0x7f, 0xaa},
662 {0x00, 0x7b, 0x9b, 0xaa}, {0x00, 0x7c, 0xba, 0xaa},
663 {0x00, 0x7d, 0xd4, 0xaa}, {0x00, 0x7e, 0xea, 0xaa},
664 {0x00, 0xd6, 0xa2, 0xaa}, {0x00, 0x73, 0x00, 0xaa},
665 {0x00, 0x74, 0x10, 0xaa}, {0x00, 0x75, 0x20, 0xaa},
666 {0x00, 0x76, 0x2b, 0xaa}, {0x00, 0x77, 0x36, 0xaa},
667 {0x00, 0x78, 0x49, 0xaa}, {0x00, 0x79, 0x5a, 0xaa},
668 {0x00, 0x7a, 0x7f, 0xaa}, {0x00, 0x7b, 0x9b, 0xaa},
669 {0x00, 0x7c, 0xba, 0xaa}, {0x00, 0x7d, 0xd4, 0xaa},
670 {0x00, 0x7e, 0xea, 0xaa}, {0x00, 0x4c, 0x07, 0xaa},
671 {0x00, 0x4b, 0xe0, 0xaa}, {0x00, 0x4e, 0x77, 0xaa},
672 {0x00, 0x59, 0x66, 0xaa}, {0x00, 0x4d, 0x0a, 0xaa},
673 {0x00, 0xd1, 0x00, 0xaa}, {0x00, 0x20, 0xc4, 0xaa},
674 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
675 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
676 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
677 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
678 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
679 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
680 {0xb9, 0x08, 0x3c, 0xcc}, {0xbc, 0x02, 0x18, 0xcc},
681 {0xbc, 0x03, 0x50, 0xcc}, {0xbc, 0x04, 0x18, 0xcc},
682 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
683 {0xbc, 0x08, 0x30, 0xcc}, {0xbc, 0x09, 0x40, 0xcc},
684 {0xbc, 0x0a, 0x10, 0xcc}, {0xbc, 0x0b, 0x00, 0xcc},
685 {0xbc, 0x0c, 0x00, 0xcc}, {0x00, 0x05, 0x00, 0xaa},
686 {0xb3, 0x5c, 0x00, 0xcc}, {0xb3, 0x01, 0x41, 0xcc},
687 {}
688};
689
690static const __u8 hv7131r_gamma[17] = {
691/* 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
692 * 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff */
693 0x04, 0x1a, 0x36, 0x55, 0x6f, 0x87, 0x9d, 0xb0, 0xc1,
694 0xcf, 0xda, 0xe4, 0xec, 0xf3, 0xf8, 0xfd, 0xff
695};
696static const __u8 hv7131r_matrix[9] = {
697 0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
698};
699static const __u8 hv7131r_initVGA_data[][4] = {
700 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
701 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
702 {0xb3, 0x00, 0x24, 0xcc},
703 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
704 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
705 {0xb3, 0x06, 0x01, 0xcc},
706 {0xb3, 0x01, 0x45, 0xcc}, {0xb3, 0x03, 0x0b, 0xcc},
707 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
708 {0xb3, 0x21, 0x00, 0xcc},
709 {0xb3, 0x22, 0x01, 0xcc}, {0xb3, 0x23, 0xe0, 0xcc},
710 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
711 {0xb3, 0x16, 0x02, 0xcc},
712 {0xb3, 0x17, 0x7f, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
713 {0xb3, 0x35, 0x91, 0xcc}, {0xb3, 0x00, 0x27, 0xcc},
714 {0xbc, 0x00, 0x73, 0xcc},
715 {0xb8, 0x00, 0x23, 0xcc}, {0x00, 0x01, 0x0c, 0xaa},
716 {0x00, 0x14, 0x01, 0xaa}, {0x00, 0x15, 0xe6, 0xaa},
717 {0x00, 0x16, 0x02, 0xaa},
718 {0x00, 0x17, 0x86, 0xaa}, {0x00, 0x23, 0x00, 0xaa},
719 {0x00, 0x25, 0x09, 0xaa}, {0x00, 0x26, 0x27, 0xaa},
720 {0x00, 0x27, 0xc0, 0xaa},
721 {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
722 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
723 {0xb8, 0x30, 0x50, 0xcc},
724 {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
725 {0xb8, 0x33, 0xf8, 0xcc}, {0xb8, 0x34, 0x65, 0xcc},
726 {0xb8, 0x35, 0x00, 0xcc},
727 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
728 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x01, 0x7d, 0xcc},
729 {0xb8, 0x81, 0x09, 0xcc},
730 {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
731 {0xb8, 0xff, 0x28, 0xcc}, {0xb9, 0x00, 0x28, 0xcc},
732 {0xb9, 0x01, 0x28, 0xcc},
733 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
734 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
735 {0xb9, 0x06, 0x3c, 0xcc},
736 {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
737 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
738 {0x00, 0x30, 0x18, 0xaa},
739 {}
740};
741
742static const __u8 hv7131r_initQVGA_data[][4] = {
743 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
744 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
745 {0xb3, 0x00, 0x24, 0xcc},
746 {0xb3, 0x00, 0x25, 0xcc}, {0xb3, 0x08, 0x01, 0xcc},
747 {0xb3, 0x09, 0x0c, 0xcc}, {0xb3, 0x05, 0x00, 0xcc},
748 {0xb3, 0x06, 0x01, 0xcc},
749 {0xb3, 0x03, 0x0b, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
750 {0xb3, 0x20, 0x00, 0xcc}, {0xb3, 0x21, 0x00, 0xcc},
751 {0xb3, 0x22, 0x01, 0xcc},
752 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x14, 0x00, 0xcc},
753 {0xb3, 0x15, 0x00, 0xcc}, {0xb3, 0x16, 0x02, 0xcc},
754 {0xb3, 0x17, 0x7f, 0xcc},
755 {0xb3, 0x34, 0x01, 0xcc}, {0xb3, 0x35, 0x91, 0xcc},
756 {0xb3, 0x00, 0x27, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
757 {0xb8, 0x00, 0x21, 0xcc},
758 {0x00, 0x01, 0x0c, 0xaa}, {0x00, 0x14, 0x01, 0xaa},
759 {0x00, 0x15, 0xe6, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
760 {0x00, 0x17, 0x86, 0xaa},
761 {0x00, 0x23, 0x00, 0xaa}, {0x00, 0x25, 0x01, 0xaa},
762 {0x00, 0x26, 0xd4, 0xaa}, {0x00, 0x27, 0xc0, 0xaa},
763 {0xbc, 0x02, 0x08, 0xcc},
764 {0xbc, 0x03, 0x70, 0xcc}, {0xbc, 0x04, 0x08, 0xcc},
765 {0xbc, 0x05, 0x00, 0xcc}, {0xbc, 0x06, 0x00, 0xcc},
766 {0xbc, 0x08, 0x3c, 0xcc},
767 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x04, 0xcc},
768 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
769 {0xb8, 0xfe, 0x02, 0xcc},
770 {0xb8, 0xff, 0x07, 0xcc}, {0xb9, 0x00, 0x14, 0xcc},
771 {0xb9, 0x01, 0x14, 0xcc}, {0xb9, 0x02, 0x14, 0xcc},
772 {0xb9, 0x03, 0x00, 0xcc},
773 {0xb9, 0x04, 0x02, 0xcc}, {0xb9, 0x05, 0x05, 0xcc},
774 {0xb9, 0x06, 0x0f, 0xcc}, {0xb9, 0x07, 0x0f, 0xcc},
775 {0xb9, 0x08, 0x0f, 0xcc},
776 {0xb8, 0x2c, 0x60, 0xcc}, {0xb8, 0x2d, 0xf8, 0xcc},
777 {0xb8, 0x2e, 0xf8, 0xcc}, {0xb8, 0x2f, 0xf8, 0xcc},
778 {0xb8, 0x30, 0x50, 0xcc},
779 {0xb8, 0x31, 0xf8, 0xcc}, {0xb8, 0x32, 0xf8, 0xcc},
780 {0xb8, 0x33, 0xf8, 0xcc},
781 {0xb8, 0x34, 0x65, 0xcc}, {0xb8, 0x35, 0x00, 0xcc},
782 {0xb8, 0x36, 0x00, 0xcc}, {0xb8, 0x37, 0x00, 0xcc},
783 {0xb8, 0x27, 0x20, 0xcc},
784 {0xb8, 0x01, 0x7d, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
785 {0xb3, 0x01, 0x41, 0xcc}, {0xb8, 0xfe, 0x00, 0xcc},
786 {0xb8, 0xff, 0x28, 0xcc},
787 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
788 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
789 {0xb9, 0x04, 0x00, 0xcc},
790 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
791 {0xb9, 0x07, 0x3c, 0xcc}, {0xb9, 0x08, 0x3c, 0xcc},
792 {0xb8, 0x8e, 0x00, 0xcc},
793 {0xb8, 0x8f, 0xff, 0xcc}, {0x00, 0x30, 0x18, 0xaa},
794 {}
795};
796
797static const __u8 ov7660_gamma[17] = {
798 0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
799 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
800};
801static const __u8 ov7660_matrix[9] = {
802 0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
803};
804static const __u8 ov7660_initVGA_data[][4] = {
805 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
806 {0x00, 0x00, 0x50, 0xdd},
807 {0xb0, 0x03, 0x01, 0xcc},
808 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
809 {0xb3, 0x05, 0x01, 0xcc},
810 {0xb3, 0x06, 0x03, 0xcc},
811 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
812 {0xb3, 0x05, 0x00, 0xcc},
813 {0xb3, 0x06, 0x01, 0xcc},
814 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
815 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
816 {0xb3, 0x21, 0x00, 0xcc},
817 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
818 {0xb3, 0x1f, 0x02, 0xcc},
819 {0xb3, 0x34, 0x01, 0xcc},
820 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
821 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
822 {0xb8, 0x01, 0x7d, 0xcc},
823 {0xbc, 0x00, 0x73, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
824 {0xb8, 0x27, 0x20, 0xcc},
825 {0xb8, 0x8f, 0x50, 0xcc},
826 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
827 {0x00, 0x12, 0x80, 0xaa},
828 {0x00, 0x12, 0x05, 0xaa},
829 {0x00, 0x1e, 0x01, 0xaa},
830 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
831 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
832 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
833 {0x00, 0x13, 0xa7, 0xaa},
834 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
835 {0x00, 0x36, 0x00, 0xaa},
836 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
837 {0x00, 0x39, 0x43, 0xaa},
838 {0x00, 0x8d, 0xcf, 0xaa},
839 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
840 {0x00, 0x0f, 0x62, 0xaa},
841 {0x00, 0x35, 0x84, 0xaa},
842 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
843 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
844 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
845 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
846 {0x00, 0x01, 0x80, 0xaa},
847 {0x00, 0x02, 0x80, 0xaa},
848 {0xb8, 0xfe, 0x00, 0xcc}, {0xb8, 0xff, 0x28, 0xcc},
849 {0xb9, 0x00, 0x28, 0xcc},
850 {0xb9, 0x01, 0x28, 0xcc}, {0xb9, 0x02, 0x28, 0xcc},
851 {0xb9, 0x03, 0x00, 0xcc},
852 {0xb9, 0x04, 0x00, 0xcc},
853 {0xb9, 0x05, 0x3c, 0xcc}, {0xb9, 0x06, 0x3c, 0xcc},
854 {0xb9, 0x07, 0x3c, 0xcc},
855 {0xb9, 0x08, 0x3c, 0xcc},
856
857 {0xb8, 0x8e, 0x00, 0xcc}, {0xb8, 0x8f, 0xff, 0xcc},
858
859 {0x00, 0x29, 0x3c, 0xaa}, {0xb3, 0x01, 0x45, 0xcc},
860 {}
861};
862static const __u8 ov7660_initQVGA_data[][4] = {
863 {0xb0, 0x4d, 0x00, 0xcc}, {0xb3, 0x01, 0x01, 0xcc},
864 {0x00, 0x00, 0x50, 0xdd}, {0xb0, 0x03, 0x01, 0xcc},
865 {0xb3, 0x00, 0x21, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
866 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x03, 0xcc},
867 {0xb3, 0x03, 0x1f, 0xcc}, {0xb3, 0x04, 0x05, 0xcc},
868 {0xb3, 0x05, 0x00, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
869 {0xb3, 0x15, 0x00, 0xcc},/* 0xb315 <-0 href startl */
870 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
871 {0xb3, 0x21, 0x00, 0xcc},
872 {0xb3, 0x23, 0xe0, 0xcc}, {0xb3, 0x1d, 0x01, 0xcc},
873 {0xb3, 0x1f, 0x02, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
874 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x00, 0x26, 0xcc},
875 {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
876 {0xb8, 0x01, 0x7d, 0xcc},
877/* sizer */
878 {0xbc, 0x00, 0xd3, 0xcc},
879 {0xb8, 0x81, 0x09, 0xcc}, {0xb8, 0x81, 0x09, 0xcc},
880 {0xb8, 0x27, 0x20, 0xcc}, {0xb8, 0x8f, 0x50, 0xcc},
881 {0x00, 0x01, 0x80, 0xaa}, {0x00, 0x02, 0x80, 0xaa},
882 {0x00, 0x12, 0x80, 0xaa}, {0x00, 0x12, 0x05, 0xaa},
883 {0x00, 0x1e, 0x01, 0xaa},
884 {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
885 {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
886 {0x00, 0x0d, 0x48, 0xaa}, {0x00, 0x0e, 0x04, 0xaa},
887 {0x00, 0x13, 0xa7, 0xaa},
888 {0x00, 0x40, 0xc1, 0xaa}, {0x00, 0x35, 0x00, 0xaa},
889 {0x00, 0x36, 0x00, 0xaa},
890 {0x00, 0x3c, 0x68, 0xaa}, {0x00, 0x1b, 0x05, 0xaa},
891 {0x00, 0x39, 0x43, 0xaa}, {0x00, 0x8d, 0xcf, 0xaa},
892 {0x00, 0x8b, 0xcc, 0xaa}, {0x00, 0x8c, 0xcc, 0xaa},
893 {0x00, 0x0f, 0x62, 0xaa}, {0x00, 0x35, 0x84, 0xaa},
894 {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
895 {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
896 {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
897 {0x00, 0x9e, 0x40, 0xaa}, {0xb8, 0x8f, 0x50, 0xcc},
898 {0x00, 0x01, 0x80, 0xaa},
899 {0x00, 0x02, 0x80, 0xaa},
900/* sizer filters */
901 {0xbc, 0x02, 0x08, 0xcc},
902 {0xbc, 0x03, 0x70, 0xcc},
903 {0xb8, 0x35, 0x00, 0xcc},
904 {0xb8, 0x36, 0x00, 0xcc},
905 {0xb8, 0x37, 0x00, 0xcc},
906 {0xbc, 0x04, 0x08, 0xcc},
907 {0xbc, 0x05, 0x00, 0xcc},
908 {0xbc, 0x06, 0x00, 0xcc},
909 {0xbc, 0x08, 0x3c, 0xcc},
910 {0xbc, 0x09, 0x40, 0xcc},
911 {0xbc, 0x0a, 0x04, 0xcc},
912 {0xbc, 0x0b, 0x00, 0xcc},
913 {0xbc, 0x0c, 0x00, 0xcc},
914/* */
915 {0xb8, 0xfe, 0x00, 0xcc},
916 {0xb8, 0xff, 0x28, 0xcc},
917/* */
918 {0xb9, 0x00, 0x28, 0xcc}, {0xb9, 0x01, 0x28, 0xcc},
919 {0xb9, 0x02, 0x28, 0xcc}, {0xb9, 0x03, 0x00, 0xcc},
920 {0xb9, 0x04, 0x00, 0xcc}, {0xb9, 0x05, 0x3c, 0xcc},
921 {0xb9, 0x06, 0x3c, 0xcc}, {0xb9, 0x07, 0x3c, 0xcc},
922 {0xb9, 0x08, 0x3c, 0xcc},
923/* */
924 {0xb8, 0x8e, 0x00, 0xcc},
925 {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
926 {0x00, 0x29, 0x3c, 0xaa},
927 {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
928 {}
929};
930
931static const __u8 ov7660_50HZ[][4] = {
932 {0x00, 0x3b, 0x08, 0xaa},
933 {0x00, 0x9d, 0x40, 0xaa},
934 {0x00, 0x13, 0xa7, 0xaa},
935 {}
936};
937
938static const __u8 ov7660_60HZ[][4] = {
939 {0x00, 0x3b, 0x00, 0xaa},
940 {0x00, 0x9e, 0x40, 0xaa},
941 {0x00, 0x13, 0xa7, 0xaa},
942 {}
943};
944
945static const __u8 ov7660_NoFliker[][4] = {
946 {0x00, 0x13, 0x87, 0xaa},
947 {}
948};
949
950static const __u8 ov7670_initVGA_JPG[][4] = {
951 {0xb3, 0x01, 0x05, 0xcc},
952 {0x00, 0x00, 0x30, 0xdd}, {0xb0, 0x03, 0x19, 0xcc},
953 {0x00, 0x00, 0x10, 0xdd},
954 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
955 {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc},
956 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
957 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
958 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
959 {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc},
960 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
961 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
962 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
963 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
964 {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0x41, 0xcc},
965 {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa},
966 {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa},
967 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa},
968 {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
969 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa},
970 {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa},
971 {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa},
972 {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa},
973 {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa},
974 {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa},
975 {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa},
976 {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa},
977 {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa},
978 {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa},
979 {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa},
980 {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa},
981 {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa},
982 {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa},
983 {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa},
984 {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa},
985 {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa},
986 {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
987 {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa},
988 {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
989 {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa},
990 {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa},
991 {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa},
992 {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa},
993 {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa},
994 {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa},
995 {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa},
996 {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa},
997 {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa},
998 {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa},
999 {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1000 {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa},
1001 {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa},
1002 {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa},
1003 {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa},
1004 {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa},
1005 {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa},
1006 {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa},
1007 {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa},
1008 {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa},
1009 {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa},
1010 {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa},
1011 {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa},
1012 {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa},
1013 {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa},
1014 {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa},
1015 {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa},
1016 {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa},
1017 {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa},
1018 {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1019 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa},
1020 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1021 {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa},
1022 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1023 {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa},
1024 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1025 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa},
1026 {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa},
1027 {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa},
1028 {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa},
1029 {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa},
1030 {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa},
1031 {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa},
1032 {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa},
1033 {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa},
1034 {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa},
1035 {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa},
1036 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa},
1037 {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa},
1038 {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa},
1039 {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa},
1040 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa},
1041 {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa},
1042 {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa},
1043 {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa},
1044 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa},
1045 {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1046 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa},
1047 {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa},
1048 {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa},
1049 {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa},
1050 {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa},
1051 {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa},
1052 {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa},
1053 {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1054 {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1055 {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa},
1056 {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa},
1057 {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa},
1058 {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1059 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa},
1060 {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1061 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa},
1062 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1063 {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa},
1064 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1065 {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc},
1066 {0xb6, 0x03, 0x02, 0xcc}, {0xb6, 0x02, 0x80, 0xcc},
1067 {0xb6, 0x05, 0x01, 0xcc}, {0xb6, 0x04, 0xe0, 0xcc},
1068 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x13, 0xcc},
1069 {0xb6, 0x18, 0x02, 0xcc}, {0xb6, 0x17, 0x58, 0xcc},
1070 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
1071 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
1072 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
1073 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc},
1074 {0x00, 0x77, 0x05, 0xaa},
1075 {},
1076};
1077
1078static const __u8 ov7670_initQVGA_JPG[][4] = {
1079 {0xb3, 0x01, 0x05, 0xcc}, {0x00, 0x00, 0x30, 0xdd},
1080 {0xb0, 0x03, 0x19, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
1081 {0xb0, 0x04, 0x02, 0xcc}, {0x00, 0x00, 0x10, 0xdd},
1082 {0xb3, 0x00, 0x66, 0xcc}, {0xb3, 0x00, 0x67, 0xcc},
1083 {0xb3, 0x35, 0xa1, 0xcc}, {0xb3, 0x34, 0x01, 0xcc},
1084 {0xb3, 0x05, 0x01, 0xcc}, {0xb3, 0x06, 0x01, 0xcc},
1085 {0xb3, 0x08, 0x01, 0xcc}, {0xb3, 0x09, 0x0c, 0xcc},
1086 {0xb3, 0x02, 0x02, 0xcc}, {0xb3, 0x03, 0x1f, 0xcc},
1087 {0xb3, 0x14, 0x00, 0xcc}, {0xb3, 0x15, 0x00, 0xcc},
1088 {0xb3, 0x16, 0x02, 0xcc}, {0xb3, 0x17, 0x7f, 0xcc},
1089 {0xb3, 0x04, 0x05, 0xcc}, {0xb3, 0x20, 0x00, 0xcc},
1090 {0xb3, 0x21, 0x00, 0xcc}, {0xb3, 0x22, 0x01, 0xcc},
1091 {0xb3, 0x23, 0xe0, 0xcc}, {0xbc, 0x00, 0xd1, 0xcc},
1092 {0xbc, 0x01, 0x01, 0xcc}, {0x00, 0x12, 0x80, 0xaa},
1093 {0x00, 0x00, 0x20, 0xdd}, {0x00, 0x12, 0x00, 0xaa},
1094 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x6b, 0x0a, 0xaa},
1095 {0x00, 0x3a, 0x04, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1096 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x7a, 0x29, 0xaa},
1097 {0x00, 0x7b, 0x0e, 0xaa}, {0x00, 0x7c, 0x1a, 0xaa},
1098 {0x00, 0x7d, 0x31, 0xaa}, {0x00, 0x7e, 0x53, 0xaa},
1099 {0x00, 0x7f, 0x60, 0xaa}, {0x00, 0x80, 0x6b, 0xaa},
1100 {0x00, 0x81, 0x73, 0xaa}, {0x00, 0x82, 0x7b, 0xaa},
1101 {0x00, 0x83, 0x82, 0xaa}, {0x00, 0x84, 0x89, 0xaa},
1102 {0x00, 0x85, 0x96, 0xaa}, {0x00, 0x86, 0xa1, 0xaa},
1103 {0x00, 0x87, 0xb7, 0xaa}, {0x00, 0x88, 0xcc, 0xaa},
1104 {0x00, 0x89, 0xe1, 0xaa}, {0x00, 0x13, 0xe0, 0xaa},
1105 {0x00, 0x00, 0x00, 0xaa}, {0x00, 0x10, 0x00, 0xaa},
1106 {0x00, 0x0d, 0x40, 0xaa}, {0x00, 0x14, 0x28, 0xaa},
1107 {0x00, 0xa5, 0x05, 0xaa}, {0x00, 0xab, 0x07, 0xaa},
1108 {0x00, 0x24, 0x95, 0xaa}, {0x00, 0x25, 0x33, 0xaa},
1109 {0x00, 0x26, 0xe3, 0xaa}, {0x00, 0x9f, 0x88, 0xaa},
1110 {0x00, 0xa0, 0x78, 0xaa}, {0x00, 0x55, 0x90, 0xaa},
1111 {0x00, 0xa1, 0x03, 0xaa}, {0x00, 0xa6, 0xe0, 0xaa},
1112 {0x00, 0xa7, 0xd8, 0xaa}, {0x00, 0xa8, 0xf0, 0xaa},
1113 {0x00, 0xa9, 0x90, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1114 {0x00, 0x13, 0xe5, 0xaa}, {0x00, 0x0e, 0x61, 0xaa},
1115 {0x00, 0x0f, 0x4b, 0xaa}, {0x00, 0x16, 0x02, 0xaa},
1116 {0x00, 0x1e, 0x07, 0xaa}, {0x00, 0x21, 0x02, 0xaa},
1117 {0x00, 0x22, 0x91, 0xaa}, {0x00, 0x29, 0x07, 0xaa},
1118 {0x00, 0x33, 0x0b, 0xaa}, {0x00, 0x35, 0x0b, 0xaa},
1119 {0x00, 0x37, 0x1d, 0xaa}, {0x00, 0x38, 0x71, 0xaa},
1120 {0x00, 0x39, 0x2a, 0xaa}, {0x00, 0x3c, 0x78, 0xaa},
1121 {0x00, 0x4d, 0x40, 0xaa}, {0x00, 0x4e, 0x20, 0xaa},
1122 {0x00, 0x74, 0x19, 0xaa}, {0x00, 0x8d, 0x4f, 0xaa},
1123 {0x00, 0x8e, 0x00, 0xaa}, {0x00, 0x8f, 0x00, 0xaa},
1124 {0x00, 0x90, 0x00, 0xaa}, {0x00, 0x91, 0x00, 0xaa},
1125 {0x00, 0x96, 0x00, 0xaa}, {0x00, 0x9a, 0x80, 0xaa},
1126 {0x00, 0xb0, 0x84, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1127 {0x00, 0xb2, 0x0e, 0xaa}, {0x00, 0xb3, 0x82, 0xaa},
1128 {0x00, 0xb8, 0x0a, 0xaa}, {0x00, 0x43, 0x14, 0xaa},
1129 {0x00, 0x44, 0xf0, 0xaa}, {0x00, 0x45, 0x45, 0xaa},
1130 {0x00, 0x46, 0x63, 0xaa}, {0x00, 0x47, 0x2d, 0xaa},
1131 {0x00, 0x48, 0x46, 0xaa}, {0x00, 0x59, 0x88, 0xaa},
1132 {0x00, 0x5a, 0xa0, 0xaa}, {0x00, 0x5b, 0xc6, 0xaa},
1133 {0x00, 0x5c, 0x7d, 0xaa}, {0x00, 0x5d, 0x5f, 0xaa},
1134 {0x00, 0x5e, 0x19, 0xaa}, {0x00, 0x6c, 0x0a, 0xaa},
1135 {0x00, 0x6d, 0x55, 0xaa}, {0x00, 0x6e, 0x11, 0xaa},
1136 {0x00, 0x6f, 0x9e, 0xaa}, {0x00, 0x69, 0x00, 0xaa},
1137 {0x00, 0x6a, 0x40, 0xaa}, {0x00, 0x01, 0x40, 0xaa},
1138 {0x00, 0x02, 0x40, 0xaa}, {0x00, 0x13, 0xe7, 0xaa},
1139 {0x00, 0x5f, 0xf0, 0xaa}, {0x00, 0x60, 0xf0, 0xaa},
1140 {0x00, 0x61, 0xf0, 0xaa}, {0x00, 0x27, 0xa0, 0xaa},
1141 {0x00, 0x28, 0x80, 0xaa}, {0x00, 0x2c, 0x90, 0xaa},
1142 {0x00, 0x4f, 0x66, 0xaa}, {0x00, 0x50, 0x66, 0xaa},
1143 {0x00, 0x51, 0x00, 0xaa}, {0x00, 0x52, 0x22, 0xaa},
1144 {0x00, 0x53, 0x5e, 0xaa}, {0x00, 0x54, 0x80, 0xaa},
1145 {0x00, 0x58, 0x9e, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1146 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x85, 0xaa},
1147 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1148 {0x00, 0x77, 0x0a, 0xaa}, {0x00, 0x3d, 0x88, 0xaa},
1149 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1150 {0x00, 0x41, 0x38, 0xaa}, {0x00, 0x62, 0x30, 0xaa},
1151 {0x00, 0x63, 0x30, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1152 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x0b, 0xaa},
1153 {0x00, 0x65, 0x00, 0xaa}, {0x00, 0x66, 0x05, 0xaa},
1154 {0x00, 0x56, 0x50, 0xaa}, {0x00, 0x34, 0x11, 0xaa},
1155 {0x00, 0xa4, 0x88, 0xaa}, {0x00, 0x96, 0x00, 0xaa},
1156 {0x00, 0x97, 0x30, 0xaa}, {0x00, 0x98, 0x20, 0xaa},
1157 {0x00, 0x99, 0x30, 0xaa}, {0x00, 0x9a, 0x84, 0xaa},
1158 {0x00, 0x9b, 0x29, 0xaa}, {0x00, 0x9c, 0x03, 0xaa},
1159 {0x00, 0x78, 0x04, 0xaa}, {0x00, 0x79, 0x01, 0xaa},
1160 {0x00, 0xc8, 0xf0, 0xaa}, {0x00, 0x79, 0x0f, 0xaa},
1161 {0x00, 0xc8, 0x00, 0xaa}, {0x00, 0x79, 0x10, 0xaa},
1162 {0x00, 0xc8, 0x7e, 0xaa}, {0x00, 0x79, 0x0a, 0xaa},
1163 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x0b, 0xaa},
1164 {0x00, 0xc8, 0x01, 0xaa}, {0x00, 0x79, 0x0c, 0xaa},
1165 {0x00, 0xc8, 0x0f, 0xaa}, {0x00, 0x79, 0x0d, 0xaa},
1166 {0x00, 0xc8, 0x20, 0xaa}, {0x00, 0x79, 0x09, 0xaa},
1167 {0x00, 0xc8, 0x80, 0xaa}, {0x00, 0x79, 0x02, 0xaa},
1168 {0x00, 0xc8, 0xc0, 0xaa}, {0x00, 0x79, 0x03, 0xaa},
1169 {0x00, 0xc8, 0x40, 0xaa}, {0x00, 0x79, 0x05, 0xaa},
1170 {0x00, 0xc8, 0x30, 0xaa}, {0x00, 0x79, 0x26, 0xaa},
1171 {0x00, 0x11, 0x40, 0xaa}, {0x00, 0x3a, 0x04, 0xaa},
1172 {0x00, 0x12, 0x00, 0xaa}, {0x00, 0x40, 0xc0, 0xaa},
1173 {0x00, 0x8c, 0x00, 0xaa}, {0x00, 0x17, 0x14, 0xaa},
1174 {0x00, 0x18, 0x02, 0xaa}, {0x00, 0x32, 0x92, 0xaa},
1175 {0x00, 0x19, 0x02, 0xaa}, {0x00, 0x1a, 0x7a, 0xaa},
1176 {0x00, 0x03, 0x0a, 0xaa}, {0x00, 0x0c, 0x00, 0xaa},
1177 {0x00, 0x3e, 0x00, 0xaa}, {0x00, 0x70, 0x3a, 0xaa},
1178 {0x00, 0x71, 0x35, 0xaa}, {0x00, 0x72, 0x11, 0xaa},
1179 {0x00, 0x73, 0xf0, 0xaa}, {0x00, 0xa2, 0x02, 0xaa},
1180 {0x00, 0xb1, 0x00, 0xaa}, {0x00, 0xb1, 0x0c, 0xaa},
1181 {0x00, 0x1e, 0x37, 0xaa}, {0x00, 0xaa, 0x14, 0xaa},
1182 {0x00, 0x24, 0x80, 0xaa}, {0x00, 0x25, 0x74, 0xaa},
1183 {0x00, 0x26, 0xd3, 0xaa}, {0x00, 0x0d, 0x00, 0xaa},
1184 {0x00, 0x14, 0x18, 0xaa}, {0x00, 0x9d, 0x99, 0xaa},
1185 {0x00, 0x9e, 0x7f, 0xaa}, {0x00, 0x64, 0x08, 0xaa},
1186 {0x00, 0x94, 0x07, 0xaa}, {0x00, 0x95, 0x06, 0xaa},
1187 {0x00, 0x66, 0x05, 0xaa}, {0x00, 0x41, 0x08, 0xaa},
1188 {0x00, 0x3f, 0x00, 0xaa}, {0x00, 0x75, 0x07, 0xaa},
1189 {0x00, 0x76, 0xe1, 0xaa}, {0x00, 0x4c, 0x00, 0xaa},
1190 {0x00, 0x77, 0x00, 0xaa}, {0x00, 0x3d, 0xc2, 0xaa},
1191 {0x00, 0x4b, 0x09, 0xaa}, {0x00, 0xc9, 0x60, 0xaa},
1192 {0x00, 0x41, 0x38, 0xaa}, {0xb6, 0x00, 0x00, 0xcc},
1193 {0xb6, 0x03, 0x01, 0xcc}, {0xb6, 0x02, 0x40, 0xcc},
1194 {0xb6, 0x05, 0x00, 0xcc}, {0xb6, 0x04, 0xf0, 0xcc},
1195 {0xb6, 0x12, 0xf8, 0xcc}, {0xb6, 0x13, 0x21, 0xcc},
1196 {0xb6, 0x18, 0x00, 0xcc}, {0xb6, 0x17, 0x96, 0xcc},
1197 {0xb6, 0x16, 0x00, 0xcc}, {0xb6, 0x22, 0x12, 0xcc},
1198 {0xb6, 0x23, 0x0b, 0xcc}, {0xbf, 0xc0, 0x39, 0xcc},
1199 {0xbf, 0xc1, 0x04, 0xcc}, {0xbf, 0xcc, 0x00, 0xcc},
1200 {0xbc, 0x02, 0x18, 0xcc}, {0xbc, 0x03, 0x50, 0xcc},
1201 {0xbc, 0x04, 0x18, 0xcc}, {0xbc, 0x05, 0x00, 0xcc},
1202 {0xbc, 0x06, 0x00, 0xcc}, {0xbc, 0x08, 0x30, 0xcc},
1203 {0xbc, 0x09, 0x40, 0xcc}, {0xbc, 0x0a, 0x10, 0xcc},
1204 {0xbc, 0x0b, 0x00, 0xcc}, {0xbc, 0x0c, 0x00, 0xcc},
1205 {0xb3, 0x5c, 0x01, 0xcc}, {0xb3, 0x01, 0x45, 0xcc},
1206 {0x00, 0x77, 0x05, 0xaa },
1207 {},
1208};
1209
1210struct sensor_info {
1211 int sensorId;
1212 __u8 I2cAdd;
1213 __u8 IdAdd;
1214 __u16 VpId;
1215 __u8 m1;
1216 __u8 m2;
1217 __u8 op;
1218 };
1219
1220static const struct sensor_info sensor_info_data[] = {
1221/* sensorId, I2cAdd, IdAdd, VpId, m1, m2, op */
1222 {SENSOR_HV7131R, 0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
1223 {SENSOR_OV7660, 0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
1224 {SENSOR_PO3130NC, 0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01},
1225 {SENSOR_MI1320, 0x80 | 0xc8, 0x00, 0x148c, 0x64, 0x65, 0x01},
1226 {SENSOR_OV7670, 0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
1227 {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
1228};
1229
1230/* read 'len' bytes in gspca_dev->usb_buf */
1231static void reg_r(struct gspca_dev *gspca_dev,
1232 __u16 req,
1233 __u16 index,
1234 __u16 len)
1235{
1236 usb_control_msg(gspca_dev->dev,
1237 usb_rcvctrlpipe(gspca_dev->dev, 0),
1238 req,
1239 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1240 1, /* value */
1241 index, gspca_dev->usb_buf, len,
1242 500);
1243}
1244
1245static void reg_w(struct usb_device *dev,
1246 __u16 req,
1247 __u16 value,
1248 __u16 index)
1249{
1250 usb_control_msg(dev,
1251 usb_sndctrlpipe(dev, 0),
1252 req,
1253 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1254 value, index, NULL, 0,
1255 500);
1256}
1257
1258static void read_sensor_register(struct gspca_dev *gspca_dev,
1259 __u16 address, __u16 *value)
1260{
1261 struct usb_device *dev = gspca_dev->dev;
1262 __u8 ldata, mdata, hdata;
1263 int retry = 50;
1264
1265 *value = 0;
1266
1267 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
1268 /*PDEBUG(D_PROBE, " I2c Bus Busy Wait 0x%02X ", tmpvalue); */
1269 if (!(gspca_dev->usb_buf[0] & 0x02)) {
1270 PDEBUG(D_ERR, "I2c Bus Busy Wait %d",
1271 gspca_dev->usb_buf[0] & 0x02);
1272 return;
1273 }
1274 reg_w(dev, 0xa0, address, 0xb33a);
1275 reg_w(dev, 0xa0, 0x02, 0xb339);
1276
1277 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1278 while (retry-- && gspca_dev->usb_buf[0]) {
1279 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1280/* PDEBUG(D_PROBE, "Read again 0xb33b %d", tmpvalue); */
1281 msleep(1);
1282 }
1283 reg_r(gspca_dev, 0xa1, 0xb33e, 1);
1284 hdata = gspca_dev->usb_buf[0];
1285 reg_r(gspca_dev, 0xa1, 0xb33d, 1);
1286 mdata = gspca_dev->usb_buf[0];
1287 reg_r(gspca_dev, 0xa1, 0xb33c, 1);
1288 ldata = gspca_dev->usb_buf[0];
1289 PDEBUG(D_PROBE, "Read Sensor h (0x%02X) m (0x%02X) l (0x%02X)",
1290 hdata, mdata, ldata);
1291 reg_r(gspca_dev, 0xa1, 0xb334, 1);
1292 if (gspca_dev->usb_buf[0] == 0x02)
1293 *value = (ldata << 8) + mdata;
1294 else
1295 *value = ldata;
1296}
1297
1298static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
1299{
1300 struct usb_device *dev = gspca_dev->dev;
1301 int i;
1302 __u16 value;
1303 const struct sensor_info *ptsensor_info;
1304
1305 reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
1306 PDEBUG(D_PROBE, "check sensor header %d", gspca_dev->usb_buf[0]);
1307 for (i = 0; i < ARRAY_SIZE(sensor_info_data); i++) {
1308 ptsensor_info = &sensor_info_data[i];
1309 reg_w(dev, 0xa0, 0x02, 0xb334);
1310 reg_w(dev, 0xa0, ptsensor_info->m1, 0xb300);
1311 reg_w(dev, 0xa0, ptsensor_info->m2, 0xb300);
1312 reg_w(dev, 0xa0, 0x01, 0xb308);
1313 reg_w(dev, 0xa0, 0x0c, 0xb309);
1314 reg_w(dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
1315/* PDEBUG(D_PROBE,
1316 "check sensor VC032X -> %d Add -> ox%02X!",
1317 i, ptsensor_info->I2cAdd); */
1318 reg_w(dev, 0xa0, ptsensor_info->op, 0xb301);
1319 read_sensor_register(gspca_dev, ptsensor_info->IdAdd, &value);
1320 if (value == ptsensor_info->VpId) {
1321/* PDEBUG(D_PROBE, "find sensor VC032X -> ox%04X!",
1322 ptsensor_info->VpId); */
1323 return ptsensor_info->sensorId;
1324 }
1325 }
1326 return -1;
1327}
1328
1329static __u8 i2c_write(struct gspca_dev *gspca_dev,
1330 __u8 reg, const __u8 *val, __u8 size)
1331{
1332 struct usb_device *dev = gspca_dev->dev;
1333
1334 if (size > 3 || size < 1)
1335 return -EINVAL;
1336 reg_r(gspca_dev, 0xa1, 0xb33f, 1);
1337 reg_w(dev, 0xa0, size, 0xb334);
1338 reg_w(dev, 0xa0, reg, 0xb33a);
1339 switch (size) {
1340 case 1:
1341 reg_w(dev, 0xa0, val[0], 0xb336);
1342 break;
1343 case 2:
1344 reg_w(dev, 0xa0, val[0], 0xb336);
1345 reg_w(dev, 0xa0, val[1], 0xb337);
1346 break;
1347 case 3:
1348 reg_w(dev, 0xa0, val[0], 0xb336);
1349 reg_w(dev, 0xa0, val[1], 0xb337);
1350 reg_w(dev, 0xa0, val[2], 0xb338);
1351 break;
1352 default:
1353 reg_w(dev, 0xa0, 0x01, 0xb334);
1354 return -EINVAL;
1355 }
1356 reg_w(dev, 0xa0, 0x01, 0xb339);
1357 reg_r(gspca_dev, 0xa1, 0xb33b, 1);
1358 return gspca_dev->usb_buf[0] == 0;
1359}
1360
1361static void put_tab_to_reg(struct gspca_dev *gspca_dev,
1362 const __u8 *tab, __u8 tabsize, __u16 addr)
1363{
1364 int j;
1365 __u16 ad = addr;
1366
1367 for (j = 0; j < tabsize; j++)
1368 reg_w(gspca_dev->dev, 0xa0, tab[j], ad++);
1369}
1370
1371static void usb_exchange(struct gspca_dev *gspca_dev,
1372 const __u8 data[][4])
1373{
1374 struct usb_device *dev = gspca_dev->dev;
1375 int i = 0;
1376
1377 for (;;) {
1378 switch (data[i][3]) {
1379 default:
1380 return;
1381 case 0xcc: /* normal write */
1382 reg_w(dev, 0xa0, data[i][2],
1383 ((data[i][0])<<8) | data[i][1]);
1384 break;
1385 case 0xaa: /* i2c op */
1386 i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
1387 break;
1388 case 0xbb: /* i2c op */
1389 i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
1390 break;
1391 case 0xdd:
1392 msleep(data[i][2] + 10);
1393 break;
1394 }
1395 i++;
1396 }
1397 /*not reached*/
1398}
1399
1400/*
1401 "GammaT"=hex:04,17,31,4f,6a,83,99,ad,bf,ce,da,e5,ee,f5,fb,ff,ff
1402 "MatrixT"=hex:60,f9,e5,e7,50,05,f3,e6,66
1403 */
1404
1405static void vc0321_reset(struct gspca_dev *gspca_dev)
1406{
1407 reg_w(gspca_dev->dev, 0xa0, 0x00, 0xb04d);
1408 reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb301);
1409 msleep(100);
1410 reg_w(gspca_dev->dev, 0xa0, 0x01, 0xb003);
1411 msleep(100);
1412}
1413
1414/* this function is called at probe time */
1415static int sd_config(struct gspca_dev *gspca_dev,
1416 const struct usb_device_id *id)
1417{
1418 struct sd *sd = (struct sd *) gspca_dev;
1419 struct usb_device *dev = gspca_dev->dev;
1420 struct cam *cam;
1421 int sensor;
1422 __u16 product;
1423
1424 product = id->idProduct;
1425 sd->bridge = BRIDGE_VC0321;
1426 switch (id->idVendor) {
1427 case 0x0ac8: /* Vimicro z-star */
1428 switch (product) {
1429 case 0x0323:
1430 sd->bridge = BRIDGE_VC0323;
1431 break;
1432 }
1433 break;
1434 case 0x17ef: /* Lenovo */
1435/* switch (product) { */
1436/* case 0x4802: * Lenovo MI1310_SOC */
1437 sd->bridge = BRIDGE_VC0323;
1438/* break; */
1439/* } */
1440 break;
1441 }
1442
1443 cam = &gspca_dev->cam;
1444 cam->dev_name = (char *) id->driver_info;
1445 cam->epaddr = 0x02;
1446 if (sd->bridge == BRIDGE_VC0321) {
1447 cam->cam_mode = vc0321_mode;
1448 cam->nmodes = ARRAY_SIZE(vc0321_mode);
1449 } else {
1450 cam->cam_mode = vc0323_mode;
1451 cam->nmodes = ARRAY_SIZE(vc0323_mode);
1452 }
1453
1454 vc0321_reset(gspca_dev);
1455 sensor = vc032x_probe_sensor(gspca_dev);
1456 switch (sensor) {
1457 case -1:
1458 PDEBUG(D_PROBE, "Unknown sensor...");
1459 return -EINVAL;
1460 case SENSOR_HV7131R:
1461 PDEBUG(D_PROBE, "Find Sensor HV7131R");
1462 sd->sensor = SENSOR_HV7131R;
1463 break;
1464 case SENSOR_MI1310_SOC:
1465 PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
1466 sd->sensor = SENSOR_MI1310_SOC;
1467 break;
1468 case SENSOR_MI1320:
1469 PDEBUG(D_PROBE, "Find Sensor MI1320");
1470 sd->sensor = SENSOR_MI1320;
1471 break;
1472 case SENSOR_OV7660:
1473 PDEBUG(D_PROBE, "Find Sensor OV7660");
1474 sd->sensor = SENSOR_OV7660;
1475 break;
1476 case SENSOR_OV7670:
1477 PDEBUG(D_PROBE, "Find Sensor OV7670");
1478 sd->sensor = SENSOR_OV7670;
1479 break;
1480 case SENSOR_PO3130NC:
1481 PDEBUG(D_PROBE, "Find Sensor PO3130NC");
1482 sd->sensor = SENSOR_PO3130NC;
1483 break;
1484 }
1485
1486 sd->qindex = 7;
1487 sd->autogain = AUTOGAIN_DEF;
1488 sd->lightfreq = FREQ_DEF;
1489
1490 if (sd->bridge == BRIDGE_VC0321) {
1491 reg_r(gspca_dev, 0x8a, 0, 3);
1492 reg_w(dev, 0x87, 0x00, 0x0f0f);
1493
1494 reg_r(gspca_dev, 0x8b, 0, 3);
1495 reg_w(dev, 0x88, 0x00, 0x0202);
1496 }
1497 return 0;
1498}
1499
1500/* this function is called at open time */
1501static int sd_open(struct gspca_dev *gspca_dev)
1502{
1503 return 0;
1504}
1505
1506static void setquality(struct gspca_dev *gspca_dev)
1507{
1508}
1509
1510static void setautogain(struct gspca_dev *gspca_dev)
1511{
1512}
1513
1514static void setlightfreq(struct gspca_dev *gspca_dev)
1515{
1516 struct sd *sd = (struct sd *) gspca_dev;
1517 static const __u8 (*ov7660_freq_tb[3])[4] =
1518 {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
1519
1520 if (sd->sensor != SENSOR_OV7660)
1521 return;
1522 usb_exchange(gspca_dev, ov7660_freq_tb[sd->lightfreq]);
1523}
1524
1525static void sd_start(struct gspca_dev *gspca_dev)
1526{
1527 struct sd *sd = (struct sd *) gspca_dev;
1528 const __u8 *GammaT = NULL;
1529 const __u8 *MatrixT = NULL;
1530 int mode;
1531
1532 /* Assume start use the good resolution from gspca_dev->mode */
1533 if (sd->bridge == BRIDGE_VC0321) {
1534 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfec);
1535 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfed);
1536 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfee);
1537 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xbfef);
1538 }
1539
1540 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
1541 switch (sd->sensor) {
1542 case SENSOR_HV7131R:
1543 GammaT = hv7131r_gamma;
1544 MatrixT = hv7131r_matrix;
1545 if (mode) {
1546 /* 320x240 */
1547 usb_exchange(gspca_dev, hv7131r_initQVGA_data);
1548 } else {
1549 /* 640x480 */
1550 usb_exchange(gspca_dev, hv7131r_initVGA_data);
1551 }
1552 break;
1553 case SENSOR_OV7660:
1554 GammaT = ov7660_gamma;
1555 MatrixT = ov7660_matrix;
1556 if (mode) {
1557 /* 320x240 */
1558 usb_exchange(gspca_dev, ov7660_initQVGA_data);
1559 } else {
1560 /* 640x480 */
1561 usb_exchange(gspca_dev, ov7660_initVGA_data);
1562 }
1563 break;
1564 case SENSOR_OV7670:
1565 /*GammaT = ov7660_gamma; */
1566 /*MatrixT = ov7660_matrix; */
1567 if (mode) {
1568 /* 320x240 */
1569 usb_exchange(gspca_dev, ov7670_initQVGA_JPG);
1570 } else {
1571 /* 640x480 */
1572 usb_exchange(gspca_dev, ov7670_initVGA_JPG);
1573 }
1574 break;
1575 case SENSOR_MI1310_SOC:
1576 if (mode) {
1577 /* 320x240 */
1578 usb_exchange(gspca_dev, mi1310_socinitQVGA_JPG);
1579 } else {
1580 /* 640x480 */
1581 usb_exchange(gspca_dev, mi1310_socinitVGA_JPG);
1582 }
1583 break;
1584 case SENSOR_MI1320:
1585 GammaT = mi1320_gamma;
1586 MatrixT = mi1320_matrix;
1587 if (mode) {
1588 /* 320x240 */
1589 usb_exchange(gspca_dev, mi1320_initQVGA_data);
1590 } else {
1591 /* 640x480 */
1592 usb_exchange(gspca_dev, mi1320_initVGA_data);
1593 }
1594 break;
1595 case SENSOR_PO3130NC:
1596 GammaT = po3130_gamma;
1597 MatrixT = po3130_matrix;
1598 if (mode) {
1599 /* 320x240 */
1600 usb_exchange(gspca_dev, po3130_initQVGA_data);
1601 } else {
1602 /* 640x480 */
1603 usb_exchange(gspca_dev, po3130_initVGA_data);
1604 }
1605 usb_exchange(gspca_dev, po3130_rundata);
1606 break;
1607 default:
1608 PDEBUG(D_PROBE, "Damned !! no sensor found Bye");
1609 return;
1610 }
1611 if (GammaT && MatrixT) {
1612 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
1613 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
1614 put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
1615 put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
1616
1617 /* Seem SHARPNESS */
1618 /*
1619 reg_w(gspca_dev->dev, 0xa0, 0x80, 0xb80a);
1620 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80b);
1621 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb80e);
1622 */
1623 /* all 0x40 ??? do nothing
1624 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb822);
1625 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb823);
1626 reg_w(gspca_dev->dev, 0xa0, 0x40, 0xb824);
1627 */
1628 /* Only works for HV7131R ??
1629 reg_r (gspca_dev, 0xa1, 0xb881, 1);
1630 reg_w(gspca_dev->dev, 0xa0, 0xfe01, 0xb881);
1631 reg_w(gspca_dev->dev, 0xa0, 0x79, 0xb801);
1632 */
1633 /* only hv7131r et ov7660
1634 reg_w(gspca_dev->dev, 0xa0, 0x20, 0xb827);
1635 reg_w(gspca_dev->dev, 0xa0, 0xff, 0xb826); * ISP_GAIN 80
1636 reg_w(gspca_dev->dev, 0xa0, 0x23, 0xb800); * ISP CTRL_BAS
1637 */
1638 /* set the led on 0x0892 0x0896 */
1639 reg_w(gspca_dev->dev, 0x89, 0xffff, 0xfdff);
1640 msleep(100);
1641 setquality(gspca_dev);
1642 setautogain(gspca_dev);
1643 setlightfreq(gspca_dev);
1644 }
1645}
1646
1647static void sd_stopN(struct gspca_dev *gspca_dev)
1648{
1649 struct usb_device *dev = gspca_dev->dev;
1650
1651 reg_w(dev, 0x89, 0xffff, 0xffff);
1652 reg_w(dev, 0xa0, 0x01, 0xb301);
1653 reg_w(dev, 0xa0, 0x09, 0xb003);
1654}
1655
1656static void sd_stop0(struct gspca_dev *gspca_dev)
1657{
1658 struct usb_device *dev = gspca_dev->dev;
1659
1660 reg_w(dev, 0x89, 0xffff, 0xffff);
1661}
1662
1663/* this function is called at close time */
1664static void sd_close(struct gspca_dev *gspca_dev)
1665{
1666/* struct usb_device *dev = gspca_dev->dev;
1667 __u8 buffread;
1668
1669 reg_w(dev, 0x89, 0xffff, 0xffff);
1670 reg_w(dev, 0xa0, 0x01, 0xb301);
1671 reg_w(dev, 0xa0, 0x09, 0xb303);
1672 reg_w(dev, 0x89, 0xffff, 0xffff);
1673*/
1674}
1675
1676static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1677 struct gspca_frame *frame, /* target */
1678 __u8 *data, /* isoc packet */
1679 int len) /* iso pkt length */
1680{
1681 struct sd *sd = (struct sd *) gspca_dev;
1682
1683 if (data[0] == 0xff && data[1] == 0xd8) {
1684 PDEBUG(D_PACK,
1685 "vc032x header packet found len %d", len);
1686 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
1687 data, 0);
1688 if (sd->bridge == BRIDGE_VC0321) {
1689#define VCHDRSZ 46
1690 data += VCHDRSZ;
1691 len -= VCHDRSZ;
1692#undef VCHDRSZ
1693 }
1694 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
1695 data, len);
1696 return;
1697 }
1698 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
1699}
1700
1701static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
1702{
1703 struct sd *sd = (struct sd *) gspca_dev;
1704
1705 sd->autogain = val;
1706 if (gspca_dev->streaming)
1707 setautogain(gspca_dev);
1708 return 0;
1709}
1710
1711static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
1712{
1713 struct sd *sd = (struct sd *) gspca_dev;
1714
1715 *val = sd->autogain;
1716 return 0;
1717}
1718
1719static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
1720{
1721 struct sd *sd = (struct sd *) gspca_dev;
1722
1723 sd->lightfreq = val;
1724 if (gspca_dev->streaming)
1725 setlightfreq(gspca_dev);
1726 return 0;
1727}
1728
1729static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
1730{
1731 struct sd *sd = (struct sd *) gspca_dev;
1732
1733 *val = sd->lightfreq;
1734 return 0;
1735}
1736
1737static int sd_querymenu(struct gspca_dev *gspca_dev,
1738 struct v4l2_querymenu *menu)
1739{
1740 switch (menu->id) {
1741 case V4L2_CID_POWER_LINE_FREQUENCY:
1742 switch (menu->index) {
1743 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
1744 strcpy((char *) menu->name, "NoFliker");
1745 return 0;
1746 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
1747 strcpy((char *) menu->name, "50 Hz");
1748 return 0;
1749 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
1750 strcpy((char *) menu->name, "60 Hz");
1751 return 0;
1752 }
1753 break;
1754 }
1755 return -EINVAL;
1756}
1757
1758/* sub-driver description */
1759static const struct sd_desc sd_desc = {
1760 .name = MODULE_NAME,
1761 .ctrls = sd_ctrls,
1762 .nctrls = ARRAY_SIZE(sd_ctrls),
1763 .config = sd_config,
1764 .open = sd_open,
1765 .start = sd_start,
1766 .stopN = sd_stopN,
1767 .stop0 = sd_stop0,
1768 .close = sd_close,
1769 .pkt_scan = sd_pkt_scan,
1770 .querymenu = sd_querymenu,
1771};
1772
1773/* -- module initialisation -- */
1774#define DVNM(name) .driver_info = (kernel_ulong_t) name
1775static const __devinitdata struct usb_device_id device_table[] = {
1776 {USB_DEVICE(0x046d, 0x0892), DVNM("Logitech Orbicam")},
1777 {USB_DEVICE(0x046d, 0x0896), DVNM("Logitech Orbicam")},
1778 {USB_DEVICE(0x0ac8, 0x0321), DVNM("Vimicro generic vc0321")},
1779 {USB_DEVICE(0x0ac8, 0x0323), DVNM("Vimicro Vc0323")},
1780 {USB_DEVICE(0x0ac8, 0x0328), DVNM("A4Tech PK-130MG")},
1781 {USB_DEVICE(0x0ac8, 0xc001), DVNM("Sony embedded vimicro")},
1782 {USB_DEVICE(0x0ac8, 0xc002), DVNM("Sony embedded vimicro")},
1783 {USB_DEVICE(0x17ef, 0x4802), DVNM("Lenovo Vc0323+MI1310_SOC")},
1784 {}
1785};
1786MODULE_DEVICE_TABLE(usb, device_table);
1787
1788/* -- device connect -- */
1789static int sd_probe(struct usb_interface *intf,
1790 const struct usb_device_id *id)
1791{
1792 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
1793 THIS_MODULE);
1794}
1795
1796static struct usb_driver sd_driver = {
1797 .name = MODULE_NAME,
1798 .id_table = device_table,
1799 .probe = sd_probe,
1800 .disconnect = gspca_disconnect,
1801};
1802
1803/* -- module insert / remove -- */
1804static int __init sd_mod_init(void)
1805{
1806 if (usb_register(&sd_driver) < 0)
1807 return -1;
1808 PDEBUG(D_PROBE, "v%s registered", version);
1809 return 0;
1810}
1811static void __exit sd_mod_exit(void)
1812{
1813 usb_deregister(&sd_driver);
1814 PDEBUG(D_PROBE, "deregistered");
1815}
1816
1817module_init(sd_mod_init);
1818module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/video/gspca/zc3xx-reg.h
new file mode 100644
index 000000000000..f52e09c2cc19
--- /dev/null
+++ b/drivers/media/video/gspca/zc3xx-reg.h
@@ -0,0 +1,261 @@
1/*
2 * zc030x registers
3 *
4 * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
5 *
6 * The register aliases used here came from this driver:
7 * http://zc0302.sourceforge.net/zc0302.php
8 *
9 * This code is placed under the terms of the GNU General Public License v2
10 */
11
12/* Define the register map */
13#define ZC3XX_R000_SYSTEMCONTROL 0x0000
14#define ZC3XX_R001_SYSTEMOPERATING 0x0001
15
16/* Picture size */
17#define ZC3XX_R002_CLOCKSELECT 0x0002
18#define ZC3XX_R003_FRAMEWIDTHHIGH 0x0003
19#define ZC3XX_R004_FRAMEWIDTHLOW 0x0004
20#define ZC3XX_R005_FRAMEHEIGHTHIGH 0x0005
21#define ZC3XX_R006_FRAMEHEIGHTLOW 0x0006
22
23/* JPEG control */
24#define ZC3XX_R008_CLOCKSETTING 0x0008
25
26/* Test mode */
27#define ZC3XX_R00B_TESTMODECONTROL 0x000b
28
29/* Frame retreiving */
30#define ZC3XX_R00C_LASTACQTIME 0x000c
31#define ZC3XX_R00D_MONITORRES 0x000d
32#define ZC3XX_R00E_TIMESTAMPHIGH 0x000e
33#define ZC3XX_R00F_TIMESTAMPLOW 0x000f
34#define ZC3XX_R018_FRAMELOST 0x0018
35#define ZC3XX_R019_AUTOADJUSTFPS 0x0019
36#define ZC3XX_R01A_LASTFRAMESTATE 0x001a
37#define ZC3XX_R025_DATACOUNTER 0x0025
38
39/* Stream and sensor specific */
40#define ZC3XX_R010_CMOSSENSORSELECT 0x0010
41#define ZC3XX_R011_VIDEOSTATUS 0x0011
42#define ZC3XX_R012_VIDEOCONTROLFUNC 0x0012
43
44/* Horizontal and vertical synchros */
45#define ZC3XX_R01D_HSYNC_0 0x001d
46#define ZC3XX_R01E_HSYNC_1 0x001e
47#define ZC3XX_R01F_HSYNC_2 0x001f
48#define ZC3XX_R020_HSYNC_3 0x0020
49
50/* Target picture size in byte */
51#define ZC3XX_R022_TARGETPICTSIZE_0 0x0022
52#define ZC3XX_R023_TARGETPICTSIZE_1 0x0023
53#define ZC3XX_R024_TARGETPICTSIZE_2 0x0024
54
55/* Audio registers */
56#define ZC3XX_R030_AUDIOADC 0x0030
57#define ZC3XX_R031_AUDIOSTREAMSTATUS 0x0031
58#define ZC3XX_R032_AUDIOSTATUS 0x0032
59
60/* Sensor interface */
61#define ZC3XX_R080_HBLANKHIGH 0x0080
62#define ZC3XX_R081_HBLANKLOW 0x0081
63#define ZC3XX_R082_RESETLEVELADDR 0x0082
64#define ZC3XX_R083_RGAINADDR 0x0083
65#define ZC3XX_R084_GGAINADDR 0x0084
66#define ZC3XX_R085_BGAINADDR 0x0085
67#define ZC3XX_R086_EXPTIMEHIGH 0x0086
68#define ZC3XX_R087_EXPTIMEMID 0x0087
69#define ZC3XX_R088_EXPTIMELOW 0x0088
70#define ZC3XX_R089_RESETBLACKHIGH 0x0089
71#define ZC3XX_R08A_RESETWHITEHIGH 0x008a
72#define ZC3XX_R08B_I2CDEVICEADDR 0x008b
73#define ZC3XX_R08C_I2CIDLEANDNACK 0x008c
74#define ZC3XX_R08D_COMPABILITYMODE 0x008d
75#define ZC3XX_R08E_COMPABILITYMODE2 0x008e
76
77/* I2C control */
78#define ZC3XX_R090_I2CCOMMAND 0x0090
79#define ZC3XX_R091_I2CSTATUS 0x0091
80#define ZC3XX_R092_I2CADDRESSSELECT 0x0092
81#define ZC3XX_R093_I2CSETVALUE 0x0093
82#define ZC3XX_R094_I2CWRITEACK 0x0094
83#define ZC3XX_R095_I2CREAD 0x0095
84#define ZC3XX_R096_I2CREADACK 0x0096
85
86/* Window inside the sensor array */
87#define ZC3XX_R097_WINYSTARTHIGH 0x0097
88#define ZC3XX_R098_WINYSTARTLOW 0x0098
89#define ZC3XX_R099_WINXSTARTHIGH 0x0099
90#define ZC3XX_R09A_WINXSTARTLOW 0x009a
91#define ZC3XX_R09B_WINHEIGHTHIGH 0x009b
92#define ZC3XX_R09C_WINHEIGHTLOW 0x009c
93#define ZC3XX_R09D_WINWIDTHHIGH 0x009d
94#define ZC3XX_R09E_WINWIDTHLOW 0x009e
95#define ZC3XX_R119_FIRSTYHIGH 0x0119
96#define ZC3XX_R11A_FIRSTYLOW 0x011a
97#define ZC3XX_R11B_FIRSTXHIGH 0x011b
98#define ZC3XX_R11C_FIRSTXLOW 0x011c
99
100/* Max sensor array size */
101#define ZC3XX_R09F_MAXXHIGH 0x009f
102#define ZC3XX_R0A0_MAXXLOW 0x00a0
103#define ZC3XX_R0A1_MAXYHIGH 0x00a1
104#define ZC3XX_R0A2_MAXYLOW 0x00a2
105#define ZC3XX_R0A3_EXPOSURETIMEHIGH 0x00a3
106#define ZC3XX_R0A4_EXPOSURETIMELOW 0x00a4
107#define ZC3XX_R0A5_EXPOSUREGAIN 0x00a5
108#define ZC3XX_R0A6_EXPOSUREBLACKLVL 0x00a6
109
110/* Other registers */
111#define ZC3XX_R100_OPERATIONMODE 0x0100
112#define ZC3XX_R101_SENSORCORRECTION 0x0101
113
114/* Gains */
115#define ZC3XX_R116_RGAIN 0x0116
116#define ZC3XX_R117_GGAIN 0x0117
117#define ZC3XX_R118_BGAIN 0x0118
118#define ZC3XX_R11D_GLOBALGAIN 0x011d
119#define ZC3XX_R1A8_DIGITALGAIN 0x01a8
120#define ZC3XX_R1A9_DIGITALLIMITDIFF 0x01a9
121#define ZC3XX_R1AA_DIGITALGAINSTEP 0x01aa
122
123/* Auto correction */
124#define ZC3XX_R180_AUTOCORRECTENABLE 0x0180
125#define ZC3XX_R181_WINXSTART 0x0181
126#define ZC3XX_R182_WINXWIDTH 0x0182
127#define ZC3XX_R183_WINXCENTER 0x0183
128#define ZC3XX_R184_WINYSTART 0x0184
129#define ZC3XX_R185_WINYWIDTH 0x0185
130#define ZC3XX_R186_WINYCENTER 0x0186
131
132/* Gain range */
133#define ZC3XX_R187_MAXGAIN 0x0187
134#define ZC3XX_R188_MINGAIN 0x0188
135
136/* Auto exposure and white balance */
137#define ZC3XX_R189_AWBSTATUS 0x0189
138#define ZC3XX_R18A_AWBFREEZE 0x018a
139#define ZC3XX_R18B_AESTATUS 0x018b
140#define ZC3XX_R18C_AEFREEZE 0x018c
141#define ZC3XX_R18F_AEUNFREEZE 0x018f
142#define ZC3XX_R190_EXPOSURELIMITHIGH 0x0190
143#define ZC3XX_R191_EXPOSURELIMITMID 0x0191
144#define ZC3XX_R192_EXPOSURELIMITLOW 0x0192
145#define ZC3XX_R195_ANTIFLICKERHIGH 0x0195
146#define ZC3XX_R196_ANTIFLICKERMID 0x0196
147#define ZC3XX_R197_ANTIFLICKERLOW 0x0197
148
149/* What is this ? */
150#define ZC3XX_R18D_YTARGET 0x018d
151#define ZC3XX_R18E_RESETLVL 0x018e
152
153/* Color */
154#define ZC3XX_R1A0_REDMEANAFTERAGC 0x01a0
155#define ZC3XX_R1A1_GREENMEANAFTERAGC 0x01a1
156#define ZC3XX_R1A2_BLUEMEANAFTERAGC 0x01a2
157#define ZC3XX_R1A3_REDMEANAFTERAWB 0x01a3
158#define ZC3XX_R1A4_GREENMEANAFTERAWB 0x01a4
159#define ZC3XX_R1A5_BLUEMEANAFTERAWB 0x01a5
160#define ZC3XX_R1A6_YMEANAFTERAE 0x01a6
161#define ZC3XX_R1A7_CALCGLOBALMEAN 0x01a7
162
163#define ZC3XX_R1A2_BLUEMEANAFTERAGC 0x01a2
164
165/* Matrixes */
166
167/* Color matrix is like :
168 R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03
169 G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13
170 B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23
171 */
172#define ZC3XX_R10A_RGB00 0x010a
173#define ZC3XX_R10B_RGB01 0x010b
174#define ZC3XX_R10C_RGB02 0x010c
175#define ZC3XX_R113_RGB03 0x0113
176#define ZC3XX_R10D_RGB10 0x010d
177#define ZC3XX_R10E_RGB11 0x010e
178#define ZC3XX_R10F_RGB12 0x010f
179#define ZC3XX_R114_RGB13 0x0114
180#define ZC3XX_R110_RGB20 0x0110
181#define ZC3XX_R111_RGB21 0x0111
182#define ZC3XX_R112_RGB22 0x0112
183#define ZC3XX_R115_RGB23 0x0115
184
185/* Gamma matrix */
186#define ZC3XX_R120_GAMMA00 0x0120
187#define ZC3XX_R121_GAMMA01 0x0121
188#define ZC3XX_R122_GAMMA02 0x0122
189#define ZC3XX_R123_GAMMA03 0x0123
190#define ZC3XX_R124_GAMMA04 0x0124
191#define ZC3XX_R125_GAMMA05 0x0125
192#define ZC3XX_R126_GAMMA06 0x0126
193#define ZC3XX_R127_GAMMA07 0x0127
194#define ZC3XX_R128_GAMMA08 0x0128
195#define ZC3XX_R129_GAMMA09 0x0129
196#define ZC3XX_R12A_GAMMA0A 0x012a
197#define ZC3XX_R12B_GAMMA0B 0x012b
198#define ZC3XX_R12C_GAMMA0C 0x012c
199#define ZC3XX_R12D_GAMMA0D 0x012d
200#define ZC3XX_R12E_GAMMA0E 0x012e
201#define ZC3XX_R12F_GAMMA0F 0x012f
202#define ZC3XX_R130_GAMMA10 0x0130
203#define ZC3XX_R131_GAMMA11 0x0131
204#define ZC3XX_R132_GAMMA12 0x0132
205#define ZC3XX_R133_GAMMA13 0x0133
206#define ZC3XX_R134_GAMMA14 0x0134
207#define ZC3XX_R135_GAMMA15 0x0135
208#define ZC3XX_R136_GAMMA16 0x0136
209#define ZC3XX_R137_GAMMA17 0x0137
210#define ZC3XX_R138_GAMMA18 0x0138
211#define ZC3XX_R139_GAMMA19 0x0139
212#define ZC3XX_R13A_GAMMA1A 0x013a
213#define ZC3XX_R13B_GAMMA1B 0x013b
214#define ZC3XX_R13C_GAMMA1C 0x013c
215#define ZC3XX_R13D_GAMMA1D 0x013d
216#define ZC3XX_R13E_GAMMA1E 0x013e
217#define ZC3XX_R13F_GAMMA1F 0x013f
218
219/* Luminance gamma */
220#define ZC3XX_R140_YGAMMA00 0x0140
221#define ZC3XX_R141_YGAMMA01 0x0141
222#define ZC3XX_R142_YGAMMA02 0x0142
223#define ZC3XX_R143_YGAMMA03 0x0143
224#define ZC3XX_R144_YGAMMA04 0x0144
225#define ZC3XX_R145_YGAMMA05 0x0145
226#define ZC3XX_R146_YGAMMA06 0x0146
227#define ZC3XX_R147_YGAMMA07 0x0147
228#define ZC3XX_R148_YGAMMA08 0x0148
229#define ZC3XX_R149_YGAMMA09 0x0149
230#define ZC3XX_R14A_YGAMMA0A 0x014a
231#define ZC3XX_R14B_YGAMMA0B 0x014b
232#define ZC3XX_R14C_YGAMMA0C 0x014c
233#define ZC3XX_R14D_YGAMMA0D 0x014d
234#define ZC3XX_R14E_YGAMMA0E 0x014e
235#define ZC3XX_R14F_YGAMMA0F 0x014f
236#define ZC3XX_R150_YGAMMA10 0x0150
237#define ZC3XX_R151_YGAMMA11 0x0151
238
239#define ZC3XX_R1C5_SHARPNESSMODE 0x01c5
240#define ZC3XX_R1C6_SHARPNESS00 0x01c6
241#define ZC3XX_R1C7_SHARPNESS01 0x01c7
242#define ZC3XX_R1C8_SHARPNESS02 0x01c8
243#define ZC3XX_R1C9_SHARPNESS03 0x01c9
244#define ZC3XX_R1CA_SHARPNESS04 0x01ca
245#define ZC3XX_R1CB_SHARPNESS05 0x01cb
246
247/* Synchronization */
248#define ZC3XX_R190_SYNC00LOW 0x0190
249#define ZC3XX_R191_SYNC00MID 0x0191
250#define ZC3XX_R192_SYNC00HIGH 0x0192
251#define ZC3XX_R195_SYNC01LOW 0x0195
252#define ZC3XX_R196_SYNC01MID 0x0196
253#define ZC3XX_R197_SYNC01HIGH 0x0197
254
255/* Dead pixels */
256#define ZC3XX_R250_DEADPIXELSMODE 0x0250
257
258/* EEPROM */
259#define ZC3XX_R300_EEPROMCONFIG 0x0300
260#define ZC3XX_R301_EEPROMACCESS 0x0301
261#define ZC3XX_R302_EEPROMSTATUS 0x0302
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
new file mode 100644
index 000000000000..b761b11c5c6a
--- /dev/null
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -0,0 +1,7623 @@
1/*
2 * Z-Star/Vimicro zc301/zc302p/vc30x library
3 * Copyright (C) 2004 2005 2006 Michel Xhaard
4 * mxhaard@magic.fr
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 * (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#define MODULE_NAME "zc3xx"
24
25#include "gspca.h"
26
27#define DRIVER_VERSION_NUMBER KERNEL_VERSION(2, 1, 7)
28static const char version[] = "2.1.7";
29
30MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>, "
31 "Serge A. Suchkov <Serge.A.S@tochka.ru>");
32MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
33MODULE_LICENSE("GPL");
34
35static int force_sensor = -1;
36
37#include "jpeg.h"
38#include "zc3xx-reg.h"
39
40/* specific webcam descriptor */
41struct sd {
42 struct gspca_dev gspca_dev; /* !! must be the first item */
43
44 __u8 brightness;
45 __u8 contrast;
46 __u8 gamma;
47 __u8 autogain;
48 __u8 lightfreq;
49 __u8 sharpness;
50
51 char qindex;
52 char sensor; /* Type of image sensor chip */
53/* !! values used in different tables */
54#define SENSOR_CS2102 0
55#define SENSOR_CS2102K 1
56#define SENSOR_GC0305 2
57#define SENSOR_HDCS2020 3
58#define SENSOR_HDCS2020b 4
59#define SENSOR_HV7131B 5
60#define SENSOR_HV7131C 6
61#define SENSOR_ICM105A 7
62#define SENSOR_MC501CB 8
63#define SENSOR_OV7620 9
64/*#define SENSOR_OV7648 9 - same values */
65#define SENSOR_OV7630C 10
66#define SENSOR_PAS106 11
67#define SENSOR_PB0330 12
68#define SENSOR_PO2030 13
69#define SENSOR_TAS5130CK 14
70#define SENSOR_TAS5130CXX 15
71#define SENSOR_TAS5130C_VF0250 16
72#define SENSOR_MAX 17
73 unsigned short chip_revision;
74};
75
76/* V4L2 controls supported by the driver */
77static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
78static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
79static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
80static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
81static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
82static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
83static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
84static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
85static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
86static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
87static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
88static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
89
90static struct ctrl sd_ctrls[] = {
91#define SD_BRIGHTNESS 0
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,
100 .default_value = 128,
101 },
102 .set = sd_setbrightness,
103 .get = sd_getbrightness,
104 },
105#define SD_CONTRAST 1
106 {
107 {
108 .id = V4L2_CID_CONTRAST,
109 .type = V4L2_CTRL_TYPE_INTEGER,
110 .name = "Contrast",
111 .minimum = 0,
112 .maximum = 256,
113 .step = 1,
114 .default_value = 128,
115 },
116 .set = sd_setcontrast,
117 .get = sd_getcontrast,
118 },
119#define SD_GAMMA 2
120 {
121 {
122 .id = V4L2_CID_GAMMA,
123 .type = V4L2_CTRL_TYPE_INTEGER,
124 .name = "Gamma",
125 .minimum = 1,
126 .maximum = 6,
127 .step = 1,
128 .default_value = 4,
129 },
130 .set = sd_setgamma,
131 .get = sd_getgamma,
132 },
133#define SD_AUTOGAIN 3
134 {
135 {
136 .id = V4L2_CID_AUTOGAIN,
137 .type = V4L2_CTRL_TYPE_BOOLEAN,
138 .name = "Auto Gain",
139 .minimum = 0,
140 .maximum = 1,
141 .step = 1,
142 .default_value = 1,
143 },
144 .set = sd_setautogain,
145 .get = sd_getautogain,
146 },
147#define SD_FREQ 4
148 {
149 {
150 .id = V4L2_CID_POWER_LINE_FREQUENCY,
151 .type = V4L2_CTRL_TYPE_MENU,
152 .name = "Light frequency filter",
153 .minimum = 0,
154 .maximum = 2, /* 0: 0, 1: 50Hz, 2:60Hz */
155 .step = 1,
156 .default_value = 1,
157 },
158 .set = sd_setfreq,
159 .get = sd_getfreq,
160 },
161#define SD_SHARPNESS 5
162 {
163 {
164 .id = V4L2_CID_SHARPNESS,
165 .type = V4L2_CTRL_TYPE_INTEGER,
166 .name = "Sharpness",
167 .minimum = 0,
168 .maximum = 3,
169 .step = 1,
170 .default_value = 2,
171 },
172 .set = sd_setsharpness,
173 .get = sd_getsharpness,
174 },
175};
176
177static struct v4l2_pix_format vga_mode[] = {
178 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
179 .bytesperline = 320,
180 .sizeimage = 320 * 240 * 3 / 8 + 590,
181 .colorspace = V4L2_COLORSPACE_JPEG,
182 .priv = 1},
183 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
184 .bytesperline = 640,
185 .sizeimage = 640 * 480 * 3 / 8 + 590,
186 .colorspace = V4L2_COLORSPACE_JPEG,
187 .priv = 0},
188};
189
190static struct v4l2_pix_format sif_mode[] = {
191 {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
192 .bytesperline = 176,
193 .sizeimage = 176 * 144 * 3 / 8 + 590,
194 .colorspace = V4L2_COLORSPACE_JPEG,
195 .priv = 1},
196 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
197 .bytesperline = 352,
198 .sizeimage = 352 * 288 * 3 / 8 + 590,
199 .colorspace = V4L2_COLORSPACE_JPEG,
200 .priv = 0},
201};
202
203/* usb exchanges */
204struct usb_action {
205 __u8 req;
206 __u8 val;
207 __u16 idx;
208};
209
210static const struct usb_action cs2102_Initial[] = {
211 {0xa1, 0x01, 0x0008},
212 {0xa1, 0x01, 0x0008},
213 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
214 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
215 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
216 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
217 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
218 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
219 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
220 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
221 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
222 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
223 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
224 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
225 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
226 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
227 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
228 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
229 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
230 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
231 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
232 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
233 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
234 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
235 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
236 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
237 {0xaa, 0x02, 0x0008},
238 {0xaa, 0x03, 0x0000},
239 {0xaa, 0x11, 0x0000},
240 {0xaa, 0x12, 0x0089},
241 {0xaa, 0x13, 0x0000},
242 {0xaa, 0x14, 0x00e9},
243 {0xaa, 0x20, 0x0000},
244 {0xaa, 0x22, 0x0000},
245 {0xaa, 0x0b, 0x0004},
246 {0xaa, 0x30, 0x0030},
247 {0xaa, 0x31, 0x0030},
248 {0xaa, 0x32, 0x0030},
249 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
250 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
251 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
252 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
253 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
254 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
255 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
256 {0xa0, 0x10, 0x01ae},
257 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
258 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
259 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
260 {0xa0, 0x00, 0x01ad},
261 {0xa1, 0x01, 0x0002},
262 {0xa1, 0x01, 0x0008},
263 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
264 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
265 {0xa1, 0x01, 0x01c8},
266 {0xa1, 0x01, 0x01c9},
267 {0xa1, 0x01, 0x01ca},
268 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
269 {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */
270 {0xa0, 0x44, ZC3XX_R121_GAMMA01},
271 {0xa0, 0x64, ZC3XX_R122_GAMMA02},
272 {0xa0, 0x84, ZC3XX_R123_GAMMA03},
273 {0xa0, 0x9d, ZC3XX_R124_GAMMA04},
274 {0xa0, 0xb2, ZC3XX_R125_GAMMA05},
275 {0xa0, 0xc4, ZC3XX_R126_GAMMA06},
276 {0xa0, 0xd3, ZC3XX_R127_GAMMA07},
277 {0xa0, 0xe0, ZC3XX_R128_GAMMA08},
278 {0xa0, 0xeb, ZC3XX_R129_GAMMA09},
279 {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A},
280 {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B},
281 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
282 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
283 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
284 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
285 {0xa0, 0x18, ZC3XX_R130_GAMMA10},
286 {0xa0, 0x20, ZC3XX_R131_GAMMA11},
287 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
288 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
289 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
290 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
291 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
292 {0xa0, 0x0e, ZC3XX_R137_GAMMA17},
293 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
294 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
295 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
296 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
297 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
298 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
299 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
300 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
301 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
302 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
303 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
304 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
305 {0xa0, 0x58, ZC3XX_R10E_RGB11},
306 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
307 {0xa0, 0xf4, ZC3XX_R110_RGB20},
308 {0xa0, 0xf4, ZC3XX_R111_RGB21},
309 {0xa0, 0x58, ZC3XX_R112_RGB22},
310 {0xa1, 0x01, 0x0180},
311 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
312 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
313 {0xaa, 0x23, 0x0001},
314 {0xaa, 0x24, 0x0055},
315 {0xaa, 0x25, 0x00cc},
316 {0xaa, 0x21, 0x003f},
317 {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
318 {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
319 {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
320 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
321 {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
322 {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
323 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
324 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
325 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
326 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
327 {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
328 {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
329 {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
330 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
331 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
332 {0xa1, 0x01, 0x0180},
333 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
334 {0xa0, 0x40, ZC3XX_R116_RGAIN},
335 {0xa0, 0x40, ZC3XX_R117_GGAIN},
336 {0xa0, 0x40, ZC3XX_R118_BGAIN},
337 {}
338};
339
340static const struct usb_action cs2102_InitialScale[] = {
341 {0xa1, 0x01, 0x0008},
342 {0xa1, 0x01, 0x0008},
343 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
344 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
345 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
346 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
347 {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
348 {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
349 {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
350 {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
351 {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
352 {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
353 {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
354 {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
355 {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
356 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
357 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
358 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
359 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
360 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
361 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
362 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
363 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
364 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
365 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
366 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
367 {0xaa, 0x02, 0x0008},
368 {0xaa, 0x03, 0x0000},
369 {0xaa, 0x11, 0x0001},
370 {0xaa, 0x12, 0x0087},
371 {0xaa, 0x13, 0x0001},
372 {0xaa, 0x14, 0x00e7},
373 {0xaa, 0x20, 0x0000},
374 {0xaa, 0x22, 0x0000},
375 {0xaa, 0x0b, 0x0004},
376 {0xaa, 0x30, 0x0030},
377 {0xaa, 0x31, 0x0030},
378 {0xaa, 0x32, 0x0030},
379 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
380 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
381 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
382 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
383 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
384 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
385 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
386 {0xa0, 0x15, 0x01ae},
387 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
388 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
389 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
390 {0xa0, 0x00, 0x01ad},
391 {0xa1, 0x01, 0x0002},
392 {0xa1, 0x01, 0x0008},
393 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
394 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
395 {0xa1, 0x01, 0x01c8},
396 {0xa1, 0x01, 0x01c9},
397 {0xa1, 0x01, 0x01ca},
398 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
399 {0xa0, 0x24, ZC3XX_R120_GAMMA00}, /* gamma 5 */
400 {0xa0, 0x44, ZC3XX_R121_GAMMA01},
401 {0xa0, 0x64, ZC3XX_R122_GAMMA02},
402 {0xa0, 0x84, ZC3XX_R123_GAMMA03},
403 {0xa0, 0x9d, ZC3XX_R124_GAMMA04},
404 {0xa0, 0xb2, ZC3XX_R125_GAMMA05},
405 {0xa0, 0xc4, ZC3XX_R126_GAMMA06},
406 {0xa0, 0xd3, ZC3XX_R127_GAMMA07},
407 {0xa0, 0xe0, ZC3XX_R128_GAMMA08},
408 {0xa0, 0xeb, ZC3XX_R129_GAMMA09},
409 {0xa0, 0xf4, ZC3XX_R12A_GAMMA0A},
410 {0xa0, 0xfb, ZC3XX_R12B_GAMMA0B},
411 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
412 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
413 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
414 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
415 {0xa0, 0x18, ZC3XX_R130_GAMMA10},
416 {0xa0, 0x20, ZC3XX_R131_GAMMA11},
417 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
418 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
419 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
420 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
421 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
422 {0xa0, 0x0e, ZC3XX_R137_GAMMA17},
423 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
424 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
425 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
426 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
427 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
428 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
429 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
430 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
431 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
432 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
433 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
434 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
435 {0xa0, 0x58, ZC3XX_R10E_RGB11},
436 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
437 {0xa0, 0xf4, ZC3XX_R110_RGB20},
438 {0xa0, 0xf4, ZC3XX_R111_RGB21},
439 {0xa0, 0x58, ZC3XX_R112_RGB22},
440 {0xa1, 0x01, 0x0180},
441 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
442 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
443 {0xaa, 0x23, 0x0000},
444 {0xaa, 0x24, 0x00aa},
445 {0xaa, 0x25, 0x00e6},
446 {0xaa, 0x21, 0x003f},
447 {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
448 {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
449 {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
450 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
451 {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
452 {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
453 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
454 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
455 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
456 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
457 {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
458 {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
459 {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
460 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
461 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
462 {0xa1, 0x01, 0x0180},
463 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
464 {0xa0, 0x40, ZC3XX_R116_RGAIN},
465 {0xa0, 0x40, ZC3XX_R117_GGAIN},
466 {0xa0, 0x40, ZC3XX_R118_BGAIN},
467 {}
468};
469static const struct usb_action cs2102_50HZ[] = {
470 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
471 {0xaa, 0x0f, 0x008c}, /* 00,0f,8c,aa */
472 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
473 {0xaa, 0x04, 0x00ac}, /* 00,04,ac,aa */
474 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
475 {0xaa, 0x11, 0x00ac}, /* 00,11,ac,aa */
476 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
477 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
478 {0xaa, 0x1d, 0x00ac}, /* 00,1d,ac,aa */
479 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
480 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
481 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
482 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
483 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
484 {0xa0, 0x42, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,42,cc */
485 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
486 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
487 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
488 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
489 {0xa0, 0x8c, ZC3XX_R01D_HSYNC_0}, /* 00,1d,8c,cc */
490 {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */
491 {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */
492 {}
493};
494static const struct usb_action cs2102_50HZScale[] = {
495 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
496 {0xaa, 0x0f, 0x0093}, /* 00,0f,93,aa */
497 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
498 {0xaa, 0x04, 0x00a1}, /* 00,04,a1,aa */
499 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
500 {0xaa, 0x11, 0x00a1}, /* 00,11,a1,aa */
501 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
502 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
503 {0xaa, 0x1d, 0x00a1}, /* 00,1d,a1,aa */
504 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
505 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
506 {0xa0, 0xf7, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f7,cc */
507 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
508 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
509 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
510 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
511 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
512 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
513 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
514 {0xa0, 0x93, ZC3XX_R01D_HSYNC_0}, /* 00,1d,93,cc */
515 {0xa0, 0xb0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,b0,cc */
516 {0xa0, 0xd0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,d0,cc */
517 {}
518};
519static const struct usb_action cs2102_60HZ[] = {
520 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
521 {0xaa, 0x0f, 0x005d}, /* 00,0f,5d,aa */
522 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
523 {0xaa, 0x04, 0x00aa}, /* 00,04,aa,aa */
524 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
525 {0xaa, 0x11, 0x00aa}, /* 00,11,aa,aa */
526 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
527 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
528 {0xaa, 0x1d, 0x00aa}, /* 00,1d,aa,aa */
529 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
530 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
531 {0xa0, 0xe4, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e4,cc */
532 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
533 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
534 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3a,cc */
535 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
536 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
537 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
538 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
539 {0xa0, 0x5d, ZC3XX_R01D_HSYNC_0}, /* 00,1d,5d,cc */
540 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
541 {0xa0, 0xd0, 0x00c8}, /* 00,c8,d0,cc */
542 {}
543};
544static const struct usb_action cs2102_60HZScale[] = {
545 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
546 {0xaa, 0x0f, 0x00b7}, /* 00,0f,b7,aa */
547 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
548 {0xaa, 0x04, 0x00be}, /* 00,04,be,aa */
549 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
550 {0xaa, 0x11, 0x00be}, /* 00,11,be,aa */
551 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
552 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
553 {0xaa, 0x1d, 0x00be}, /* 00,1d,be,aa */
554 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
555 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
556 {0xa0, 0xfc, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,fc,cc */
557 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
558 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
559 {0xa0, 0x69, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,69,cc */
560 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
561 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
562 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
563 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
564 {0xa0, 0xb7, ZC3XX_R01D_HSYNC_0}, /* 00,1d,b7,cc */
565 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
566 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
567 {}
568};
569static const struct usb_action cs2102_NoFliker[] = {
570 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
571 {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */
572 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
573 {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */
574 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
575 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
576 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
577 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
578 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
579 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
580 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
581 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
582 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
583 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
584 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
585 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
586 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
587 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
588 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
589 {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */
590 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
591 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
592 {}
593};
594static const struct usb_action cs2102_NoFlikerScale[] = {
595 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
596 {0xaa, 0x0f, 0x0059}, /* 00,0f,59,aa */
597 {0xaa, 0x03, 0x0005}, /* 00,03,05,aa */
598 {0xaa, 0x04, 0x0080}, /* 00,04,80,aa */
599 {0xaa, 0x10, 0x0005}, /* 00,10,05,aa */
600 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
601 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa */
602 {0xaa, 0x1c, 0x0005}, /* 00,1c,05,aa */
603 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
604 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
605 {0xa0, 0x3f, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,3f,cc */
606 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
607 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
608 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
609 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
610 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
611 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
612 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
613 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
614 {0xa0, 0x59, ZC3XX_R01D_HSYNC_0}, /* 00,1d,59,cc */
615 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
616 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
617 {}
618};
619
620/* CS2102_KOCOM */
621static const struct usb_action cs2102K_Initial[] = {
622 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
623 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
624 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
625 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
626 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
627 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
628 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
629 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
630 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
631 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
632 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
633 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
634 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
635 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
636 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
637 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
638 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
639 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
640 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
641 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
642 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
643 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
644 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
645 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
646 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
647 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
648 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
649 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
650 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
651 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
652 {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
653 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
654 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
655 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
656 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
657 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
658 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
659 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
660 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
661 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
662 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
663 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
664 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
665 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
666 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
667 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
668 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
669 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
670 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
671 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
672 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
673 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
674 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
675 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
676 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
677 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
678 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
679 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
680 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
681 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
682 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
683 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
684 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
685 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
686 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
687 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
688 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
689 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
690 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
691 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
692 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
693 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
694 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
695 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
696 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
697 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
698 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
699 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
700 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
701 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
702 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
703 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
704 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
705 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
706 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
707 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
708 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
709 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
710 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
711 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
712 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
713 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
714 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
715 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
716 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
717 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
718 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
719 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
720 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
721 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
722 {0xa0, 0x00, 0x01ad},
723 {0xa0, 0x01, 0x01b1},
724 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
725 {0xa0, 0x60, ZC3XX_R116_RGAIN},
726 {0xa0, 0x40, ZC3XX_R117_GGAIN},
727 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
728 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
729 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
730 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
731 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
732 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
733 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
734 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
735 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
736 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
737 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
738 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
739 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
740 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
741 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
742 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
743 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
744 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
745 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
746 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
747 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
748 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
749 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
750 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
751 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
752 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
753 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
754 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
755 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
756 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
757 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
758 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
759 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
760 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
761 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
762 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
763 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
764 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
765 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
766 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
767 {0xa0, 0x58, ZC3XX_R10E_RGB11},
768 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
769 {0xa0, 0xf4, ZC3XX_R110_RGB20},
770 {0xa0, 0xf4, ZC3XX_R111_RGB21},
771 {0xa0, 0x58, ZC3XX_R112_RGB22},
772 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
773 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
774 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
775 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
776 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
777 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
778 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
779 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
780 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
781 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
782 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
783 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
784 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
785 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
786 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
787 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
788 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
789 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
790 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
791 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
792 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
793 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
794 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
795 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
796 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
797 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
798 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
799 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
800 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
801 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
802 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
803 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
804 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
805 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
806 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
807 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
808 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
809 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
810 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
811 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
812 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
813 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
814 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
815 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
816 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
817 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
818 {0xa0, 0x60, ZC3XX_R116_RGAIN},
819 {0xa0, 0x40, ZC3XX_R117_GGAIN},
820 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
821 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
822 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
823 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
824 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
825 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
826 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
827 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
828 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
829 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
830 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
831 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
832 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
833 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
834 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
835 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
836 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
837 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
838 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
839 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
840 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
841 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
842 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
843 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
844 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
845 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
846 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
847 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
848 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
849 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
850 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
851 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
852 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
853 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
854 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
855 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
856 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
857 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
858 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
859 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
860 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
861 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
862 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
863 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
864 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
865 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
866 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
867 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
868 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
869 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
870 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
871 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
872 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
873 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
874 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
875 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
876 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
877 {}
878};
879
880static const struct usb_action cs2102K_InitialScale[] = {
881 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
882 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
883 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
884 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
885 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
886 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
887 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
888 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
889 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
890 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
891 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
892 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
893 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
894 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
895 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
896 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
897 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
898 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
899 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
900 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
901 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
902 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
903 {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
904 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
905 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
906 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
907 {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
908 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
909 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
910 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
911 {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
912 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
913 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
914 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
915 {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
916 {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
917 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
918 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
919 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
920 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
921 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
922 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
923 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
924 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
925 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
926 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
927 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
928 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
929 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
930 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
931 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
932 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
933 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
934 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
935 {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
936 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
937 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
938 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
939 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
940 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
941 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
942 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
943 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
944 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
945 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
946 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
947 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
948 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
949 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
950 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
951 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
952 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
953 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
954 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
955 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
956 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
957 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
958 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
959 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
960 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
961 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
962 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
963 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
964 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
965 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
966 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
967 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
968 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
969 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
970 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
971 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
972 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
973 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
974 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
975 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
976 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
977 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
978 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
979 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
980 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
981 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
982 {0xa0, 0x00, 0x01ad},
983 {0xa0, 0x01, 0x01b1},
984 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
985 {0xa0, 0x60, ZC3XX_R116_RGAIN},
986 {0xa0, 0x40, ZC3XX_R117_GGAIN},
987 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
988 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
989 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
990 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
991 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
992 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
993 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
994 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
995 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
996 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
997 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
998 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
999 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1000 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1001 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1002 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1003 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1004 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1005 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1006 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1007 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1008 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1009 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1010 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1011 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1012 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1013 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1014 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1015 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1016 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1017 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1018 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1019 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1020 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1021 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1022 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1023 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
1024 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
1025 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
1026 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
1027 {0xa0, 0x58, ZC3XX_R10E_RGB11},
1028 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
1029 {0xa0, 0xf4, ZC3XX_R110_RGB20},
1030 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1031 {0xa0, 0x58, ZC3XX_R112_RGB22},
1032 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1033 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1034 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1035 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1036 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1037 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1038 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1039 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1040 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1041 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1042 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1043 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1044 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1045 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1046 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1047 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1048 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1049 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1050 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1051 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1052 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1053 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1054 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1055 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1056 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1057 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1058 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1059 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1060 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1061 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1062 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1063 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1064 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1065 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1066 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1067 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1068 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1069 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1070 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1071 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1072 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1073 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1074 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1075 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1076 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1077 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1078 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1079 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1080 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1081 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1082 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1083 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1084 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1085 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1086 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1087 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1088 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1089 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1090 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1091 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1092 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1093 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1094 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1095 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1096 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1097 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1098 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1099 {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
1100 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1101 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1102 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1103 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1104 {0xa0, 0x0A, ZC3XX_R092_I2CADDRESSSELECT},
1105 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1106 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1107 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1108 {0xa0, 0x0B, ZC3XX_R092_I2CADDRESSSELECT},
1109 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1110 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1111 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1112 {0xa0, 0x0C, ZC3XX_R092_I2CADDRESSSELECT},
1113 {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
1114 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1115 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1116 {0xa0, 0x0D, ZC3XX_R092_I2CADDRESSSELECT},
1117 {0xa0, 0xA3, ZC3XX_R093_I2CSETVALUE},
1118 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1119 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1120 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
1121 {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
1122 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1123 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1124 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
1125 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1126 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1127 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1128 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
1129 {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
1130 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1131 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1132 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
1133 {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
1134 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1135 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1136 {0xa0, 0x0E, ZC3XX_R092_I2CADDRESSSELECT},
1137 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1138 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1139 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1140 {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
1141 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1142 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1143 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1144 {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
1145 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1146 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1147 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1148 {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
1149 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1150 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1151 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1152 {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
1153 {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
1154 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1155 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1156 {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
1157 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1158 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1159 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1160 {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
1161 {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
1162 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1163 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1164 {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
1165 {0xa0, 0x0C, ZC3XX_R093_I2CSETVALUE},
1166 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1167 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1168 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1169 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1170 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1171 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1172 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
1173 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1174 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
1175 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1176 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1177 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1178 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1179 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1180 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1181 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1182 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1183 {0xa0, 0x00, 0x01ad},
1184 {0xa0, 0x01, 0x01b1},
1185 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1186 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1187 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1188 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1189 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1190 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1191 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1192 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
1193 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
1194 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
1195 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1196 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
1197 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
1198 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
1199 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
1200 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
1201 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
1202 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
1203 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
1204 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
1205 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
1206 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
1207 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1208 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1209 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
1210 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1211 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1212 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1213 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1214 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1215 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1216 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1217 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1218 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1219 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1220 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1221 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1222 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1223 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1224 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
1225 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
1226 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
1227 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
1228 {0xa0, 0x58, ZC3XX_R10E_RGB11},
1229 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
1230 {0xa0, 0xf4, ZC3XX_R110_RGB20},
1231 {0xa0, 0xf4, ZC3XX_R111_RGB21},
1232 {0xa0, 0x58, ZC3XX_R112_RGB22},
1233 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1234 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1235 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1236 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1237 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1238 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1239 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1240 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1241 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1242 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1243 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1244 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1245 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1246 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1247 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1248 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1249 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1250 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1251 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1252 {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
1253 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1254 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1255 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1256 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1257 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1258 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1259 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
1260 {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
1261 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1262 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
1263 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
1264 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1265 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1266 {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
1267 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1268 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1269 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
1270 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
1271 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
1272 {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
1273 {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
1274 {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
1275 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1276 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
1277 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1278 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1279 {0xa0, 0x60, ZC3XX_R116_RGAIN},
1280 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1281 {0xa0, 0x4c, ZC3XX_R118_BGAIN},
1282 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1283 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1284 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1285 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1286 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1287 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1288 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1289 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1290 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1291 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1292 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1293 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1294 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1295 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1296 {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
1297 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1298 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1299 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1300 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1301 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1302 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1303 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1304 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1305 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1306 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1307 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1308 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1309 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1310 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1311 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1312 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1313 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1314 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1315 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1316 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1317 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1318 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1319 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1320 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1321 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1322 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1323 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1324 {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
1325 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1326 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1327 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1328 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1329 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1330 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1331 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1332 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1333 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1334 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1335 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1336 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1337 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1338 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1339 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1340 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1341 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1342 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1343 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1344 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1345 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1346 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1347 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1348 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1349 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1350 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1351 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1352 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1353 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1354 {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
1355 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1356 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1357 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1358 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
1359 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1360 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1361 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1362 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1363 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1364 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1365 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1366 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
1367 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1368 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1369 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1370 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1371 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1372 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1373 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1374 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1375 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1376 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1377 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1378 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1379 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1380 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1381 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1382 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1383 {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
1384 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1385 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1386 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1387 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1388 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1389 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1390 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1391 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1392 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1393 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1394 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1395 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1396 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1397 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1398 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1399 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1400 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1401 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1402 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1403 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1404 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1405 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1406 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1407 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1408 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1409 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1410 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1411 {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
1412 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1413 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1414 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1415 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1416 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1417 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1418 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1419 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1420 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1421 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1422 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1423 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1424 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1425 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1426 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
1427 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1428 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1429 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1430 {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
1431 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1432 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1433 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1434 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1435 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
1436 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1437 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1438 {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
1439 {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
1440 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1441 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1442 {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
1443 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
1444 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1445 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1446 {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
1447 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
1448 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
1449 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
1450 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1451 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1452 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
1453 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
1454 {}
1455};
1456
1457static const struct usb_action gc0305_Initial[] = { /* 640x480 */
1458 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1459 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1460 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1461 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
1462 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1463 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1464 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1465 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1466 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1467 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1468 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1469 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1470 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1471 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1472 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1473 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
1474 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
1475 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1476 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa */
1477 {0xaa, 0x15, 0x0003}, /* 00,15,03,aa */
1478 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1479 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1480 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1481 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1482 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1483 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1484 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1485 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1486 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1487 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1488 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1489 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1490 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1491 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1492 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1493 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1494 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1495 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1496 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1497 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1498 {0xaa, 0x17, 0x00e6}, /* 00,17,e6,aa */
1499 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1500 {0xaa, 0x19, 0x0086}, /* 00,19,86,aa */
1501 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1502 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1503 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1504 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1505 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1506 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1507 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1508 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1509 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1510 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1511 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1512 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1513 {0xa0, 0x85, ZC3XX_R18D_YTARGET}, /* 01,8d,85,cc */
1514 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1515 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1516 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1517 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1518 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1519 {}
1520};
1521static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
1522 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
1523 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
1524 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
1525 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
1526 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
1527 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
1528 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
1529 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
1530 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
1531 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
1532 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
1533 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
1534 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
1535 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
1536 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
1537 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
1538 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
1539 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
1540 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
1541 {0xaa, 0x15, 0x0001}, /* 00,15,01,aa */
1542 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
1543 {0xaa, 0x02, 0x0000}, /* 00,02,00,aa */
1544 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
1545 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa */
1546 {0xaa, 0x1d, 0x0080}, /* 00,1d,80,aa */
1547 {0xaa, 0x1f, 0x0008}, /* 00,1f,08,aa */
1548 {0xaa, 0x21, 0x0012}, /* 00,21,12,aa */
1549 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc */
1550 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc */
1551 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc */
1552 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
1553 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa */
1554 {0xaa, 0x0b, 0x00b0}, /* 00,0b,b0,aa */
1555 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa */
1556 {0xaa, 0x0d, 0x00b0}, /* 00,0d,b0,aa */
1557 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa */
1558 {0xaa, 0x0f, 0x00b0}, /* 00,0f,b0,aa */
1559 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
1560 {0xaa, 0x11, 0x00b0}, /* 00,11,b0,aa */
1561 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa */
1562 {0xaa, 0x17, 0x00e8}, /* 00,17,e8,aa */
1563 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa */
1564 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa */
1565 {0xaa, 0x20, 0x0000}, /* 00,20,00,aa */
1566 {0xaa, 0x1b, 0x0020}, /* 00,1b,20,aa */
1567 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc */
1568 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
1569 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
1570 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc */
1571 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc */
1572 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
1573 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
1574 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
1575 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
1576 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
1577 {0xa0, 0x00, 0x011e}, /* 01,1e,00,cc */
1578 {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
1579 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
1580 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
1581 {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
1582 {}
1583};
1584static const struct usb_action gc0305_50HZ[] = {
1585 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1586 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
1587 {0xaa, 0x84, 0x0038}, /* 00,84,38,aa */ /* win: 00,84,ec */
1588 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1589 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1590 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
1591 /* win: 01,92,10 */
1592 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1593 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1594 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc */
1595 /* win: 01,97,ec */
1596 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1597 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1598 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1599 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1600 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1601 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1602 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1603 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1604 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1605 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1606/* {0xa0, 0x85, ZC3XX_R18D_YTARGET}, * 01,8d,85,cc *
1607 * if 640x480 */
1608 {}
1609};
1610static const struct usb_action gc0305_60HZ[] = {
1611 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1612 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1613 {0xaa, 0x84, 0x00ec}, /* 00,84,ec,aa */
1614 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1615 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc */
1616 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
1617 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1618 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1619 {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,ec,cc */
1620 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1621 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1622 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
1623 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc */
1624 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1625 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1626 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1627 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1628 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1629 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
1630 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1631 {}
1632};
1633
1634static const struct usb_action gc0305_NoFliker[] = {
1635 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
1636 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
1637 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
1638 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
1639 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
1640 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,00,cc */
1641 {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,48,cc */
1642 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
1643 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
1644 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
1645 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc */
1646 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc */
1647 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc */
1648 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
1649 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
1650 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
1651 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,60,cc */
1652 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
1653 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* 01,8d,80,cc */
1654 {}
1655};
1656
1657/* play poker with registers at your own risk !! */
1658static const struct usb_action hdcs2020xx_Initial[] = {
1659 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1660 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1661 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},
1662 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
1663 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1664 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1665 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1666 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW},
1667 /* D0 ?? E0 did not start */
1668 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1669 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1670 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1671 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
1672 {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW},
1673 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
1674 {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW},
1675 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
1676 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
1677 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
1678 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
1679 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1680 {0xaa, 0x02, 0x0002},
1681 {0xaa, 0x07, 0x0006},
1682 {0xaa, 0x08, 0x0002},
1683 {0xaa, 0x09, 0x0006},
1684 {0xaa, 0x0a, 0x0001},
1685 {0xaa, 0x0b, 0x0001},
1686 {0xaa, 0x0c, 0x0008},
1687 {0xaa, 0x0d, 0x0000},
1688 {0xaa, 0x10, 0x0000},
1689 {0xaa, 0x12, 0x0005},
1690 {0xaa, 0x13, 0x0063},
1691 {0xaa, 0x15, 0x0070},
1692 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
1693 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1694 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1695 {0xa0, 0x00, 0x01ad},
1696 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1697 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1698 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1699 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1700 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1701 {0xa1, 0x01, 0x0002},
1702 {0xa1, 0x01, 0x0008},
1703 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1704 {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1705 {0xa1, 0x01, 0x01c8},
1706 {0xa1, 0x01, 0x01c9},
1707 {0xa1, 0x01, 0x01ca},
1708 {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1709 {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
1710 {0xa0, 0x37, ZC3XX_R121_GAMMA01},
1711 {0xa0, 0x58, ZC3XX_R122_GAMMA02},
1712 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1713 {0xa0, 0x91, ZC3XX_R124_GAMMA04},
1714 {0xa0, 0xa6, ZC3XX_R125_GAMMA05},
1715 {0xa0, 0xb8, ZC3XX_R126_GAMMA06},
1716 {0xa0, 0xc7, ZC3XX_R127_GAMMA07},
1717 {0xa0, 0xd3, ZC3XX_R128_GAMMA08},
1718 {0xa0, 0xde, ZC3XX_R129_GAMMA09},
1719 {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A},
1720 {0xa0, 0xed, ZC3XX_R12B_GAMMA0B},
1721 {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C},
1722 {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D},
1723 {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E},
1724 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1725 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1726 {0xa0, 0x23, ZC3XX_R131_GAMMA11},
1727 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1728 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1729 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1730 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1731 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1732 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1733 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1734 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1735 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1736 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1737 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1738 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1739 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1740 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1741
1742 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
1743 {0xa0, 0xf5, ZC3XX_R10B_RGB01},
1744 {0xa0, 0xff, ZC3XX_R10C_RGB02},
1745 {0xa0, 0xf9, ZC3XX_R10D_RGB10},
1746 {0xa0, 0x51, ZC3XX_R10E_RGB11},
1747 {0xa0, 0xf5, ZC3XX_R10F_RGB12},
1748 {0xa0, 0xfb, ZC3XX_R110_RGB20},
1749 {0xa0, 0xed, ZC3XX_R111_RGB21},
1750 {0xa0, 0x5f, ZC3XX_R112_RGB22},
1751
1752 {0xa1, 0x01, 0x0180},
1753 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1754 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1755 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1756 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1757 {0xaa, 0x20, 0x0004},
1758 {0xaa, 0x21, 0x003d},
1759 {0xaa, 0x03, 0x0041},
1760 {0xaa, 0x04, 0x0010},
1761 {0xaa, 0x05, 0x003d},
1762 {0xaa, 0x0e, 0x0001},
1763 {0xaa, 0x0f, 0x0000},
1764 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
1765 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
1766 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1767 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
1768 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
1769 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1770 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1771 {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW},
1772 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1773 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1774 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0},
1775 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},
1776 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},
1777 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
1778 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},
1779 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},
1780 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
1781 {0xa1, 0x01, 0x0195},
1782 {0xa1, 0x01, 0x0196},
1783 {0xa1, 0x01, 0x0197},
1784 {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
1785 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
1786 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1787 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1788 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1789 {0xa0, 0x85, ZC3XX_R118_BGAIN},
1790 {0xa1, 0x01, 0x0116},
1791 {0xa1, 0x01, 0x0118},
1792 {0xa1, 0x01, 0x0180},
1793 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1794 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1795 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1796 {0xa0, 0x85, ZC3XX_R118_BGAIN},
1797 {0xa1, 0x01, 0x0116},
1798 {0xa1, 0x01, 0x0118},
1799/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
1800 {0xa0, 0x00, 0x0007},
1801 {}
1802};
1803
1804static const struct usb_action hdcs2020xx_InitialScale[] = {
1805 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1806 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
1807 {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},
1808 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
1809 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1810 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1811 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1812 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1813 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1814 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1815 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1816 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
1817 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1818 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
1819 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1820 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
1821 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
1822 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
1823 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
1824 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
1825 {0xaa, 0x02, 0x0002},
1826 {0xaa, 0x07, 0x0006},
1827 {0xaa, 0x08, 0x0002},
1828 {0xaa, 0x09, 0x0006},
1829 {0xaa, 0x0a, 0x0001},
1830 {0xaa, 0x0b, 0x0001},
1831 {0xaa, 0x0c, 0x0008},
1832 {0xaa, 0x0d, 0x0000},
1833 {0xaa, 0x10, 0x0000},
1834 {0xaa, 0x12, 0x0005},
1835 {0xaa, 0x13, 0x0063},
1836 {0xaa, 0x15, 0x0070},
1837 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1838 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1839 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1840 {0xa0, 0x00, 0x01ad},
1841 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1842 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1843 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1844 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1845 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1846 {0xa1, 0x01, 0x0002},
1847 {0xa1, 0x01, 0x0008},
1848 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1849 {0xa0, 0x04, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
1850 {0xa1, 0x01, 0x01c8},
1851 {0xa1, 0x01, 0x01c9},
1852 {0xa1, 0x01, 0x01ca},
1853 {0xa0, 0x07, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
1854 {0xa0, 0x11, ZC3XX_R120_GAMMA00}, /* gamma ~4*/
1855 {0xa0, 0x37, ZC3XX_R121_GAMMA01},
1856 {0xa0, 0x58, ZC3XX_R122_GAMMA02},
1857 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
1858 {0xa0, 0x91, ZC3XX_R124_GAMMA04},
1859 {0xa0, 0xa6, ZC3XX_R125_GAMMA05},
1860 {0xa0, 0xb8, ZC3XX_R126_GAMMA06},
1861 {0xa0, 0xc7, ZC3XX_R127_GAMMA07},
1862 {0xa0, 0xd3, ZC3XX_R128_GAMMA08},
1863 {0xa0, 0xde, ZC3XX_R129_GAMMA09},
1864 {0xa0, 0xe6, ZC3XX_R12A_GAMMA0A},
1865 {0xa0, 0xed, ZC3XX_R12B_GAMMA0B},
1866 {0xa0, 0xf3, ZC3XX_R12C_GAMMA0C},
1867 {0xa0, 0xf8, ZC3XX_R12D_GAMMA0D},
1868 {0xa0, 0xfb, ZC3XX_R12E_GAMMA0E},
1869 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
1870 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
1871 {0xa0, 0x23, ZC3XX_R131_GAMMA11},
1872 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
1873 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
1874 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
1875 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
1876 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
1877 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
1878 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
1879 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
1880 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
1881 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
1882 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
1883 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
1884 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
1885 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
1886 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
1887 {0xa0, 0xff, ZC3XX_R10B_RGB01},
1888 {0xa0, 0xff, ZC3XX_R10C_RGB02},
1889 {0xa0, 0xff, ZC3XX_R10D_RGB10},
1890 {0xa0, 0x60, ZC3XX_R10E_RGB11},
1891 {0xa0, 0xff, ZC3XX_R10F_RGB12},
1892 {0xa0, 0xff, ZC3XX_R110_RGB20},
1893 {0xa0, 0xff, ZC3XX_R111_RGB21},
1894 {0xa0, 0x60, ZC3XX_R112_RGB22},
1895
1896 {0xa1, 0x01, 0x0180},
1897 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
1898 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
1899 {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
1900 {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
1901 {0xaa, 0x20, 0x0002},
1902 {0xaa, 0x21, 0x001b},
1903 {0xaa, 0x03, 0x0044},
1904 {0xaa, 0x04, 0x0008},
1905 {0xaa, 0x05, 0x001b},
1906 {0xaa, 0x0e, 0x0001},
1907 {0xaa, 0x0f, 0x0000},
1908 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
1909 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
1910 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1911 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1912 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
1913 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
1914 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
1915 {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW},
1916 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
1917 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
1918 {0xa0, 0x44, ZC3XX_R01D_HSYNC_0},
1919 {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},
1920 {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},
1921 {0xa0, 0xeb, ZC3XX_R020_HSYNC_3},
1922 {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},
1923 {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},
1924 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
1925 {0xa1, 0x01, 0x0195},
1926 {0xa1, 0x01, 0x0196},
1927 {0xa1, 0x01, 0x0197},
1928 {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
1929 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
1930 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
1931 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1932 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1933 {0xa0, 0x99, ZC3XX_R118_BGAIN},
1934 {0xa1, 0x01, 0x0116},
1935 {0xa1, 0x01, 0x0118},
1936 {0xa1, 0x01, 0x0180},
1937 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
1938 {0xa0, 0x1d, ZC3XX_R116_RGAIN},
1939 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1940 {0xa0, 0x99, ZC3XX_R118_BGAIN},
1941/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
1942 {0xa0, 0x00, 0x0007},
1943/* {0xa0, 0x18, 0x00fe}, */
1944 {}
1945};
1946static const struct usb_action hdcs2020xb_Initial[] = {
1947 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
1948 {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
1949 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* qtable 0x05 */
1950 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
1951 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
1952 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
1953 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
1954 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
1955 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
1956 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
1957 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
1958 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
1959 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
1960 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
1961 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
1962 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
1963 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
1964 {0xaa, 0x1c, 0x0000},
1965 {0xaa, 0x0a, 0x0001},
1966 {0xaa, 0x0b, 0x0006},
1967 {0xaa, 0x0c, 0x007b},
1968 {0xaa, 0x0d, 0x00a7},
1969 {0xaa, 0x03, 0x00fb},
1970 {0xaa, 0x05, 0x0000},
1971 {0xaa, 0x06, 0x0003},
1972 {0xaa, 0x09, 0x0008},
1973
1974 {0xaa, 0x0f, 0x0018}, /* set sensor gain */
1975 {0xaa, 0x10, 0x0018},
1976 {0xaa, 0x11, 0x0018},
1977 {0xaa, 0x12, 0x0018},
1978
1979 {0xaa, 0x15, 0x004e},
1980 {0xaa, 0x1c, 0x0004},
1981 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
1982 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
1983 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
1984 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
1985 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
1986 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
1987 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
1988 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
1989 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
1990 {0xa1, 0x01, 0x0002},
1991 {0xa1, 0x01, 0x0008},
1992 {0xa1, 0x01, 0x0180},
1993 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
1994 {0xa0, 0x40, ZC3XX_R116_RGAIN},
1995 {0xa0, 0x40, ZC3XX_R117_GGAIN},
1996 {0xa0, 0x40, ZC3XX_R118_BGAIN},
1997 {0xa1, 0x01, 0x0008},
1998 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
1999 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2000 {0xa1, 0x01, 0x01c8},
2001 {0xa1, 0x01, 0x01c9},
2002 {0xa1, 0x01, 0x01ca},
2003 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2004 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
2005 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
2006 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
2007 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
2008 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
2009 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
2010 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
2011 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
2012 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
2013 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
2014 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
2015 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
2016 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
2017 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
2018 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
2019 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
2020 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
2021 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
2022 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
2023 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
2024 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
2025 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
2026 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
2027 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
2028 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
2029 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
2030 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
2031 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
2032 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
2033 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
2034 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
2035 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
2036
2037 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
2038 {0xa0, 0xed, ZC3XX_R10B_RGB01},
2039 {0xa0, 0xed, ZC3XX_R10C_RGB02},
2040 {0xa0, 0xed, ZC3XX_R10D_RGB10},
2041 {0xa0, 0x66, ZC3XX_R10E_RGB11},
2042 {0xa0, 0xed, ZC3XX_R10F_RGB12},
2043 {0xa0, 0xed, ZC3XX_R110_RGB20},
2044 {0xa0, 0xed, ZC3XX_R111_RGB21},
2045 {0xa0, 0x66, ZC3XX_R112_RGB22},
2046
2047 {0xa1, 0x01, 0x0180},
2048 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2049 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2050 {0xaa, 0x13, 0x0031},
2051 {0xaa, 0x14, 0x0001},
2052 {0xaa, 0x0e, 0x0004},
2053 {0xaa, 0x19, 0x00cd},
2054 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2055 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
2056 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
2057 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2058 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2059 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
2060 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2061 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2062
2063 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 0x14 */
2064 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
2065 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
2066 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
2067 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
2068 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
2069 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2070 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2071 {0xa1, 0x01, 0x0180},
2072 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2073 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2074 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2075 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2076 {}
2077};
2078static const struct usb_action hdcs2020xb_InitialScale[] = {
2079 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2080 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2081 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2082 {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
2083 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2084 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2085 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2086 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2087 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2088 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2089 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2090 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2091 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2092 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2093 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2094 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2095 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2096 {0xaa, 0x1c, 0x0000},
2097 {0xaa, 0x0a, 0x0001},
2098 {0xaa, 0x0b, 0x0006},
2099 {0xaa, 0x0c, 0x007a},
2100 {0xaa, 0x0d, 0x00a7},
2101 {0xaa, 0x03, 0x00fb},
2102 {0xaa, 0x05, 0x0000},
2103 {0xaa, 0x06, 0x0003},
2104 {0xaa, 0x09, 0x0008},
2105 {0xaa, 0x0f, 0x0018}, /* original setting */
2106 {0xaa, 0x10, 0x0018},
2107 {0xaa, 0x11, 0x0018},
2108 {0xaa, 0x12, 0x0018},
2109 {0xaa, 0x15, 0x004e},
2110 {0xaa, 0x1c, 0x0004},
2111 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
2112 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2113 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
2114 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2115 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2116 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2117 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2118 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2119 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2120 {0xa1, 0x01, 0x0002},
2121 {0xa1, 0x01, 0x0008},
2122 {0xa1, 0x01, 0x0180},
2123 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2124 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2125 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2126 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2127 {0xa1, 0x01, 0x0008},
2128 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2129 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2130 {0xa1, 0x01, 0x01c8},
2131 {0xa1, 0x01, 0x01c9},
2132 {0xa1, 0x01, 0x01ca},
2133 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2134 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
2135 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
2136 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
2137 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
2138 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
2139 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
2140 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
2141 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
2142 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
2143 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
2144 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
2145 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
2146 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
2147 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
2148 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
2149 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
2150 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
2151 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
2152 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
2153 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
2154 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
2155 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
2156 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
2157 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
2158 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
2159 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
2160 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
2161 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
2162 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
2163 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
2164 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
2165 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
2166 {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
2167 {0xa0, 0xed, ZC3XX_R10B_RGB01},
2168 {0xa0, 0xed, ZC3XX_R10C_RGB02},
2169 {0xa0, 0xed, ZC3XX_R10D_RGB10},
2170 {0xa0, 0x66, ZC3XX_R10E_RGB11},
2171 {0xa0, 0xed, ZC3XX_R10F_RGB12},
2172 {0xa0, 0xed, ZC3XX_R110_RGB20},
2173 {0xa0, 0xed, ZC3XX_R111_RGB21},
2174 {0xa0, 0x66, ZC3XX_R112_RGB22},
2175 {0xa1, 0x01, 0x0180},
2176 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2177 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2178 /**** set exposure ***/
2179 {0xaa, 0x13, 0x0031},
2180 {0xaa, 0x14, 0x0001},
2181 {0xaa, 0x0e, 0x0004},
2182 {0xaa, 0x19, 0x00cd},
2183 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2184 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
2185 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
2186 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2187 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2188 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
2189 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2190 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2191 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
2192 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
2193 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
2194 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
2195 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
2196 {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
2197 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2198 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2199 {0xa1, 0x01, 0x0180},
2200 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2201 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2202 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2203 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2204 {}
2205};
2206static const struct usb_action hdcs2020b_50HZ[] = {
2207 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2208 {0xaa, 0x13, 0x0018}, /* 00,13,18,aa */
2209 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2210 {0xaa, 0x0e, 0x0005}, /* 00,0e,05,aa */
2211 {0xaa, 0x19, 0x001f}, /* 00,19,1f,aa */
2212 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2213 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2214 {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
2215 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2216 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2217 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
2218 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2219 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2220 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
2221 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
2222 {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
2223 {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
2224 {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
2225 {}
2226};
2227static const struct usb_action hdcs2020b_60HZ[] = {
2228 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2229 {0xaa, 0x13, 0x0031}, /* 00,13,31,aa */
2230 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2231 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
2232 {0xaa, 0x19, 0x00cd}, /* 00,19,cd,aa */
2233 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2234 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2235 {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
2236 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2237 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2238 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
2239 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2240 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2241 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
2242 {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
2243 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
2244 {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
2245 {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
2246 {}
2247};
2248static const struct usb_action hdcs2020b_NoFliker[] = {
2249 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
2250 {0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
2251 {0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
2252 {0xaa, 0x0e, 0x0004}, /* 00,0e,04,aa */
2253 {0xaa, 0x19, 0x0000}, /* 00,19,00,aa */
2254 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
2255 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
2256 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
2257 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
2258 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
2259 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
2260 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
2261 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
2262 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
2263 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
2264 {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
2265 {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
2266 {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
2267 {}
2268};
2269
2270static const struct usb_action hv7131bxx_Initial[] = {
2271 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2272 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2273 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
2274 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2275 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2276 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
2277 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2278 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2279 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2280 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2281 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2282 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2283 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2284 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2285 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2286 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2287 {0xaa, 0x30, 0x002d},
2288 {0xaa, 0x01, 0x0005},
2289 {0xaa, 0x11, 0x0000},
2290 {0xaa, 0x13, 0x0001}, /* {0xaa, 0x13, 0x0000}, */
2291 {0xaa, 0x14, 0x0001},
2292 {0xaa, 0x15, 0x00e8},
2293 {0xaa, 0x16, 0x0002},
2294 {0xaa, 0x17, 0x0086},
2295 {0xaa, 0x31, 0x0038},
2296 {0xaa, 0x32, 0x0038},
2297 {0xaa, 0x33, 0x0038},
2298 {0xaa, 0x5b, 0x0001},
2299 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2300 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2301 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2302 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
2303 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2304 {0xa0, 0x00, 0x01ad},
2305 {0xa0, 0xc0, 0x019b},
2306 {0xa0, 0xa0, 0x019c},
2307 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
2308 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2309 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2310 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2311 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2312 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2313 {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */
2314 {0xa1, 0x01, 0x0002},
2315 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2316 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2317 {0xa1, 0x01, 0x0091},
2318 {0xa1, 0x01, 0x0095},
2319 {0xa1, 0x01, 0x0096},
2320
2321 {0xa1, 0x01, 0x0008},
2322 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2323 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2324 {0xa1, 0x01, 0x01c8},
2325 {0xa1, 0x01, 0x01c9},
2326 {0xa1, 0x01, 0x01ca},
2327 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2328
2329 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
2330 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
2331 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
2332 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
2333 {0xa0, 0x50, ZC3XX_R10E_RGB11},
2334 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
2335 {0xa0, 0xf8, ZC3XX_R110_RGB20},
2336 {0xa0, 0xf8, ZC3XX_R111_RGB21},
2337 {0xa0, 0x50, ZC3XX_R112_RGB22},
2338 {0xa1, 0x01, 0x0180},
2339 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2340 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2341 {0xaa, 0x25, 0x0007},
2342 {0xaa, 0x26, 0x00a1},
2343 {0xaa, 0x27, 0x0020},
2344 {0xaa, 0x20, 0x0000},
2345 {0xaa, 0x21, 0x00a0},
2346 {0xaa, 0x22, 0x0016},
2347 {0xaa, 0x23, 0x0040},
2348
2349 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2F */
2350 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
2351 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},
2352 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2353 {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
2354 {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
2355 {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},
2356 {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},
2357 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
2358 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
2359 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2360 {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},
2361 {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},
2362 {0xa0, 0x40, ZC3XX_R020_HSYNC_3},
2363 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2364 {0xa1, 0x01, 0x001d},
2365 {0xa1, 0x01, 0x001e},
2366 {0xa1, 0x01, 0x001f},
2367 {0xa1, 0x01, 0x0020},
2368 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2369 {0xa1, 0x01, 0x0180},
2370 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2371 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2372 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2373 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2374/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
2375 {}
2376};
2377
2378static const struct usb_action hv7131bxx_InitialScale[] = {
2379 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2380 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2381 {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
2382 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2383 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2384 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
2385 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2386 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2387 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2388 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2389 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2390 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2391 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2392 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2393 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2394 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2395 {0xaa, 0x30, 0x002d},
2396 {0xaa, 0x01, 0x0005},
2397 {0xaa, 0x11, 0x0001},
2398 {0xaa, 0x13, 0x0000}, /* {0xaa, 0x13, 0x0001}; */
2399 {0xaa, 0x14, 0x0001},
2400 {0xaa, 0x15, 0x00e6},
2401 {0xaa, 0x16, 0x0002},
2402 {0xaa, 0x17, 0x0086},
2403 {0xaa, 0x31, 0x0038},
2404 {0xaa, 0x32, 0x0038},
2405 {0xaa, 0x33, 0x0038},
2406 {0xaa, 0x5b, 0x0001},
2407 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2408 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2409 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2410 {0xa0, 0x70, ZC3XX_R18D_YTARGET},
2411 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2412 {0xa0, 0x00, 0x01ad},
2413 {0xa0, 0xc0, 0x019b},
2414 {0xa0, 0xa0, 0x019c},
2415 {0xa0, 0x02, ZC3XX_R188_MINGAIN},
2416 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2417 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2418 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2419 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2420 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2421 {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}, */
2422 {0xa1, 0x01, 0x0002},
2423 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2424 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2425 {0xa1, 0x01, 0x0091},
2426 {0xa1, 0x01, 0x0095},
2427 {0xa1, 0x01, 0x0096},
2428 {0xa1, 0x01, 0x0008},
2429 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2430 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2431 {0xa1, 0x01, 0x01c8},
2432 {0xa1, 0x01, 0x01c9},
2433 {0xa1, 0x01, 0x01ca},
2434 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2435
2436 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
2437 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
2438 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
2439 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
2440 {0xa0, 0x50, ZC3XX_R10E_RGB11},
2441 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
2442 {0xa0, 0xf8, ZC3XX_R110_RGB20},
2443 {0xa0, 0xf8, ZC3XX_R111_RGB21},
2444 {0xa0, 0x50, ZC3XX_R112_RGB22},
2445 {0xa1, 0x01, 0x0180},
2446 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2447 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2448 {0xaa, 0x25, 0x0007},
2449 {0xaa, 0x26, 0x00a1},
2450 {0xaa, 0x27, 0x0020},
2451 {0xaa, 0x20, 0x0000},
2452 {0xaa, 0x21, 0x0040},
2453 {0xaa, 0x22, 0x0013},
2454 {0xaa, 0x23, 0x004c},
2455 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2456 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 4d */
2457 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 60 */
2458 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2459 {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
2460 {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
2461 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
2462 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
2463 {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},
2464 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
2465 {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
2466 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
2467 {0xa0, 0x13, ZC3XX_R01F_HSYNC_2},
2468 {0xa0, 0x4c, ZC3XX_R020_HSYNC_3},
2469 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
2470 {0xa1, 0x01, 0x001d},
2471 {0xa1, 0x01, 0x001e},
2472 {0xa1, 0x01, 0x001f},
2473 {0xa1, 0x01, 0x0020},
2474 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2475 {0xa1, 0x01, 0x0180},
2476 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2477 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2478 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2479 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2480/* {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, */
2481 {}
2482};
2483
2484static const struct usb_action hv7131cxx_Initial[] = {
2485 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2486 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2487 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2488 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2489 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2490 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2491 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2492 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2493 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2494 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2495 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2496 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2497 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2498 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2499 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2500 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2501 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2502 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2503 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2504 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2505 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2506 {0xaa, 0x01, 0x000c},
2507 {0xaa, 0x11, 0x0000},
2508 {0xaa, 0x13, 0x0000},
2509 {0xaa, 0x14, 0x0001},
2510 {0xaa, 0x15, 0x00e8},
2511 {0xaa, 0x16, 0x0002},
2512 {0xaa, 0x17, 0x0088},
2513
2514 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2515 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2516 {0xa0, 0x89, ZC3XX_R18D_YTARGET},
2517 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2518 {0xa0, 0x00, 0x01ad},
2519 {0xa0, 0xc0, 0x019b},
2520 {0xa0, 0xa0, 0x019c},
2521 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2522 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2523 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2524 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2525 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2526 {0xa1, 0x01, 0x0002},
2527 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2528 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2529 {0xa1, 0x01, 0x0091},
2530 {0xa1, 0x01, 0x0095},
2531 {0xa1, 0x01, 0x0096},
2532
2533 {0xa1, 0x01, 0x0008},
2534 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2535 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2536 {0xa1, 0x01, 0x01c8},
2537 {0xa1, 0x01, 0x01c9},
2538 {0xa1, 0x01, 0x01ca},
2539 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2540
2541 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2542 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2543 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2544 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2545 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2546 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2547 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2548 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2549 {0xa0, 0x60, ZC3XX_R112_RGB22},
2550 {0xa1, 0x01, 0x0180},
2551 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2552 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2553 {0xaa, 0x25, 0x0007},
2554 {0xaa, 0x26, 0x0053},
2555 {0xaa, 0x27, 0x0000},
2556
2557 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2558 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */
2559 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */
2560 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2561 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2562 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2563 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2564 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2565 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2566 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2567 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP},
2568 {0xa1, 0x01, 0x001d},
2569 {0xa1, 0x01, 0x001e},
2570 {0xa1, 0x01, 0x001f},
2571 {0xa1, 0x01, 0x0020},
2572 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2573 {0xa1, 0x01, 0x0180},
2574 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2575 {}
2576};
2577
2578static const struct usb_action hv7131cxx_InitialScale[] = {
2579 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2580
2581 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* diff */
2582 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
2583 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2584 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2585 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2586
2587 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2588 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
2589
2590 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2591 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2592 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2593 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 1e0 */
2594
2595 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
2596 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
2597 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2598 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2599 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2600 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2601 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
2602 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
2603 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
2604 {0xaa, 0x01, 0x000c},
2605 {0xaa, 0x11, 0x0000},
2606 {0xaa, 0x13, 0x0000},
2607 {0xaa, 0x14, 0x0001},
2608 {0xaa, 0x15, 0x00e8},
2609 {0xaa, 0x16, 0x0002},
2610 {0xaa, 0x17, 0x0088},
2611
2612 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00 */
2613
2614 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2615 {0xa0, 0x89, ZC3XX_R18D_YTARGET},
2616 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
2617 {0xa0, 0x00, 0x01ad},
2618 {0xa0, 0xc0, 0x019b},
2619 {0xa0, 0xa0, 0x019c},
2620 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2621 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2622 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2623 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2624 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2625 {0xa1, 0x01, 0x0002},
2626 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
2627 /* read the i2c chips ident */
2628 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
2629 {0xa1, 0x01, 0x0091},
2630 {0xa1, 0x01, 0x0095},
2631 {0xa1, 0x01, 0x0096},
2632
2633 {0xa1, 0x01, 0x0008},
2634 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2635 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2636 {0xa1, 0x01, 0x01c8},
2637 {0xa1, 0x01, 0x01c9},
2638 {0xa1, 0x01, 0x01ca},
2639 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2640
2641 {0xa0, 0x60, ZC3XX_R10A_RGB00}, /* matrix */
2642 {0xa0, 0xf0, ZC3XX_R10B_RGB01},
2643 {0xa0, 0xf0, ZC3XX_R10C_RGB02},
2644 {0xa0, 0xf0, ZC3XX_R10D_RGB10},
2645 {0xa0, 0x60, ZC3XX_R10E_RGB11},
2646 {0xa0, 0xf0, ZC3XX_R10F_RGB12},
2647 {0xa0, 0xf0, ZC3XX_R110_RGB20},
2648 {0xa0, 0xf0, ZC3XX_R111_RGB21},
2649 {0xa0, 0x60, ZC3XX_R112_RGB22},
2650 {0xa1, 0x01, 0x0180},
2651 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
2652 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2653 {0xaa, 0x25, 0x0007},
2654 {0xaa, 0x26, 0x0053},
2655 {0xaa, 0x27, 0x0000},
2656
2657 {0xa0, 0x10, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 2f */
2658 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 9b */
2659 {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW}, /* 80 */
2660
2661 {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
2662 {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
2663 {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
2664
2665 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2666 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2667 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
2668 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2669 {0xa0, 0x13, ZC3XX_R1AA_DIGITALGAINSTEP},
2670 {0xa1, 0x01, 0x001d},
2671 {0xa1, 0x01, 0x001e},
2672 {0xa1, 0x01, 0x001f},
2673 {0xa1, 0x01, 0x0020},
2674 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
2675 {0xa1, 0x01, 0x0180},
2676 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2677 {}
2678};
2679
2680static const struct usb_action icm105axx_Initial[] = {
2681 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2682 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
2683 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2684 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2685 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2686 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2687 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2688 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2689 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2690 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2691 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2692 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2693 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2694 {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
2695 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2696 {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
2697 {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
2698 {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
2699 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2700 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
2701 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2702 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
2703 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
2704 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2705 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2706 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2707 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2708 {0xaa, 0x01, 0x0010},
2709 {0xaa, 0x03, 0x0000},
2710 {0xaa, 0x04, 0x0001},
2711 {0xaa, 0x05, 0x0020},
2712 {0xaa, 0x06, 0x0001},
2713 {0xaa, 0x08, 0x0000},
2714 {0xaa, 0x03, 0x0001},
2715 {0xaa, 0x04, 0x0011},
2716 {0xaa, 0x05, 0x00a0},
2717 {0xaa, 0x06, 0x0001},
2718 {0xaa, 0x08, 0x0000},
2719 {0xaa, 0x03, 0x0002},
2720 {0xaa, 0x04, 0x0013},
2721 {0xaa, 0x05, 0x0020},
2722 {0xaa, 0x06, 0x0001},
2723 {0xaa, 0x08, 0x0000},
2724 {0xaa, 0x03, 0x0003},
2725 {0xaa, 0x04, 0x0015},
2726 {0xaa, 0x05, 0x0020},
2727 {0xaa, 0x06, 0x0005},
2728 {0xaa, 0x08, 0x0000},
2729 {0xaa, 0x03, 0x0004},
2730 {0xaa, 0x04, 0x0017},
2731 {0xaa, 0x05, 0x0020},
2732 {0xaa, 0x06, 0x000d},
2733 {0xaa, 0x08, 0x0000},
2734 {0xaa, 0x03, 0x0005},
2735 {0xaa, 0x04, 0x0019},
2736 {0xaa, 0x05, 0x0020},
2737 {0xaa, 0x06, 0x0005},
2738 {0xaa, 0x08, 0x0000},
2739 {0xaa, 0x03, 0x0006},
2740 {0xaa, 0x04, 0x0017},
2741 {0xaa, 0x05, 0x0026},
2742 {0xaa, 0x06, 0x0005},
2743 {0xaa, 0x08, 0x0000},
2744 {0xaa, 0x03, 0x0007},
2745 {0xaa, 0x04, 0x0019},
2746 {0xaa, 0x05, 0x0022},
2747 {0xaa, 0x06, 0x0005},
2748 {0xaa, 0x08, 0x0000},
2749 {0xaa, 0x03, 0x0008},
2750 {0xaa, 0x04, 0x0021},
2751 {0xaa, 0x05, 0x00aa},
2752 {0xaa, 0x06, 0x0005},
2753 {0xaa, 0x08, 0x0000},
2754 {0xaa, 0x03, 0x0009},
2755 {0xaa, 0x04, 0x0023},
2756 {0xaa, 0x05, 0x00aa},
2757 {0xaa, 0x06, 0x000d},
2758 {0xaa, 0x08, 0x0000},
2759 {0xaa, 0x03, 0x000a},
2760 {0xaa, 0x04, 0x0025},
2761 {0xaa, 0x05, 0x00aa},
2762 {0xaa, 0x06, 0x0005},
2763 {0xaa, 0x08, 0x0000},
2764 {0xaa, 0x03, 0x000b},
2765 {0xaa, 0x04, 0x00ec},
2766 {0xaa, 0x05, 0x002e},
2767 {0xaa, 0x06, 0x0005},
2768 {0xaa, 0x08, 0x0000},
2769 {0xaa, 0x03, 0x000c},
2770 {0xaa, 0x04, 0x00fa},
2771 {0xaa, 0x05, 0x002a},
2772 {0xaa, 0x06, 0x0005},
2773 {0xaa, 0x08, 0x0000},
2774 {0xaa, 0x07, 0x000d},
2775 {0xaa, 0x01, 0x0005},
2776 {0xaa, 0x94, 0x0002},
2777 {0xaa, 0x90, 0x0000},
2778 {0xaa, 0x91, 0x001f},
2779 {0xaa, 0x10, 0x0064},
2780 {0xaa, 0x9b, 0x00f0},
2781 {0xaa, 0x9c, 0x0002},
2782 {0xaa, 0x14, 0x001a},
2783 {0xaa, 0x20, 0x0080},
2784 {0xaa, 0x22, 0x0080},
2785 {0xaa, 0x24, 0x0080},
2786 {0xaa, 0x26, 0x0080},
2787 {0xaa, 0x00, 0x0084},
2788 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2789 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2790 {0xaa, 0xa8, 0x00c0},
2791 {0xa1, 0x01, 0x0002},
2792 {0xa1, 0x01, 0x0008},
2793 {0xa1, 0x01, 0x0180},
2794 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2795 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2796 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2797 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2798 {0xa1, 0x01, 0x0008},
2799
2800 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2801 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2802 {0xa1, 0x01, 0x01c8},
2803 {0xa1, 0x01, 0x01c9},
2804 {0xa1, 0x01, 0x01ca},
2805 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2806 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2807 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2808 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2809 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2810 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2811 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2812 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2813 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2814 {0xa0, 0x52, ZC3XX_R112_RGB22},
2815 {0xa1, 0x01, 0x0180},
2816 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2817 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
2818 {0xaa, 0x0d, 0x0003},
2819 {0xaa, 0x0c, 0x008c},
2820 {0xaa, 0x0e, 0x0095},
2821 {0xaa, 0x0f, 0x0002},
2822 {0xaa, 0x1c, 0x0094},
2823 {0xaa, 0x1d, 0x0002},
2824 {0xaa, 0x20, 0x0080},
2825 {0xaa, 0x22, 0x0080},
2826 {0xaa, 0x24, 0x0080},
2827 {0xaa, 0x26, 0x0080},
2828 {0xaa, 0x00, 0x0084},
2829 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
2830 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
2831 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
2832 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
2833 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
2834 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
2835 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
2836 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
2837 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
2838 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
2839 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
2840 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
2841 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
2842 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
2843 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
2844 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
2845 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
2846 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
2847 {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
2848 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2849 {0xa1, 0x01, 0x0180},
2850 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
2851 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2852 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2853 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2854 {}
2855};
2856
2857static const struct usb_action icm105axx_InitialScale[] = {
2858 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
2859 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
2860 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
2861 {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
2862 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
2863 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
2864 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
2865 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
2866 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
2867 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
2868 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
2869 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
2870 {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
2871 {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
2872 {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
2873 {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
2874 {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
2875 {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
2876 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
2877 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
2878 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
2879 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
2880 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
2881 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
2882 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
2883 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
2884 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
2885 {0xaa, 0x01, 0x0010},
2886 {0xaa, 0x03, 0x0000},
2887 {0xaa, 0x04, 0x0001},
2888 {0xaa, 0x05, 0x0020},
2889 {0xaa, 0x06, 0x0001},
2890 {0xaa, 0x08, 0x0000},
2891 {0xaa, 0x03, 0x0001},
2892 {0xaa, 0x04, 0x0011},
2893 {0xaa, 0x05, 0x00a0},
2894 {0xaa, 0x06, 0x0001},
2895 {0xaa, 0x08, 0x0000},
2896 {0xaa, 0x03, 0x0002},
2897 {0xaa, 0x04, 0x0013},
2898 {0xaa, 0x05, 0x0020},
2899 {0xaa, 0x06, 0x0001},
2900 {0xaa, 0x08, 0x0000},
2901 {0xaa, 0x03, 0x0003},
2902 {0xaa, 0x04, 0x0015},
2903 {0xaa, 0x05, 0x0020},
2904 {0xaa, 0x06, 0x0005},
2905 {0xaa, 0x08, 0x0000},
2906 {0xaa, 0x03, 0x0004},
2907 {0xaa, 0x04, 0x0017},
2908 {0xaa, 0x05, 0x0020},
2909 {0xaa, 0x06, 0x000d},
2910 {0xaa, 0x08, 0x0000},
2911 {0xaa, 0x03, 0x0005},
2912 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
2913 {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
2914 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
2915 {0xa1, 0x01, 0x0091},
2916 {0xaa, 0x05, 0x0020},
2917 {0xaa, 0x06, 0x0005},
2918 {0xaa, 0x08, 0x0000},
2919 {0xaa, 0x03, 0x0006},
2920 {0xaa, 0x04, 0x0017},
2921 {0xaa, 0x05, 0x0026},
2922 {0xaa, 0x06, 0x0005},
2923 {0xaa, 0x08, 0x0000},
2924 {0xaa, 0x03, 0x0007},
2925 {0xaa, 0x04, 0x0019},
2926 {0xaa, 0x05, 0x0022},
2927 {0xaa, 0x06, 0x0005},
2928 {0xaa, 0x08, 0x0000},
2929 {0xaa, 0x03, 0x0008},
2930 {0xaa, 0x04, 0x0021},
2931 {0xaa, 0x05, 0x00aa},
2932 {0xaa, 0x06, 0x0005},
2933 {0xaa, 0x08, 0x0000},
2934 {0xaa, 0x03, 0x0009},
2935 {0xaa, 0x04, 0x0023},
2936 {0xaa, 0x05, 0x00aa},
2937 {0xaa, 0x06, 0x000d},
2938 {0xaa, 0x08, 0x0000},
2939 {0xaa, 0x03, 0x000a},
2940 {0xaa, 0x04, 0x0025},
2941 {0xaa, 0x05, 0x00aa},
2942 {0xaa, 0x06, 0x0005},
2943 {0xaa, 0x08, 0x0000},
2944 {0xaa, 0x03, 0x000b},
2945 {0xaa, 0x04, 0x00ec},
2946 {0xaa, 0x05, 0x002e},
2947 {0xaa, 0x06, 0x0005},
2948 {0xaa, 0x08, 0x0000},
2949 {0xaa, 0x03, 0x000c},
2950 {0xaa, 0x04, 0x00fa},
2951 {0xaa, 0x05, 0x002a},
2952 {0xaa, 0x06, 0x0005},
2953 {0xaa, 0x08, 0x0000},
2954 {0xaa, 0x07, 0x000d},
2955 {0xaa, 0x01, 0x0005},
2956 {0xaa, 0x94, 0x0002},
2957 {0xaa, 0x90, 0x0000},
2958 {0xaa, 0x91, 0x0010},
2959 {0xaa, 0x10, 0x0064},
2960 {0xaa, 0x9b, 0x00f0},
2961 {0xaa, 0x9c, 0x0002},
2962 {0xaa, 0x14, 0x001a},
2963 {0xaa, 0x20, 0x0080},
2964 {0xaa, 0x22, 0x0080},
2965 {0xaa, 0x24, 0x0080},
2966 {0xaa, 0x26, 0x0080},
2967 {0xaa, 0x00, 0x0084},
2968 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
2969 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
2970 {0xaa, 0xa8, 0x0080},
2971 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
2972 {0xa1, 0x01, 0x0002},
2973 {0xa1, 0x01, 0x0008},
2974 {0xa1, 0x01, 0x0180},
2975 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
2976 {0xa0, 0x40, ZC3XX_R116_RGAIN},
2977 {0xa0, 0x40, ZC3XX_R117_GGAIN},
2978 {0xa0, 0x40, ZC3XX_R118_BGAIN},
2979 {0xa1, 0x01, 0x0008},
2980
2981 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
2982 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
2983 {0xa1, 0x01, 0x01c8},
2984 {0xa1, 0x01, 0x01c9},
2985 {0xa1, 0x01, 0x01ca},
2986 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
2987
2988 {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
2989 {0xa0, 0xf7, ZC3XX_R10B_RGB01},
2990 {0xa0, 0xf7, ZC3XX_R10C_RGB02},
2991 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
2992 {0xa0, 0x52, ZC3XX_R10E_RGB11},
2993 {0xa0, 0xf7, ZC3XX_R10F_RGB12},
2994 {0xa0, 0xf7, ZC3XX_R110_RGB20},
2995 {0xa0, 0xf7, ZC3XX_R111_RGB21},
2996 {0xa0, 0x52, ZC3XX_R112_RGB22},
2997 {0xa1, 0x01, 0x0180},
2998 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
2999 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
3000 {0xaa, 0x0d, 0x0003},
3001 {0xaa, 0x0c, 0x0020},
3002 {0xaa, 0x0e, 0x000e},
3003 {0xaa, 0x0f, 0x0002},
3004 {0xaa, 0x1c, 0x000d},
3005 {0xaa, 0x1d, 0x0002},
3006 {0xaa, 0x20, 0x0080},
3007 {0xaa, 0x22, 0x0080},
3008 {0xaa, 0x24, 0x0080},
3009 {0xaa, 0x26, 0x0080},
3010 {0xaa, 0x00, 0x0084},
3011 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
3012 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
3013 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3014 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
3015 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
3016 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3017 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3018 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
3019 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3020 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3021 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3022 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
3023 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
3024 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
3025 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
3026 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
3027 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
3028 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3029 {0xa1, 0x01, 0x0180},
3030 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3031 {0xa0, 0x40, ZC3XX_R116_RGAIN},
3032 {0xa0, 0x40, ZC3XX_R117_GGAIN},
3033 {0xa0, 0x40, ZC3XX_R118_BGAIN},
3034 {}
3035};
3036static const struct usb_action icm105a_50HZ[] = {
3037 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3038 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3039 {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
3040 {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
3041 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3042 {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
3043 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3044 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3045 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3046 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3047 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3048 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3049 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3050 {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
3051 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3052 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3053 {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
3054 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3055 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3056 {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
3057 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3058 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3059 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3060 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3061 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
3062 {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
3063 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
3064 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3065 {}
3066};
3067static const struct usb_action icm105a_50HZScale[] = {
3068 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3069 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3070 {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
3071 {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
3072 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3073 {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
3074 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3075 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3076 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3077 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3078 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3079 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3080 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3081 {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
3082 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3083 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3084 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3085 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3086 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3087 {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
3088 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3089 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3090 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3091 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3092 {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
3093 {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
3094 {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
3095 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3096 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3097 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3098 {}
3099};
3100static const struct usb_action icm105a_60HZ[] = {
3101 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3102 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3103 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3104 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
3105 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3106 {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
3107 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3108 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3109 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3110 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3111 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3112 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3113 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3114 {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
3115 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3116 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3117 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
3118 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3119 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3120 {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
3121 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3122 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3123 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3124 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3125 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3126 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3127 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3128 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3129 {}
3130};
3131static const struct usb_action icm105a_60HZScale[] = {
3132 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3133 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3134 {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
3135 {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
3136 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3137 {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
3138 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3139 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3140 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3141 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3142 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3143 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3144 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3145 {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
3146 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3147 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3148 {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
3149 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3150 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3151 {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
3152 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3153 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3154 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
3155 {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
3156 {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
3157 {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
3158 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
3159 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3160 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3161 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3162 {}
3163};
3164static const struct usb_action icm105a_NoFliker[] = {
3165 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3166 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3167 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3168 {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
3169 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3170 {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
3171 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3172 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3173 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3174 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3175 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3176 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3177 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3178 {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
3179 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3180 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3181 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3182 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3183 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3184 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3185 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3186 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3187 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3188 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
3189 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3190 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3191 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3192 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3193 {}
3194};
3195static const struct usb_action icm105a_NoFlikerScale[] = {
3196 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3197 {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
3198 {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
3199 {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
3200 {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
3201 {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
3202 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
3203 {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
3204 {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
3205 {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
3206 {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
3207 {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
3208 {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
3209 {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
3210 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3211 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3212 {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
3213 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3214 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3215 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
3216 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
3217 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
3218 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
3219 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
3220 {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
3221 {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
3222 {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
3223 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
3224 {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
3225 {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
3226 {}
3227};
3228
3229static const struct usb_action MC501CB_InitialScale[] = {
3230 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3231 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
3232 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
3233 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3234 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
3235 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3236 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3237 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3238 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3239 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3240 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3241 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3242 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3243 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3244 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3245 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3246 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3247 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3248 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3249 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
3250 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
3251 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
3252 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
3253 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3254 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3255 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
3256 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3257 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
3258 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3259 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
3260 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
3261 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
3262 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3263 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
3264 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
3265 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
3266 {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
3267 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3268 {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
3269 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
3270 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
3271 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
3272 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
3273 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
3274 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
3275 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
3276 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
3277 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
3278 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
3279 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
3280 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
3281 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
3282 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
3283 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
3284 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
3285 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
3286 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
3287 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
3288 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
3289 {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
3290 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
3291 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
3292 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
3293 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
3294 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
3295 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
3296 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
3297 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
3298 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
3299 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
3300 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
3301 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
3302 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
3303 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
3304 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
3305 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
3306 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
3307 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
3308 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3309 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
3310 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
3311 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
3312 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3313 {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
3314 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
3315 {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
3316 {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
3317 {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
3318 {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
3319 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
3320 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
3321 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3322 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3323 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3324 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3325 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3326 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3327 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3328 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3329 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3330 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
3331 {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
3332 {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
3333 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3334 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
3335 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
3336 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
3337 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
3338 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
3339 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
3340
3341 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3342 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3343 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3344 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3345 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3346 {}
3347};
3348
3349static const struct usb_action MC501CB_Initial[] = { /* 320x240 */
3350 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3351 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
3352 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
3353 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3354 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
3355 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3356 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3357 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3358 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3359 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3360 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3361 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3362 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3363 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3364 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3365 {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
3366 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
3367 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
3368 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3369 {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
3370 {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
3371 {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
3372 {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
3373 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3374 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3375 {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
3376 {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
3377 {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
3378 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3379 {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
3380 {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
3381 {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
3382 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3383 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
3384 {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
3385 {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
3386 {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
3387 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3388 {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
3389 {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
3390 {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
3391 {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
3392 {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
3393 {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
3394 {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
3395 {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
3396 {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
3397 {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
3398 {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
3399 {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
3400 {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
3401 {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
3402 {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
3403 {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
3404 {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
3405 {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
3406 {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
3407 {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
3408 {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
3409 {0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
3410 {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
3411 {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
3412 {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
3413 {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
3414 {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
3415 {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
3416 {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
3417 {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
3418 {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
3419 {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
3420 {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
3421 {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
3422 {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
3423 {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
3424 {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
3425 {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
3426 {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
3427 {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
3428 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
3429 {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
3430 {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
3431 {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
3432 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3433 {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
3434 {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
3435 {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
3436 {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
3437 {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
3438 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3439 {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
3440 {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
3441 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
3442 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3443 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
3444 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3445 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3446 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3447 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3448 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3449 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3450 {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
3451 {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
3452 {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
3453 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3454 {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
3455 {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
3456 {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
3457 {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
3458 {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
3459 {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
3460 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3461 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3462 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3463 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3464 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3465 {}
3466};
3467
3468static const struct usb_action MC501CB_50HZ[] = {
3469 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3470 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3471 {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
3472 {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
3473 {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
3474 {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
3475 {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
3476 {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
3477 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3478 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3479 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
3480 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
3481 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
3482 {}
3483};
3484
3485static const struct usb_action MC501CB_50HZScale[] = {
3486 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3487 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3488 {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
3489 {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
3490 {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
3491 {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
3492 {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
3493 {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
3494 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3495 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3496 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3497 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3498 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3499 {}
3500};
3501
3502static const struct usb_action MC501CB_60HZ[] = {
3503 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3504 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3505 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3506 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3507 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3508 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3509 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3510 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3511 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3512 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3513 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3514 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3515 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3516 {}
3517};
3518
3519static const struct usb_action MC501CB_60HZScale[] = {
3520 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3521 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3522 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3523 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3524 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3525 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3526 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3527 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3528 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3529 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3530 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3531 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3532 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3533 {}
3534};
3535
3536static const struct usb_action MC501CB_NoFliker[] = {
3537 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3538 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3539 {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
3540 {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
3541 {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
3542 {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
3543 {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
3544 {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
3545 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3546 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3547 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3548 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3549 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3550 {}
3551};
3552
3553static const struct usb_action MC501CB_NoFlikerScale[] = {
3554 {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
3555 {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
3556 {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
3557 {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
3558 {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
3559 {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
3560 {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
3561 {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
3562 {}
3563};
3564
3565/* from zs211.inf - HKR,%OV7620%,Initial - 640x480 */
3566static const struct usb_action OV7620_mode0[] = {
3567 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3568 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
3569 {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3570 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3571 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3572 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3573 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3574 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3575 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3576 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3577 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3578 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3579 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3580 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3581 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3582 {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
3583 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3584 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3585 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3586 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3587 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3588 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3589 {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
3590 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
3591 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3592 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3593 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3594 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3595 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3596 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3597 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3598 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3599 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3600 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3601 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3602 {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
3603 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3604 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3605 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3606 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3607 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3608 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3609 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3610 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3611 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3612 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3613 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3614 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3615 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3616 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3617 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3618 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3619 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3620 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3621 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3622 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3623 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3624 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3625 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3626 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3627 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3628 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3629 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3630 {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
3631 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3632 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3633 {}
3634};
3635
3636/* from zs211.inf - HKR,%OV7620%,InitialScale - 320x240 */
3637static const struct usb_action OV7620_mode1[] = {
3638 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
3639 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT}, /* 00,02,50,cc */
3640 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
3641 /* mx change? */
3642 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
3643 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
3644 {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
3645 {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
3646 {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
3647 {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
3648 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
3649 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
3650 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
3651 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
3652 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
3653 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
3654 {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
3655 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
3656 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
3657 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
3658 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
3659 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
3660 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
3661 {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d6,cc */
3662 /* OV7648 00,9c,d8,cc */
3663 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
3664 {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
3665 {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
3666 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3667 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3668 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
3669 {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
3670 {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
3671 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
3672 {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
3673 {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
3674 {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
3675 {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
3676 {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
3677 {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
3678 {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
3679 {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
3680 {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
3681 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
3682 {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
3683 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3684 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3685 {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
3686 {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
3687 {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
3688 {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
3689 {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
3690 {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
3691 {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
3692 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
3693 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
3694 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
3695 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
3696 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
3697 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
3698 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
3699 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
3700 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
3701 {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
3702 {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
3703 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,50,cc */
3704 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
3705 {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
3706 {}
3707};
3708
3709/* from zs211.inf - HKR,%OV7620%\AE,50HZ */
3710static const struct usb_action OV7620_50HZ[] = {
3711 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3712 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3713 {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
3714 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3715 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3716 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3717 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3718 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3719 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3720 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3721 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3722 {0xaa, 0x10, 0x0082}, /* 00,10,82,aa */
3723 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3724/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3725 if mode0 (640x480) */
3726 {}
3727};
3728
3729/* from zs211.inf - HKR,%OV7620%\AE,60HZ */
3730static const struct usb_action OV7620_60HZ[] = {
3731 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3732 /* (bug in zs211.inf) */
3733 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3734 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3735 {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
3736 {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
3737 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3738 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3739 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3740 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3741 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3742 {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
3743 {0xaa, 0x10, 0x0020}, /* 00,10,20,aa */
3744 {0xaa, 0x76, 0x0003}, /* 00,76,03,aa */
3745/* {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, * 00,02,40,cc
3746 * if mode0 (640x480) */
3747/* ?? in gspca v1, it was
3748 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3749 {0xa1, 0x01, 0x0037}, */
3750 {}
3751};
3752
3753/* from zs211.inf - HKR,%OV7620%\AE,NoFliker */
3754static const struct usb_action OV7620_NoFliker[] = {
3755 {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
3756 /* (bug in zs211.inf) */
3757 {0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
3758 {0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
3759 {0xaa, 0x75, 0x008e}, /* 00,75,8e,aa */
3760 {0xaa, 0x2d, 0x0001}, /* 00,2d,01,aa */
3761 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
3762 {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
3763 {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
3764 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
3765 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
3766 {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
3767/* {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT}, * 00,02,44,cc
3768 - if mode1 (320x240) */
3769/* ?? was
3770 {0xa0, 0x00, 0x0039}, * 00,00,00,dd *
3771 {0xa1, 0x01, 0x0037}, */
3772 {}
3773};
3774
3775static const struct usb_action ov7630c_Initial[] = {
3776 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3777 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3778 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3779 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
3780 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3781 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3782 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3783 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3784 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3785 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3786 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3787 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3788 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3789 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3790 {0xaa, 0x12, 0x0080},
3791 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3792 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3793 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3794 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3795 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3796 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3797 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3798 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3799 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3800 {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
3801 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
3802 {0xaa, 0x12, 0x0069},
3803 {0xaa, 0x04, 0x0020},
3804 {0xaa, 0x06, 0x0050},
3805 {0xaa, 0x13, 0x0083},
3806 {0xaa, 0x14, 0x0000},
3807 {0xaa, 0x15, 0x0024},
3808 {0xaa, 0x17, 0x0018},
3809 {0xaa, 0x18, 0x00ba},
3810 {0xaa, 0x19, 0x0002},
3811 {0xaa, 0x1a, 0x00f6},
3812 {0xaa, 0x1b, 0x0002},
3813 {0xaa, 0x20, 0x00c2},
3814 {0xaa, 0x24, 0x0060},
3815 {0xaa, 0x25, 0x0040},
3816 {0xaa, 0x26, 0x0030},
3817 {0xaa, 0x27, 0x00ea},
3818 {0xaa, 0x28, 0x00a0},
3819 {0xaa, 0x21, 0x0000},
3820 {0xaa, 0x2a, 0x0081},
3821 {0xaa, 0x2b, 0x0096},
3822 {0xaa, 0x2d, 0x0094},
3823 {0xaa, 0x2f, 0x003d},
3824 {0xaa, 0x30, 0x0024},
3825 {0xaa, 0x60, 0x0000},
3826 {0xaa, 0x61, 0x0040},
3827 {0xaa, 0x68, 0x007c},
3828 {0xaa, 0x6f, 0x0015},
3829 {0xaa, 0x75, 0x0088},
3830 {0xaa, 0x77, 0x00b5},
3831 {0xaa, 0x01, 0x0060},
3832 {0xaa, 0x02, 0x0060},
3833 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3834 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3835 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3836 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3837 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3838 {0xa0, 0x00, 0x01ad},
3839 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3840 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3841 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3842 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3843 {0xa0, 0x60, ZC3XX_R116_RGAIN},
3844 {0xa0, 0x46, ZC3XX_R118_BGAIN},
3845 {0xa0, 0x04, ZC3XX_R113_RGB03},
3846/* 0x10, */
3847 {0xa1, 0x01, 0x0002},
3848 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3849 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3850 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3851 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3852 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3853 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3854 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3855 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3856 {0xa0, 0x50, ZC3XX_R112_RGB22},
3857/* 0x03, */
3858 {0xa1, 0x01, 0x0008},
3859 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
3860 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
3861 {0xa1, 0x01, 0x01c8},
3862 {0xa1, 0x01, 0x01c9},
3863 {0xa1, 0x01, 0x01ca},
3864 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
3865 {0xa0, 0x01, ZC3XX_R120_GAMMA00}, /* gamma 2 ?*/
3866 {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
3867 {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
3868 {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
3869 {0xa0, 0x53, ZC3XX_R124_GAMMA04},
3870 {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
3871 {0xa0, 0x85, ZC3XX_R126_GAMMA06},
3872 {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
3873 {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
3874 {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
3875 {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
3876 {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
3877 {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
3878 {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
3879 {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
3880 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
3881 {0xa0, 0x05, ZC3XX_R130_GAMMA10},
3882 {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
3883 {0xa0, 0x16, ZC3XX_R132_GAMMA12},
3884 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
3885 {0xa0, 0x19, ZC3XX_R134_GAMMA14},
3886 {0xa0, 0x19, ZC3XX_R135_GAMMA15},
3887 {0xa0, 0x17, ZC3XX_R136_GAMMA16},
3888 {0xa0, 0x15, ZC3XX_R137_GAMMA17},
3889 {0xa0, 0x12, ZC3XX_R138_GAMMA18},
3890 {0xa0, 0x10, ZC3XX_R139_GAMMA19},
3891 {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
3892 {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
3893 {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
3894 {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
3895 {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
3896 {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
3897 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
3898 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
3899 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
3900 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
3901 {0xa0, 0x50, ZC3XX_R10E_RGB11},
3902 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
3903 {0xa0, 0xf8, ZC3XX_R110_RGB20},
3904 {0xa0, 0xf8, ZC3XX_R111_RGB21},
3905 {0xa0, 0x50, ZC3XX_R112_RGB22},
3906
3907 {0xa1, 0x01, 0x0180},
3908 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
3909 {0xaa, 0x10, 0x001b},
3910 {0xaa, 0x76, 0x0002},
3911 {0xaa, 0x2a, 0x0081},
3912 {0xaa, 0x2b, 0x0000},
3913 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
3914 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
3915 {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
3916 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
3917 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
3918 {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
3919 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
3920 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
3921 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
3922 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
3923 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
3924 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
3925 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
3926 {0xaa, 0x13, 0x0083}, /* 40 */
3927 {0xa1, 0x01, 0x0180},
3928 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
3929 {}
3930};
3931
3932static const struct usb_action ov7630c_InitialScale[] = {
3933 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
3934 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
3935 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
3936 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
3937 {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
3938 {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
3939 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
3940 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
3941 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
3942 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
3943 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
3944 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
3945
3946 {0xaa, 0x12, 0x0080},
3947 {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
3948 {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
3949 {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
3950 {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
3951 {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
3952 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
3953 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
3954 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
3955 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
3956 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
3957 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
3958 {0xaa, 0x12, 0x0069}, /* i2c */
3959 {0xaa, 0x04, 0x0020},
3960 {0xaa, 0x06, 0x0050},
3961 {0xaa, 0x13, 0x00c3},
3962 {0xaa, 0x14, 0x0000},
3963 {0xaa, 0x15, 0x0024},
3964 {0xaa, 0x19, 0x0003},
3965 {0xaa, 0x1a, 0x00f6},
3966 {0xaa, 0x1b, 0x0002},
3967 {0xaa, 0x20, 0x00c2},
3968 {0xaa, 0x24, 0x0060},
3969 {0xaa, 0x25, 0x0040},
3970 {0xaa, 0x26, 0x0030},
3971 {0xaa, 0x27, 0x00ea},
3972 {0xaa, 0x28, 0x00a0},
3973 {0xaa, 0x21, 0x0000},
3974 {0xaa, 0x2a, 0x0081},
3975 {0xaa, 0x2b, 0x0096},
3976 {0xaa, 0x2d, 0x0084},
3977 {0xaa, 0x2f, 0x003d},
3978 {0xaa, 0x30, 0x0024},
3979 {0xaa, 0x60, 0x0000},
3980 {0xaa, 0x61, 0x0040},
3981 {0xaa, 0x68, 0x007c},
3982 {0xaa, 0x6f, 0x0015},
3983 {0xaa, 0x75, 0x0088},
3984 {0xaa, 0x77, 0x00b5},
3985 {0xaa, 0x01, 0x0060},
3986 {0xaa, 0x02, 0x0060},
3987 {0xaa, 0x17, 0x0018},
3988 {0xaa, 0x18, 0x00ba},
3989 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
3990 {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
3991 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
3992 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
3993 {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
3994 {0xa0, 0x00, 0x01ad},
3995 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
3996 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
3997 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
3998 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
3999 {0xa0, 0x60, ZC3XX_R116_RGAIN},
4000 {0xa0, 0x46, ZC3XX_R118_BGAIN},
4001 {0xa0, 0x04, ZC3XX_R113_RGB03},
4002
4003 {0xa1, 0x01, 0x0002},
4004 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
4005 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
4006 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4007 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
4008 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
4009 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
4010 {0xa0, 0x00, ZC3XX_R110_RGB20},
4011 {0xa0, 0xf6, ZC3XX_R111_RGB21},
4012 {0xa0, 0x4a, ZC3XX_R112_RGB22},
4013
4014 {0xa1, 0x01, 0x0008},
4015 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4016 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4017 {0xa1, 0x01, 0x01c8},
4018 {0xa1, 0x01, 0x01c9},
4019 {0xa1, 0x01, 0x01ca},
4020 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4021 {0xa0, 0x16, ZC3XX_R120_GAMMA00}, /* gamma ~4 */
4022 {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
4023 {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
4024 {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
4025 {0xa0, 0x94, ZC3XX_R124_GAMMA04},
4026 {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
4027 {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
4028 {0xa0, 0xca, ZC3XX_R127_GAMMA07},
4029 {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
4030 {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
4031 {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
4032 {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
4033 {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
4034 {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
4035 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
4036 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4037 {0xa0, 0x20, ZC3XX_R130_GAMMA10},
4038 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4039 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4040 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4041 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4042 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4043 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4044 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4045 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4046 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4047 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4048 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4049 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4050 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4051 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
4052 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
4053 {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
4054 {0xa0, 0xfe, ZC3XX_R10B_RGB01},
4055 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4056 {0xa0, 0xf7, ZC3XX_R10D_RGB10},
4057 {0xa0, 0x4d, ZC3XX_R10E_RGB11},
4058 {0xa0, 0xfc, ZC3XX_R10F_RGB12},
4059 {0xa0, 0x00, ZC3XX_R110_RGB20},
4060 {0xa0, 0xf6, ZC3XX_R111_RGB21},
4061 {0xa0, 0x4a, ZC3XX_R112_RGB22},
4062
4063 {0xa1, 0x01, 0x0180},
4064 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4065 {0xaa, 0x10, 0x000d},
4066 {0xaa, 0x76, 0x0002},
4067 {0xaa, 0x2a, 0x0081},
4068 {0xaa, 0x2b, 0x0000},
4069 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4070 {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
4071 {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
4072 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4073 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4074 {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
4075 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4076 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4077 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
4078 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
4079 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
4080 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
4081 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4082 {0xaa, 0x13, 0x00c3},
4083
4084 {0xa1, 0x01, 0x0180},
4085 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4086 {}
4087};
4088
4089static const struct usb_action pas106b_Initial_com[] = {
4090/* Sream and Sensor specific */
4091 {0xa1, 0x01, 0x0010}, /* CMOSSensorSelect */
4092/* System */
4093 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
4094 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
4095/* Picture size */
4096 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* ClockSelect */
4097 {0xa0, 0x03, 0x003a},
4098 {0xa0, 0x0c, 0x003b},
4099 {0xa0, 0x04, 0x0038},
4100 {}
4101};
4102
4103static const struct usb_action pas106b_Initial[] = { /* 176x144 */
4104/* JPEG control */
4105 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4106/* Sream and Sensor specific */
4107 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, /* CMOSSensorSelect */
4108/* Picture size */
4109 {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH}, /* FrameWidthHigh 00 */
4110 {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW}, /* FrameWidthLow B0 */
4111 {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* FrameHeightHigh 00 */
4112 {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW}, /* FrameHightLow 90 */
4113/* System */
4114 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* SystemOperating */
4115/* Sream and Sensor specific */
4116 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4117 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4118/* Sensor Interface */
4119 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* Compatibily Mode */
4120/* Window inside sensor array */
4121 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* WinXStartLow */
4122 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* FirstYLow */
4123 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* FirstxLow */
4124 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, /* WinHeightLow */
4125 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, /* WinWidthLow */
4126/* Init the sensor */
4127 {0xaa, 0x02, 0x0004},
4128 {0xaa, 0x08, 0x0000},
4129 {0xaa, 0x09, 0x0005},
4130 {0xaa, 0x0a, 0x0002},
4131 {0xaa, 0x0b, 0x0002},
4132 {0xaa, 0x0c, 0x0005},
4133 {0xaa, 0x0d, 0x0000},
4134 {0xaa, 0x0e, 0x0002},
4135 {0xaa, 0x14, 0x0081},
4136
4137/* Other registors */
4138 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
4139/* Frame retreiving */
4140 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
4141/* Gains */
4142 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, /* DigitalGain */
4143/* Unknown */
4144 {0xa0, 0x00, 0x01ad},
4145/* Sharpness */
4146 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
4147 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* Sharpness05 */
4148/* Other registors */
4149 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4150/* Auto exposure and white balance */
4151 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4152/*Dead pixels */
4153 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4154/* EEPROM */
4155 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4156/* JPEG control */
4157 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4158 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4159 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4160/* Other registers */
4161 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4162/* Auto exposure and white balance */
4163 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4164/*Dead pixels */
4165 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4166/* EEPROM */
4167 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4168/* JPEG control */
4169 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4170 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4171 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4172
4173 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
4174 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
4175 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4176 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
4177 {0xa0, 0x58, ZC3XX_R10E_RGB11},
4178 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
4179 {0xa0, 0xf4, ZC3XX_R110_RGB20},
4180 {0xa0, 0xf4, ZC3XX_R111_RGB21},
4181 {0xa0, 0x58, ZC3XX_R112_RGB22},
4182/* Auto correction */
4183 {0xa0, 0x03, ZC3XX_R181_WINXSTART}, /* WinXstart */
4184 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, /* WinXWidth */
4185 {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, /* WinXCenter */
4186 {0xa0, 0x03, ZC3XX_R184_WINYSTART}, /* WinYStart */
4187 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, /* WinYWidth */
4188 {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, /* WinYCenter */
4189 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4190
4191/* Auto exposure and white balance */
4192 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* ExposureLimitHigh */
4193 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* ExposureLimitMid */
4194 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, /* ExposureLimitLow */
4195 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* AntiFlickerHigh */
4196 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* AntiFlickerLow */
4197 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* AntiFlickerLow */
4198 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* AEBFreeze */
4199 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* AEBUnfreeze */
4200/* sensor on */
4201 {0xaa, 0x07, 0x00b1},
4202 {0xaa, 0x05, 0x0003},
4203 {0xaa, 0x04, 0x0001},
4204 {0xaa, 0x03, 0x003b},
4205/* Gains */
4206 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* DigitalLimitDiff */
4207 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* DigitalGainStep */
4208 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4209 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4210/* Auto correction */
4211 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4212 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
4213 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4214/* Gains */
4215 {0xa0, 0x40, ZC3XX_R116_RGAIN}, /* RGain */
4216 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* GGain */
4217 {0xa0, 0x40, ZC3XX_R118_BGAIN}, /* BGain */
4218 {}
4219};
4220
4221static const struct usb_action pas106b_InitialScale[] = { /* 352x288 */
4222/* JPEG control */
4223 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4224/* Sream and Sensor specific */
4225 {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT}, /* CMOSSensorSelect */
4226/* Picture size */
4227 {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH}, /* FrameWidthHigh */
4228 {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW}, /* FrameWidthLow */
4229 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* FrameHeightHigh */
4230 {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW}, /* FrameHightLow */
4231/* System */
4232 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* SystemOperating */
4233/* Sream and Sensor specific */
4234 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4235 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* VideoControlFunction */
4236/* Sensor Interface */
4237 {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* Compatibily Mode */
4238/* Window inside sensor array */
4239 {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW}, /* WinXStartLow */
4240 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* FirstYLow */
4241 {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW}, /* FirstxLow */
4242 {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW}, /* WinHeightLow */
4243 {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW}, /* WinWidthLow */
4244/* Init the sensor */
4245 {0xaa, 0x02, 0x0004},
4246 {0xaa, 0x08, 0x0000},
4247 {0xaa, 0x09, 0x0005},
4248 {0xaa, 0x0a, 0x0002},
4249 {0xaa, 0x0b, 0x0002},
4250 {0xaa, 0x0c, 0x0005},
4251 {0xaa, 0x0d, 0x0000},
4252 {0xaa, 0x0e, 0x0002},
4253 {0xaa, 0x14, 0x0081},
4254
4255/* Other registors */
4256 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* SensorCorrection */
4257/* Frame retreiving */
4258 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* AutoAdjustFPS */
4259/* Gains */
4260 {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN}, /* DigitalGain */
4261/* Unknown */
4262 {0xa0, 0x00, 0x01ad},
4263/* Sharpness */
4264 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* SharpnessMode */
4265 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* Sharpness05 */
4266/* Other registors */
4267 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4268/* Auto exposure and white balance */
4269 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4270 {0xa0, 0x80, ZC3XX_R18D_YTARGET}, /* ????????? */
4271/*Dead pixels */
4272 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4273/* EEPROM */
4274 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4275/* JPEG control */
4276 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4277 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4278 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4279/* Other registers */
4280 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* OperationMode */
4281/* Auto exposure and white balance */
4282 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* AWBStatus */
4283/*Dead pixels */
4284 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* DeadPixelsMode */
4285/* EEPROM */
4286 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* EEPROMAccess */
4287/* JPEG control */
4288 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* ClockSetting */
4289 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4290 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4291
4292 {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
4293 {0xa0, 0xf4, ZC3XX_R10B_RGB01},
4294 {0xa0, 0xf4, ZC3XX_R10C_RGB02},
4295 {0xa0, 0xf4, ZC3XX_R10D_RGB10},
4296 {0xa0, 0x58, ZC3XX_R10E_RGB11},
4297 {0xa0, 0xf4, ZC3XX_R10F_RGB12},
4298 {0xa0, 0xf4, ZC3XX_R110_RGB20},
4299 {0xa0, 0xf4, ZC3XX_R111_RGB21},
4300 {0xa0, 0x58, ZC3XX_R112_RGB22},
4301/* Auto correction */
4302 {0xa0, 0x03, ZC3XX_R181_WINXSTART}, /* WinXstart */
4303 {0xa0, 0x08, ZC3XX_R182_WINXWIDTH}, /* WinXWidth */
4304 {0xa0, 0x16, ZC3XX_R183_WINXCENTER}, /* WinXCenter */
4305 {0xa0, 0x03, ZC3XX_R184_WINYSTART}, /* WinYStart */
4306 {0xa0, 0x05, ZC3XX_R185_WINYWIDTH}, /* WinYWidth */
4307 {0xa0, 0x14, ZC3XX_R186_WINYCENTER}, /* WinYCenter */
4308 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4309
4310/* Auto exposure and white balance */
4311 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* ExposureLimitHigh 0 */
4312 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* ExposureLimitMid */
4313 {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW}, /* ExposureLimitLow 0xb1 */
4314
4315 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* AntiFlickerHigh 0x00 */
4316 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* AntiFlickerLow 0x00 */
4317 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* AntiFlickerLow 0x87 */
4318
4319 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* AEBFreeze 0x10 0x0c */
4320 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* AEBUnfreeze 0x30 0x18 */
4321/* sensor on */
4322 {0xaa, 0x07, 0x00b1},
4323 {0xaa, 0x05, 0x0003},
4324 {0xaa, 0x04, 0x0001},
4325 {0xaa, 0x03, 0x003b},
4326/* Gains */
4327 {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* DigitalLimitDiff */
4328 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* DigitalGainStep */
4329 {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4330 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN}, /* GlobalGain */
4331/* Auto correction */
4332 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4333 {0xa1, 0x01, 0x0180}, /* AutoCorrectEnable */
4334 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* AutoCorrectEnable */
4335/* Gains */
4336 {0xa0, 0x40, ZC3XX_R116_RGAIN}, /* RGain */
4337 {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* GGain */
4338 {0xa0, 0x40, ZC3XX_R118_BGAIN}, /* BGain */
4339
4340 {0xa0, 0x00, 0x0007}, /* AutoCorrectEnable */
4341 {0xa0, 0xff, ZC3XX_R018_FRAMELOST}, /* Frame adjust */
4342 {}
4343};
4344static const struct usb_action pas106b_50HZ[] = {
4345 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4346 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4347 {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
4348 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4349 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4350 {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
4351 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4352 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
4353 {0xaa, 0x03, 0x0021}, /* 00,03,21,aa */
4354 {0xaa, 0x04, 0x000c}, /* 00,04,0c,aa */
4355 {0xaa, 0x05, 0x0002}, /* 00,05,02,aa */
4356 {0xaa, 0x07, 0x001c}, /* 00,07,1c,aa */
4357 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
4358 {}
4359};
4360static const struct usb_action pas106b_60HZ[] = {
4361 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4362 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4363 {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
4364 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4365 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4366 {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
4367 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4368 {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,30,cc */
4369 {0xaa, 0x03, 0x001c}, /* 00,03,1c,aa */
4370 {0xaa, 0x04, 0x0004}, /* 00,04,04,aa */
4371 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
4372 {0xaa, 0x07, 0x00c4}, /* 00,07,c4,aa */
4373 {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
4374 {}
4375};
4376static const struct usb_action pas106b_NoFliker[] = {
4377 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4378 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
4379 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
4380 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4381 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4382 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
4383 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4384 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4385 {0xaa, 0x03, 0x0013}, /* 00,03,13,aa */
4386 {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
4387 {0xaa, 0x05, 0x0001}, /* 00,05,01,aa */
4388 {0xaa, 0x07, 0x0030}, /* 00,07,30,aa */
4389 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4390 {}
4391};
4392
4393static const struct usb_action pb03303x_Initial[] = {
4394 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4395 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4396 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4397 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4398 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4399 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4400 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4401 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4402 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */
4403 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4404 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
4405 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
4406 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4407 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4408 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4409 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4410 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4411 {0xaa, 0x01, 0x0001},
4412 {0xaa, 0x06, 0x0000},
4413 {0xaa, 0x08, 0x0483},
4414 {0xaa, 0x01, 0x0004},
4415 {0xaa, 0x08, 0x0006},
4416 {0xaa, 0x02, 0x0011},
4417 {0xaa, 0x03, 0x01e7},
4418 {0xaa, 0x04, 0x0287},
4419 {0xaa, 0x07, 0x3002},
4420 {0xaa, 0x20, 0x1100},
4421 {0xaa, 0x35, 0x0050},
4422 {0xaa, 0x30, 0x0005},
4423 {0xaa, 0x31, 0x0000},
4424 {0xaa, 0x58, 0x0078},
4425 {0xaa, 0x62, 0x0411},
4426 {0xaa, 0x2b, 0x0028},
4427 {0xaa, 0x2c, 0x0030},
4428 {0xaa, 0x2d, 0x0030},
4429 {0xaa, 0x2e, 0x0028},
4430 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4431 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4432 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4433 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4434 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4435 {0xa0, 0x00, 0x01ad},
4436 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4437 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4438 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4439 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4440 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4441 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
4442 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4443 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4444
4445 {0xa1, 0x01, 0x0002},
4446 {0xa0, 0x09, 0x01ad},
4447 {0xa0, 0x15, 0x01ae},
4448 {0xa0, 0x0d, 0x003a},
4449 {0xa0, 0x02, 0x003b},
4450 {0xa0, 0x00, 0x0038},
4451 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4452 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4453 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4454 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4455 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4456 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4457 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4458 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4459 {0xa0, 0x50, ZC3XX_R112_RGB22},
4460
4461 {0xa1, 0x01, 0x0008},
4462 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4463 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4464 {0xa1, 0x01, 0x01c8},
4465 {0xa1, 0x01, 0x01c9},
4466 {0xa1, 0x01, 0x01ca},
4467 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4468 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
4469 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
4470 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
4471 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
4472 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
4473 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
4474 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
4475 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
4476 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
4477 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
4478 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
4479 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
4480 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
4481 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
4482 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
4483 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4484 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
4485 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4486 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4487 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4488 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4489 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4490 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4491 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4492 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4493 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4494 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4495 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4496 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4497 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4498 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
4499 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
4500 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4501 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4502 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4503 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4504 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4505 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4506 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4507 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4508 {0xa0, 0x50, ZC3XX_R112_RGB22},
4509
4510 {0xa1, 0x01, 0x0180},
4511 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4512 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4513 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4514 {0xaa, 0x05, 0x0009},
4515 {0xaa, 0x09, 0x0134},
4516 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4517 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4518 {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW},
4519 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4520 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4521 {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW},
4522 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4523 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4524 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4525 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4526 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4527 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4528 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4529 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4530 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4531 {0xa0, 0x09, 0x01ad},
4532 {0xa0, 0x15, 0x01ae},
4533 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4534 {0xa1, 0x01, 0x0180},
4535 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4536 {}
4537};
4538
4539static const struct usb_action pb03303x_InitialScale[] = {
4540 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4541 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
4542 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4543 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
4544 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4545 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4546 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4547 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4548 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR}, /* 8b -> dc */
4549 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4550 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
4551 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
4552 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4553 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4554 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4555 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4556 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
4557 {0xaa, 0x01, 0x0001},
4558 {0xaa, 0x06, 0x0000},
4559 {0xaa, 0x08, 0x0483},
4560 {0xaa, 0x01, 0x0004},
4561 {0xaa, 0x08, 0x0006},
4562 {0xaa, 0x02, 0x0011},
4563 {0xaa, 0x03, 0x01e7},
4564 {0xaa, 0x04, 0x0287},
4565 {0xaa, 0x07, 0x3002},
4566 {0xaa, 0x20, 0x1100},
4567 {0xaa, 0x35, 0x0050},
4568 {0xaa, 0x30, 0x0005},
4569 {0xaa, 0x31, 0x0000},
4570 {0xaa, 0x58, 0x0078},
4571 {0xaa, 0x62, 0x0411},
4572 {0xaa, 0x2b, 0x0028},
4573 {0xaa, 0x2c, 0x0030},
4574 {0xaa, 0x2d, 0x0030},
4575 {0xaa, 0x2e, 0x0028},
4576 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4577 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4578 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4579 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4580 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4581 {0xa0, 0x00, 0x01ad},
4582 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4583 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4584 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4585 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4586 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4587 {0xa0, 0x78, ZC3XX_R18D_YTARGET},
4588 {0xa0, 0x61, ZC3XX_R116_RGAIN},
4589 {0xa0, 0x65, ZC3XX_R118_BGAIN},
4590
4591 {0xa1, 0x01, 0x0002},
4592
4593 {0xa0, 0x09, 0x01ad},
4594 {0xa0, 0x15, 0x01ae},
4595
4596 {0xa0, 0x0d, 0x003a},
4597 {0xa0, 0x02, 0x003b},
4598 {0xa0, 0x00, 0x0038},
4599 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4600 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4601 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4602 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4603 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4604 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4605 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4606 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4607 {0xa0, 0x50, ZC3XX_R112_RGB22},
4608
4609 {0xa1, 0x01, 0x0008},
4610 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4611 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4612 {0xa1, 0x01, 0x01c8},
4613 {0xa1, 0x01, 0x01c9},
4614 {0xa1, 0x01, 0x01ca},
4615 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4616
4617 {0xa0, 0x13, ZC3XX_R120_GAMMA00}, /* gamma 4 */
4618 {0xa0, 0x38, ZC3XX_R121_GAMMA01},
4619 {0xa0, 0x59, ZC3XX_R122_GAMMA02},
4620 {0xa0, 0x79, ZC3XX_R123_GAMMA03},
4621 {0xa0, 0x92, ZC3XX_R124_GAMMA04},
4622 {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
4623 {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
4624 {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
4625 {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
4626 {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
4627 {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
4628 {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
4629 {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
4630 {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
4631 {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
4632 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
4633 {0xa0, 0x26, ZC3XX_R130_GAMMA10},
4634 {0xa0, 0x22, ZC3XX_R131_GAMMA11},
4635 {0xa0, 0x20, ZC3XX_R132_GAMMA12},
4636 {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
4637 {0xa0, 0x16, ZC3XX_R134_GAMMA14},
4638 {0xa0, 0x13, ZC3XX_R135_GAMMA15},
4639 {0xa0, 0x10, ZC3XX_R136_GAMMA16},
4640 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
4641 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
4642 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
4643 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
4644 {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
4645 {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
4646 {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
4647 {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
4648 {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
4649 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4650 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4651 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4652 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4653 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4654 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4655 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4656 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4657 {0xa0, 0x50, ZC3XX_R112_RGB22},
4658
4659 {0xa1, 0x01, 0x0180},
4660 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4661 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4662 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4663 {0xaa, 0x05, 0x0009},
4664 {0xaa, 0x09, 0x0134},
4665 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4666 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4667 {0xa0, 0xec, ZC3XX_R192_EXPOSURELIMITLOW},
4668 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4669 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4670 {0xa0, 0x9c, ZC3XX_R197_ANTIFLICKERLOW},
4671 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
4672 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
4673 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4674 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4675 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4676 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
4677 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
4678 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4679 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4680 {0xa0, 0x09, 0x01ad},
4681 {0xa0, 0x15, 0x01ae},
4682 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4683 {0xa1, 0x01, 0x0180},
4684 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4685 {}
4686};
4687static const struct usb_action pb0330xx_Initial[] = {
4688 {0xa1, 0x01, 0x0008},
4689 {0xa1, 0x01, 0x0008},
4690 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4691 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4692 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4693 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
4694 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4695 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4696 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4697 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4698 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4699 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4700 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4701 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4702 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4703 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4704 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4705 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4706 {0xaa, 0x01, 0x0006},
4707 {0xaa, 0x02, 0x0011},
4708 {0xaa, 0x03, 0x01e7},
4709 {0xaa, 0x04, 0x0287},
4710 {0xaa, 0x06, 0x0003},
4711 {0xaa, 0x07, 0x3002},
4712 {0xaa, 0x20, 0x1100},
4713 {0xaa, 0x2f, 0xf7b0},
4714 {0xaa, 0x30, 0x0005},
4715 {0xaa, 0x31, 0x0000},
4716 {0xaa, 0x34, 0x0100},
4717 {0xaa, 0x35, 0x0060},
4718 {0xaa, 0x3d, 0x068f},
4719 {0xaa, 0x40, 0x01e0},
4720 {0xaa, 0x58, 0x0078},
4721 {0xaa, 0x62, 0x0411},
4722 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4723 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4724 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4725 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4726 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4727 {0xa0, 0x00, 0x01ad},
4728 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4729 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4730 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4731 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4732 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4733 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4734 {0xa1, 0x01, 0x0002},
4735 {0xa0, 0x09, 0x01ad},
4736 {0xa0, 0x15, 0x01ae},
4737 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
4738 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
4739 {0xa1, 0x01, 0x0091},
4740 {0xa1, 0x01, 0x0095},
4741 {0xa1, 0x01, 0x0096},
4742 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4743 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4744 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4745 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4746 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4747 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4748 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4749 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4750 {0xa0, 0x50, ZC3XX_R112_RGB22},
4751 {0xa1, 0x01, 0x0008},
4752 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4753 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4754 {0xa1, 0x01, 0x01c8},
4755 {0xa1, 0x01, 0x01c9},
4756 {0xa1, 0x01, 0x01ca},
4757 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4758
4759 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4760 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4761 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4762 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4763 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4764 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4765 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4766 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4767 {0xa0, 0x50, ZC3XX_R112_RGB22},
4768 {0xa1, 0x01, 0x0180},
4769 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4770 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4771 {0xaa, 0x05, 0x0066},
4772 {0xaa, 0x09, 0x02b2},
4773 {0xaa, 0x10, 0x0002},
4774
4775 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4776 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4777 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4778 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4779 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4780 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4781 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4782 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4783 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4784 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4785 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4786 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4787 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4788 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4789 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4790 {0xa0, 0x09, 0x01ad},
4791 {0xa0, 0x15, 0x01ae},
4792 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4793 {0xa1, 0x01, 0x0180},
4794 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4795 {0xa1, 0x01, 0x0008},
4796 {0xa1, 0x01, 0x0007},
4797/* {0xa0, 0x30, 0x0007}, */
4798/* {0xa0, 0x00, 0x0007}, */
4799 {}
4800};
4801
4802static const struct usb_action pb0330xx_InitialScale[] = {
4803 {0xa1, 0x01, 0x0008},
4804 {0xa1, 0x01, 0x0008},
4805 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
4806 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00 */
4807 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
4808 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 10 */
4809 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
4810 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
4811 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
4812 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
4813 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
4814 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4815 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
4816 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
4817 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
4818 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
4819 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
4820 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4821 {0xaa, 0x01, 0x0006},
4822 {0xaa, 0x02, 0x0011},
4823 {0xaa, 0x03, 0x01e7},
4824 {0xaa, 0x04, 0x0287},
4825 {0xaa, 0x06, 0x0003},
4826 {0xaa, 0x07, 0x3002},
4827 {0xaa, 0x20, 0x1100},
4828 {0xaa, 0x2f, 0xf7b0},
4829 {0xaa, 0x30, 0x0005},
4830 {0xaa, 0x31, 0x0000},
4831 {0xaa, 0x34, 0x0100},
4832 {0xaa, 0x35, 0x0060},
4833 {0xaa, 0x3d, 0x068f},
4834 {0xaa, 0x40, 0x01e0},
4835 {0xaa, 0x58, 0x0078},
4836 {0xaa, 0x62, 0x0411},
4837 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
4838 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
4839 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
4840 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
4841 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
4842 {0xa0, 0x00, 0x01ad},
4843 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
4844 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
4845 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
4846 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
4847 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
4848 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
4849 {0xa1, 0x01, 0x0002},
4850 {0xa0, 0x09, 0x01ad},
4851 {0xa0, 0x15, 0x01ae},
4852 {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT},
4853 {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND},
4854 {0xa1, 0x01, 0x0091},
4855 {0xa1, 0x01, 0x0095},
4856 {0xa1, 0x01, 0x0096},
4857 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4858 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4859 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4860 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4861 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4862 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4863 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4864 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4865 {0xa0, 0x50, ZC3XX_R112_RGB22},
4866 {0xa1, 0x01, 0x0008},
4867 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
4868 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
4869 {0xa1, 0x01, 0x01c8},
4870 {0xa1, 0x01, 0x01c9},
4871 {0xa1, 0x01, 0x01ca},
4872 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
4873
4874 {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
4875 {0xa0, 0xf8, ZC3XX_R10B_RGB01},
4876 {0xa0, 0xf8, ZC3XX_R10C_RGB02},
4877 {0xa0, 0xf8, ZC3XX_R10D_RGB10},
4878 {0xa0, 0x50, ZC3XX_R10E_RGB11},
4879 {0xa0, 0xf8, ZC3XX_R10F_RGB12},
4880 {0xa0, 0xf8, ZC3XX_R110_RGB20},
4881 {0xa0, 0xf8, ZC3XX_R111_RGB21},
4882 {0xa0, 0x50, ZC3XX_R112_RGB22},
4883 {0xa1, 0x01, 0x0180},
4884 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
4885 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
4886 {0xaa, 0x05, 0x0066},
4887 {0xaa, 0x09, 0x02b2},
4888 {0xaa, 0x10, 0x0002},
4889 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
4890 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
4891 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
4892 {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
4893 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
4894 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
4895 {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
4896 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
4897 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
4898 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
4899 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
4900 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
4901 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
4902 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
4903 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
4904 {0xa0, 0x09, 0x01ad},
4905 {0xa0, 0x15, 0x01ae},
4906 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
4907 {0xa1, 0x01, 0x0180},
4908 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
4909 {0xa1, 0x01, 0x0008},
4910 {0xa1, 0x01, 0x0007},
4911/* {0xa0, 0x30, 0x0007}, */
4912/* {0xa0, 0x00, 0x0007}, */
4913 {}
4914};
4915static const struct usb_action pb0330_50HZ[] = {
4916 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4917 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4918 {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,ee,cc */
4919 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4920 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4921 {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
4922 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4923 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4924 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4925 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4926 {0xa0, 0x68, ZC3XX_R01D_HSYNC_0}, /* 00,1d,68,cc */
4927 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc */
4928 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc */
4929 {}
4930};
4931static const struct usb_action pb0330_50HZScale[] = {
4932 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4933 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4934 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4935 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */
4936 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4937 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4938 {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */
4939 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4940 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4941 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4942 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4943 {0xa0, 0xe5, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e5,cc */
4944 {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f0,cc */
4945 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
4946 {}
4947};
4948static const struct usb_action pb0330_60HZ[] = {
4949 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4950 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4951 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4952 {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,dd,cc */
4953 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4954 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4955 {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
4956 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4957 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4958 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4959 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4960 {0xa0, 0x43, ZC3XX_R01D_HSYNC_0}, /* 00,1d,43,cc */
4961 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
4962 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4963 {}
4964};
4965static const struct usb_action pb0330_60HZScale[] = {
4966 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4967 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4968 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4969 {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,a0,cc */
4970 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4971 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4972 {0xa0, 0x7a, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7a,cc */
4973 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4974 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4975 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
4976 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
4977 {0xa0, 0x41, ZC3XX_R01D_HSYNC_0}, /* 00,1d,41,cc */
4978 {0xa0, 0x50, ZC3XX_R01E_HSYNC_1}, /* 00,1e,50,cc */
4979 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4980 {}
4981};
4982static const struct usb_action pb0330_NoFliker[] = {
4983 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
4984 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
4985 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
4986 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
4987 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
4988 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
4989 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
4990 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
4991 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
4992 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
4993 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
4994 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */
4995 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
4996 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
4997 {}
4998};
4999static const struct usb_action pb0330_NoFlikerScale[] = {
5000 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5001 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5002 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,07,cc */
5003 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5004 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5005 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5006 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5007 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5008 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5009 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5010 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5011 {0xa0, 0x09, ZC3XX_R01D_HSYNC_0}, /* 00,1d,09,cc */
5012 {0xa0, 0x40, ZC3XX_R01E_HSYNC_1}, /* 00,1e,40,cc */
5013 {0xa0, 0x90, ZC3XX_R01F_HSYNC_2}, /* 00,1f,90,cc */
5014 {}
5015};
5016
5017/* from oem9.inf - HKR,%PO2030%,Initial - 640x480 - (close to CS2102) */
5018static const struct usb_action PO2030_mode0[] = {
5019 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
5020 {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT}, /* 00,02,04,cc */
5021 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
5022 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
5023 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
5024 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
5025 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
5026 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
5027 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
5028 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
5029 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
5030 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
5031 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
5032 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
5033 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
5034 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
5035 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
5036 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
5037 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
5038 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5039 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5040 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
5041 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
5042 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
5043 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
5044 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc */
5045 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
5046 {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
5047 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
5048 {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
5049 {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
5050 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
5051 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
5052 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
5053 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
5054 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
5055 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
5056 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
5057 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
5058 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
5059 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
5060 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
5061 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
5062 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
5063 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
5064 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
5065 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
5066 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
5067 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
5068 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
5069 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5070 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5071 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5072 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5073 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5074 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5075 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5076 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5077 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5078 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5079 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5080 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5081 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5082 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5083 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5084 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5085 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5086 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5087 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5088 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5089 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5090 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5091 {}
5092};
5093
5094/* from oem9.inf - HKR,%PO2030%,InitialScale - 320x240 */
5095static const struct usb_action PO2030_mode1[] = {
5096 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
5097 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
5098 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
5099 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
5100 {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
5101 {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
5102 {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
5103 {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
5104 {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
5105 {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
5106 {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
5107 {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
5108 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
5109 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
5110 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
5111 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
5112 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
5113 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
5114 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
5115 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5116 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5117 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
5118 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
5119 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
5120 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
5121 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
5122 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
5123 {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
5124 {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
5125 {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
5126 {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
5127 {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
5128 {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
5129 {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
5130 {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
5131 {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
5132 {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
5133 {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
5134 {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
5135 {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
5136 {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
5137 {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
5138 {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
5139 {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
5140 {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
5141 {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
5142 {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
5143 {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
5144 {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
5145 {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
5146 {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
5147 {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
5148 {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
5149 {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
5150 {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
5151 {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
5152 {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
5153 {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
5154 {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
5155 {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
5156 {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
5157 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
5158 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
5159 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
5160 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
5161 {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
5162 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
5163 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
5164 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
5165 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
5166 {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
5167 {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
5168 {}
5169};
5170
5171static const struct usb_action PO2030_50HZ[] = {
5172 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5173 {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
5174 {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
5175 {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
5176 {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
5177 {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
5178 {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
5179 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5180 {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
5181 {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
5182 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5183 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5184 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5185 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5186 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5187 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5188 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5189 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5190 {}
5191};
5192
5193static const struct usb_action PO2030_60HZ[] = {
5194 {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
5195 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5196 {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
5197 {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
5198 {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
5199 {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
5200 {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
5201 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5202 {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
5203 {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
5204 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
5205 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
5206 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
5207 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
5208 {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
5209 {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
5210 /* win: 01,8d,80 */
5211 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
5212 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
5213 {}
5214};
5215
5216static const struct usb_action PO2030_NoFliker[] = {
5217 {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
5218 {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
5219 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
5220 {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
5221 {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
5222 {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
5223 {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
5224 {}
5225};
5226
5227/* TEST */
5228static const struct usb_action tas5130CK_Initial[] = {
5229 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5230 {0xa0, 0x01, 0x003b},
5231 {0xa0, 0x0e, 0x003a},
5232 {0xa0, 0x01, 0x0038},
5233 {0xa0, 0x0b, 0x0039},
5234 {0xa0, 0x00, 0x0038},
5235 {0xa0, 0x0b, 0x0039},
5236 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5237 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5238 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
5239 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
5240 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5241 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5242 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5243 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5244 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5245 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5246 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
5247 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
5248 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
5249 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
5250 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
5251 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5252 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5253 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5254 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
5255 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5256 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5257 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
5258 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5259 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5260 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5261 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5262 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
5263 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5264 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5265 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5266 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
5267 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5268 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5269 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5270 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
5271 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5272 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5273 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
5274 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5275 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5276 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5277 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
5278 {0xa0, 0xE7, ZC3XX_R093_I2CSETVALUE},
5279 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5280 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5281 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
5282 {0xa0, 0x87, ZC3XX_R093_I2CSETVALUE},
5283 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
5284 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5285 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
5286 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
5287 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
5288 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5289 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
5290 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5291 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
5292 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5293 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
5294 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5295 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5296 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5297 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5298 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5299 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5300 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5301 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5302 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5303 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5304 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5305 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5306 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5307 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5308 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5309 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5310 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5311 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5312 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5313 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5314 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5315 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5316 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5317 {0xa0, 0x2c, ZC3XX_R092_I2CADDRESSSELECT},
5318 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5319 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5320 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5321 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5322 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5323 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5324 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5325 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5326 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5327 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5328 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5329 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5330 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5331 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5332 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5333 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5334 {0xa0, 0x09, 0x01ad},
5335 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5336 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5337 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5338 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5339 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5340 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5341 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5342 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5343 {0xa0, 0x09, 0x01ad},
5344 {0xa0, 0x15, 0x01ae},
5345 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5346 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5347 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5348 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5349 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5350 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5351 {0xa0, 0xec, ZC3XX_R110_RGB20},
5352 {0xa0, 0x03, ZC3XX_R111_RGB21},
5353 {0xa0, 0x51, ZC3XX_R112_RGB22},
5354 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5355 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5356 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5357 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5358 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5359 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5360 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5361 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5362 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5363 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5364 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5365 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5366 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5367 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5368 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5369 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5370 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5371 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5372 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5373 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5374 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5375 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5376 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5377 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5378 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5379 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5380 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5381 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5382 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5383 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5384 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5385 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5386 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5387 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5388 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5389 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5390 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5391 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5392 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5393 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5394 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5395 {0xa0, 0xec, ZC3XX_R110_RGB20},
5396 {0xa0, 0x03, ZC3XX_R111_RGB21},
5397 {0xa0, 0x51, ZC3XX_R112_RGB22},
5398 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5399 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5400 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5401 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5402 {0xa0, 0x09, ZC3XX_R093_I2CSETVALUE},
5403 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5404 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5405 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5406 {0xa0, 0x34, ZC3XX_R093_I2CSETVALUE},
5407 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5408 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5409 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5410 {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
5411 {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
5412 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5413 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5414 {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
5415 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5416 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5417 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5418 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5419 {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
5420 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
5421 {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
5422 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5423 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5424 {0xa0, 0x09, 0x01ad},
5425 {0xa0, 0x15, 0x01ae},
5426 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5427 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5428 {}
5429};
5430
5431static const struct usb_action tas5130CK_InitialScale[] = {
5432 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5433 {0xa0, 0x01, 0x003b},
5434 {0xa0, 0x0e, 0x003a},
5435 {0xa0, 0x01, 0x0038},
5436 {0xa0, 0x0b, 0x0039},
5437 {0xa0, 0x00, 0x0038},
5438 {0xa0, 0x0b, 0x0039},
5439 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5440 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5441 {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
5442 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
5443 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5444 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5445 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5446 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5447 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5448 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5449 {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
5450 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
5451 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
5452 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
5453 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
5454 {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
5455 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5456 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5457 {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
5458 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5459 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5460 {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
5461 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5462 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5463 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5464 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5465 {0xa0, 0x83, ZC3XX_R093_I2CSETVALUE},
5466 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5467 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5468 {0xa0, 0x01, ZC3XX_R092_I2CADDRESSSELECT},
5469 {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
5470 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5471 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5472 {0xa0, 0x08, ZC3XX_R092_I2CADDRESSSELECT},
5473 {0xa0, 0x06, ZC3XX_R093_I2CSETVALUE},
5474 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5475 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5476 {0xa0, 0x02, ZC3XX_R092_I2CADDRESSSELECT},
5477 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5478 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5479 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5480 {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
5481 {0xa0, 0xe5, ZC3XX_R093_I2CSETVALUE},
5482 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5483 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5484 {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
5485 {0xa0, 0x85, ZC3XX_R093_I2CSETVALUE},
5486 {0xa0, 0x02, ZC3XX_R094_I2CWRITEACK},
5487 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5488 {0xa0, 0x07, ZC3XX_R092_I2CADDRESSSELECT},
5489 {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
5490 {0xa0, 0x30, ZC3XX_R094_I2CWRITEACK},
5491 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5492 {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
5493 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5494 {0xa0, 0x51, ZC3XX_R094_I2CWRITEACK},
5495 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5496 {0xa0, 0x35, ZC3XX_R092_I2CADDRESSSELECT},
5497 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5498 {0xa0, 0x50, ZC3XX_R094_I2CWRITEACK},
5499 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5500 {0xa0, 0x30, ZC3XX_R092_I2CADDRESSSELECT},
5501 {0xa0, 0x05, ZC3XX_R093_I2CSETVALUE},
5502 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5503 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5504 {0xa0, 0x31, ZC3XX_R092_I2CADDRESSSELECT},
5505 {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
5506 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5507 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5508 {0xa0, 0x58, ZC3XX_R092_I2CADDRESSSELECT},
5509 {0xa0, 0x78, ZC3XX_R093_I2CSETVALUE},
5510 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5511 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5512 {0xa0, 0x62, ZC3XX_R092_I2CADDRESSSELECT},
5513 {0xa0, 0x11, ZC3XX_R093_I2CSETVALUE},
5514 {0xa0, 0x04, ZC3XX_R094_I2CWRITEACK},
5515 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5516 {0xa0, 0x2B, ZC3XX_R092_I2CADDRESSSELECT},
5517 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5518 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5519 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5520 {0xa0, 0x2C, ZC3XX_R092_I2CADDRESSSELECT},
5521 {0xa0, 0x7F, ZC3XX_R093_I2CSETVALUE},
5522 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5523 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5524 {0xa0, 0x2D, ZC3XX_R092_I2CADDRESSSELECT},
5525 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5526 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5527 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5528 {0xa0, 0x2e, ZC3XX_R092_I2CADDRESSSELECT},
5529 {0xa0, 0x7f, ZC3XX_R093_I2CSETVALUE},
5530 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5531 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5532 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
5533 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
5534 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5535 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5536 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5537 {0xa0, 0x09, 0x01ad},
5538 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5539 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5540 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5541 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5542 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5543 {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
5544 {0xa0, 0x61, ZC3XX_R116_RGAIN},
5545 {0xa0, 0x65, ZC3XX_R118_BGAIN},
5546 {0xa0, 0x09, 0x01ad},
5547 {0xa0, 0x15, 0x01ae},
5548 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5549 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5550 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5551 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5552 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5553 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5554 {0xa0, 0xec, ZC3XX_R110_RGB20},
5555 {0xa0, 0x03, ZC3XX_R111_RGB21},
5556 {0xa0, 0x51, ZC3XX_R112_RGB22},
5557 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5558 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5559 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5560 {0xa0, 0x38, ZC3XX_R120_GAMMA00}, /* gamma > 5 */
5561 {0xa0, 0x51, ZC3XX_R121_GAMMA01},
5562 {0xa0, 0x6e, ZC3XX_R122_GAMMA02},
5563 {0xa0, 0x8c, ZC3XX_R123_GAMMA03},
5564 {0xa0, 0xa2, ZC3XX_R124_GAMMA04},
5565 {0xa0, 0xb6, ZC3XX_R125_GAMMA05},
5566 {0xa0, 0xc8, ZC3XX_R126_GAMMA06},
5567 {0xa0, 0xd6, ZC3XX_R127_GAMMA07},
5568 {0xa0, 0xe2, ZC3XX_R128_GAMMA08},
5569 {0xa0, 0xed, ZC3XX_R129_GAMMA09},
5570 {0xa0, 0xf5, ZC3XX_R12A_GAMMA0A},
5571 {0xa0, 0xfc, ZC3XX_R12B_GAMMA0B},
5572 {0xa0, 0xff, ZC3XX_R12C_GAMMA0C},
5573 {0xa0, 0xff, ZC3XX_R12D_GAMMA0D},
5574 {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
5575 {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
5576 {0xa0, 0x12, ZC3XX_R130_GAMMA10},
5577 {0xa0, 0x1b, ZC3XX_R131_GAMMA11},
5578 {0xa0, 0x1d, ZC3XX_R132_GAMMA12},
5579 {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
5580 {0xa0, 0x15, ZC3XX_R134_GAMMA14},
5581 {0xa0, 0x12, ZC3XX_R135_GAMMA15},
5582 {0xa0, 0x0f, ZC3XX_R136_GAMMA16},
5583 {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
5584 {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
5585 {0xa0, 0x09, ZC3XX_R139_GAMMA19},
5586 {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
5587 {0xa0, 0x05, ZC3XX_R13B_GAMMA1B},
5588 {0xa0, 0x00, ZC3XX_R13C_GAMMA1C},
5589 {0xa0, 0x00, ZC3XX_R13D_GAMMA1D},
5590 {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
5591 {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
5592 {0xa0, 0x4c, ZC3XX_R10A_RGB00}, /* matrix */
5593 {0xa0, 0xf1, ZC3XX_R10B_RGB01},
5594 {0xa0, 0x03, ZC3XX_R10C_RGB02},
5595 {0xa0, 0xfe, ZC3XX_R10D_RGB10},
5596 {0xa0, 0x51, ZC3XX_R10E_RGB11},
5597 {0xa0, 0xf1, ZC3XX_R10F_RGB12},
5598 {0xa0, 0xec, ZC3XX_R110_RGB20},
5599 {0xa0, 0x03, ZC3XX_R111_RGB21},
5600 {0xa0, 0x51, ZC3XX_R112_RGB22},
5601 {0xa0, 0x10, ZC3XX_R180_AUTOCORRECTENABLE},
5602 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5603 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5604 {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
5605 {0xa0, 0x62, ZC3XX_R093_I2CSETVALUE},
5606 {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
5607 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5608 {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
5609 {0xa0, 0xaa, ZC3XX_R093_I2CSETVALUE},
5610 {0xa0, 0x01, ZC3XX_R094_I2CWRITEACK},
5611 {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
5612 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5613 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
5614 {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
5615 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5616 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5617 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
5618 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
5619 {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
5620 {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
5621 {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
5622 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
5623 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
5624 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
5625 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5626 {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
5627 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5628 {0xa0, 0x09, 0x01ad},
5629 {0xa0, 0x15, 0x01ae},
5630 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5631 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5632 {0xa0, 0x30, 0x0007},
5633 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
5634 {0xa0, 0x00, 0x0007},
5635 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5636 {}
5637};
5638
5639static const struct usb_action tas5130cxx_Initial[] = {
5640 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5641 {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
5642 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5643 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5644 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5645 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5646 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5647 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5648 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5649 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5650 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5651
5652 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5653 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5654 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5655 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5656
5657 {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
5658 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5659 {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
5660 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5661 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
5662 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5663 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
5664 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5665 {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
5666 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5667 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5668 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
5669 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5670 {0xa0, 0x00, 0x01ad},
5671 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5672 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5673 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5674 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5675 {0xa1, 0x01, 0x0002},
5676 {0xa1, 0x01, 0x0008},
5677 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* clock ? */
5678 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5679 {0xa1, 0x01, 0x01c8},
5680 {0xa1, 0x01, 0x01c9},
5681 {0xa1, 0x01, 0x01ca},
5682 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5683
5684 {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */
5685 {0xa0, 0xec, ZC3XX_R10B_RGB01},
5686 {0xa0, 0xec, ZC3XX_R10C_RGB02},
5687 {0xa0, 0xec, ZC3XX_R10D_RGB10},
5688 {0xa0, 0x68, ZC3XX_R10E_RGB11},
5689 {0xa0, 0xec, ZC3XX_R10F_RGB12},
5690 {0xa0, 0xec, ZC3XX_R110_RGB20},
5691 {0xa0, 0xec, ZC3XX_R111_RGB21},
5692 {0xa0, 0x68, ZC3XX_R112_RGB22},
5693
5694 {0xa1, 0x01, 0x018d},
5695 {0xa0, 0x90, ZC3XX_R18D_YTARGET}, /* 90 */
5696 {0xa1, 0x01, 0x0180},
5697 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5698 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5699
5700 {0xaa, 0xa3, 0x0001},
5701 {0xaa, 0xa4, 0x0077},
5702 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
5703 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW},
5704
5705 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 00 */
5706 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 03 */
5707 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* e8 */
5708 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 0 */
5709 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 0 */
5710 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 7d */
5711
5712 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5713 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5714 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 08 */
5715 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 24 */
5716 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0},
5717 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
5718 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
5719 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5720 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH},
5721 {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
5722 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN}, /* 50 */
5723 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5724 {0xa1, 0x01, 0x0180},
5725 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5726 {}
5727};
5728static const struct usb_action tas5130cxx_InitialScale[] = {
5729 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5730 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
5731 {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
5732
5733 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5734 {0xa1, 0x01, 0x0008},
5735
5736 {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
5737 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5738 {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
5739 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
5740 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
5741 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
5742 {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
5743 {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
5744 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
5745 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
5746 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
5747 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
5748 {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
5749 {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
5750 {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
5751 {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
5752 {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
5753 {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
5754 {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
5755 {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
5756 {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
5757 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
5758 {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
5759 {0xa0, 0x68, ZC3XX_R18D_YTARGET},
5760 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
5761 {0xa0, 0x00, 0x01ad},
5762 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
5763 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
5764 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
5765 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
5766 {0xa1, 0x01, 0x0002},
5767 {0xa1, 0x01, 0x0008},
5768
5769 {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
5770 {0xa1, 0x01, 0x0008}, /* clock ? */
5771 {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00}, /* sharpness+ */
5772 {0xa1, 0x01, 0x01c8},
5773 {0xa1, 0x01, 0x01c9},
5774 {0xa1, 0x01, 0x01ca},
5775 {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05}, /* sharpness- */
5776
5777 {0xa0, 0x68, ZC3XX_R10A_RGB00}, /* matrix */
5778 {0xa0, 0xec, ZC3XX_R10B_RGB01},
5779 {0xa0, 0xec, ZC3XX_R10C_RGB02},
5780 {0xa0, 0xec, ZC3XX_R10D_RGB10},
5781 {0xa0, 0x68, ZC3XX_R10E_RGB11},
5782 {0xa0, 0xec, ZC3XX_R10F_RGB12},
5783 {0xa0, 0xec, ZC3XX_R110_RGB20},
5784 {0xa0, 0xec, ZC3XX_R111_RGB21},
5785 {0xa0, 0x68, ZC3XX_R112_RGB22},
5786
5787 {0xa1, 0x01, 0x018d},
5788 {0xa0, 0x90, ZC3XX_R18D_YTARGET},
5789 {0xa1, 0x01, 0x0180},
5790 {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
5791 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
5792 {0xaa, 0xa3, 0x0001},
5793 {0xaa, 0xa4, 0x0063},
5794 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
5795 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW},
5796 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
5797 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
5798 {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW},
5799 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
5800 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
5801 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
5802 {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
5803 {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
5804 {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
5805 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
5806 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0},
5807 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1},
5808 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
5809 {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
5810 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH},
5811 {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
5812 {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
5813 {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
5814 {0xa1, 0x01, 0x0180},
5815 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
5816 {}
5817};
5818static const struct usb_action tas5130cxx_50HZ[] = {
5819 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5820 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5821 {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
5822 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5823 {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
5824 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5825 {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
5826 {0xa0, 0x38, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,38,cc */
5827 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5828 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5829 {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
5830 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5831 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5832 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5833 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5834 {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
5835 {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
5836 {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
5837 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5838 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5839 {}
5840};
5841static const struct usb_action tas5130cxx_50HZScale[] = {
5842 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5843 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5844 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5845 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5846 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5847 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5848 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5849 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */
5850 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5851 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5852 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5853 {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */
5854 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5855 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5856 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5857 {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
5858 {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
5859 {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
5860 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5861 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5862 {}
5863};
5864static const struct usb_action tas5130cxx_60HZ[] = {
5865 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5866 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5867 {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
5868 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5869 {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
5870 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5871 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */
5872 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5873 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5874 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5875 {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
5876 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5877 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5878 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5879 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5880 {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
5881 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5882 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5883 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5884 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5885 {}
5886};
5887static const struct usb_action tas5130cxx_60HZScale[] = {
5888 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5889 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5890 {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
5891 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5892 {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
5893 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5894 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5895 {0xa0, 0xe8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,e8,cc */
5896 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5897 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5898 {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
5899 {0xa0, 0x14, ZC3XX_R18C_AEFREEZE}, /* 01,8c,14,cc */
5900 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5901 {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
5902 {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,26,cc */
5903 {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
5904 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5905 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5906 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5907 {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
5908 {}
5909};
5910static const struct usb_action tas5130cxx_NoFliker[] = {
5911 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5912 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5913 {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
5914 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5915 {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
5916 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5917 {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,01,cc */
5918 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5919 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5920 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5921 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5922 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5923 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5924 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5925 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5926 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5927 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5928 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5929 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5930 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5931 {}
5932};
5933
5934static const struct usb_action tas5130cxx_NoFlikerScale[] = {
5935 {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
5936 {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
5937 {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
5938 {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
5939 {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
5940 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
5941 {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,03,cc */
5942 {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,f0,cc */
5943 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
5944 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
5945 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
5946 {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
5947 {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
5948 {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
5949 {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
5950 {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
5951 {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
5952 {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
5953 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
5954 {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
5955 {}
5956};
5957
5958static const struct usb_action tas5130c_vf0250_Initial[] = {
5959 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
5960 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
5961 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
5962 {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc,
5963 * 0<->10 */
5964 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
5965 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
5966 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
5967 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
5968 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5969 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
5970 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
5971 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
5972 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
5973 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
5974 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
5975 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
5976 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e6,cc,
5977 * 6<->8 */
5978 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc,
5979 * 6<->8 */
5980 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
5981 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
5982 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
5983 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
5984 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
5985 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
5986 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
5987 {0xaa, 0x01, 0x0000},
5988 {0xaa, 0x01, 0x0000},
5989 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
5990 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
5991 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
5992 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
5993 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
5994 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
5995 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
5996 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
5997 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
5998 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
5999 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
6000 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
6001 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
6002 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
6003 {0xa0, 0x00, 0x0039},
6004 {0xa1, 0x01, 0x0037},
6005 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
6006 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */
6007 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
6008 {0xaa, 0x19, 0x0088}, /* 00,19,86,aa, */
6009 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
6010 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
6011 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
6012 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
6013 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
6014 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
6015 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
6016 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
6017 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
6018 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
6019 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
6020 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
6021 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
6022 {}
6023};
6024
6025static const struct usb_action tas5130c_vf0250_InitialScale[] = {
6026 {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */
6027 {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */
6028 {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */
6029 {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc, */
6030 {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */
6031 {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */
6032 {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */
6033 {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc, */
6034 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
6035 {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc, */
6036 {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc, */
6037 {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc, */
6038 {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc, */
6039 {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc, */
6040 {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc, */
6041 {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc, */
6042 {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc,
6043 * 8<->6 */
6044 {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc,
6045 * 8<->6 */
6046 {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */
6047 {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */
6048 {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */
6049 {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */
6050 {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */
6051 {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */
6052 {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
6053 {0xaa, 0x01, 0x0000},
6054 {0xaa, 0x01, 0x0000},
6055 {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */
6056 {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */
6057 {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */
6058 {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */
6059 {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */
6060 {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */
6061 {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */
6062 {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */
6063 {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */
6064 {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */
6065 {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */
6066 {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */
6067 {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */
6068 {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */
6069 {0xa0, 0x00, 0x0039},
6070 {0xa1, 0x01, 0x0037},
6071 {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */
6072 {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */
6073 {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */
6074 {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */
6075 {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */
6076 {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */
6077 {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */
6078 {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */
6079 {0xa0, 0x76, ZC3XX_R189_AWBSTATUS}, /* 01,89,76,cc, */
6080 {0xa0, 0x09, 0x01ad}, /* 01,ad,09,cc, */
6081 {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc, */
6082 {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */
6083 {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */
6084 {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */
6085 {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */
6086 {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */
6087 {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */
6088 {}
6089};
6090/* "50HZ" light frequency banding filter */
6091static const struct usb_action tas5130c_vf0250_50HZ[] = {
6092 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6093 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
6094 {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */
6095 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6096 {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
6097 {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
6098 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6099 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6100 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */
6101 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6102 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6103 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6104 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6105 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6106 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6107 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6108 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6109 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6110 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6111 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6112 {}
6113};
6114
6115/* "50HZScale" light frequency banding filter */
6116static const struct usb_action tas5130c_vf0250_50HZScale[] = {
6117 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6118 {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */
6119 {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */
6120 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6121 {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */
6122 {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */
6123 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6124 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6125 {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,8e,cc, */
6126 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6127 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6128 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6129 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6130 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6131 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6132 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6133 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6134 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6135 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6136 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6137 {}
6138};
6139
6140/* "60HZ" light frequency banding filter */
6141static const struct usb_action tas5130c_vf0250_60HZ[] = {
6142 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6143 {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */
6144 {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */
6145 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6146 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
6147 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
6148 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6149 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6150 {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3b,cc, */
6151 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6152 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6153 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */
6154 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */
6155 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6156 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6157 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6158 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6159 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6160 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6161 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */
6162 {}
6163};
6164
6165/* "60HZScale" light frequency banding ilter */
6166static const struct usb_action tas5130c_vf0250_60HZScale[] = {
6167 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6168 {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */
6169 {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */
6170 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6171 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */
6172 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */
6173 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,5,00,cc, */
6174 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,6,00,cc, */
6175 {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,7,76,cc, */
6176 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,c,0e,cc, */
6177 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,f,15,cc, */
6178 {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,9,10,cc, */
6179 {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,a,24,cc, */
6180 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,d,62,cc, */
6181 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,e,90,cc, */
6182 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,f,c8,cc, */
6183 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */
6184 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */
6185 {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */
6186 {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,d,78,cc */
6187 {}
6188};
6189
6190/* "NoFliker" light frequency banding flter */
6191static const struct usb_action tas5130c_vf0250_NoFliker[] = {
6192 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
6193 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6194 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
6195 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
6196 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */
6197 {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */
6198 {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */
6199 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6200 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6201 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
6202 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6203 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6204 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6205 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6206 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6207 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6208 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6209 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
6210 {}
6211};
6212
6213/* "NoFlikerScale" light frequency banding filter */
6214static const struct usb_action tas5130c_vf0250_NoFlikerScale[] = {
6215 {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
6216 {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
6217 {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
6218 {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */
6219 {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */
6220 {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc, */
6221 {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc, */
6222 {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */
6223 {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */
6224 {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */
6225 {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */
6226 {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */
6227 {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */
6228 {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */
6229 {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */
6230 {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */
6231 {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */
6232 {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,03,cc */
6233 {}
6234};
6235
6236static int reg_r_i(struct gspca_dev *gspca_dev,
6237 __u16 index)
6238{
6239 usb_control_msg(gspca_dev->dev,
6240 usb_rcvctrlpipe(gspca_dev->dev, 0),
6241 0xa1,
6242 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6243 0x01, /* value */
6244 index, gspca_dev->usb_buf, 1,
6245 500);
6246 return gspca_dev->usb_buf[0];
6247}
6248
6249static int reg_r(struct gspca_dev *gspca_dev,
6250 __u16 index)
6251{
6252 int ret;
6253
6254 ret = reg_r_i(gspca_dev, index);
6255 PDEBUG(D_USBI, "reg r [%04x] -> %02x", index, ret);
6256 return ret;
6257}
6258
6259static void reg_w_i(struct usb_device *dev,
6260 __u8 value,
6261 __u16 index)
6262{
6263 usb_control_msg(dev,
6264 usb_sndctrlpipe(dev, 0),
6265 0xa0,
6266 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
6267 value, index, NULL, 0,
6268 500);
6269}
6270
6271static void reg_w(struct usb_device *dev,
6272 __u8 value,
6273 __u16 index)
6274{
6275 PDEBUG(D_USBO, "reg w %02x -> [%04x]", value, index);
6276 reg_w_i(dev, value, index);
6277}
6278
6279static __u16 i2c_read(struct gspca_dev *gspca_dev,
6280 __u8 reg)
6281{
6282 __u8 retbyte;
6283 __u8 retval[2];
6284
6285 reg_w_i(gspca_dev->dev, reg, 0x92);
6286 reg_w_i(gspca_dev->dev, 0x02, 0x90); /* <- read command */
6287 msleep(25);
6288 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
6289 retval[0] = reg_r_i(gspca_dev, 0x0095); /* read Lowbyte */
6290 retval[1] = reg_r_i(gspca_dev, 0x0096); /* read Hightbyte */
6291 PDEBUG(D_USBO, "i2c r [%02x] -> (%02x) %02x%02x",
6292 reg, retbyte, retval[1], retval[0]);
6293 return (retval[1] << 8) | retval[0];
6294}
6295
6296static __u8 i2c_write(struct gspca_dev *gspca_dev,
6297 __u8 reg,
6298 __u8 valL,
6299 __u8 valH)
6300{
6301 __u8 retbyte;
6302
6303 reg_w_i(gspca_dev->dev, reg, 0x92);
6304 reg_w_i(gspca_dev->dev, valL, 0x93);
6305 reg_w_i(gspca_dev->dev, valH, 0x94);
6306 reg_w_i(gspca_dev->dev, 0x01, 0x90); /* <- write command */
6307 msleep(5);
6308 retbyte = reg_r_i(gspca_dev, 0x0091); /* read status */
6309 PDEBUG(D_USBO, "i2c w [%02x] %02x%02x (%02x)",
6310 reg, valH, valL, retbyte);
6311 return retbyte;
6312}
6313
6314static void usb_exchange(struct gspca_dev *gspca_dev,
6315 const struct usb_action *action)
6316{
6317 while (action->req) {
6318 switch (action->req) {
6319 case 0xa0: /* write register */
6320 reg_w(gspca_dev->dev, action->val, action->idx);
6321 break;
6322 case 0xa1: /* read status */
6323 reg_r(gspca_dev, action->idx);
6324 break;
6325 case 0xaa:
6326 i2c_write(gspca_dev,
6327 action->val, /* reg */
6328 action->idx & 0xff, /* valL */
6329 action->idx >> 8); /* valH */
6330 break;
6331 default:
6332/* case 0xdd: * delay */
6333 msleep(action->val / 64 + 10);
6334 break;
6335 }
6336 action++;
6337/* msleep(1); */
6338 }
6339}
6340
6341static void setmatrix(struct gspca_dev *gspca_dev)
6342{
6343 struct sd *sd = (struct sd *) gspca_dev;
6344 int i;
6345 const __u8 *matrix;
6346 static const __u8 gc0305_matrix[9] =
6347 {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
6348 static const __u8 ov7620_matrix[9] =
6349 {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
6350 static const __u8 po2030_matrix[9] =
6351 {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
6352
6353 switch (sd->sensor) {
6354 case SENSOR_GC0305:
6355 matrix = gc0305_matrix;
6356 break;
6357 case SENSOR_MC501CB:
6358 return; /* no matrix? */
6359 case SENSOR_OV7620:
6360/* case SENSOR_OV7648: */
6361 matrix = ov7620_matrix;
6362 break;
6363 case SENSOR_PO2030:
6364 matrix = po2030_matrix;
6365 break;
6366 case SENSOR_TAS5130C_VF0250: /* no matrix? */
6367 return;
6368 default: /* matrix already loaded */
6369 return;
6370 }
6371 for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
6372 reg_w(gspca_dev->dev, matrix[i], 0x010a + i);
6373}
6374
6375static void setbrightness(struct gspca_dev *gspca_dev)
6376{
6377 struct sd *sd = (struct sd *) gspca_dev;
6378 __u8 brightness;
6379
6380 switch (sd->sensor) {
6381 case SENSOR_GC0305:
6382 case SENSOR_OV7620:
6383 case SENSOR_PO2030:
6384 return;
6385 }
6386/*fixme: is it really write to 011d and 018d for all other sensors? */
6387 brightness = sd->brightness;
6388 reg_w(gspca_dev->dev, brightness, 0x011d);
6389 if (brightness < 0x70)
6390 brightness += 0x10;
6391 else
6392 brightness = 0x80;
6393 reg_w(gspca_dev->dev, brightness, 0x018d);
6394}
6395
6396static void setsharpness(struct gspca_dev *gspca_dev)
6397{
6398 struct sd *sd = (struct sd *) gspca_dev;
6399 struct usb_device *dev = gspca_dev->dev;
6400 int sharpness;
6401 static const __u8 sharpness_tb[][2] = {
6402 {0x02, 0x03},
6403 {0x04, 0x07},
6404 {0x08, 0x0f},
6405 {0x10, 0x1e}
6406 };
6407
6408 sharpness = sd->sharpness;
6409 reg_w(dev, sharpness_tb[sharpness][0], 0x01c6);
6410 reg_r(gspca_dev, 0x01c8);
6411 reg_r(gspca_dev, 0x01c9);
6412 reg_r(gspca_dev, 0x01ca);
6413 reg_w(dev, sharpness_tb[sharpness][1], 0x01cb);
6414}
6415
6416static void setcontrast(struct gspca_dev *gspca_dev)
6417{
6418 struct sd *sd = (struct sd *) gspca_dev;
6419 struct usb_device *dev = gspca_dev->dev;
6420 const __u8 *Tgamma, *Tgradient;
6421 int g, i, k;
6422 static const __u8 kgamma_tb[16] = /* delta for contrast */
6423 {0x15, 0x0d, 0x0a, 0x09, 0x08, 0x08, 0x08, 0x08,
6424 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
6425 static const __u8 kgrad_tb[16] =
6426 {0x1b, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00,
6427 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04};
6428 static const __u8 Tgamma_1[16] =
6429 {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
6430 0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff};
6431 static const __u8 Tgradient_1[16] =
6432 {0x00, 0x01, 0x05, 0x0b, 0x10, 0x15, 0x18, 0x1a,
6433 0x1a, 0x18, 0x16, 0x14, 0x12, 0x0f, 0x0d, 0x06};
6434 static const __u8 Tgamma_2[16] =
6435 {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
6436 0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff};
6437 static const __u8 Tgradient_2[16] =
6438 {0x05, 0x0f, 0x16, 0x1a, 0x19, 0x19, 0x17, 0x15,
6439 0x12, 0x10, 0x0e, 0x0b, 0x09, 0x08, 0x06, 0x03};
6440 static const __u8 Tgamma_3[16] =
6441 {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
6442 0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff};
6443 static const __u8 Tgradient_3[16] =
6444 {0x0c, 0x16, 0x1b, 0x1c, 0x19, 0x18, 0x15, 0x12,
6445 0x10, 0x0d, 0x0b, 0x09, 0x08, 0x06, 0x05, 0x03};
6446 static const __u8 Tgamma_4[16] =
6447 {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
6448 0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff};
6449 static const __u8 Tgradient_4[16] =
6450 {0x26, 0x22, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0d,
6451 0x0b, 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02};
6452 static const __u8 Tgamma_5[16] =
6453 {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
6454 0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff};
6455 static const __u8 Tgradient_5[16] =
6456 {0x37, 0x26, 0x20, 0x1a, 0x14, 0x10, 0x0e, 0x0b,
6457 0x09, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x02};
6458 static const __u8 Tgamma_6[16] = /* ?? was gamma 5 */
6459 {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
6460 0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff};
6461 static const __u8 Tgradient_6[16] =
6462 {0x18, 0x20, 0x20, 0x1c, 0x16, 0x13, 0x10, 0x0e,
6463 0x0b, 0x09, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01};
6464 static const __u8 *gamma_tb[] = {
6465 NULL, Tgamma_1, Tgamma_2,
6466 Tgamma_3, Tgamma_4, Tgamma_5, Tgamma_6
6467 };
6468 static const __u8 *gradient_tb[] = {
6469 NULL, Tgradient_1, Tgradient_2,
6470 Tgradient_3, Tgradient_4, Tgradient_5, Tgradient_6
6471 };
6472#ifdef CONFIG_VIDEO_ADV_DEBUG
6473 __u8 v[16];
6474#endif
6475
6476 Tgamma = gamma_tb[sd->gamma];
6477 Tgradient = gradient_tb[sd->gamma];
6478
6479 k = (sd->contrast - 128) /* -128 / 128 */
6480 * Tgamma[0];
6481 PDEBUG(D_CONF, "gamma:%d contrast:%d gamma coeff: %d/128",
6482 sd->gamma, sd->contrast, k);
6483 for (i = 0; i < 16; i++) {
6484 g = Tgamma[i] + kgamma_tb[i] * k / 128;
6485 if (g > 0xff)
6486 g = 0xff;
6487 else if (g <= 0)
6488 g = 1;
6489 reg_w(dev, g, 0x0120 + i); /* gamma */
6490#ifdef CONFIG_VIDEO_ADV_DEBUG
6491 if (gspca_debug & D_CONF)
6492 v[i] = g;
6493#endif
6494 }
6495 PDEBUG(D_CONF, "tb: %02x %02x %02x %02x %02x %02x %02x %02x",
6496 v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
6497 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6498 v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
6499 for (i = 0; i < 16; i++) {
6500 g = Tgradient[i] - kgrad_tb[i] * k / 128;
6501 if (g > 0xff)
6502 g = 0xff;
6503 else if (g <= 0) {
6504 if (i != 15)
6505 g = 0;
6506 else
6507 g = 1;
6508 }
6509 reg_w(dev, g, 0x0130 + i); /* gradient */
6510#ifdef CONFIG_VIDEO_ADV_DEBUG
6511 if (gspca_debug & D_CONF)
6512 v[i] = g;
6513#endif
6514 }
6515 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6516 v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
6517 PDEBUG(D_CONF, " %02x %02x %02x %02x %02x %02x %02x %02x",
6518 v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]);
6519}
6520
6521static void setquality(struct gspca_dev *gspca_dev)
6522{
6523 struct sd *sd = (struct sd *) gspca_dev;
6524 struct usb_device *dev = gspca_dev->dev;
6525 __u8 quality;
6526 __u8 frxt;
6527
6528 switch (sd->sensor) {
6529 case SENSOR_GC0305:
6530 case SENSOR_OV7620:
6531 case SENSOR_PO2030:
6532 return;
6533 }
6534/*fixme: is it really 0008 0007 0018 for all other sensors? */
6535 quality = sd->qindex;
6536 reg_w(dev, quality, 0x0008);
6537 frxt = 0x30;
6538 reg_w(dev, frxt, 0x0007);
6539 switch (quality) {
6540 case 0:
6541 case 1:
6542 case 2:
6543 frxt = 0xff;
6544 break;
6545 case 3:
6546 frxt = 0xf0;
6547 break;
6548 case 4:
6549 frxt = 0xe0;
6550 break;
6551 case 5:
6552 frxt = 0x20;
6553 break;
6554 }
6555 reg_w(dev, frxt, 0x0018);
6556}
6557
6558/* Matches the sensor's internal frame rate to the lighting frequency.
6559 * Valid frequencies are:
6560 * 50Hz, for European and Asian lighting (default)
6561 * 60Hz, for American lighting
6562 * 0 = No Fliker (for outdoore usage)
6563 * Returns: 0 for success
6564 */
6565static int setlightfreq(struct gspca_dev *gspca_dev)
6566{
6567 struct sd *sd = (struct sd *) gspca_dev;
6568 int i, mode;
6569 const struct usb_action *zc3_freq;
6570 static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
6571/* SENSOR_CS2102 0 */
6572 {cs2102_NoFliker, cs2102_NoFlikerScale,
6573 cs2102_50HZ, cs2102_50HZScale,
6574 cs2102_60HZ, cs2102_60HZScale},
6575/* SENSOR_CS2102K 1 */
6576 {cs2102_NoFliker, cs2102_NoFlikerScale,
6577 cs2102_50HZ, cs2102_50HZScale,
6578 cs2102_60HZ, cs2102_60HZScale},
6579/* SENSOR_GC0305 2 */
6580 {gc0305_NoFliker, gc0305_NoFliker,
6581 gc0305_50HZ, gc0305_50HZ,
6582 gc0305_60HZ, gc0305_60HZ},
6583/* SENSOR_HDCS2020 3 */
6584 {NULL, NULL,
6585 NULL, NULL,
6586 NULL, NULL},
6587/* SENSOR_HDCS2020b 4 */
6588 {hdcs2020b_NoFliker, hdcs2020b_NoFliker,
6589 hdcs2020b_50HZ, hdcs2020b_50HZ,
6590 hdcs2020b_60HZ, hdcs2020b_60HZ},
6591/* SENSOR_HV7131B 5 */
6592 {NULL, NULL,
6593 NULL, NULL,
6594 NULL, NULL},
6595/* SENSOR_HV7131C 6 */
6596 {NULL, NULL,
6597 NULL, NULL,
6598 NULL, NULL},
6599/* SENSOR_ICM105A 7 */
6600 {icm105a_NoFliker, icm105a_NoFlikerScale,
6601 icm105a_50HZ, icm105a_50HZScale,
6602 icm105a_60HZ, icm105a_60HZScale},
6603/* SENSOR_MC501CB 8 */
6604 {MC501CB_NoFliker, MC501CB_NoFlikerScale,
6605 MC501CB_50HZ, MC501CB_50HZScale,
6606 MC501CB_60HZ, MC501CB_60HZScale},
6607/* SENSOR_OV7620 9 */
6608 {OV7620_NoFliker, OV7620_NoFliker,
6609 OV7620_50HZ, OV7620_50HZ,
6610 OV7620_60HZ, OV7620_60HZ},
6611/* SENSOR_OV7630C 10 */
6612 {NULL, NULL,
6613 NULL, NULL,
6614 NULL, NULL},
6615/* SENSOR_PAS106 11 */
6616 {pas106b_NoFliker, pas106b_NoFliker,
6617 pas106b_50HZ, pas106b_50HZ,
6618 pas106b_60HZ, pas106b_60HZ},
6619/* SENSOR_PB0330 12 */
6620 {pb0330_NoFliker, pb0330_NoFlikerScale,
6621 pb0330_50HZ, pb0330_50HZScale,
6622 pb0330_60HZ, pb0330_60HZScale},
6623/* SENSOR_PO2030 13 */
6624 {PO2030_NoFliker, PO2030_NoFliker,
6625 PO2030_50HZ, PO2030_50HZ,
6626 PO2030_60HZ, PO2030_60HZ},
6627/* SENSOR_TAS5130CK 14 */
6628 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
6629 tas5130cxx_50HZ, tas5130cxx_50HZScale,
6630 tas5130cxx_60HZ, tas5130cxx_60HZScale},
6631/* SENSOR_TAS5130CXX 15 */
6632 {tas5130cxx_NoFliker, tas5130cxx_NoFlikerScale,
6633 tas5130cxx_50HZ, tas5130cxx_50HZScale,
6634 tas5130cxx_60HZ, tas5130cxx_60HZScale},
6635/* SENSOR_TAS5130C_VF0250 16 */
6636 {tas5130c_vf0250_NoFliker, tas5130c_vf0250_NoFlikerScale,
6637 tas5130c_vf0250_50HZ, tas5130c_vf0250_50HZScale,
6638 tas5130c_vf0250_60HZ, tas5130c_vf0250_60HZScale},
6639 };
6640
6641 i = sd->lightfreq * 2;
6642 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
6643 if (!mode)
6644 i++; /* 640x480 */
6645 zc3_freq = freq_tb[(int) sd->sensor][i];
6646 if (zc3_freq != NULL) {
6647 usb_exchange(gspca_dev, zc3_freq);
6648 switch (sd->sensor) {
6649 case SENSOR_GC0305:
6650 if (mode /* if 320x240 */
6651 && sd->lightfreq == 1) /* and 50Hz */
6652 reg_w(gspca_dev->dev, 0x85, 0x018d);
6653 /* win: 0x80, 0x018d */
6654 break;
6655 case SENSOR_OV7620:
6656 if (!mode) { /* if 640x480 */
6657 if (sd->lightfreq != 0) /* and 50 or 60 Hz */
6658 reg_w(gspca_dev->dev, 0x40, 0x0002);
6659 else
6660 reg_w(gspca_dev->dev, 0x44, 0x0002);
6661 }
6662 break;
6663 }
6664 }
6665 return 0;
6666}
6667
6668static void setautogain(struct gspca_dev *gspca_dev)
6669{
6670 struct sd *sd = (struct sd *) gspca_dev;
6671 __u8 autoval;
6672
6673 if (sd->autogain)
6674 autoval = 0x42;
6675 else
6676 autoval = 0x02;
6677 reg_w(gspca_dev->dev, autoval, 0x0180);
6678}
6679
6680static void send_unknown(struct usb_device *dev, int sensor)
6681{
6682 reg_w(dev, 0x01, 0x0000); /* led off */
6683 switch (sensor) {
6684 case SENSOR_PAS106:
6685 reg_w(dev, 0x03, 0x003a);
6686 reg_w(dev, 0x0c, 0x003b);
6687 reg_w(dev, 0x08, 0x0038);
6688 break;
6689 case SENSOR_GC0305:
6690 case SENSOR_OV7620:
6691 case SENSOR_PB0330:
6692 case SENSOR_PO2030:
6693 reg_w(dev, 0x0d, 0x003a);
6694 reg_w(dev, 0x02, 0x003b);
6695 reg_w(dev, 0x00, 0x0038);
6696 break;
6697 }
6698}
6699
6700/* start probe 2 wires */
6701static void start_2wr_probe(struct usb_device *dev, int sensor)
6702{
6703 reg_w(dev, 0x01, 0x0000);
6704 reg_w(dev, sensor, 0x0010);
6705 reg_w(dev, 0x01, 0x0001);
6706 reg_w(dev, 0x03, 0x0012);
6707 reg_w(dev, 0x01, 0x0012);
6708/* msleep(2); */
6709}
6710
6711static int sif_probe(struct gspca_dev *gspca_dev)
6712{
6713 __u16 checkword;
6714
6715 start_2wr_probe(gspca_dev->dev, 0x0f); /* PAS106 */
6716 reg_w(gspca_dev->dev, 0x08, 0x008d);
6717 msleep(150);
6718 checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
6719 | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
6720 PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
6721 if (checkword == 0x0007) {
6722 send_unknown(gspca_dev->dev, SENSOR_PAS106);
6723 return 0x0f; /* PAS106 */
6724 }
6725 return -1;
6726}
6727
6728static int vga_2wr_probe(struct gspca_dev *gspca_dev)
6729{
6730 struct usb_device *dev = gspca_dev->dev;
6731 __u8 retbyte;
6732 __u16 checkword;
6733
6734 start_2wr_probe(dev, 0x00); /* HV7131B */
6735 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6736 retbyte = i2c_read(gspca_dev, 0x01);
6737 if (retbyte != 0)
6738 return 0x00; /* HV7131B */
6739
6740 start_2wr_probe(dev, 0x04); /* CS2102 */
6741 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6742 retbyte = i2c_read(gspca_dev, 0x01);
6743 if (retbyte != 0)
6744 return 0x04; /* CS2102 */
6745
6746 start_2wr_probe(dev, 0x06); /* OmniVision */
6747 reg_w(dev, 0x08, 0x8d);
6748 i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
6749 retbyte = i2c_read(gspca_dev, 0x11);
6750 if (retbyte != 0) {
6751 /* (should have returned 0xaa) --> Omnivision? */
6752 /* reg_r 0x10 -> 0x06 --> */
6753 goto ov_check;
6754 }
6755
6756 start_2wr_probe(dev, 0x08); /* HDCS2020 */
6757 i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
6758 retbyte = i2c_read(gspca_dev, 0x15);
6759 if (retbyte != 0)
6760 return 0x08; /* HDCS2020 */
6761
6762 start_2wr_probe(dev, 0x0a); /* PB0330 */
6763 i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
6764 retbyte = i2c_read(gspca_dev, 0x07);
6765 if (retbyte != 0)
6766 return 0x0a; /* PB0330 */
6767 retbyte = i2c_read(gspca_dev, 0x03);
6768 if (retbyte != 0)
6769 return 0x0a; /* PB0330 ?? */
6770 retbyte = i2c_read(gspca_dev, 0x04);
6771 if (retbyte != 0)
6772 return 0x0a; /* PB0330 ?? */
6773
6774 start_2wr_probe(dev, 0x0c); /* ICM105A */
6775 i2c_write(gspca_dev, 0x01, 0x11, 0x00);
6776 retbyte = i2c_read(gspca_dev, 0x01);
6777 if (retbyte != 0)
6778 return 0x0c; /* ICM105A */
6779
6780 start_2wr_probe(dev, 0x0e); /* PAS202BCB */
6781 reg_w(dev, 0x08, 0x8d);
6782 i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
6783 msleep(500);
6784 retbyte = i2c_read(gspca_dev, 0x03);
6785 if (retbyte != 0)
6786 return 0x0e; /* PAS202BCB */
6787
6788 start_2wr_probe(dev, 0x02); /* ?? */
6789 i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
6790 retbyte = i2c_read(gspca_dev, 0x01);
6791 if (retbyte != 0)
6792 return 0x02; /* ?? */
6793ov_check:
6794 reg_r(gspca_dev, 0x0010); /* ?? */
6795 reg_r(gspca_dev, 0x0010);
6796
6797 reg_w(dev, 0x01, 0x0000);
6798 reg_w(dev, 0x01, 0x0001);
6799 reg_w(dev, 0x06, 0x0010); /* OmniVision */
6800 reg_w(dev, 0xa1, 0x008b);
6801 reg_w(dev, 0x08, 0x008d);
6802 msleep(500);
6803 reg_w(dev, 0x01, 0x0012);
6804 i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
6805 retbyte = i2c_read(gspca_dev, 0x0a);
6806 checkword = retbyte << 8;
6807 retbyte = i2c_read(gspca_dev, 0x0b);
6808 checkword |= retbyte;
6809 PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", checkword);
6810 switch (checkword) {
6811 case 0x7631: /* OV7630C */
6812 reg_w(dev, 0x06, 0x0010);
6813 break;
6814 case 0x7620: /* OV7620 */
6815 case 0x7648: /* OV7648 */
6816 break;
6817 default:
6818 return -1; /* not OmniVision */
6819 }
6820 return checkword;
6821}
6822
6823struct sensor_by_chipset_revision {
6824 __u16 revision;
6825 __u8 internal_sensor_id;
6826};
6827static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
6828 {0xc001, 0x13}, /* MI0360 */
6829 {0xe001, 0x13},
6830 {0x8001, 0x13},
6831 {0x8000, 0x14}, /* CS2102K */
6832 {0x8400, 0x15}, /* TAS5130K */
6833 {0, 0}
6834};
6835
6836static int vga_3wr_probe(struct gspca_dev *gspca_dev)
6837{
6838 struct sd *sd = (struct sd *) gspca_dev;
6839 struct usb_device *dev = gspca_dev->dev;
6840 int i;
6841 __u8 retbyte;
6842 __u16 checkword;
6843
6844/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
6845 reg_w(dev, 0x02, 0x0010);
6846 reg_r(gspca_dev, 0x10);
6847 reg_w(dev, 0x01, 0x0000);
6848 reg_w(dev, 0x00, 0x0010);
6849 reg_w(dev, 0x01, 0x0001);
6850 reg_w(dev, 0x91, 0x008b);
6851 reg_w(dev, 0x03, 0x0012);
6852 reg_w(dev, 0x01, 0x0012);
6853 reg_w(dev, 0x05, 0x0012);
6854 retbyte = i2c_read(gspca_dev, 0x14);
6855 if (retbyte != 0)
6856 return 0x11; /* HV7131R */
6857 retbyte = i2c_read(gspca_dev, 0x15);
6858 if (retbyte != 0)
6859 return 0x11; /* HV7131R */
6860 retbyte = i2c_read(gspca_dev, 0x16);
6861 if (retbyte != 0)
6862 return 0x11; /* HV7131R */
6863
6864 reg_w(dev, 0x02, 0x0010);
6865 retbyte = reg_r(gspca_dev, 0x000b);
6866 checkword = retbyte << 8;
6867 retbyte = reg_r(gspca_dev, 0x000a);
6868 checkword |= retbyte;
6869 PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", checkword);
6870 reg_r(gspca_dev, 0x0010);
6871 /* this is tested only once anyway */
6872 i = 0;
6873 while (chipset_revision_sensor[i].revision) {
6874 if (chipset_revision_sensor[i].revision == checkword) {
6875 sd->chip_revision = checkword;
6876 send_unknown(dev, SENSOR_PB0330);
6877 return chipset_revision_sensor[i].internal_sensor_id;
6878 }
6879 i++;
6880 }
6881
6882 reg_w(dev, 0x01, 0x0000);
6883 reg_w(dev, 0x01, 0x0001);
6884 reg_w(dev, 0xdd, 0x008b);
6885 reg_w(dev, 0x0a, 0x0010);
6886 reg_w(dev, 0x03, 0x0012);
6887 reg_w(dev, 0x01, 0x0012);
6888 retbyte = i2c_read(gspca_dev, 0x00);
6889 if (retbyte != 0) {
6890 PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
6891 return 0x0a; /* ?? */
6892 }
6893
6894 reg_w(dev, 0x01, 0x0000);
6895 reg_w(dev, 0x01, 0x0001);
6896 reg_w(dev, 0x98, 0x008b);
6897 reg_w(dev, 0x01, 0x0010);
6898 reg_w(dev, 0x03, 0x0012);
6899 msleep(2);
6900 reg_w(dev, 0x01, 0x0012);
6901 retbyte = i2c_read(gspca_dev, 0x00);
6902 if (retbyte != 0) {
6903 PDEBUG(D_PROBE, "probe 3wr vga type %02x", retbyte);
6904 send_unknown(dev, SENSOR_GC0305);
6905 return retbyte; /* 0x29 = gc0305 - should continue? */
6906 }
6907
6908 reg_w(dev, 0x01, 0x0000); /* check OmniVision */
6909 reg_w(dev, 0x01, 0x0001);
6910 reg_w(dev, 0xa1, 0x008b);
6911 reg_w(dev, 0x08, 0x008d);
6912 reg_w(dev, 0x06, 0x0010);
6913 reg_w(dev, 0x01, 0x0012);
6914 reg_w(dev, 0x05, 0x0012);
6915 if (i2c_read(gspca_dev, 0x1c) == 0x7f /* OV7610 - manufacturer ID */
6916 && i2c_read(gspca_dev, 0x1d) == 0xa2) {
6917 send_unknown(dev, SENSOR_OV7620);
6918 return 0x06; /* OmniVision confirm ? */
6919 }
6920
6921 reg_w(dev, 0x01, 0x00);
6922 reg_w(dev, 0x00, 0x02);
6923 reg_w(dev, 0x01, 0x10);
6924 reg_w(dev, 0x01, 0x01);
6925 reg_w(dev, 0xee, 0x8b);
6926 reg_w(dev, 0x03, 0x12);
6927/* msleep(150); */
6928 reg_w(dev, 0x01, 0x12);
6929 reg_w(dev, 0x05, 0x12);
6930 retbyte = i2c_read(gspca_dev, 0x00); /* ID 0 */
6931 checkword = retbyte << 8;
6932 retbyte = i2c_read(gspca_dev, 0x01); /* ID 1 */
6933 checkword |= retbyte;
6934 PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", checkword);
6935 if (checkword == 0x2030) {
6936 retbyte = i2c_read(gspca_dev, 0x02); /* revision number */
6937 PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
6938 send_unknown(dev, SENSOR_PO2030);
6939 return checkword;
6940 }
6941
6942 reg_w(dev, 0x01, 0x00);
6943 reg_w(dev, 0x0a, 0x10);
6944 reg_w(dev, 0xd3, 0x8b);
6945 reg_w(dev, 0x01, 0x01);
6946 reg_w(dev, 0x03, 0x12);
6947 reg_w(dev, 0x01, 0x12);
6948 reg_w(dev, 0x05, 0x01);
6949 reg_w(dev, 0xd3, 0x8b);
6950 retbyte = i2c_read(gspca_dev, 0x01);
6951 if (retbyte != 0) {
6952 PDEBUG(D_PROBE, "probe 3wr vga type 0a ?");
6953 return 0x0a; /* ?? */
6954 }
6955 return -1;
6956}
6957
6958static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
6959{
6960 struct sd *sd = (struct sd *) gspca_dev;
6961 int sensor, sensor2;
6962
6963 switch (sd->sensor) {
6964 case SENSOR_MC501CB:
6965 case SENSOR_TAS5130C_VF0250:
6966 return -1; /* don't probe */
6967 }
6968 sensor = vga_2wr_probe(gspca_dev);
6969 if (sensor >= 0) {
6970 if (sensor < 0x7600)
6971 return sensor;
6972 /* next probe is needed for OmniVision ? */
6973 }
6974 sensor2 = vga_3wr_probe(gspca_dev);
6975 if (sensor2 >= 0) {
6976 if (sensor >= 0)
6977 return sensor;
6978 return sensor2;
6979 }
6980 return sif_probe(gspca_dev);
6981}
6982
6983/* this function is called at probe time */
6984static int sd_config(struct gspca_dev *gspca_dev,
6985 const struct usb_device_id *id)
6986{
6987 struct sd *sd = (struct sd *) gspca_dev;
6988 struct cam *cam;
6989 int sensor;
6990 int vga = 1; /* 1: vga, 0: sif */
6991 static const __u8 gamma[SENSOR_MAX] = {
6992 5, /* SENSOR_CS2102 0 */
6993 5, /* SENSOR_CS2102K 1 */
6994 4, /* SENSOR_GC0305 2 */
6995 4, /* SENSOR_HDCS2020 3 */
6996 4, /* SENSOR_HDCS2020b 4 */
6997 4, /* SENSOR_HV7131B 5 */
6998 4, /* SENSOR_HV7131C 6 */
6999 4, /* SENSOR_ICM105A 7 */
7000 4, /* SENSOR_MC501CB 8 */
7001 3, /* SENSOR_OV7620 9 */
7002 4, /* SENSOR_OV7630C 10 */
7003 4, /* SENSOR_PAS106 11 */
7004 4, /* SENSOR_PB0330 12 */
7005 4, /* SENSOR_PO2030 13 */
7006 4, /* SENSOR_TAS5130CK 14 */
7007 4, /* SENSOR_TAS5130CXX 15 */
7008 3, /* SENSOR_TAS5130C_VF0250 16 */
7009 };
7010
7011 /* define some sensors from the vendor/product */
7012 sd->sharpness = 2;
7013 switch (id->idVendor) {
7014 case 0x041e: /* Creative */
7015 switch (id->idProduct) {
7016 case 0x4051: /* zc301 chips */
7017 case 0x4053:
7018 sd->sensor = SENSOR_TAS5130C_VF0250;
7019 break;
7020 }
7021 break;
7022 case 0x046d: /* Logitech Labtec */
7023 switch (id->idProduct) {
7024 case 0x08dd:
7025 sd->sensor = SENSOR_MC501CB;
7026 break;
7027 }
7028 break;
7029 case 0x0ac8: /* Vimicro z-star */
7030 switch (id->idProduct) {
7031 case 0x305b:
7032 sd->sensor = SENSOR_TAS5130C_VF0250;
7033 break;
7034 }
7035 break;
7036 }
7037 sensor = zcxx_probeSensor(gspca_dev);
7038 if (sensor >= 0)
7039 PDEBUG(D_PROBE, "probe sensor -> %02x", sensor);
7040 if ((unsigned) force_sensor < SENSOR_MAX) {
7041 sd->sensor = force_sensor;
7042 PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
7043 } else {
7044 switch (sensor) {
7045 case -1:
7046 switch (sd->sensor) {
7047 case SENSOR_MC501CB:
7048 PDEBUG(D_PROBE, "Sensor MC501CB");
7049 break;
7050 case SENSOR_TAS5130C_VF0250:
7051 PDEBUG(D_PROBE, "Sensor Tas5130 (VF0250)");
7052 break;
7053 default:
7054 PDEBUG(D_PROBE,
7055 "Sensor UNKNOW_0 force Tas5130");
7056 sd->sensor = SENSOR_TAS5130CXX;
7057 }
7058 break;
7059 case 0:
7060 PDEBUG(D_PROBE, "Find Sensor HV7131B");
7061 sd->sensor = SENSOR_HV7131B;
7062 break;
7063 case 0x04:
7064 PDEBUG(D_PROBE, "Find Sensor CS2102");
7065 sd->sensor = SENSOR_CS2102;
7066 break;
7067 case 0x08:
7068 PDEBUG(D_PROBE, "Find Sensor HDCS2020(b)");
7069 sd->sensor = SENSOR_HDCS2020b;
7070 break;
7071 case 0x0a:
7072 PDEBUG(D_PROBE,
7073 "Find Sensor PB0330. Chip revision %x",
7074 sd->chip_revision);
7075 sd->sensor = SENSOR_PB0330;
7076 break;
7077 case 0x0c:
7078 PDEBUG(D_PROBE, "Find Sensor ICM105A");
7079 sd->sensor = SENSOR_ICM105A;
7080 break;
7081 case 0x0e:
7082 PDEBUG(D_PROBE, "Find Sensor HDCS2020");
7083 sd->sensor = SENSOR_HDCS2020;
7084 sd->sharpness = 1;
7085 break;
7086 case 0x0f:
7087 PDEBUG(D_PROBE, "Find Sensor PAS106");
7088 sd->sensor = SENSOR_PAS106;
7089 vga = 0; /* SIF */
7090 break;
7091 case 0x10:
7092 case 0x12:
7093 PDEBUG(D_PROBE, "Find Sensor TAS5130");
7094 sd->sensor = SENSOR_TAS5130CXX;
7095 break;
7096 case 0x11:
7097 PDEBUG(D_PROBE, "Find Sensor HV7131R(c)");
7098 sd->sensor = SENSOR_HV7131C;
7099 break;
7100 case 0x13:
7101 PDEBUG(D_PROBE,
7102 "Find Sensor MI0360. Chip revision %x",
7103 sd->chip_revision);
7104 sd->sensor = SENSOR_PB0330;
7105 break;
7106 case 0x14:
7107 PDEBUG(D_PROBE,
7108 "Find Sensor CS2102K?. Chip revision %x",
7109 sd->chip_revision);
7110 sd->sensor = SENSOR_CS2102K;
7111 break;
7112 case 0x15:
7113 PDEBUG(D_PROBE,
7114 "Find Sensor TAS5130CK?. Chip revision %x",
7115 sd->chip_revision);
7116 sd->sensor = SENSOR_TAS5130CK;
7117 break;
7118 case 0x29:
7119 PDEBUG(D_PROBE, "Find Sensor GC0305");
7120 sd->sensor = SENSOR_GC0305;
7121 break;
7122 case 0x2030:
7123 PDEBUG(D_PROBE, "Find Sensor PO2030");
7124 sd->sensor = SENSOR_PO2030;
7125 sd->sharpness = 0; /* from win traces */
7126 break;
7127 case 0x7620:
7128 PDEBUG(D_PROBE, "Find Sensor OV7620");
7129 sd->sensor = SENSOR_OV7620;
7130 break;
7131 case 0x7648:
7132 PDEBUG(D_PROBE, "Find Sensor OV7648");
7133 sd->sensor = SENSOR_OV7620; /* same sensor (?) */
7134 break;
7135 default:
7136 PDEBUG(D_ERR|D_PROBE, "Unknown sensor %02x", sensor);
7137 return -EINVAL;
7138 }
7139 }
7140 if (sensor < 0x20) {
7141 if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
7142 reg_w(gspca_dev->dev, 0x02, 0x0010);
7143 else
7144 reg_w(gspca_dev->dev, sensor & 0x0f, 0x0010);
7145 reg_r(gspca_dev, 0x0010);
7146 }
7147
7148 cam = &gspca_dev->cam;
7149 cam->dev_name = (char *) id->driver_info;
7150 cam->epaddr = 0x01;
7151/*fixme:test*/
7152 gspca_dev->nbalt--;
7153 if (vga) {
7154 cam->cam_mode = vga_mode;
7155 cam->nmodes = ARRAY_SIZE(vga_mode);
7156 } else {
7157 cam->cam_mode = sif_mode;
7158 cam->nmodes = ARRAY_SIZE(sif_mode);
7159 }
7160 sd->qindex = 1;
7161 sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
7162 sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
7163 sd->gamma = gamma[(int) sd->sensor];
7164 sd->autogain = sd_ctrls[SD_AUTOGAIN].qctrl.default_value;
7165 sd->lightfreq = sd_ctrls[SD_FREQ].qctrl.default_value;
7166 sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
7167
7168 /* switch the led off */
7169 reg_w(gspca_dev->dev, 0x01, 0x0000);
7170 return 0;
7171}
7172
7173/* this function is called at open time */
7174static int sd_open(struct gspca_dev *gspca_dev)
7175{
7176 reg_w(gspca_dev->dev, 0x01, 0x0000);
7177 return 0;
7178}
7179
7180static void sd_start(struct gspca_dev *gspca_dev)
7181{
7182 struct sd *sd = (struct sd *) gspca_dev;
7183 struct usb_device *dev = gspca_dev->dev;
7184 const struct usb_action *zc3_init;
7185 int mode;
7186 static const struct usb_action *init_tb[SENSOR_MAX][2] = {
7187 {cs2102_InitialScale, cs2102_Initial}, /* 0 */
7188 {cs2102K_InitialScale, cs2102K_Initial}, /* 1 */
7189 {gc0305_Initial, gc0305_InitialScale}, /* 2 */
7190 {hdcs2020xx_InitialScale, hdcs2020xx_Initial}, /* 3 */
7191 {hdcs2020xb_InitialScale, hdcs2020xb_Initial}, /* 4 */
7192 {hv7131bxx_InitialScale, hv7131bxx_Initial}, /* 5 */
7193 {hv7131cxx_InitialScale, hv7131cxx_Initial}, /* 6 */
7194 {icm105axx_InitialScale, icm105axx_Initial}, /* 7 */
7195 {MC501CB_InitialScale, MC501CB_Initial}, /* 9 */
7196 {OV7620_mode0, OV7620_mode1}, /* 9 */
7197 {ov7630c_InitialScale, ov7630c_Initial}, /* 10 */
7198 {pas106b_InitialScale, pas106b_Initial}, /* 11 */
7199 {pb0330xx_InitialScale, pb0330xx_Initial}, /* 12 */
7200/* or {pb03303x_InitialScale, pb03303x_Initial}, */
7201 {PO2030_mode0, PO2030_mode1}, /* 13 */
7202 {tas5130CK_InitialScale, tas5130CK_Initial}, /* 14 */
7203 {tas5130cxx_InitialScale, tas5130cxx_Initial}, /* 15 */
7204 {tas5130c_vf0250_InitialScale, tas5130c_vf0250_Initial},
7205 /* 16 */
7206 };
7207
7208 mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
7209 zc3_init = init_tb[(int) sd->sensor][mode];
7210 switch (sd->sensor) {
7211 case SENSOR_HV7131B:
7212 case SENSOR_HV7131C:
7213 zcxx_probeSensor(gspca_dev);
7214 break;
7215 case SENSOR_PAS106:
7216 usb_exchange(gspca_dev, pas106b_Initial_com);
7217 break;
7218 case SENSOR_PB0330:
7219 if (mode) {
7220 if (sd->chip_revision == 0xc001
7221 || sd->chip_revision == 0xe001
7222 || sd->chip_revision == 0x8001)
7223 zc3_init = pb03303x_Initial;
7224 } else {
7225 if (sd->chip_revision == 0xc001
7226 || sd->chip_revision == 0xe001
7227 || sd->chip_revision == 0x8001)
7228 zc3_init = pb03303x_InitialScale;
7229 }
7230 break;
7231 }
7232 usb_exchange(gspca_dev, zc3_init);
7233
7234 switch (sd->sensor) {
7235 case SENSOR_GC0305:
7236 case SENSOR_OV7620:
7237 case SENSOR_PO2030:
7238 msleep(100); /* ?? */
7239 reg_r(gspca_dev, 0x0002); /* --> 0x40 */
7240 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7241 reg_w(dev, 0x15, 0x01ae);
7242 reg_w(dev, 0x0d, 0x003a);
7243 reg_w(dev, 0x02, 0x003b);
7244 reg_w(dev, 0x00, 0x0038);
7245 break;
7246 }
7247
7248 setmatrix(gspca_dev);
7249 setbrightness(gspca_dev);
7250 switch (sd->sensor) {
7251 case SENSOR_OV7620:
7252 reg_r(gspca_dev, 0x0008);
7253 reg_w(dev, 0x00, 0x0008);
7254 break;
7255 case SENSOR_GC0305:
7256 reg_r(gspca_dev, 0x0008);
7257 /* fall thru */
7258 case SENSOR_PO2030:
7259 reg_w(dev, 0x03, 0x0008);
7260 break;
7261 }
7262 setsharpness(gspca_dev);
7263
7264 /* set the gamma tables when not set */
7265 switch (sd->sensor) {
7266 case SENSOR_CS2102: /* gamma set in xxx_Initial */
7267 case SENSOR_CS2102K:
7268 case SENSOR_HDCS2020:
7269 case SENSOR_HDCS2020b:
7270 case SENSOR_PB0330: /* pb with chip_revision - see above */
7271 case SENSOR_OV7630C:
7272 case SENSOR_TAS5130CK:
7273 break;
7274 default:
7275 setcontrast(gspca_dev);
7276 break;
7277 }
7278 setmatrix(gspca_dev); /* one more time? */
7279 switch (sd->sensor) {
7280 case SENSOR_OV7620:
7281 reg_r(gspca_dev, 0x0180); /* from win */
7282 reg_w(dev, 0x00, 0x0180);
7283 break;
7284 default:
7285 setquality(gspca_dev);
7286 break;
7287 }
7288 setlightfreq(gspca_dev);
7289
7290 switch (sd->sensor) {
7291 case SENSOR_GC0305:
7292 case SENSOR_OV7620:
7293 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7294 reg_w(dev, 0x15, 0x01ae);
7295 sd->autogain = 0;
7296 break;
7297 case SENSOR_PO2030:
7298 reg_w(dev, 0x40, 0x0117); /* (from win traces) */
7299 reg_r(gspca_dev, 0x0180);
7300 break;
7301 }
7302
7303 setautogain(gspca_dev);
7304 switch (sd->sensor) {
7305 case SENSOR_GC0305:
7306/* setlightfreq(gspca_dev); ?? (end: 80 -> [18d]) */
7307 reg_w(dev, 0x09, 0x01ad); /* (from win traces) */
7308 reg_w(dev, 0x15, 0x01ae);
7309 reg_w(dev, 0x40, 0x0180);
7310 reg_w(dev, 0x40, 0x0117);
7311 reg_r(gspca_dev, 0x0180);
7312 sd->autogain = 1;
7313 setautogain(gspca_dev);
7314 break;
7315 case SENSOR_OV7620:
7316 i2c_read(gspca_dev, 0x13); /*fixme: returns 0xa3 */
7317 i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
7318 /*fixme: returned value to send? */
7319 reg_w(dev, 0x40, 0x0117); /* (from win traces) */
7320 reg_r(gspca_dev, 0x0180);
7321 setautogain(gspca_dev);
7322 msleep(500);
7323 break;
7324 case SENSOR_PO2030:
7325 msleep(500);
7326 reg_r(gspca_dev, 0x0008);
7327 reg_r(gspca_dev, 0x0007);
7328 reg_w(dev, 0x00, 0x0007); /* (from win traces) */
7329 reg_w(dev, 0x02, 0x0008);
7330 break;
7331 }
7332}
7333
7334static void sd_stopN(struct gspca_dev *gspca_dev)
7335{
7336}
7337
7338static void sd_stop0(struct gspca_dev *gspca_dev)
7339{
7340 struct sd *sd = (struct sd *) gspca_dev;
7341
7342 send_unknown(gspca_dev->dev, sd->sensor);
7343}
7344
7345/* this function is called at close time */
7346static void sd_close(struct gspca_dev *gspca_dev)
7347{
7348}
7349
7350static void sd_pkt_scan(struct gspca_dev *gspca_dev,
7351 struct gspca_frame *frame,
7352 __u8 *data,
7353 int len)
7354{
7355
7356 if (data[0] == 0xff && data[1] == 0xd8) { /* start of frame */
7357 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
7358 data, 0);
7359 /* put the JPEG header in the new frame */
7360 jpeg_put_header(gspca_dev, frame,
7361 ((struct sd *) gspca_dev)->qindex,
7362 0x21);
7363 /* remove the webcam's header:
7364 * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
7365 * - 'ss ss' is the frame sequence number (BE)
7366 * - 'ww ww' and 'hh hh' are the window dimensions (BE)
7367 * - 'pp pp' is the packet sequence number (BE)
7368 */
7369 data += 18;
7370 len -= 18;
7371 }
7372 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
7373}
7374
7375static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
7376{
7377 struct sd *sd = (struct sd *) gspca_dev;
7378
7379 sd->brightness = val;
7380 if (gspca_dev->streaming)
7381 setbrightness(gspca_dev);
7382 return 0;
7383}
7384
7385static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
7386{
7387 struct sd *sd = (struct sd *) gspca_dev;
7388
7389 *val = sd->brightness;
7390 return 0;
7391}
7392
7393static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
7394{
7395 struct sd *sd = (struct sd *) gspca_dev;
7396
7397 sd->contrast = val;
7398 if (gspca_dev->streaming)
7399 setcontrast(gspca_dev);
7400 return 0;
7401}
7402
7403static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
7404{
7405 struct sd *sd = (struct sd *) gspca_dev;
7406
7407 *val = sd->contrast;
7408 return 0;
7409}
7410
7411static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
7412{
7413 struct sd *sd = (struct sd *) gspca_dev;
7414
7415 sd->autogain = val;
7416 if (gspca_dev->streaming)
7417 setautogain(gspca_dev);
7418 return 0;
7419}
7420
7421static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
7422{
7423 struct sd *sd = (struct sd *) gspca_dev;
7424
7425 *val = sd->autogain;
7426 return 0;
7427}
7428
7429static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
7430{
7431 struct sd *sd = (struct sd *) gspca_dev;
7432
7433 sd->gamma = val;
7434 if (gspca_dev->streaming)
7435 setcontrast(gspca_dev);
7436 return 0;
7437}
7438
7439static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
7440{
7441 struct sd *sd = (struct sd *) gspca_dev;
7442
7443 *val = sd->gamma;
7444 return 0;
7445}
7446
7447static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
7448{
7449 struct sd *sd = (struct sd *) gspca_dev;
7450
7451 sd->lightfreq = val;
7452 if (gspca_dev->streaming)
7453 setlightfreq(gspca_dev);
7454 return 0;
7455}
7456
7457static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
7458{
7459 struct sd *sd = (struct sd *) gspca_dev;
7460
7461 *val = sd->lightfreq;
7462 return 0;
7463}
7464
7465static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
7466{
7467 struct sd *sd = (struct sd *) gspca_dev;
7468
7469 sd->sharpness = val;
7470 if (gspca_dev->streaming)
7471 setsharpness(gspca_dev);
7472 return 0;
7473}
7474
7475static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
7476{
7477 struct sd *sd = (struct sd *) gspca_dev;
7478
7479 *val = sd->sharpness;
7480 return 0;
7481}
7482
7483static int sd_querymenu(struct gspca_dev *gspca_dev,
7484 struct v4l2_querymenu *menu)
7485{
7486 switch (menu->id) {
7487 case V4L2_CID_POWER_LINE_FREQUENCY:
7488 switch (menu->index) {
7489 case 0: /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
7490 strcpy((char *) menu->name, "NoFliker");
7491 return 0;
7492 case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
7493 strcpy((char *) menu->name, "50 Hz");
7494 return 0;
7495 case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
7496 strcpy((char *) menu->name, "60 Hz");
7497 return 0;
7498 }
7499 break;
7500 }
7501 return -EINVAL;
7502}
7503
7504static const struct sd_desc sd_desc = {
7505 .name = MODULE_NAME,
7506 .ctrls = sd_ctrls,
7507 .nctrls = sizeof sd_ctrls / sizeof sd_ctrls[0],
7508 .config = sd_config,
7509 .open = sd_open,
7510 .start = sd_start,
7511 .stopN = sd_stopN,
7512 .stop0 = sd_stop0,
7513 .close = sd_close,
7514 .pkt_scan = sd_pkt_scan,
7515 .querymenu = sd_querymenu,
7516};
7517
7518#define DVNM(name) .driver_info = (kernel_ulong_t) name
7519static const __devinitdata struct usb_device_id device_table[] = {
7520 {USB_DEVICE(0x041e, 0x041e), DVNM("Creative WebCam Live!")},
7521#ifndef CONFIG_USB_ZC0301
7522 {USB_DEVICE(0x041e, 0x4017), DVNM("Creative Webcam Mobile PD1090")},
7523 {USB_DEVICE(0x041e, 0x401c), DVNM("Creative NX")},
7524 {USB_DEVICE(0x041e, 0x401e), DVNM("Creative Nx Pro")},
7525 {USB_DEVICE(0x041e, 0x401f), DVNM("Creative Webcam Notebook PD1171")},
7526#endif
7527 {USB_DEVICE(0x041e, 0x4029), DVNM("Creative WebCam Vista Pro")},
7528#ifndef CONFIG_USB_ZC0301
7529 {USB_DEVICE(0x041e, 0x4034), DVNM("Creative Instant P0620")},
7530 {USB_DEVICE(0x041e, 0x4035), DVNM("Creative Instant P0620D")},
7531 {USB_DEVICE(0x041e, 0x4036), DVNM("Creative Live !")},
7532 {USB_DEVICE(0x041e, 0x403a), DVNM("Creative Nx Pro 2")},
7533#endif
7534 {USB_DEVICE(0x041e, 0x4051), DVNM("Creative Notebook Pro (VF0250)")},
7535 {USB_DEVICE(0x041e, 0x4053), DVNM("Creative Live!Cam Video IM")},
7536#ifndef CONFIG_USB_ZC0301
7537 {USB_DEVICE(0x0458, 0x7007), DVNM("Genius VideoCam V2")},
7538 {USB_DEVICE(0x0458, 0x700c), DVNM("Genius VideoCam V3")},
7539 {USB_DEVICE(0x0458, 0x700f), DVNM("Genius VideoCam Web V2")},
7540#endif
7541 {USB_DEVICE(0x0461, 0x0a00), DVNM("MicroInnovation WebCam320")},
7542 {USB_DEVICE(0x046d, 0x08a0), DVNM("Logitech QC IM")},
7543 {USB_DEVICE(0x046d, 0x08a1), DVNM("Logitech QC IM 0x08A1 +sound")},
7544 {USB_DEVICE(0x046d, 0x08a2), DVNM("Labtec Webcam Pro")},
7545 {USB_DEVICE(0x046d, 0x08a3), DVNM("Logitech QC Chat")},
7546 {USB_DEVICE(0x046d, 0x08a6), DVNM("Logitech QCim")},
7547 {USB_DEVICE(0x046d, 0x08a7), DVNM("Logitech QuickCam Image")},
7548 {USB_DEVICE(0x046d, 0x08a9), DVNM("Logitech Notebook Deluxe")},
7549 {USB_DEVICE(0x046d, 0x08aa), DVNM("Labtec Webcam Notebook")},
7550 {USB_DEVICE(0x046d, 0x08ac), DVNM("Logitech QuickCam Cool")},
7551 {USB_DEVICE(0x046d, 0x08ad), DVNM("Logitech QCCommunicate STX")},
7552#ifndef CONFIG_USB_ZC0301
7553 {USB_DEVICE(0x046d, 0x08ae), DVNM("Logitech QuickCam for Notebooks")},
7554#endif
7555 {USB_DEVICE(0x046d, 0x08af), DVNM("Logitech QuickCam Cool")},
7556 {USB_DEVICE(0x046d, 0x08b9), DVNM("Logitech QC IM ???")},
7557 {USB_DEVICE(0x046d, 0x08d7), DVNM("Logitech QCam STX")},
7558 {USB_DEVICE(0x046d, 0x08d9), DVNM("Logitech QuickCam IM/Connect")},
7559 {USB_DEVICE(0x046d, 0x08d8), DVNM("Logitech Notebook Deluxe")},
7560 {USB_DEVICE(0x046d, 0x08da), DVNM("Logitech QuickCam Messenger")},
7561 {USB_DEVICE(0x046d, 0x08dd), DVNM("Logitech QuickCam for Notebooks")},
7562 {USB_DEVICE(0x0471, 0x0325), DVNM("Philips SPC 200 NC")},
7563 {USB_DEVICE(0x0471, 0x0326), DVNM("Philips SPC 300 NC")},
7564 {USB_DEVICE(0x0471, 0x032d), DVNM("Philips spc210nc")},
7565 {USB_DEVICE(0x0471, 0x032e), DVNM("Philips spc315nc")},
7566 {USB_DEVICE(0x055f, 0xc005), DVNM("Mustek Wcam300A")},
7567#ifndef CONFIG_USB_ZC0301
7568 {USB_DEVICE(0x055f, 0xd003), DVNM("Mustek WCam300A")},
7569 {USB_DEVICE(0x055f, 0xd004), DVNM("Mustek WCam300 AN")},
7570#endif
7571 {USB_DEVICE(0x0698, 0x2003), DVNM("CTX M730V built in")},
7572 {USB_DEVICE(0x0ac8, 0x0302), DVNM("Z-star Vimicro zc0302")},
7573#ifndef CONFIG_USB_ZC0301
7574 {USB_DEVICE(0x0ac8, 0x301b), DVNM("Z-Star zc301b")},
7575 {USB_DEVICE(0x0ac8, 0x303b), DVNM("Vimicro 0x303b")},
7576#endif
7577 {USB_DEVICE(0x0ac8, 0x305b), DVNM("Z-star Vimicro zc0305b")},
7578#ifndef CONFIG_USB_ZC0301
7579 {USB_DEVICE(0x0ac8, 0x307b), DVNM("Z-Star 307b")},
7580 {USB_DEVICE(0x10fd, 0x0128), DVNM("Typhoon Webshot II 300k 0x0128")},
7581 {USB_DEVICE(0x10fd, 0x8050), DVNM("Typhoon Webshot II USB 300k")},
7582#endif
7583 {} /* end of entry */
7584};
7585#undef DVNAME
7586MODULE_DEVICE_TABLE(usb, device_table);
7587
7588/* -- device connect -- */
7589static int sd_probe(struct usb_interface *intf,
7590 const struct usb_device_id *id)
7591{
7592 return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
7593 THIS_MODULE);
7594}
7595
7596/* USB driver */
7597static struct usb_driver sd_driver = {
7598 .name = MODULE_NAME,
7599 .id_table = device_table,
7600 .probe = sd_probe,
7601 .disconnect = gspca_disconnect,
7602};
7603
7604static int __init sd_mod_init(void)
7605{
7606 if (usb_register(&sd_driver) < 0)
7607 return -1;
7608 PDEBUG(D_PROBE, "v%s registered", version);
7609 return 0;
7610}
7611
7612static void __exit sd_mod_exit(void)
7613{
7614 usb_deregister(&sd_driver);
7615 PDEBUG(D_PROBE, "deregistered");
7616}
7617
7618module_init(sd_mod_init);
7619module_exit(sd_mod_exit);
7620
7621module_param(force_sensor, int, 0644);
7622MODULE_PARM_DESC(force_sensor,
7623 "Force sensor. Only for experts!!!");